summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/libANGLE
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE')
-rw-r--r--gfx/angle/checkout/src/libANGLE/AttributeMap.cpp147
-rw-r--r--gfx/angle/checkout/src/libANGLE/AttributeMap.h100
-rw-r--r--gfx/angle/checkout/src/libANGLE/BinaryStream.h286
-rw-r--r--gfx/angle/checkout/src/libANGLE/BlobCache.cpp277
-rw-r--r--gfx/angle/checkout/src/libANGLE/BlobCache.h182
-rw-r--r--gfx/angle/checkout/src/libANGLE/Buffer.cpp449
-rw-r--r--gfx/angle/checkout/src/libANGLE/Buffer.h218
-rw-r--r--gfx/angle/checkout/src/libANGLE/Caps.cpp1371
-rw-r--r--gfx/angle/checkout/src/libANGLE/Caps.h786
-rw-r--r--gfx/angle/checkout/src/libANGLE/Compiler.cpp422
-rw-r--r--gfx/angle/checkout/src/libANGLE/Compiler.h78
-rw-r--r--gfx/angle/checkout/src/libANGLE/Config.cpp416
-rw-r--r--gfx/angle/checkout/src/libANGLE/Config.h115
-rw-r--r--gfx/angle/checkout/src/libANGLE/Constants.h125
-rw-r--r--gfx/angle/checkout/src/libANGLE/Context.cpp10472
-rw-r--r--gfx/angle/checkout/src/libANGLE/Context.h901
-rw-r--r--gfx/angle/checkout/src/libANGLE/Context.inl.h176
-rw-r--r--gfx/angle/checkout/src/libANGLE/Context_gl.cpp3706
-rw-r--r--gfx/angle/checkout/src/libANGLE/Context_gl_1_autogen.h349
-rw-r--r--gfx/angle/checkout/src/libANGLE/Context_gl_2_autogen.h44
-rw-r--r--gfx/angle/checkout/src/libANGLE/Context_gl_3_autogen.h82
-rw-r--r--gfx/angle/checkout/src/libANGLE/Context_gl_4_autogen.h358
-rw-r--r--gfx/angle/checkout/src/libANGLE/Context_gles_1_0.cpp746
-rw-r--r--gfx/angle/checkout/src/libANGLE/Context_gles_1_0_autogen.h109
-rw-r--r--gfx/angle/checkout/src/libANGLE/Context_gles_2_0_autogen.h190
-rw-r--r--gfx/angle/checkout/src/libANGLE/Context_gles_3_0_autogen.h164
-rw-r--r--gfx/angle/checkout/src/libANGLE/Context_gles_3_1_autogen.h133
-rw-r--r--gfx/angle/checkout/src/libANGLE/Context_gles_3_2_autogen.h83
-rw-r--r--gfx/angle/checkout/src/libANGLE/Context_gles_ext_autogen.h616
-rw-r--r--gfx/angle/checkout/src/libANGLE/Debug.cpp507
-rw-r--r--gfx/angle/checkout/src/libANGLE/Debug.h180
-rw-r--r--gfx/angle/checkout/src/libANGLE/Device.cpp133
-rw-r--r--gfx/angle/checkout/src/libANGLE/Device.h60
-rw-r--r--gfx/angle/checkout/src/libANGLE/Display.cpp2506
-rw-r--r--gfx/angle/checkout/src/libANGLE/Display.h427
-rw-r--r--gfx/angle/checkout/src/libANGLE/EGLSync.cpp114
-rw-r--r--gfx/angle/checkout/src/libANGLE/EGLSync.h72
-rw-r--r--gfx/angle/checkout/src/libANGLE/Error.cpp67
-rw-r--r--gfx/angle/checkout/src/libANGLE/Error.h206
-rw-r--r--gfx/angle/checkout/src/libANGLE/Error.inc91
-rw-r--r--gfx/angle/checkout/src/libANGLE/ErrorStrings.h627
-rw-r--r--gfx/angle/checkout/src/libANGLE/Fence.cpp124
-rw-r--r--gfx/angle/checkout/src/libANGLE/Fence.h88
-rw-r--r--gfx/angle/checkout/src/libANGLE/Framebuffer.cpp2727
-rw-r--r--gfx/angle/checkout/src/libANGLE/Framebuffer.h538
-rw-r--r--gfx/angle/checkout/src/libANGLE/FramebufferAttachment.cpp350
-rw-r--r--gfx/angle/checkout/src/libANGLE/FramebufferAttachment.h307
-rw-r--r--gfx/angle/checkout/src/libANGLE/GLES1Renderer.cpp1197
-rw-r--r--gfx/angle/checkout/src/libANGLE/GLES1Renderer.h340
-rw-r--r--gfx/angle/checkout/src/libANGLE/GLES1Shaders.inc1218
-rw-r--r--gfx/angle/checkout/src/libANGLE/GLES1State.cpp609
-rw-r--r--gfx/angle/checkout/src/libANGLE/GLES1State.h351
-rw-r--r--gfx/angle/checkout/src/libANGLE/HandleAllocator.cpp184
-rw-r--r--gfx/angle/checkout/src/libANGLE/HandleAllocator.h65
-rw-r--r--gfx/angle/checkout/src/libANGLE/Image.cpp581
-rw-r--r--gfx/angle/checkout/src/libANGLE/Image.h216
-rw-r--r--gfx/angle/checkout/src/libANGLE/ImageIndex.cpp388
-rw-r--r--gfx/angle/checkout/src/libANGLE/ImageIndex.h133
-rw-r--r--gfx/angle/checkout/src/libANGLE/IndexRangeCache.cpp116
-rw-r--r--gfx/angle/checkout/src/libANGLE/IndexRangeCache.h63
-rw-r--r--gfx/angle/checkout/src/libANGLE/InfoLog.h90
-rw-r--r--gfx/angle/checkout/src/libANGLE/LoggingAnnotator.cpp63
-rw-r--r--gfx/angle/checkout/src/libANGLE/LoggingAnnotator.h39
-rw-r--r--gfx/angle/checkout/src/libANGLE/MemoryObject.cpp66
-rw-r--r--gfx/angle/checkout/src/libANGLE/MemoryObject.h60
-rw-r--r--gfx/angle/checkout/src/libANGLE/MemoryProgramCache.cpp283
-rw-r--r--gfx/angle/checkout/src/libANGLE/MemoryProgramCache.h87
-rw-r--r--gfx/angle/checkout/src/libANGLE/MemoryShaderCache.cpp155
-rw-r--r--gfx/angle/checkout/src/libANGLE/MemoryShaderCache.h60
-rw-r--r--gfx/angle/checkout/src/libANGLE/Observer.cpp113
-rw-r--r--gfx/angle/checkout/src/libANGLE/Observer.h167
-rw-r--r--gfx/angle/checkout/src/libANGLE/Overlay.cpp103
-rw-r--r--gfx/angle/checkout/src/libANGLE/Overlay.h154
-rw-r--r--gfx/angle/checkout/src/libANGLE/OverlayWidgets.cpp737
-rw-r--r--gfx/angle/checkout/src/libANGLE/OverlayWidgets.h201
-rw-r--r--gfx/angle/checkout/src/libANGLE/Overlay_autogen.cpp824
-rw-r--r--gfx/angle/checkout/src/libANGLE/Overlay_autogen.h83
-rw-r--r--gfx/angle/checkout/src/libANGLE/Overlay_font_autogen.cpp5078
-rw-r--r--gfx/angle/checkout/src/libANGLE/Overlay_font_autogen.h27
-rw-r--r--gfx/angle/checkout/src/libANGLE/PixelLocalStorage.cpp826
-rw-r--r--gfx/angle/checkout/src/libANGLE/PixelLocalStorage.h177
-rw-r--r--gfx/angle/checkout/src/libANGLE/Platform.cpp76
-rw-r--r--gfx/angle/checkout/src/libANGLE/Program.cpp3810
-rw-r--r--gfx/angle/checkout/src/libANGLE/Program.h897
-rw-r--r--gfx/angle/checkout/src/libANGLE/ProgramExecutable.cpp1785
-rw-r--r--gfx/angle/checkout/src/libANGLE/ProgramExecutable.h517
-rw-r--r--gfx/angle/checkout/src/libANGLE/ProgramLinkedResources.cpp2377
-rw-r--r--gfx/angle/checkout/src/libANGLE/ProgramLinkedResources.h333
-rw-r--r--gfx/angle/checkout/src/libANGLE/ProgramPipeline.cpp721
-rw-r--r--gfx/angle/checkout/src/libANGLE/ProgramPipeline.h176
-rw-r--r--gfx/angle/checkout/src/libANGLE/Query.cpp96
-rw-r--r--gfx/angle/checkout/src/libANGLE/Query.h60
-rw-r--r--gfx/angle/checkout/src/libANGLE/RefCountObject.h327
-rw-r--r--gfx/angle/checkout/src/libANGLE/Renderbuffer.cpp423
-rw-r--r--gfx/angle/checkout/src/libANGLE/Renderbuffer.h181
-rw-r--r--gfx/angle/checkout/src/libANGLE/ResourceManager.cpp522
-rw-r--r--gfx/angle/checkout/src/libANGLE/ResourceManager.h353
-rw-r--r--gfx/angle/checkout/src/libANGLE/ResourceMap.h346
-rw-r--r--gfx/angle/checkout/src/libANGLE/Sampler.cpp211
-rw-r--r--gfx/angle/checkout/src/libANGLE/Sampler.h92
-rw-r--r--gfx/angle/checkout/src/libANGLE/Semaphore.cpp52
-rw-r--r--gfx/angle/checkout/src/libANGLE/Semaphore.h57
-rw-r--r--gfx/angle/checkout/src/libANGLE/Shader.cpp1331
-rw-r--r--gfx/angle/checkout/src/libANGLE/Shader.h305
-rw-r--r--gfx/angle/checkout/src/libANGLE/SizedMRUCache.h156
-rw-r--r--gfx/angle/checkout/src/libANGLE/State.cpp3866
-rw-r--r--gfx/angle/checkout/src/libANGLE/State.h1258
-rw-r--r--gfx/angle/checkout/src/libANGLE/Stream.cpp282
-rw-r--r--gfx/angle/checkout/src/libANGLE/Stream.h149
-rw-r--r--gfx/angle/checkout/src/libANGLE/Surface.cpp941
-rw-r--r--gfx/angle/checkout/src/libANGLE/Surface.h388
-rw-r--r--gfx/angle/checkout/src/libANGLE/Texture.cpp2494
-rw-r--r--gfx/angle/checkout/src/libANGLE/Texture.h738
-rw-r--r--gfx/angle/checkout/src/libANGLE/Thread.cpp168
-rw-r--r--gfx/angle/checkout/src/libANGLE/Thread.h80
-rw-r--r--gfx/angle/checkout/src/libANGLE/TransformFeedback.cpp347
-rw-r--r--gfx/angle/checkout/src/libANGLE/TransformFeedback.h120
-rw-r--r--gfx/angle/checkout/src/libANGLE/Uniform.cpp179
-rw-r--r--gfx/angle/checkout/src/libANGLE/Uniform.h138
-rw-r--r--gfx/angle/checkout/src/libANGLE/VaryingPacking.cpp1152
-rw-r--r--gfx/angle/checkout/src/libANGLE/VaryingPacking.h329
-rw-r--r--gfx/angle/checkout/src/libANGLE/Version.h34
-rw-r--r--gfx/angle/checkout/src/libANGLE/Version.inc59
-rw-r--r--gfx/angle/checkout/src/libANGLE/VertexArray.cpp906
-rw-r--r--gfx/angle/checkout/src/libANGLE/VertexArray.h436
-rw-r--r--gfx/angle/checkout/src/libANGLE/VertexAttribute.cpp170
-rw-r--r--gfx/angle/checkout/src/libANGLE/VertexAttribute.h139
-rw-r--r--gfx/angle/checkout/src/libANGLE/VertexAttribute.inc58
-rw-r--r--gfx/angle/checkout/src/libANGLE/WorkerThread.cpp356
-rw-r--r--gfx/angle/checkout/src/libANGLE/WorkerThread.h94
-rw-r--r--gfx/angle/checkout/src/libANGLE/angletypes.cpp1039
-rw-r--r--gfx/angle/checkout/src/libANGLE/angletypes.h1203
-rw-r--r--gfx/angle/checkout/src/libANGLE/angletypes.inc35
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/FrameCapture.h1208
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/FrameCapture_mock.cpp55
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/capture_egl.h69
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/capture_gl_1_autogen.h2072
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/capture_gl_2_autogen.h266
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/capture_gl_3_autogen.h609
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/capture_gl_4_autogen.h2524
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/capture_gles_1_0_autogen.h582
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/capture_gles_2_0_autogen.h1195
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/capture_gles_3_0_autogen.h1079
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/capture_gles_3_1_autogen.h728
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/capture_gles_3_2_autogen.h553
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/capture_gles_ext_autogen.h5231
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/frame_capture_utils.h23
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/frame_capture_utils_autogen.h3257
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/frame_capture_utils_mock.cpp19
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/gl_enum_utils.h32
-rw-r--r--gfx/angle/checkout/src/libANGLE/capture/gl_enum_utils_autogen.h419
-rw-r--r--gfx/angle/checkout/src/libANGLE/entry_points_utils.h127
-rw-r--r--gfx/angle/checkout/src/libANGLE/es3_copy_conversion_table_autogen.cpp171
-rw-r--r--gfx/angle/checkout/src/libANGLE/features.h56
-rw-r--r--gfx/angle/checkout/src/libANGLE/format_map_autogen.cpp1781
-rw-r--r--gfx/angle/checkout/src/libANGLE/format_map_desktop.cpp128
-rw-r--r--gfx/angle/checkout/src/libANGLE/formatutils.cpp3220
-rw-r--r--gfx/angle/checkout/src/libANGLE/formatutils.h577
-rw-r--r--gfx/angle/checkout/src/libANGLE/gles_extensions_autogen.cpp278
-rw-r--r--gfx/angle/checkout/src/libANGLE/gles_extensions_autogen.h727
-rw-r--r--gfx/angle/checkout/src/libANGLE/histogram_macros.h110
-rw-r--r--gfx/angle/checkout/src/libANGLE/queryconversions.cpp315
-rw-r--r--gfx/angle/checkout/src/libANGLE/queryconversions.h138
-rw-r--r--gfx/angle/checkout/src/libANGLE/queryutils.cpp4525
-rw-r--r--gfx/angle/checkout/src/libANGLE/queryutils.h293
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/BufferImpl.cpp39
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/BufferImpl.h98
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/CompilerImpl.h32
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/ContextImpl.cpp88
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/ContextImpl.h274
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/DeviceImpl.cpp18
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/DeviceImpl.h42
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/DisplayImpl.cpp168
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/DisplayImpl.h169
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/EGLImplFactory.h104
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/EGLReusableSync.cpp116
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/EGLReusableSync.h54
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/EGLSyncImpl.cpp37
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/EGLSyncImpl.h57
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/FenceNVImpl.h38
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/Format.h238
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/FormatID_autogen.h264
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/Format_table_autogen.cpp762
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h65
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/FramebufferImpl.cpp18
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/FramebufferImpl.h123
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/GLImplFactory.h116
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/ImageImpl.cpp30
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/ImageImpl.h68
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/MemoryObjectImpl.h47
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/OverlayImpl.h42
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/ProgramImpl.cpp18
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/ProgramImpl.h176
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/ProgramPipelineImpl.cpp26
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/ProgramPipelineImpl.h42
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/QueryImpl.cpp21
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/QueryImpl.h49
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/RenderTargetCache.h186
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/RenderbufferImpl.cpp19
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/RenderbufferImpl.h164
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/SamplerImpl.h44
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/SemaphoreImpl.h50
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/ShaderImpl.cpp105
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/ShaderImpl.h77
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/StreamProducerImpl.h40
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/SurfaceImpl.cpp158
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/SurfaceImpl.h136
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/SyncImpl.h45
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/TextureImpl.cpp200
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/TextureImpl.h254
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/TransformFeedbackImpl.cpp19
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/TransformFeedbackImpl.h42
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/VertexArrayImpl.cpp18
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/VertexArrayImpl.h70
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/copyvertex.h80
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/copyvertex.inc.h635
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/BufferD3D.cpp191
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/BufferD3D.h89
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/CompilerD3D.cpp24
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/CompilerD3D.h32
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/ContextD3D.h24
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/DeviceD3D.cpp84
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/DeviceD3D.h39
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/DisplayD3D.cpp462
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/DisplayD3D.h179
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicHLSL.cpp1537
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicHLSL.h212
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp919
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.h28
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/EGLImageD3D.cpp93
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/EGLImageD3D.h55
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/FramebufferD3D.cpp402
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/FramebufferD3D.h143
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/HLSLCompiler.cpp387
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/HLSLCompiler.h74
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/ImageD3D.cpp56
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/ImageD3D.h105
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexBuffer.cpp183
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexBuffer.h125
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexDataManager.cpp318
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexDataManager.h112
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp19
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/NativeWindowD3D.h38
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/ProgramD3D.cpp3412
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/ProgramD3D.h613
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp31
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderTargetD3D.h44
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp126
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderbufferD3D.h63
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/RendererD3D.cpp247
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/RendererD3D.h489
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/SamplerD3D.h33
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderD3D.cpp391
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderD3D.h126
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp67
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h57
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/SurfaceD3D.cpp517
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/SurfaceD3D.h145
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/SwapChainD3D.cpp34
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/SwapChainD3D.h83
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/TextureD3D.cpp4640
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/TextureD3D.h1050
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/TextureStorage.h135
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexBuffer.cpp308
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexBuffer.h189
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexDataManager.cpp683
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexDataManager.h163
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp1943
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Blit11.h300
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Blit11Helper_autogen.inc1575
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp1888
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Buffer11.h234
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp813
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Clear11.h102
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Context11.cpp1048
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Context11.h282
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp148
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h60
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.cpp209
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.h70
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp234
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Fence11.h76
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp452
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h100
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Image11.cpp676
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Image11.h128
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp160
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h58
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp313
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h123
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/MappedSubresourceVerifier11.cpp119
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/MappedSubresourceVerifier11.h63
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h38
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp271
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h96
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Program11.cpp34
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Program11.h28
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp21
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h27
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Query11.cpp357
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Query11.h71
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp323
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h124
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp403
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h133
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp4454
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Renderer11.h632
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp560
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h411
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp116
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h69
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp4004
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StateManager11.h692
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.cpp166
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.h44
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp1119
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h134
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp4352
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h1003
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp131
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h61
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp103
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Trim11.h43
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp375
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h112
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp167
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h65
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.cpp457
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h116
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp1029
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/formatutils11.h64
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp2751
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h478
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h80
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h65
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h65
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h65
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h145
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11_fl9vs.h71
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewgs.h83
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewvs.h80
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11vs.h69
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/cleardepth11ps.h74
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h128
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps1.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps2.h91
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps3.h97
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps4.h104
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps5.h110
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps6.h116
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps7.h122
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps8.h128
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps1.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps2.h91
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps3.h97
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps4.h104
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps5.h110
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps6.h116
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps7.h122
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps8.h128
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps1.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps2.h91
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps3.h97
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps4.h104
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps5.h110
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps6.h116
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps7.h122
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps8.h128
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_2d_ps.h76
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_2darray_ps.h86
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_3d_ps.h80
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_2d_ps.h76
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_2darray_ps.h86
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_3d_ps.h80
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_2d_ps.h76
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_2darray_ps.h86
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_3d_ps.h80
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_565_2d_ps.h84
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_565_2darray_ps.h94
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_565_3d_ps.h88
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_2d_ps.h76
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_2darray_ps.h86
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_3d_ps.h80
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_4444_2d_ps.h82
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_4444_2darray_ps.h92
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_4444_3d_ps.h86
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_5551_2d_ps.h82
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_5551_2darray_ps.h92
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_5551_3d_ps.h86
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_2d_ps.h82
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_2darray_ps.h91
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_3d_ps.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_2d_ps.h82
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_2darray_ps.h91
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_3d_ps.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_2d_ps.h82
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_2darray_ps.h91
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_3d_ps.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_565_2d_ps.h90
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_565_2darray_ps.h100
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_565_3d_ps.h93
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_2d_ps.h82
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_2darray_ps.h91
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_3d_ps.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_4444_2d_ps.h88
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_4444_2darray_ps.h98
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_4444_3d_ps.h91
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_5551_2d_ps.h88
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_5551_2darray_ps.h98
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_5551_3d_ps.h91
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgb_2darray_ps.h96
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgb_3d_ps.h90
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgba_2darray_ps.h94
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgba_3d_ps.h88
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgb_2darray_ps.h94
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgb_3d_ps.h88
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgba_2darray_ps.h92
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgba_3d_ps.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgb_2darray_ps.h102
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgb_3d_ps.h95
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgba_2darray_ps.h100
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgba_3d_ps.h93
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_2d_ps.h81
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_2darray_ps.h91
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_3d_ps.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_2d_ps.h79
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_2darray_ps.h89
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_3d_ps.h83
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_2d_ps.h79
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_2darray_ps.h89
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_3d_ps.h80
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_2d_ps.h77
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_2darray_ps.h87
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_3d_ps.h80
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_2d_ps.h87
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_2darray_ps.h97
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_3d_ps.h90
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_2d_ps.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_2darray_ps.h95
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_3d_ps.h88
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h91
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h93
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h75
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrougha2d11ps.h103
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h73
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h103
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2darray11ps.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h79
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h98
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2darray11ps.h83
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h77
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h104
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2darray11ps.h86
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2darrayi11ps.h90
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2darrayui11ps.h90
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h83
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h83
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h80
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h86
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h86
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h104
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2darray11ps.h86
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2darrayi11ps.h90
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2darrayui11ps.h90
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h83
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h83
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h80
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h86
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h86
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h103
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d_565_11ps.h118
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darray11ps.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darray_565_11ps.h91
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darrayi11ps.h89
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darrayui11ps.h89
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h82
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h82
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h79
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d_565_11ps.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h93
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d_4444_11ps.h112
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d_5551_11ps.h112
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darray11ps.h81
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darray_4444_11ps.h89
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darray_5551_11ps.h89
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darrayi11ps.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darrayui11ps.h85
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h78
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h80
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h78
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h74
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d_4444_11ps.h83
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d_5551_11ps.h83
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h81
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h81
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvecolor2dps.h103
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h81
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h92
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h83
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h84
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h135
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h126
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h129
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h139
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h132
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h135
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h139
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h132
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h135
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp35
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h118
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp3269
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h90
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp218
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h53
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp760
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Blit9.h166
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp141
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Buffer9.h63
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Context9.cpp529
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Context9.h265
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp48
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h38
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp73
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Fence9.h39
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp416
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h89
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Image9.cpp907
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Image9.h112
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp161
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h57
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp37
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h35
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Query9.cpp176
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Query9.h50
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp160
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h98
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp3338
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Renderer9.h586
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h110
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp51
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h35
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp888
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/StateManager9.h211
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp472
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h80
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp575
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h186
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h57
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp153
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h56
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp262
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h68
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp695
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/formatutils9.h59
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp845
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h105
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskpremultps.h50
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h48
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskunmultps.h54
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminancepremultps.h50
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h53
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceunmultps.h54
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h37
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h46
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h197
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/driver_utils_d3d.cpp26
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/driver_utils_d3d.h21
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/formatutilsD3D.h24
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d_format.cpp206
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d_format.h58
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/driver_utils.cpp438
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/driver_utils.h278
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/dxgi_format_map.h27
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/dxgi_format_map_autogen.cpp516
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/dxgi_support_table.h43
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/dxgi_support_table_autogen.cpp3042
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/gl/functionsgl_enums.h1376
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/load_functions_table.h20
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/load_functions_table_autogen.cpp5465
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.cpp1583
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.h499
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/serial_utils.h126
-rw-r--r--gfx/angle/checkout/src/libANGLE/trace.h26
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationEGL.cpp6782
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationEGL.h201
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationEGL_autogen.h510
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES.cpp8666
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES.h1272
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES1.cpp2129
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES1.h20
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES1_autogen.h395
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES2.cpp6544
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES2.h207
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES2_autogen.h666
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES3.cpp5311
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES3.h72
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES31.cpp3157
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES31.h300
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES31_autogen.h415
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES32.cpp628
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES32.h20
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES32_autogen.h281
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationES3_autogen.h578
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationESEXT.cpp3599
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationESEXT.h20
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationESEXT_autogen.h2646
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationGL1.cpp2421
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationGL1_autogen.h1192
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationGL2.cpp262
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationGL2_autogen.h158
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationGL3.cpp634
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationGL3_autogen.h367
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationGL4.cpp2223
-rw-r--r--gfx/angle/checkout/src/libANGLE/validationGL4_autogen.h1375
617 files changed, 274826 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/AttributeMap.cpp b/gfx/angle/checkout/src/libANGLE/AttributeMap.cpp
new file mode 100644
index 0000000000..6b56aee142
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/AttributeMap.cpp
@@ -0,0 +1,147 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "libANGLE/AttributeMap.h"
+
+#include "common/debug.h"
+
+namespace egl
+{
+
+AttributeMap::AttributeMap() = default;
+
+AttributeMap::AttributeMap(const AttributeMap &other) = default;
+
+AttributeMap &AttributeMap::operator=(const AttributeMap &other) = default;
+
+AttributeMap::~AttributeMap() = default;
+
+void AttributeMap::insert(EGLAttrib key, EGLAttrib value)
+{
+ mValidatedAttributes[key] = value;
+}
+
+bool AttributeMap::contains(EGLAttrib key) const
+{
+ return (attribs().find(key) != attribs().end());
+}
+
+EGLAttrib AttributeMap::get(EGLAttrib key) const
+{
+ auto iter = attribs().find(key);
+ ASSERT(iter != attribs().end());
+ return iter->second;
+}
+
+EGLAttrib AttributeMap::get(EGLAttrib key, EGLAttrib defaultValue) const
+{
+ auto iter = attribs().find(key);
+ return (iter != attribs().end()) ? iter->second : defaultValue;
+}
+
+EGLint AttributeMap::getAsInt(EGLAttrib key) const
+{
+ return static_cast<EGLint>(get(key));
+}
+
+EGLint AttributeMap::getAsInt(EGLAttrib key, EGLint defaultValue) const
+{
+ return static_cast<EGLint>(get(key, static_cast<EGLAttrib>(defaultValue)));
+}
+
+bool AttributeMap::isEmpty() const
+{
+ return attribs().empty();
+}
+
+std::vector<EGLint> AttributeMap::toIntVector() const
+{
+ std::vector<EGLint> ret;
+ for (const auto &pair : attribs())
+ {
+ ret.push_back(static_cast<EGLint>(pair.first));
+ ret.push_back(static_cast<EGLint>(pair.second));
+ }
+ ret.push_back(EGL_NONE);
+
+ return ret;
+}
+
+AttributeMap::const_iterator AttributeMap::begin() const
+{
+ return attribs().begin();
+}
+
+AttributeMap::const_iterator AttributeMap::end() const
+{
+ return attribs().end();
+}
+
+bool AttributeMap::validate(const ValidationContext *val,
+ const egl::Display *display,
+ AttributeValidationFunc validationFunc) const
+{
+ if (mIntPointer)
+ {
+ for (const EGLint *curAttrib = mIntPointer; curAttrib[0] != EGL_NONE; curAttrib += 2)
+ {
+ if (!validationFunc(val, display, curAttrib[0]))
+ {
+ return false;
+ }
+
+ mValidatedAttributes[static_cast<EGLAttrib>(curAttrib[0])] =
+ static_cast<EGLAttrib>(curAttrib[1]);
+ }
+ mIntPointer = nullptr;
+ }
+
+ if (mAttribPointer)
+ {
+ for (const EGLAttrib *curAttrib = mAttribPointer; curAttrib[0] != EGL_NONE; curAttrib += 2)
+ {
+ if (!validationFunc(val, display, curAttrib[0]))
+ {
+ return false;
+ }
+
+ mValidatedAttributes[curAttrib[0]] = curAttrib[1];
+ }
+ mAttribPointer = nullptr;
+ }
+
+ return true;
+}
+
+void AttributeMap::initializeWithoutValidation() const
+{
+ auto alwaysTrue = [](const ValidationContext *, const egl::Display *, EGLAttrib) {
+ return true;
+ };
+ (void)validate(nullptr, nullptr, alwaysTrue);
+}
+
+// static
+AttributeMap AttributeMap::CreateFromIntArray(const EGLint *attributes)
+{
+ AttributeMap map;
+ map.mIntPointer = attributes;
+ return map;
+}
+
+// static
+AttributeMap AttributeMap::CreateFromAttribArray(const EGLAttrib *attributes)
+{
+ AttributeMap map;
+ map.mAttribPointer = attributes;
+ return map;
+}
+
+bool AttributeMap::isValidated() const
+{
+ return mIntPointer == nullptr && mAttribPointer == nullptr;
+}
+} // namespace egl
diff --git a/gfx/angle/checkout/src/libANGLE/AttributeMap.h b/gfx/angle/checkout/src/libANGLE/AttributeMap.h
new file mode 100644
index 0000000000..60ba913fe1
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/AttributeMap.h
@@ -0,0 +1,100 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef LIBANGLE_ATTRIBUTEMAP_H_
+#define LIBANGLE_ATTRIBUTEMAP_H_
+
+#include "common/FastVector.h"
+#include "common/PackedEnums.h"
+
+#include <EGL/egl.h>
+
+#include <functional>
+#include <vector>
+
+namespace egl
+{
+class Display;
+struct ValidationContext;
+
+// Validates {key, value} for each attribute. Generates an error and returns false on invalid usage.
+using AttributeValidationFunc =
+ std::function<bool(const ValidationContext *, const Display *, EGLAttrib)>;
+
+class AttributeMap final
+{
+ public:
+ static constexpr size_t kMapSize = 2;
+ using Map = angle::FlatUnorderedMap<EGLAttrib, EGLAttrib, kMapSize>;
+
+ AttributeMap();
+ AttributeMap(const AttributeMap &other);
+ AttributeMap &operator=(const AttributeMap &other);
+ ~AttributeMap();
+
+ void insert(EGLAttrib key, EGLAttrib value);
+ bool contains(EGLAttrib key) const;
+
+ EGLAttrib get(EGLAttrib key) const;
+ EGLAttrib get(EGLAttrib key, EGLAttrib defaultValue) const;
+ EGLint getAsInt(EGLAttrib key) const;
+ EGLint getAsInt(EGLAttrib key, EGLint defaultValue) const;
+
+ template <typename PackedEnumT>
+ PackedEnumT getAsPackedEnum(EGLAttrib key) const
+ {
+ return FromEGLenum<PackedEnumT>(static_cast<EGLenum>(get(key)));
+ }
+
+ using const_iterator = Map::const_iterator;
+
+ template <typename PackedEnumT>
+ PackedEnumT getAsPackedEnum(EGLAttrib key, PackedEnumT defaultValue) const
+ {
+ const_iterator iter = attribs().find(key);
+ return (attribs().find(key) != attribs().end())
+ ? FromEGLenum<PackedEnumT>(static_cast<EGLenum>(iter->second))
+ : defaultValue;
+ }
+
+ bool isEmpty() const;
+ std::vector<EGLint> toIntVector() const;
+
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ [[nodiscard]] bool validate(const ValidationContext *val,
+ const egl::Display *display,
+ AttributeValidationFunc validationFunc) const;
+
+ // TODO: remove this and validate at every call site. http://anglebug.com/6671
+ void initializeWithoutValidation() const;
+
+ static AttributeMap CreateFromIntArray(const EGLint *attributes);
+ static AttributeMap CreateFromAttribArray(const EGLAttrib *attributes);
+
+ private:
+ bool isValidated() const;
+
+ const Map &attribs() const
+ {
+ ASSERT(isValidated());
+ return mValidatedAttributes;
+ }
+
+ Map &attribs()
+ {
+ ASSERT(isValidated());
+ return mValidatedAttributes;
+ }
+
+ mutable const EGLint *mIntPointer = nullptr;
+ mutable const EGLAttrib *mAttribPointer = nullptr;
+ mutable Map mValidatedAttributes;
+};
+} // namespace egl
+
+#endif // LIBANGLE_ATTRIBUTEMAP_H_
diff --git a/gfx/angle/checkout/src/libANGLE/BinaryStream.h b/gfx/angle/checkout/src/libANGLE/BinaryStream.h
new file mode 100644
index 0000000000..35672f62e8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/BinaryStream.h
@@ -0,0 +1,286 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BinaryStream.h: Provides binary serialization of simple types.
+
+#ifndef LIBANGLE_BINARYSTREAM_H_
+#define LIBANGLE_BINARYSTREAM_H_
+
+#include <stdint.h>
+#include <cstddef>
+#include <string>
+#include <vector>
+
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+
+namespace gl
+{
+template <typename IntT>
+struct PromotedIntegerType
+{
+ using type = typename std::conditional<
+ std::is_signed<IntT>::value,
+ typename std::conditional<sizeof(IntT) <= 4, int32_t, int64_t>::type,
+ typename std::conditional<sizeof(IntT) <= 4, uint32_t, uint64_t>::type>::type;
+};
+
+class BinaryInputStream : angle::NonCopyable
+{
+ public:
+ BinaryInputStream(const void *data, size_t length)
+ {
+ mError = false;
+ mOffset = 0;
+ mData = static_cast<const uint8_t *>(data);
+ mLength = length;
+ }
+
+ // readInt will generate an error for bool types
+ template <class IntT>
+ IntT readInt()
+ {
+ static_assert(!std::is_same<bool, std::remove_cv<IntT>()>(), "Use readBool");
+ using PromotedIntT = typename PromotedIntegerType<IntT>::type;
+ PromotedIntT value = 0;
+ read(&value);
+ ASSERT(angle::IsValueInRangeForNumericType<IntT>(value));
+ return static_cast<IntT>(value);
+ }
+
+ template <class IntT>
+ void readInt(IntT *outValue)
+ {
+ *outValue = readInt<IntT>();
+ }
+
+ template <class IntT, class VectorElementT>
+ void readIntVector(std::vector<VectorElementT> *param)
+ {
+ size_t size = readInt<size_t>();
+ for (size_t index = 0; index < size; ++index)
+ {
+ param->push_back(readInt<IntT>());
+ }
+ }
+
+ template <class EnumT>
+ EnumT readEnum()
+ {
+ using UnderlyingType = typename std::underlying_type<EnumT>::type;
+ return static_cast<EnumT>(readInt<UnderlyingType>());
+ }
+
+ template <class EnumT>
+ void readEnum(EnumT *outValue)
+ {
+ *outValue = readEnum<EnumT>();
+ }
+
+ bool readBool()
+ {
+ int value = 0;
+ read(&value);
+ return (value > 0);
+ }
+
+ void readBool(bool *outValue) { *outValue = readBool(); }
+
+ void readBytes(unsigned char outArray[], size_t count) { read<unsigned char>(outArray, count); }
+
+ std::string readString()
+ {
+ std::string outString;
+ readString(&outString);
+ return outString;
+ }
+
+ void readString(std::string *v)
+ {
+ size_t length;
+ readInt(&length);
+
+ if (mError)
+ {
+ return;
+ }
+
+ angle::CheckedNumeric<size_t> checkedOffset(mOffset);
+ checkedOffset += length;
+
+ if (!checkedOffset.IsValid() || mOffset + length > mLength)
+ {
+ mError = true;
+ return;
+ }
+
+ v->assign(reinterpret_cast<const char *>(mData) + mOffset, length);
+ mOffset = checkedOffset.ValueOrDie();
+ }
+
+ float readFloat()
+ {
+ float f;
+ read(&f, 1);
+ return f;
+ }
+
+ void skip(size_t length)
+ {
+ angle::CheckedNumeric<size_t> checkedOffset(mOffset);
+ checkedOffset += length;
+
+ if (!checkedOffset.IsValid() || mOffset + length > mLength)
+ {
+ mError = true;
+ return;
+ }
+
+ mOffset = checkedOffset.ValueOrDie();
+ }
+
+ size_t offset() const { return mOffset; }
+ size_t remainingSize() const
+ {
+ ASSERT(mLength >= mOffset);
+ return mLength - mOffset;
+ }
+
+ bool error() const { return mError; }
+
+ bool endOfStream() const { return mOffset == mLength; }
+
+ const uint8_t *data() { return mData; }
+
+ private:
+ bool mError;
+ size_t mOffset;
+ const uint8_t *mData;
+ size_t mLength;
+
+ template <typename T>
+ void read(T *v, size_t num)
+ {
+ static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
+
+ angle::CheckedNumeric<size_t> checkedLength(num);
+ checkedLength *= sizeof(T);
+ if (!checkedLength.IsValid())
+ {
+ mError = true;
+ return;
+ }
+
+ angle::CheckedNumeric<size_t> checkedOffset(mOffset);
+ checkedOffset += checkedLength;
+
+ if (!checkedOffset.IsValid() || checkedOffset.ValueOrDie() > mLength)
+ {
+ mError = true;
+ return;
+ }
+
+ memcpy(v, mData + mOffset, checkedLength.ValueOrDie());
+ mOffset = checkedOffset.ValueOrDie();
+ }
+
+ template <typename T>
+ void read(T *v)
+ {
+ read(v, 1);
+ }
+};
+
+class BinaryOutputStream : angle::NonCopyable
+{
+ public:
+ BinaryOutputStream();
+ ~BinaryOutputStream();
+
+ // writeInt also handles bool types
+ template <class IntT>
+ void writeInt(IntT param)
+ {
+ static_assert(std::is_integral<IntT>::value, "Not an integral type");
+ static_assert(!std::is_same<bool, std::remove_cv<IntT>()>(), "Use writeBool");
+ using PromotedIntT = typename PromotedIntegerType<IntT>::type;
+ ASSERT(angle::IsValueInRangeForNumericType<PromotedIntT>(param));
+ PromotedIntT intValue = static_cast<PromotedIntT>(param);
+ write(&intValue, 1);
+ }
+
+ // Specialized writeInt for values that can also be exactly -1.
+ template <class UintT>
+ void writeIntOrNegOne(UintT param)
+ {
+ if (param == static_cast<UintT>(-1))
+ {
+ writeInt(-1);
+ }
+ else
+ {
+ writeInt(param);
+ }
+ }
+
+ template <class IntT>
+ void writeIntVector(const std::vector<IntT> &param)
+ {
+ writeInt(param.size());
+ for (IntT element : param)
+ {
+ writeIntOrNegOne(element);
+ }
+ }
+
+ template <class EnumT>
+ void writeEnum(EnumT param)
+ {
+ using UnderlyingType = typename std::underlying_type<EnumT>::type;
+ writeInt<UnderlyingType>(static_cast<UnderlyingType>(param));
+ }
+
+ void writeString(const std::string &v)
+ {
+ writeInt(v.length());
+ write(v.c_str(), v.length());
+ }
+
+ void writeBytes(const unsigned char *bytes, size_t count) { write(bytes, count); }
+
+ void writeBool(bool value)
+ {
+ int intValue = value ? 1 : 0;
+ write(&intValue, 1);
+ }
+
+ void writeFloat(float value) { write(&value, 1); }
+
+ size_t length() const { return mData.size(); }
+
+ const void *data() const { return mData.size() ? &mData[0] : nullptr; }
+
+ const std::vector<uint8_t> &getData() const { return mData; }
+
+ private:
+ template <typename T>
+ void write(const T *v, size_t num)
+ {
+ static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
+ const char *asBytes = reinterpret_cast<const char *>(v);
+ mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T));
+ }
+
+ std::vector<uint8_t> mData;
+};
+
+inline BinaryOutputStream::BinaryOutputStream() {}
+
+inline BinaryOutputStream::~BinaryOutputStream() = default;
+
+} // namespace gl
+
+#endif // LIBANGLE_BINARYSTREAM_H_
diff --git a/gfx/angle/checkout/src/libANGLE/BlobCache.cpp b/gfx/angle/checkout/src/libANGLE/BlobCache.cpp
new file mode 100644
index 0000000000..6a3e2dcc56
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/BlobCache.cpp
@@ -0,0 +1,277 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// BlobCache: Stores keyed blobs in memory to support EGL_ANDROID_blob_cache.
+// Can be used in conjunction with the platform layer to warm up the cache from
+// disk. MemoryProgramCache uses this to handle caching of compiled programs.
+
+#include "libANGLE/BlobCache.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/histogram_macros.h"
+#include "platform/PlatformMethods.h"
+
+#define USE_SYSTEM_ZLIB
+#include "compression_utils_portable.h"
+
+namespace egl
+{
+
+namespace
+{
+enum CacheResult
+{
+ kCacheMiss,
+ kCacheHitMemory,
+ kCacheHitDisk,
+ kCacheResultMax,
+};
+
+} // anonymous namespace
+
+// In oder to store more cache in blob cache, compress cacheData to compressedData
+// before being stored.
+bool CompressBlobCacheData(const size_t cacheSize,
+ const uint8_t *cacheData,
+ angle::MemoryBuffer *compressedData)
+{
+ uLong uncompressedSize = static_cast<uLong>(cacheSize);
+ uLong expectedCompressedSize = zlib_internal::GzipExpectedCompressedSize(uncompressedSize);
+
+ // Allocate memory.
+ if (!compressedData->resize(expectedCompressedSize))
+ {
+ ERR() << "Failed to allocate memory for compression";
+ return false;
+ }
+
+ int zResult = zlib_internal::GzipCompressHelper(compressedData->data(), &expectedCompressedSize,
+ cacheData, uncompressedSize, nullptr, nullptr);
+
+ if (zResult != Z_OK)
+ {
+ ERR() << "Failed to compress cache data: " << zResult;
+ return false;
+ }
+
+ // Resize it to expected size.
+ if (!compressedData->resize(expectedCompressedSize))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool DecompressBlobCacheData(const uint8_t *compressedData,
+ const size_t compressedSize,
+ angle::MemoryBuffer *uncompressedData)
+{
+ // Call zlib function to decompress.
+ uint32_t uncompressedSize =
+ zlib_internal::GetGzipUncompressedSize(compressedData, compressedSize);
+
+ // Allocate enough memory.
+ if (!uncompressedData->resize(uncompressedSize))
+ {
+ ERR() << "Failed to allocate memory for decompression";
+ return false;
+ }
+
+ uLong destLen = uncompressedSize;
+ int zResult = zlib_internal::GzipUncompressHelper(
+ uncompressedData->data(), &destLen, compressedData, static_cast<uLong>(compressedSize));
+
+ if (zResult != Z_OK)
+ {
+ ERR() << "Failed to decompress data: " << zResult << "\n";
+ return false;
+ }
+
+ // Resize it to expected size.
+ if (!uncompressedData->resize(destLen))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+BlobCache::BlobCache(size_t maxCacheSizeBytes)
+ : mBlobCache(maxCacheSizeBytes), mSetBlobFunc(nullptr), mGetBlobFunc(nullptr)
+{}
+
+BlobCache::~BlobCache() {}
+
+void BlobCache::put(const BlobCache::Key &key, angle::MemoryBuffer &&value)
+{
+ if (areBlobCacheFuncsSet())
+ {
+ std::scoped_lock<std::mutex> lock(mBlobCacheMutex);
+ // Store the result in the application's cache
+ mSetBlobFunc(key.data(), key.size(), value.data(), value.size());
+ }
+ else
+ {
+ populate(key, std::move(value), CacheSource::Memory);
+ }
+}
+
+bool BlobCache::compressAndPut(const BlobCache::Key &key,
+ angle::MemoryBuffer &&uncompressedValue,
+ size_t *compressedSize)
+{
+ angle::MemoryBuffer compressedValue;
+ if (!CompressBlobCacheData(uncompressedValue.size(), uncompressedValue.data(),
+ &compressedValue))
+ {
+ return false;
+ }
+ if (compressedSize != nullptr)
+ *compressedSize = compressedValue.size();
+ put(key, std::move(compressedValue));
+ return true;
+}
+
+void BlobCache::putApplication(const BlobCache::Key &key, const angle::MemoryBuffer &value)
+{
+ if (areBlobCacheFuncsSet())
+ {
+ std::scoped_lock<std::mutex> lock(mBlobCacheMutex);
+ mSetBlobFunc(key.data(), key.size(), value.data(), value.size());
+ }
+}
+
+void BlobCache::populate(const BlobCache::Key &key, angle::MemoryBuffer &&value, CacheSource source)
+{
+ std::scoped_lock<std::mutex> lock(mBlobCacheMutex);
+ CacheEntry newEntry;
+ newEntry.first = std::move(value);
+ newEntry.second = source;
+
+ // Cache it inside blob cache only if caching inside the application is not possible.
+ mBlobCache.put(key, std::move(newEntry), newEntry.first.size());
+}
+
+bool BlobCache::get(angle::ScratchBuffer *scratchBuffer,
+ const BlobCache::Key &key,
+ BlobCache::Value *valueOut,
+ size_t *bufferSizeOut)
+{
+ // Look into the application's cache, if there is such a cache
+ if (areBlobCacheFuncsSet())
+ {
+ std::scoped_lock<std::mutex> lock(mBlobCacheMutex);
+ EGLsizeiANDROID valueSize = mGetBlobFunc(key.data(), key.size(), nullptr, 0);
+ if (valueSize <= 0)
+ {
+ return false;
+ }
+
+ angle::MemoryBuffer *scratchMemory;
+ bool result = scratchBuffer->get(valueSize, &scratchMemory);
+ if (!result)
+ {
+ ERR() << "Failed to allocate memory for binary blob";
+ return false;
+ }
+
+ EGLsizeiANDROID originalValueSize = valueSize;
+ valueSize = mGetBlobFunc(key.data(), key.size(), scratchMemory->data(), valueSize);
+
+ // Make sure the key/value pair still exists/is unchanged after the second call
+ // (modifications to the application cache by another thread are a possibility)
+ if (valueSize != originalValueSize)
+ {
+ // This warning serves to find issues with the application cache, none of which are
+ // currently known to be thread-safe. If such a use ever arises, this WARN can be
+ // removed.
+ WARN() << "Binary blob no longer available in cache (removed by a thread?)";
+ return false;
+ }
+
+ *valueOut = BlobCache::Value(scratchMemory->data(), scratchMemory->size());
+ *bufferSizeOut = valueSize;
+ return true;
+ }
+
+ std::scoped_lock<std::mutex> lock(mBlobCacheMutex);
+ // Otherwise we are doing caching internally, so try to find it there
+ const CacheEntry *entry;
+ bool result = mBlobCache.get(key, &entry);
+
+ if (result)
+ {
+
+ *valueOut = BlobCache::Value(entry->first.data(), entry->first.size());
+ *bufferSizeOut = entry->first.size();
+ }
+
+ return result;
+}
+
+bool BlobCache::getAt(size_t index, const BlobCache::Key **keyOut, BlobCache::Value *valueOut)
+{
+ std::scoped_lock<std::mutex> lock(mBlobCacheMutex);
+ const CacheEntry *valueBuf;
+ bool result = mBlobCache.getAt(index, keyOut, &valueBuf);
+ if (result)
+ {
+ *valueOut = BlobCache::Value(valueBuf->first.data(), valueBuf->first.size());
+ }
+ return result;
+}
+
+BlobCache::GetAndDecompressResult BlobCache::getAndDecompress(
+ angle::ScratchBuffer *scratchBuffer,
+ const BlobCache::Key &key,
+ angle::MemoryBuffer *uncompressedValueOut)
+{
+ ASSERT(uncompressedValueOut);
+
+ Value compressedValue;
+ size_t compressedSize;
+ if (!get(scratchBuffer, key, &compressedValue, &compressedSize))
+ {
+ return GetAndDecompressResult::NotFound;
+ }
+
+ {
+ // This needs to be locked because `DecompressBlobCacheData` is reading shared memory from
+ // `compressedValue.data()`.
+ std::scoped_lock<std::mutex> lock(mBlobCacheMutex);
+ if (!DecompressBlobCacheData(compressedValue.data(), compressedSize, uncompressedValueOut))
+ {
+ return GetAndDecompressResult::DecompressFailure;
+ }
+ }
+
+ return GetAndDecompressResult::GetSuccess;
+}
+
+void BlobCache::remove(const BlobCache::Key &key)
+{
+ std::scoped_lock<std::mutex> lock(mBlobCacheMutex);
+ mBlobCache.eraseByKey(key);
+}
+
+void BlobCache::setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get)
+{
+ std::scoped_lock<std::mutex> lock(mBlobCacheMutex);
+ mSetBlobFunc = set;
+ mGetBlobFunc = get;
+}
+
+bool BlobCache::areBlobCacheFuncsSet() const
+{
+ std::scoped_lock<std::mutex> lock(mBlobCacheMutex);
+ // Either none or both of the callbacks should be set.
+ ASSERT((mSetBlobFunc != nullptr) == (mGetBlobFunc != nullptr));
+
+ return mSetBlobFunc != nullptr && mGetBlobFunc != nullptr;
+}
+
+} // namespace egl
diff --git a/gfx/angle/checkout/src/libANGLE/BlobCache.h b/gfx/angle/checkout/src/libANGLE/BlobCache.h
new file mode 100644
index 0000000000..772eee04aa
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/BlobCache.h
@@ -0,0 +1,182 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// BlobCache: Stores compiled and linked programs in memory so they don't
+// always have to be re-compiled. Can be used in conjunction with the platform
+// layer to warm up the cache from disk.
+
+#ifndef LIBANGLE_BLOB_CACHE_H_
+#define LIBANGLE_BLOB_CACHE_H_
+
+#include <array>
+#include <cstring>
+
+#include <anglebase/sha1.h>
+#include "common/MemoryBuffer.h"
+#include "common/hash_utils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/SizedMRUCache.h"
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace egl
+{
+// 160-bit SHA-1 hash key used for hasing a program. BlobCache opts in using fixed keys for
+// simplicity and efficiency.
+static constexpr size_t kBlobCacheKeyLength = angle::base::kSHA1Length;
+using BlobCacheKey = std::array<uint8_t, kBlobCacheKeyLength>;
+} // namespace egl
+
+namespace std
+{
+template <>
+struct hash<egl::BlobCacheKey>
+{
+ // Simple routine to hash four ints.
+ size_t operator()(const egl::BlobCacheKey &key) const
+ {
+ return angle::ComputeGenericHash(key.data(), key.size());
+ }
+};
+} // namespace std
+
+namespace egl
+{
+
+bool CompressBlobCacheData(const size_t cacheSize,
+ const uint8_t *cacheData,
+ angle::MemoryBuffer *compressedData);
+bool DecompressBlobCacheData(const uint8_t *compressedData,
+ const size_t compressedSize,
+ angle::MemoryBuffer *uncompressedData);
+
+class BlobCache final : angle::NonCopyable
+{
+ public:
+ // 160-bit SHA-1 hash key used for hasing a program. BlobCache opts in using fixed keys for
+ // simplicity and efficiency.
+ static constexpr size_t kKeyLength = kBlobCacheKeyLength;
+ using Key = BlobCacheKey;
+ class Value
+ {
+ public:
+ Value() : mPtr(nullptr), mSize(0) {}
+ Value(const uint8_t *ptr, size_t sz) : mPtr(ptr), mSize(sz) {}
+
+ // A very basic struct to hold the pointer and size together. The objects of this class
+ // don't own the memory.
+ const uint8_t *data() { return mPtr; }
+ size_t size() { return mSize; }
+
+ const uint8_t &operator[](size_t pos) const
+ {
+ ASSERT(pos < mSize);
+ return mPtr[pos];
+ }
+
+ private:
+ const uint8_t *mPtr;
+ size_t mSize;
+ };
+ enum class CacheSource
+ {
+ Memory,
+ Disk,
+ };
+
+ explicit BlobCache(size_t maxCacheSizeBytes);
+ ~BlobCache();
+
+ // Store a key-blob pair in the cache. If application callbacks are set, the application cache
+ // will be used. Otherwise the value is cached in this object.
+ void put(const BlobCache::Key &key, angle::MemoryBuffer &&value);
+
+ // Store a key-blob pair in the cache, but compress the blob before insertion. Returns false if
+ // compression fails, returns true otherwise.
+ bool compressAndPut(const BlobCache::Key &key,
+ angle::MemoryBuffer &&uncompressedValue,
+ size_t *compressedSize);
+
+ // Store a key-blob pair in the application cache, only if application callbacks are set.
+ void putApplication(const BlobCache::Key &key, const angle::MemoryBuffer &value);
+
+ // Store a key-blob pair in the cache without making callbacks to the application. This is used
+ // to repopulate this object's cache on startup without generating callback calls.
+ void populate(const BlobCache::Key &key,
+ angle::MemoryBuffer &&value,
+ CacheSource source = CacheSource::Disk);
+
+ // Check if the cache contains the blob corresponding to this key. If application callbacks are
+ // set, those will be used. Otherwise they key is looked up in this object's cache.
+ [[nodiscard]] bool get(angle::ScratchBuffer *scratchBuffer,
+ const BlobCache::Key &key,
+ BlobCache::Value *valueOut,
+ size_t *bufferSizeOut);
+
+ // For querying the contents of the cache.
+ [[nodiscard]] bool getAt(size_t index,
+ const BlobCache::Key **keyOut,
+ BlobCache::Value *valueOut);
+
+ enum class GetAndDecompressResult
+ {
+ GetSuccess,
+ NotFound,
+ DecompressFailure,
+ };
+ [[nodiscard]] GetAndDecompressResult getAndDecompress(
+ angle::ScratchBuffer *scratchBuffer,
+ const BlobCache::Key &key,
+ angle::MemoryBuffer *uncompressedValueOut);
+
+ // Evict a blob from the binary cache.
+ void remove(const BlobCache::Key &key);
+
+ // Empty the cache.
+ void clear() { mBlobCache.clear(); }
+
+ // Resize the cache. Discards current contents.
+ void resize(size_t maxCacheSizeBytes) { mBlobCache.resize(maxCacheSizeBytes); }
+
+ // Returns the number of entries in the cache.
+ size_t entryCount() const { return mBlobCache.entryCount(); }
+
+ // Reduces the current cache size and returns the number of bytes freed.
+ size_t trim(size_t limit) { return mBlobCache.shrinkToSize(limit); }
+
+ // Returns the current cache size in bytes.
+ size_t size() const { return mBlobCache.size(); }
+
+ // Returns whether the cache is empty
+ bool empty() const { return mBlobCache.empty(); }
+
+ // Returns the maximum cache size in bytes.
+ size_t maxSize() const { return mBlobCache.maxSize(); }
+
+ void setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+
+ bool areBlobCacheFuncsSet() const;
+
+ bool isCachingEnabled() const { return areBlobCacheFuncsSet() || maxSize() > 0; }
+
+ std::mutex &getMutex() { return mBlobCacheMutex; }
+
+ private:
+ // This internal cache is used only if the application is not providing caching callbacks
+ using CacheEntry = std::pair<angle::MemoryBuffer, CacheSource>;
+
+ mutable std::mutex mBlobCacheMutex;
+ angle::SizedMRUCache<BlobCache::Key, CacheEntry> mBlobCache;
+
+ EGLSetBlobFuncANDROID mSetBlobFunc;
+ EGLGetBlobFuncANDROID mGetBlobFunc;
+};
+
+} // namespace egl
+
+#endif // LIBANGLE_MEMORY_PROGRAM_CACHE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Buffer.cpp b/gfx/angle/checkout/src/libANGLE/Buffer.cpp
new file mode 100644
index 0000000000..440cfd873a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Buffer.cpp
@@ -0,0 +1,449 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Buffer.cpp: Implements the gl::Buffer class, representing storage of vertex and/or
+// index data. Implements GL buffer objects and related functionality.
+// [OpenGL ES 2.0.24] section 2.9 page 21.
+
+#include "libANGLE/Buffer.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/BufferImpl.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+
+namespace gl
+{
+namespace
+{
+constexpr angle::SubjectIndex kImplementationSubjectIndex = 0;
+constexpr size_t kInvalidContentsObserverIndex = std::numeric_limits<size_t>::max();
+} // anonymous namespace
+
+BufferState::BufferState()
+ : mLabel(),
+ mUsage(BufferUsage::StaticDraw),
+ mSize(0),
+ mAccessFlags(0),
+ mAccess(GL_WRITE_ONLY_OES),
+ mMapped(GL_FALSE),
+ mMapPointer(nullptr),
+ mMapOffset(0),
+ mMapLength(0),
+ mBindingCount(0),
+ mTransformFeedbackIndexedBindingCount(0),
+ mTransformFeedbackGenericBindingCount(0),
+ mImmutable(GL_FALSE),
+ mStorageExtUsageFlags(0),
+ mExternal(GL_FALSE)
+{}
+
+BufferState::~BufferState() {}
+
+Buffer::Buffer(rx::GLImplFactory *factory, BufferID id)
+ : RefCountObject(factory->generateSerial(), id),
+ mImpl(factory->createBuffer(mState)),
+ mImplObserver(this, kImplementationSubjectIndex)
+{
+ mImplObserver.bind(mImpl);
+}
+
+Buffer::~Buffer()
+{
+ SafeDelete(mImpl);
+}
+
+void Buffer::onDestroy(const Context *context)
+{
+ // In tests, mImpl might be null.
+ if (mImpl)
+ mImpl->destroy(context);
+}
+
+angle::Result Buffer::setLabel(const Context *context, const std::string &label)
+{
+ mState.mLabel = label;
+ if (mImpl)
+ {
+ return mImpl->onLabelUpdate(context);
+ }
+ return angle::Result::Continue;
+}
+
+const std::string &Buffer::getLabel() const
+{
+ return mState.mLabel;
+}
+
+angle::Result Buffer::bufferStorageExternal(Context *context,
+ BufferBinding target,
+ GLsizeiptr size,
+ GLeglClientBufferEXT clientBuffer,
+ GLbitfield flags)
+{
+ return bufferExternalDataImpl(context, target, clientBuffer, size, flags);
+}
+
+angle::Result Buffer::bufferStorage(Context *context,
+ BufferBinding target,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags)
+{
+ return bufferDataImpl(context, target, data, size, BufferUsage::InvalidEnum, flags);
+}
+
+angle::Result Buffer::bufferData(Context *context,
+ BufferBinding target,
+ const void *data,
+ GLsizeiptr size,
+ BufferUsage usage)
+{
+ GLbitfield flags = (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT_EXT);
+ return bufferDataImpl(context, target, data, size, usage, flags);
+}
+
+angle::Result Buffer::bufferDataImpl(Context *context,
+ BufferBinding target,
+ const void *data,
+ GLsizeiptr size,
+ BufferUsage usage,
+ GLbitfield flags)
+{
+ const void *dataForImpl = data;
+
+ if (mState.isMapped())
+ {
+ // Per the OpenGL ES 3.0 spec, buffers are implicity unmapped when a call to
+ // BufferData happens on a mapped buffer:
+ //
+ // If any portion of the buffer object is mapped in the current context or any context
+ // current to another thread, it is as though UnmapBuffer (see section 2.10.3) is
+ // executed in each such context prior to deleting the existing data store.
+ //
+ GLboolean dontCare = GL_FALSE;
+ ANGLE_TRY(unmap(context, &dontCare));
+ }
+
+ // If we are using robust resource init, make sure the buffer starts cleared.
+ // Note: the Context is checked for nullptr because of some testing code.
+ // TODO(jmadill): Investigate lazier clearing.
+ if (context && context->isRobustResourceInitEnabled() && !data && size > 0)
+ {
+ angle::MemoryBuffer *scratchBuffer = nullptr;
+ ANGLE_CHECK_GL_ALLOC(
+ context, context->getZeroFilledBuffer(static_cast<size_t>(size), &scratchBuffer));
+ dataForImpl = scratchBuffer->data();
+ }
+
+ if (mImpl->setDataWithUsageFlags(context, target, nullptr, dataForImpl, size, usage, flags) ==
+ angle::Result::Stop)
+ {
+ // If setData fails, the buffer contents are undefined. Set a zero size to indicate that.
+ mIndexRangeCache.clear();
+ mState.mSize = 0;
+
+ // Notify when storage changes.
+ onStateChange(angle::SubjectMessage::SubjectChanged);
+
+ return angle::Result::Stop;
+ }
+
+ bool wholeBuffer = size == mState.mSize;
+
+ mIndexRangeCache.clear();
+ mState.mUsage = usage;
+ mState.mSize = size;
+ mState.mImmutable = (usage == BufferUsage::InvalidEnum);
+ mState.mStorageExtUsageFlags = flags;
+
+ // Notify when storage changes.
+ if (wholeBuffer)
+ {
+ onContentsChange();
+ }
+ else
+ {
+ onStateChange(angle::SubjectMessage::SubjectChanged);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer::bufferExternalDataImpl(Context *context,
+ BufferBinding target,
+ GLeglClientBufferEXT clientBuffer,
+ GLsizeiptr size,
+ GLbitfield flags)
+{
+ if (mState.isMapped())
+ {
+ // Per the OpenGL ES 3.0 spec, buffers are implicitly unmapped when a call to
+ // BufferData happens on a mapped buffer:
+ //
+ // If any portion of the buffer object is mapped in the current context or any context
+ // current to another thread, it is as though UnmapBuffer (see section 2.10.3) is
+ // executed in each such context prior to deleting the existing data store.
+ //
+ GLboolean dontCare = GL_FALSE;
+ ANGLE_TRY(unmap(context, &dontCare));
+ }
+
+ if (mImpl->setDataWithUsageFlags(context, target, clientBuffer, nullptr, size,
+ BufferUsage::InvalidEnum, flags) == angle::Result::Stop)
+ {
+ // If setData fails, the buffer contents are undefined. Set a zero size to indicate that.
+ mIndexRangeCache.clear();
+ mState.mSize = 0;
+
+ // Notify when storage changes.
+ onStateChange(angle::SubjectMessage::SubjectChanged);
+
+ return angle::Result::Stop;
+ }
+
+ mIndexRangeCache.clear();
+ mState.mUsage = BufferUsage::InvalidEnum;
+ mState.mSize = size;
+ mState.mImmutable = GL_TRUE;
+ mState.mStorageExtUsageFlags = flags;
+ mState.mExternal = GL_TRUE;
+
+ // Notify when storage changes.
+ onStateChange(angle::SubjectMessage::SubjectChanged);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer::bufferSubData(const Context *context,
+ BufferBinding target,
+ const void *data,
+ GLsizeiptr size,
+ GLintptr offset)
+{
+ ANGLE_TRY(mImpl->setSubData(context, target, data, size, offset));
+
+ mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset),
+ static_cast<unsigned int>(size));
+
+ // Notify when data changes.
+ onContentsChange();
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer::copyBufferSubData(const Context *context,
+ Buffer *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size)
+{
+ ANGLE_TRY(
+ mImpl->copySubData(context, source->getImplementation(), sourceOffset, destOffset, size));
+
+ mIndexRangeCache.invalidateRange(static_cast<unsigned int>(destOffset),
+ static_cast<unsigned int>(size));
+
+ // Notify when data changes.
+ onContentsChange();
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer::map(const Context *context, GLenum access)
+{
+ ASSERT(!mState.mMapped);
+
+ mState.mMapPointer = nullptr;
+ ANGLE_TRY(mImpl->map(context, access, &mState.mMapPointer));
+
+ ASSERT(access == GL_WRITE_ONLY_OES);
+
+ mState.mMapped = GL_TRUE;
+ mState.mMapOffset = 0;
+ mState.mMapLength = mState.mSize;
+ mState.mAccess = access;
+ mState.mAccessFlags = GL_MAP_WRITE_BIT;
+ mIndexRangeCache.clear();
+
+ // Notify when state changes.
+ onStateChange(angle::SubjectMessage::SubjectMapped);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer::mapRange(const Context *context,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ ASSERT(!mState.mMapped);
+ ASSERT(offset + length <= mState.mSize);
+
+ mState.mMapPointer = nullptr;
+ ANGLE_TRY(mImpl->mapRange(context, offset, length, access, &mState.mMapPointer));
+
+ mState.mMapped = GL_TRUE;
+ mState.mMapOffset = static_cast<GLint64>(offset);
+ mState.mMapLength = static_cast<GLint64>(length);
+ mState.mAccess = GL_WRITE_ONLY_OES;
+ mState.mAccessFlags = access;
+
+ // The OES_mapbuffer extension states that GL_WRITE_ONLY_OES is the only valid
+ // value for GL_BUFFER_ACCESS_OES because it was written against ES2. Since there is
+ // no update for ES3 and the GL_READ_ONLY and GL_READ_WRITE enums don't exist for ES,
+ // we cannot properly set GL_BUFFER_ACCESS_OES when glMapBufferRange is called.
+
+ if ((access & GL_MAP_WRITE_BIT) > 0)
+ {
+ mIndexRangeCache.invalidateRange(static_cast<unsigned int>(offset),
+ static_cast<unsigned int>(length));
+ }
+
+ // Notify when state changes.
+ onStateChange(angle::SubjectMessage::SubjectMapped);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer::unmap(const Context *context, GLboolean *result)
+{
+ ASSERT(mState.mMapped);
+
+ *result = GL_FALSE;
+ ANGLE_TRY(mImpl->unmap(context, result));
+
+ mState.mMapped = GL_FALSE;
+ mState.mMapPointer = nullptr;
+ mState.mMapOffset = 0;
+ mState.mMapLength = 0;
+ mState.mAccess = GL_WRITE_ONLY_OES;
+ mState.mAccessFlags = 0;
+
+ // Notify when data changes.
+ onStateChange(angle::SubjectMessage::SubjectUnmapped);
+
+ return angle::Result::Continue;
+}
+
+void Buffer::onDataChanged()
+{
+ mIndexRangeCache.clear();
+
+ // Notify when data changes.
+ onContentsChange();
+
+ mImpl->onDataChanged();
+}
+
+angle::Result Buffer::getIndexRange(const gl::Context *context,
+ DrawElementsType type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ IndexRange *outRange) const
+{
+ if (mIndexRangeCache.findRange(type, offset, count, primitiveRestartEnabled, outRange))
+ {
+ return angle::Result::Continue;
+ }
+
+ ANGLE_TRY(
+ mImpl->getIndexRange(context, type, offset, count, primitiveRestartEnabled, outRange));
+
+ mIndexRangeCache.addRange(type, offset, count, primitiveRestartEnabled, *outRange);
+
+ return angle::Result::Continue;
+}
+
+GLint64 Buffer::getMemorySize() const
+{
+ GLint64 implSize = mImpl->getMemorySize();
+ return implSize > 0 ? implSize : mState.mSize;
+}
+
+bool Buffer::isDoubleBoundForTransformFeedback() const
+{
+ return mState.mTransformFeedbackIndexedBindingCount > 1;
+}
+
+void Buffer::onTFBindingChanged(const Context *context, bool bound, bool indexed)
+{
+ ASSERT(bound || mState.mBindingCount > 0);
+ mState.mBindingCount += bound ? 1 : -1;
+ if (indexed)
+ {
+ ASSERT(bound || mState.mTransformFeedbackIndexedBindingCount > 0);
+ mState.mTransformFeedbackIndexedBindingCount += bound ? 1 : -1;
+
+ onStateChange(angle::SubjectMessage::BindingChanged);
+ }
+ else
+ {
+ mState.mTransformFeedbackGenericBindingCount += bound ? 1 : -1;
+ }
+}
+
+angle::Result Buffer::getSubData(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size,
+ void *outData)
+{
+ return mImpl->getSubData(context, offset, size, outData);
+}
+
+void Buffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
+{
+ // Pass it along!
+ ASSERT(index == kImplementationSubjectIndex);
+ ASSERT(message == angle::SubjectMessage::SubjectChanged ||
+ message == angle::SubjectMessage::InternalMemoryAllocationChanged);
+ onStateChange(message);
+}
+
+size_t Buffer::getContentsObserverIndex(VertexArray *vertexArray, uint32_t bufferIndex) const
+{
+ for (size_t observerIndex = 0; observerIndex < mContentsObservers.size(); ++observerIndex)
+ {
+ const ContentsObserver &observer = mContentsObservers[observerIndex];
+ if (observer.vertexArray == vertexArray && observer.bufferIndex == bufferIndex)
+ {
+ return observerIndex;
+ }
+ }
+
+ return kInvalidContentsObserverIndex;
+}
+
+void Buffer::addContentsObserver(VertexArray *vertexArray, uint32_t bufferIndex)
+{
+ if (getContentsObserverIndex(vertexArray, bufferIndex) == kInvalidContentsObserverIndex)
+ {
+ mContentsObservers.push_back({vertexArray, bufferIndex});
+ }
+}
+
+void Buffer::removeContentsObserver(VertexArray *vertexArray, uint32_t bufferIndex)
+{
+ size_t foundObserver = getContentsObserverIndex(vertexArray, bufferIndex);
+ if (foundObserver != kInvalidContentsObserverIndex)
+ {
+ size_t lastObserverIndex = mContentsObservers.size() - 1;
+ if (foundObserver != lastObserverIndex)
+ {
+ mContentsObservers[foundObserver] = mContentsObservers[lastObserverIndex];
+ }
+ mContentsObservers.pop_back();
+ }
+}
+
+void Buffer::onContentsChange()
+{
+ for (const ContentsObserver &observer : mContentsObservers)
+ {
+ observer.vertexArray->onBufferContentsChange(observer.bufferIndex);
+ }
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Buffer.h b/gfx/angle/checkout/src/libANGLE/Buffer.h
new file mode 100644
index 0000000000..b71f6af89b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Buffer.h
@@ -0,0 +1,218 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Buffer.h: Defines the gl::Buffer class, representing storage of vertex and/or
+// index data. Implements GL buffer objects and related functionality.
+// [OpenGL ES 2.0.24] section 2.9 page 21.
+
+#ifndef LIBANGLE_BUFFER_H_
+#define LIBANGLE_BUFFER_H_
+
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/IndexRangeCache.h"
+#include "libANGLE/Observer.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+class BufferImpl;
+class GLImplFactory;
+} // namespace rx
+
+namespace gl
+{
+class Buffer;
+class Context;
+
+class BufferState final : angle::NonCopyable
+{
+ public:
+ BufferState();
+ ~BufferState();
+
+ BufferUsage getUsage() const { return mUsage; }
+ GLbitfield getAccessFlags() const { return mAccessFlags; }
+ GLenum getAccess() const { return mAccess; }
+ GLboolean isMapped() const { return mMapped; }
+ void *getMapPointer() const { return mMapPointer; }
+ GLint64 getMapOffset() const { return mMapOffset; }
+ GLint64 getMapLength() const { return mMapLength; }
+ GLint64 getSize() const { return mSize; }
+ bool isBoundForTransformFeedback() const { return mTransformFeedbackIndexedBindingCount != 0; }
+ std::string getLabel() const { return mLabel; }
+
+ private:
+ friend class Buffer;
+
+ std::string mLabel;
+
+ BufferUsage mUsage;
+ GLint64 mSize;
+ GLbitfield mAccessFlags;
+ GLenum mAccess;
+ GLboolean mMapped;
+ void *mMapPointer;
+ GLint64 mMapOffset;
+ GLint64 mMapLength;
+ int mBindingCount;
+ int mTransformFeedbackIndexedBindingCount;
+ int mTransformFeedbackGenericBindingCount;
+ GLboolean mImmutable;
+ GLbitfield mStorageExtUsageFlags;
+ GLboolean mExternal;
+};
+
+// Some Vertex Array Objects track buffer data updates.
+struct ContentsObserver
+{
+ VertexArray *vertexArray = nullptr;
+ uint32_t bufferIndex = 0;
+};
+
+ANGLE_INLINE bool operator==(const ContentsObserver &lhs, const ContentsObserver &rhs)
+{
+ return lhs.vertexArray == rhs.vertexArray && lhs.bufferIndex == rhs.bufferIndex;
+}
+
+class Buffer final : public RefCountObject<BufferID>,
+ public LabeledObject,
+ public angle::ObserverInterface,
+ public angle::Subject
+{
+ public:
+ Buffer(rx::GLImplFactory *factory, BufferID id);
+ ~Buffer() override;
+ void onDestroy(const Context *context) override;
+
+ angle::Result setLabel(const Context *context, const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ angle::Result bufferStorageExternal(Context *context,
+ BufferBinding target,
+ GLsizeiptr size,
+ GLeglClientBufferEXT clientBuffer,
+ GLbitfield flags);
+ angle::Result bufferStorage(Context *context,
+ BufferBinding target,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags);
+ angle::Result bufferData(Context *context,
+ BufferBinding target,
+ const void *data,
+ GLsizeiptr size,
+ BufferUsage usage);
+ angle::Result bufferSubData(const Context *context,
+ BufferBinding target,
+ const void *data,
+ GLsizeiptr size,
+ GLintptr offset);
+ angle::Result copyBufferSubData(const Context *context,
+ Buffer *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size);
+ angle::Result map(const Context *context, GLenum access);
+ angle::Result mapRange(const Context *context,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access);
+ angle::Result unmap(const Context *context, GLboolean *result);
+
+ // These are called when another operation changes Buffer data.
+ void onDataChanged();
+
+ angle::Result getIndexRange(const gl::Context *context,
+ DrawElementsType type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ IndexRange *outRange) const;
+ const BufferState &getState() const { return mState; }
+ BufferUsage getUsage() const { return mState.mUsage; }
+ GLbitfield getAccessFlags() const { return mState.mAccessFlags; }
+ GLenum getAccess() const { return mState.mAccess; }
+ GLboolean isMapped() const { return mState.mMapped; }
+ bool isPersistentlyMapped() const
+ {
+ return (mState.mStorageExtUsageFlags & GL_MAP_PERSISTENT_BIT_EXT) != 0;
+ }
+ void *getMapPointer() const { return mState.mMapPointer; }
+ GLint64 getMapOffset() const { return mState.mMapOffset; }
+ GLint64 getMapLength() const { return mState.mMapLength; }
+ GLint64 getSize() const { return mState.mSize; }
+ GLint64 getMemorySize() const;
+ GLboolean isImmutable() const { return mState.mImmutable; }
+ GLbitfield getStorageExtUsageFlags() const { return mState.mStorageExtUsageFlags; }
+
+ // Buffers are always initialized immediately when allocated
+ InitState initState() const { return InitState::Initialized; }
+
+ rx::BufferImpl *getImplementation() const { return mImpl; }
+
+ // Note: we pass "isWebGL" to this function to clarify it's only valid if WebGL is enabled.
+ // We pass the boolean flag instead of the pointer because this header can't read Context.h.
+ ANGLE_INLINE bool hasWebGLXFBBindingConflict(bool isWebGL) const
+ {
+ if (!isWebGL)
+ {
+ return false;
+ }
+
+ // The transform feedback generic binding point is not an indexed binding point but it also
+ // does not count as a non-transform-feedback use of the buffer, so we subtract it from the
+ // binding count when checking if the buffer is bound to a non-transform-feedback location.
+ // See https://crbug.com/853978
+ return mState.mTransformFeedbackIndexedBindingCount > 0 &&
+ mState.mTransformFeedbackIndexedBindingCount !=
+ mState.mBindingCount - mState.mTransformFeedbackGenericBindingCount;
+ }
+
+ bool isDoubleBoundForTransformFeedback() const;
+ void onTFBindingChanged(const Context *context, bool bound, bool indexed);
+ void onNonTFBindingChanged(int incr) { mState.mBindingCount += incr; }
+ angle::Result getSubData(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size,
+ void *outData);
+
+ // angle::ObserverInterface implementation.
+ void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
+
+ void addContentsObserver(VertexArray *vertexArray, uint32_t bufferIndex);
+ void removeContentsObserver(VertexArray *vertexArray, uint32_t bufferIndex);
+
+ private:
+ angle::Result bufferDataImpl(Context *context,
+ BufferBinding target,
+ const void *data,
+ GLsizeiptr size,
+ BufferUsage usage,
+ GLbitfield flags);
+ angle::Result bufferExternalDataImpl(Context *context,
+ BufferBinding target,
+ GLeglClientBufferEXT clientBuffer,
+ GLsizeiptr size,
+ GLbitfield flags);
+
+ void onContentsChange();
+ size_t getContentsObserverIndex(VertexArray *vertexArray, uint32_t bufferIndex) const;
+
+ BufferState mState;
+ rx::BufferImpl *mImpl;
+ angle::ObserverBinding mImplObserver;
+
+ angle::FastVector<ContentsObserver, angle::kMaxFixedObservers> mContentsObservers;
+ mutable IndexRangeCache mIndexRangeCache;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_BUFFER_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Caps.cpp b/gfx/angle/checkout/src/libANGLE/Caps.cpp
new file mode 100644
index 0000000000..d0b27ebbc2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Caps.cpp
@@ -0,0 +1,1371 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "libANGLE/Caps.h"
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+#include "libANGLE/formatutils.h"
+
+#include "angle_gl.h"
+
+#include <algorithm>
+#include <sstream>
+
+static void InsertExtensionString(const std::string &extension,
+ bool supported,
+ std::vector<std::string> *extensionVector)
+{
+ if (supported)
+ {
+ extensionVector->push_back(extension);
+ }
+}
+
+namespace gl
+{
+
+TextureCaps::TextureCaps() = default;
+
+TextureCaps::TextureCaps(const TextureCaps &other) = default;
+
+TextureCaps &TextureCaps::operator=(const TextureCaps &other) = default;
+
+TextureCaps::~TextureCaps() = default;
+
+GLuint TextureCaps::getMaxSamples() const
+{
+ return !sampleCounts.empty() ? *sampleCounts.rbegin() : 0;
+}
+
+GLuint TextureCaps::getNearestSamples(GLuint requestedSamples) const
+{
+ if (requestedSamples == 0)
+ {
+ return 0;
+ }
+
+ for (SupportedSampleSet::const_iterator i = sampleCounts.begin(); i != sampleCounts.end(); i++)
+ {
+ GLuint samples = *i;
+ if (samples >= requestedSamples)
+ {
+ return samples;
+ }
+ }
+
+ return 0;
+}
+
+TextureCaps GenerateMinimumTextureCaps(GLenum sizedInternalFormat,
+ const Version &clientVersion,
+ const Extensions &extensions)
+{
+ TextureCaps caps;
+
+ const InternalFormat &internalFormatInfo = GetSizedInternalFormatInfo(sizedInternalFormat);
+ caps.texturable = internalFormatInfo.textureSupport(clientVersion, extensions);
+ caps.filterable = internalFormatInfo.filterSupport(clientVersion, extensions);
+ caps.textureAttachment = internalFormatInfo.textureAttachmentSupport(clientVersion, extensions);
+ caps.renderbuffer = internalFormatInfo.renderbufferSupport(clientVersion, extensions);
+ caps.blendable = internalFormatInfo.blendSupport(clientVersion, extensions);
+
+ caps.sampleCounts.insert(0);
+ if (internalFormatInfo.isRequiredRenderbufferFormat(clientVersion))
+ {
+ if ((clientVersion.major >= 3 && clientVersion.minor >= 1) ||
+ (clientVersion.major >= 3 && !internalFormatInfo.isInt()))
+ {
+ caps.sampleCounts.insert(4);
+ }
+ }
+
+ return caps;
+}
+
+TextureCapsMap::TextureCapsMap() {}
+
+TextureCapsMap::~TextureCapsMap() {}
+
+void TextureCapsMap::insert(GLenum internalFormat, const TextureCaps &caps)
+{
+ angle::FormatID formatID = angle::Format::InternalFormatToID(internalFormat);
+ get(formatID) = caps;
+}
+
+void TextureCapsMap::clear()
+{
+ mFormatData.fill(TextureCaps());
+}
+
+const TextureCaps &TextureCapsMap::get(GLenum internalFormat) const
+{
+ angle::FormatID formatID = angle::Format::InternalFormatToID(internalFormat);
+ return get(formatID);
+}
+
+const TextureCaps &TextureCapsMap::get(angle::FormatID formatID) const
+{
+ return mFormatData[formatID];
+}
+
+TextureCaps &TextureCapsMap::get(angle::FormatID formatID)
+{
+ return mFormatData[formatID];
+}
+
+void TextureCapsMap::set(angle::FormatID formatID, const TextureCaps &caps)
+{
+ get(formatID) = caps;
+}
+
+void InitMinimumTextureCapsMap(const Version &clientVersion,
+ const Extensions &extensions,
+ TextureCapsMap *capsMap)
+{
+ for (GLenum internalFormat : GetAllSizedInternalFormats())
+ {
+ capsMap->insert(internalFormat,
+ GenerateMinimumTextureCaps(internalFormat, clientVersion, extensions));
+ }
+}
+
+Extensions::Extensions() = default;
+
+Extensions::Extensions(const Extensions &other) = default;
+
+Extensions &Extensions::operator=(const Extensions &other) = default;
+
+std::vector<std::string> Extensions::getStrings() const
+{
+ std::vector<std::string> extensionStrings;
+
+ for (const auto &extensionInfo : GetExtensionInfoMap())
+ {
+ if (this->*(extensionInfo.second.ExtensionsMember))
+ {
+ extensionStrings.push_back(extensionInfo.first);
+ }
+ }
+
+ return extensionStrings;
+}
+
+Limitations::Limitations() = default;
+Limitations::Limitations(const Limitations &other) = default;
+
+Limitations &Limitations::operator=(const Limitations &other) = default;
+
+static bool GetFormatSupportBase(const TextureCapsMap &textureCaps,
+ const GLenum *requiredFormats,
+ size_t requiredFormatsSize,
+ bool requiresTexturing,
+ bool requiresFiltering,
+ bool requiresAttachingTexture,
+ bool requiresRenderbufferSupport,
+ bool requiresBlending)
+{
+ for (size_t i = 0; i < requiredFormatsSize; i++)
+ {
+ const TextureCaps &cap = textureCaps.get(requiredFormats[i]);
+ if (requiresTexturing && !cap.texturable)
+ {
+ return false;
+ }
+
+ if (requiresFiltering && !cap.filterable)
+ {
+ return false;
+ }
+
+ if (requiresAttachingTexture && !cap.textureAttachment)
+ {
+ return false;
+ }
+
+ if (requiresRenderbufferSupport && !cap.renderbuffer)
+ {
+ return false;
+ }
+
+ if (requiresBlending && !cap.blendable)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+template <size_t N>
+static bool GetFormatSupport(const TextureCapsMap &textureCaps,
+ const GLenum (&requiredFormats)[N],
+ bool requiresTexturing,
+ bool requiresFiltering,
+ bool requiresAttachingTexture,
+ bool requiresRenderbufferSupport,
+ bool requiresBlending)
+{
+ return GetFormatSupportBase(textureCaps, requiredFormats, N, requiresTexturing,
+ requiresFiltering, requiresAttachingTexture,
+ requiresRenderbufferSupport, requiresBlending);
+}
+
+// Check for GL_OES_packed_depth_stencil support
+static bool DeterminePackedDepthStencilSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_DEPTH24_STENCIL8,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, false, false, true, true, false);
+}
+
+// Checks for GL_NV_read_depth support
+static bool DetermineReadDepthSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_DEPTH_COMPONENT16,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, true, false, false);
+}
+
+// Checks for GL_NV_read_stencil support
+static bool DetermineReadStencilSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_STENCIL_INDEX8,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, false, false, true, false, false);
+}
+
+// Checks for GL_NV_depth_buffer_float2 support
+static bool DetermineDepthBufferFloat2Support(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_DEPTH_COMPONENT32F,
+ GL_DEPTH32F_STENCIL8,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, true, false, false);
+}
+
+// Checks for GL_OES_rgb8_rgba8 support
+static bool DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_RGB8,
+ GL_RGBA8,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, false, false, false, true, false);
+}
+
+// Checks for GL_EXT_texture_format_BGRA8888 support
+static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_BGRA8_EXT,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, true, true, false);
+}
+
+// Checks for GL_EXT_read_format_bgra support
+static bool DetermineBGRAReadFormatSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_BGRA8_EXT,
+ // TODO(http://anglebug.com/4302): GL_EXT_read_format_bgra specifies 2 more types, which are
+ // currently ignored. The equivalent formats would be: GL_BGRA4_ANGLEX, GL_BGR5_A1_ANGLEX
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, true, true, false);
+}
+
+// Checks for GL_OES_color_buffer_half_float support
+static bool DetermineColorBufferHalfFloatSupport(const TextureCapsMap &textureCaps)
+{
+ // EXT_color_buffer_half_float issue #2 states that an implementation doesn't need to support
+ // rendering to any of the formats but is expected to be able to render to at least one. WebGL
+ // requires that at least RGBA16F is renderable so we make the same requirement.
+ constexpr GLenum requiredFormats[] = {
+ GL_RGBA16F,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, false, false, true, true, false);
+}
+
+// Checks for GL_OES_texture_half_float support
+static bool DetermineHalfFloatTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_RGBA16F, GL_RGB16F, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE16F_EXT, GL_ALPHA16F_EXT,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, false, false, false);
+}
+
+// Checks for GL_OES_texture_half_float_linear support
+static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &textureCaps,
+ bool checkLegacyFormats)
+{
+ constexpr GLenum requiredFormats[] = {GL_RGBA16F, GL_RGB16F};
+ // If GL_OES_texture_half_float is present, this extension must also support legacy formats
+ // introduced by that extension
+ constexpr GLenum requiredFormatsES2[] = {GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE16F_EXT,
+ GL_ALPHA16F_EXT};
+
+ if (checkLegacyFormats &&
+ !GetFormatSupport(textureCaps, requiredFormatsES2, false, true, false, false, false))
+ {
+ return false;
+ }
+
+ return GetFormatSupport(textureCaps, requiredFormats, false, true, false, false, false);
+}
+
+// Checks for GL_OES_texture_float support
+static bool DetermineFloatTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_RGBA32F, GL_RGB32F, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE32F_EXT, GL_ALPHA32F_EXT,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, false, false, false);
+}
+
+// Checks for GL_OES_texture_float_linear support
+static bool DetermineFloatTextureFilteringSupport(const TextureCapsMap &textureCaps,
+ bool checkLegacyFormats)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_RGBA32F,
+ GL_RGB32F,
+ };
+ // If GL_OES_texture_float is present, this extension must also support legacy formats
+ // introduced by that extension
+ constexpr GLenum requiredFormatsES2[] = {
+ GL_LUMINANCE_ALPHA32F_EXT,
+ GL_LUMINANCE32F_EXT,
+ GL_ALPHA32F_EXT,
+ };
+
+ if (checkLegacyFormats &&
+ !GetFormatSupport(textureCaps, requiredFormatsES2, false, true, false, false, false))
+ {
+ return false;
+ }
+
+ return GetFormatSupport(textureCaps, requiredFormats, false, true, false, false, false);
+}
+
+// Checks for GL_EXT_texture_rg support
+static bool DetermineRGTextureSupport(const TextureCapsMap &textureCaps,
+ bool checkHalfFloatFormats,
+ bool checkFloatFormats)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_R8,
+ GL_RG8,
+ };
+ constexpr GLenum requiredHalfFloatFormats[] = {
+ GL_R16F,
+ GL_RG16F,
+ };
+ constexpr GLenum requiredFloatFormats[] = {
+ GL_R32F,
+ GL_RG32F,
+ };
+
+ if (checkHalfFloatFormats &&
+ !GetFormatSupport(textureCaps, requiredHalfFloatFormats, true, false, false, false, false))
+ {
+ return false;
+ }
+
+ if (checkFloatFormats &&
+ !GetFormatSupport(textureCaps, requiredFloatFormats, true, false, false, false, false))
+ {
+ return false;
+ }
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, true, true, false);
+}
+
+static bool DetermineTextureFormat2101010Support(const TextureCapsMap &textureCaps)
+{
+ // GL_EXT_texture_type_2_10_10_10_REV specifies both RGBA and RGB support whereas desktop GL
+ // only specifies RGBA support, so check both RGBA and RGB before marking as supported.
+ constexpr GLenum requiredFormats[] = {
+ GL_RGB10_A2,
+ GL_RGB10_UNORM_ANGLEX,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for GL_EXT_texture_compression_dxt1 support
+static bool DetermineDXT1TextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for GL_ANGLE_texture_compression_dxt3 support
+static bool DetermineDXT3TextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for GL_ANGLE_texture_compression_dxt5 support
+static bool DetermineDXT5TextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for GL_EXT_texture_compression_s3tc_srgb support
+static bool DetermineS3TCsRGBTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,
+ GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
+ GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
+ GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for GL_KHR_texture_compression_astc_ldr support
+static bool DetermineASTCLDRTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_COMPRESSED_RGBA_ASTC_5x4_KHR,
+ GL_COMPRESSED_RGBA_ASTC_5x5_KHR, GL_COMPRESSED_RGBA_ASTC_6x5_KHR,
+ GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_COMPRESSED_RGBA_ASTC_8x5_KHR,
+ GL_COMPRESSED_RGBA_ASTC_8x6_KHR, GL_COMPRESSED_RGBA_ASTC_8x8_KHR,
+ GL_COMPRESSED_RGBA_ASTC_10x5_KHR, GL_COMPRESSED_RGBA_ASTC_10x6_KHR,
+ GL_COMPRESSED_RGBA_ASTC_10x8_KHR, GL_COMPRESSED_RGBA_ASTC_10x10_KHR,
+ GL_COMPRESSED_RGBA_ASTC_12x10_KHR, GL_COMPRESSED_RGBA_ASTC_12x12_KHR,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for GL_OES_texture_compression_astc support
+static bool DetermineASTCOESTExtureSupport(const TextureCapsMap &textureCaps)
+{
+ if (!DetermineASTCLDRTextureSupport(textureCaps))
+ {
+ return false;
+ }
+
+ // The OES version of the extension also requires the 3D ASTC formats
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RGBA_ASTC_3x3x3_OES, GL_COMPRESSED_RGBA_ASTC_4x3x3_OES,
+ GL_COMPRESSED_RGBA_ASTC_4x4x3_OES, GL_COMPRESSED_RGBA_ASTC_4x4x4_OES,
+ GL_COMPRESSED_RGBA_ASTC_5x4x4_OES, GL_COMPRESSED_RGBA_ASTC_5x5x4_OES,
+ GL_COMPRESSED_RGBA_ASTC_5x5x5_OES, GL_COMPRESSED_RGBA_ASTC_6x5x5_OES,
+ GL_COMPRESSED_RGBA_ASTC_6x6x5_OES, GL_COMPRESSED_RGBA_ASTC_6x6x6_OES,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES,
+ GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for GL_ETC1_RGB8_OES support
+static bool DetermineETC1RGB8TextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_ETC1_RGB8_OES,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for OES_compressed_ETC2_RGB8_texture support
+static bool DetermineETC2RGB8TextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RGB8_ETC2,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for OES_compressed_ETC2_sRGB8_texture support
+static bool DetermineETC2sRGB8TextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_SRGB8_ETC2,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for OES_compressed_ETC2_punchthroughA_RGBA8_texture support
+static bool DetermineETC2PunchthroughARGB8TextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for OES_compressed_ETC2_punchthroughA_sRGB8_alpha_texture support
+static bool DetermineETC2PunchthroughAsRGB8AlphaTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for OES_compressed_ETC2_RGBA8_texture support
+static bool DetermineETC2RGBA8TextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RGBA8_ETC2_EAC,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for OES_compressed_ETC2_sRGB8_alpha8_texture support
+static bool DetermineETC2sRGB8Alpha8TextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for OES_compressed_EAC_R11_unsigned_texture support
+static bool DetermineEACR11UnsignedTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_R11_EAC,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for OES_compressed_EAC_R11_signed_texture support
+static bool DetermineEACR11SignedTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_SIGNED_R11_EAC,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for OES_compressed_EAC_RG11_unsigned_texture support
+static bool DetermineEACRG11UnsignedTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RG11_EAC,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for OES_compressed_EAC_RG11_signed_texture support
+static bool DetermineEACRG11SignedTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_SIGNED_RG11_EAC,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for GL_EXT_sRGB support
+static bool DetermineSRGBTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFilterFormats[] = {
+ GL_SRGB8,
+ GL_SRGB8_ALPHA8,
+ };
+
+ constexpr GLenum requiredRenderFormats[] = {
+ GL_SRGB8_ALPHA8,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false, false, false) &&
+ GetFormatSupport(textureCaps, requiredRenderFormats, true, false, true, true, false);
+}
+
+// Check for GL_EXT_texture_sRGB_R8 support
+static bool DetermineSRGBR8TextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFilterFormats[] = {GL_SR8_EXT};
+
+ return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false, false, false);
+}
+
+// Check for GL_EXT_texture_sRGB_RG8 support
+static bool DetermineSRGBRG8TextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFilterFormats[] = {GL_SRG8_EXT};
+
+ return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false, false, false);
+}
+
+// Check for GL_ANGLE_depth_texture support
+static bool DetermineDepthTextureANGLESupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_DEPTH_COMPONENT16,
+#if !defined(ANGLE_PLATFORM_IOS) && \
+ (!defined(ANGLE_PLATFORM_MACCATALYST) || !defined(ANGLE_CPU_ARM64))
+ // anglebug.com/6082
+ // TODO(dino): Temporarily Removing the need for GL_DEPTH_COMPONENT32_OES
+ // because it is not supported on iOS.
+ // TODO(dino): I think this needs to be a runtime check when running an iOS app on Mac.
+ GL_DEPTH_COMPONENT32_OES,
+#endif
+ GL_DEPTH24_STENCIL8_OES,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, true, false, false);
+}
+
+// Check for GL_OES_depth_texture support
+static bool DetermineDepthTextureOESSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_DEPTH_COMPONENT16,
+#if !defined(ANGLE_PLATFORM_IOS) && \
+ (!defined(ANGLE_PLATFORM_MACCATALYST) || !defined(ANGLE_CPU_ARM64))
+ // anglebug.com/6082
+ // TODO(dino): Temporarily Removing the need for GL_DEPTH_COMPONENT32_OES
+ // because it is not supported on iOS.
+ // TODO(dino): I think this needs to be a runtime check when running an iOS app on Mac.
+ GL_DEPTH_COMPONENT32_OES,
+#endif
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, true, true, false);
+}
+
+// Check for GL_OES_depth24
+static bool DetermineDepth24OESSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_DEPTH_COMPONENT24_OES,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, false, false, false, true, false);
+}
+
+// Check for GL_OES_depth32 support
+static bool DetermineDepth32Support(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_DEPTH_COMPONENT32_OES,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, false, false, true, true, false);
+}
+
+// Check for GL_CHROMIUM_color_buffer_float_rgb support
+static bool DetermineColorBufferFloatRGBSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_RGB32F,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, true, false, false);
+}
+
+// Check for GL_CHROMIUM_color_buffer_float_rgba support
+static bool DetermineColorBufferFloatRGBASupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_RGBA32F,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, true, true, false);
+}
+
+// Check for GL_EXT_color_buffer_float support
+static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum nonBlendableFormats[] = {
+ GL_R32F,
+ GL_RG32F,
+ GL_RGBA32F,
+ };
+
+ constexpr GLenum blendableFormats[] = {
+ GL_R16F,
+ GL_RG16F,
+ GL_RGBA16F,
+ GL_R11F_G11F_B10F,
+ };
+
+ return GetFormatSupport(textureCaps, nonBlendableFormats, true, false, true, true, false) &&
+ GetFormatSupport(textureCaps, blendableFormats, true, false, true, true, true);
+}
+
+// Check for GL_EXT_float_blend support
+static bool DetermineFloatBlendSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_R32F,
+ GL_RG32F,
+ GL_RGBA32F,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, false, true, true, true);
+}
+
+// Check for GL_EXT_texture_norm16 support
+static bool DetermineTextureNorm16Support(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFilterFormats[] = {
+ GL_R16_EXT, GL_RG16_EXT, GL_RGB16_EXT, GL_RGBA16_EXT,
+ GL_R16_SNORM_EXT, GL_RG16_SNORM_EXT, GL_RGB16_SNORM_EXT, GL_RGBA16_SNORM_EXT,
+ };
+
+ constexpr GLenum requiredRenderFormats[] = {
+ GL_R16_EXT,
+ GL_RG16_EXT,
+ GL_RGBA16_EXT,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false, false, false) &&
+ GetFormatSupport(textureCaps, requiredRenderFormats, true, false, true, true, false);
+}
+
+// Check for EXT_texture_compression_rgtc support
+static bool DetermineRGTCTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RED_RGTC1_EXT, GL_COMPRESSED_SIGNED_RED_RGTC1_EXT,
+ GL_COMPRESSED_RED_GREEN_RGTC2_EXT, GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT};
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for EXT_texture_compression_bptc support
+static bool DetermineBPTCTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT,
+ GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT};
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for GL_IMG_texture_compression_pvrtc support
+static bool DeterminePVRTCTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG,
+ GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG};
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Check for GL_EXT_pvrtc_sRGB support
+static bool DeterminePVRTCsRGBTextureSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT, GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT,
+ GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT, GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT};
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+bool DetermineCompressedTextureETCSupport(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {GL_COMPRESSED_R11_EAC,
+ GL_COMPRESSED_SIGNED_R11_EAC,
+ GL_COMPRESSED_RG11_EAC,
+ GL_COMPRESSED_SIGNED_RG11_EAC,
+ GL_COMPRESSED_RGB8_ETC2,
+ GL_COMPRESSED_SRGB8_ETC2,
+ GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ GL_COMPRESSED_RGBA8_ETC2_EAC,
+ GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC};
+
+ return GetFormatSupport(textureCaps, requiredFormats, true, true, false, false, false);
+}
+
+// Checks for GL_OES_texture_stencil8 support
+static bool DetermineStencilIndex8Support(const TextureCapsMap &textureCaps)
+{
+ constexpr GLenum requiredFormats[] = {
+ GL_STENCIL_INDEX8,
+ };
+
+ return GetFormatSupport(textureCaps, requiredFormats, false, false, true, false, false);
+}
+
+void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps)
+{
+ // TODO(ynovikov): rgb8Rgba8OES, colorBufferHalfFloatEXT, textureHalfFloatOES,
+ // textureHalfFloatLinearOES, textureFloatOES, textureFloatLinearOES, textureRgEXT, sRGB,
+ // colorBufferFloatRgbCHROMIUM, colorBufferFloatRgbaCHROMIUM and colorBufferFloatEXT were
+ // verified. Verify the rest.
+ packedDepthStencilOES = DeterminePackedDepthStencilSupport(textureCaps);
+ rgb8Rgba8OES = DetermineRGB8AndRGBA8TextureSupport(textureCaps);
+ readDepthNV = DetermineReadDepthSupport(textureCaps);
+ readStencilNV = DetermineReadStencilSupport(textureCaps);
+ depthBufferFloat2NV = DetermineDepthBufferFloat2Support(textureCaps);
+ textureFormatBGRA8888EXT = DetermineBGRA8TextureSupport(textureCaps);
+ readFormatBgraEXT = DetermineBGRAReadFormatSupport(textureCaps);
+ textureHalfFloatOES = DetermineHalfFloatTextureSupport(textureCaps);
+ textureHalfFloatLinearOES =
+ DetermineHalfFloatTextureFilteringSupport(textureCaps, textureHalfFloatOES);
+ textureFloatOES = DetermineFloatTextureSupport(textureCaps);
+ textureFloatLinearOES = DetermineFloatTextureFilteringSupport(textureCaps, textureFloatOES);
+ textureRgEXT = DetermineRGTextureSupport(textureCaps, textureHalfFloatOES, textureFloatOES);
+ colorBufferHalfFloatEXT =
+ textureHalfFloatOES && DetermineColorBufferHalfFloatSupport(textureCaps);
+ textureType2101010REVEXT = DetermineTextureFormat2101010Support(textureCaps);
+ textureCompressionDxt1EXT = DetermineDXT1TextureSupport(textureCaps);
+ textureCompressionDxt3ANGLE = DetermineDXT3TextureSupport(textureCaps);
+ textureCompressionDxt5ANGLE = DetermineDXT5TextureSupport(textureCaps);
+ textureCompressionS3tcSrgbEXT = DetermineS3TCsRGBTextureSupport(textureCaps);
+ textureCompressionAstcLdrKHR = DetermineASTCLDRTextureSupport(textureCaps);
+ textureCompressionAstcOES = DetermineASTCOESTExtureSupport(textureCaps);
+ compressedETC1RGB8TextureOES = DetermineETC1RGB8TextureSupport(textureCaps);
+ compressedETC2RGB8TextureOES = DetermineETC2RGB8TextureSupport(textureCaps);
+ compressedETC2SRGB8TextureOES = DetermineETC2sRGB8TextureSupport(textureCaps);
+ compressedETC2PunchthroughARGBA8TextureOES =
+ DetermineETC2PunchthroughARGB8TextureSupport(textureCaps);
+ compressedETC2PunchthroughASRGB8AlphaTextureOES =
+ DetermineETC2PunchthroughAsRGB8AlphaTextureSupport(textureCaps);
+ compressedETC2RGBA8TextureOES = DetermineETC2RGBA8TextureSupport(textureCaps);
+ compressedETC2SRGB8Alpha8TextureOES = DetermineETC2sRGB8Alpha8TextureSupport(textureCaps);
+ compressedEACR11UnsignedTextureOES = DetermineEACR11UnsignedTextureSupport(textureCaps);
+ compressedEACR11SignedTextureOES = DetermineEACR11SignedTextureSupport(textureCaps);
+ compressedEACRG11UnsignedTextureOES = DetermineEACRG11UnsignedTextureSupport(textureCaps);
+ compressedEACRG11SignedTextureOES = DetermineEACRG11SignedTextureSupport(textureCaps);
+ sRGBEXT = DetermineSRGBTextureSupport(textureCaps);
+ textureSRGBR8EXT = DetermineSRGBR8TextureSupport(textureCaps);
+ textureSRGBRG8EXT = DetermineSRGBRG8TextureSupport(textureCaps);
+ depthTextureANGLE = DetermineDepthTextureANGLESupport(textureCaps);
+ depthTextureOES = DetermineDepthTextureOESSupport(textureCaps);
+ depth24OES = DetermineDepth24OESSupport(textureCaps);
+ depth32OES = DetermineDepth32Support(textureCaps);
+ colorBufferFloatRgbCHROMIUM = DetermineColorBufferFloatRGBSupport(textureCaps);
+ colorBufferFloatRgbaCHROMIUM = DetermineColorBufferFloatRGBASupport(textureCaps);
+ colorBufferFloatEXT = DetermineColorBufferFloatSupport(textureCaps);
+ floatBlendEXT = DetermineFloatBlendSupport(textureCaps);
+ textureNorm16EXT = DetermineTextureNorm16Support(textureCaps);
+ textureCompressionRgtcEXT = DetermineRGTCTextureSupport(textureCaps);
+ textureCompressionBptcEXT = DetermineBPTCTextureSupport(textureCaps);
+ textureCompressionPvrtcIMG = DeterminePVRTCTextureSupport(textureCaps);
+ pvrtcSRGBEXT = DeterminePVRTCsRGBTextureSupport(textureCaps);
+ textureStencil8OES = DetermineStencilIndex8Support(textureCaps);
+}
+
+TypePrecision::TypePrecision() = default;
+
+TypePrecision::TypePrecision(const TypePrecision &other) = default;
+
+TypePrecision &TypePrecision::operator=(const TypePrecision &other) = default;
+
+void TypePrecision::setIEEEFloat()
+{
+ range = {{127, 127}};
+ precision = 23;
+}
+
+void TypePrecision::setIEEEHalfFloat()
+{
+ range = {{15, 15}};
+ precision = 10;
+}
+
+void TypePrecision::setTwosComplementInt(unsigned int bits)
+{
+ range = {{static_cast<GLint>(bits) - 1, static_cast<GLint>(bits) - 2}};
+ precision = 0;
+}
+
+void TypePrecision::setSimulatedFloat(unsigned int r, unsigned int p)
+{
+ range = {{static_cast<GLint>(r), static_cast<GLint>(r)}};
+ precision = static_cast<GLint>(p);
+}
+
+void TypePrecision::setSimulatedInt(unsigned int r)
+{
+ range = {{static_cast<GLint>(r), static_cast<GLint>(r)}};
+ precision = 0;
+}
+
+void TypePrecision::get(GLint *returnRange, GLint *returnPrecision) const
+{
+ std::copy(range.begin(), range.end(), returnRange);
+ *returnPrecision = precision;
+}
+
+Caps::Caps() = default;
+Caps::Caps(const Caps &other) = default;
+Caps::~Caps() = default;
+Caps &Caps::operator=(const Caps &other) = default;
+
+Caps GenerateMinimumCaps(const Version &clientVersion, const Extensions &extensions)
+{
+ Caps caps;
+
+ // GLES1 emulation (Minimums taken from Table 6.20 / 6.22 (ES 1.1 spec))
+ if (clientVersion < Version(2, 0))
+ {
+ caps.maxMultitextureUnits = 2;
+ caps.maxLights = 8;
+ caps.maxClipPlanes = 1;
+
+ caps.maxModelviewMatrixStackDepth = 16;
+ caps.maxProjectionMatrixStackDepth = 2;
+ caps.maxTextureMatrixStackDepth = 2;
+
+ caps.minSmoothPointSize = 1.0f;
+ caps.maxSmoothPointSize = 1.0f;
+ }
+
+ if (clientVersion >= Version(2, 0))
+ {
+ // Table 6.18
+ caps.max2DTextureSize = 64;
+ caps.maxCubeMapTextureSize = 16;
+ caps.maxViewportWidth = caps.max2DTextureSize;
+ caps.maxViewportHeight = caps.max2DTextureSize;
+ caps.minAliasedPointSize = 1;
+ caps.maxAliasedPointSize = 1;
+ caps.minAliasedLineWidth = 1;
+ caps.maxAliasedLineWidth = 1;
+
+ // Table 6.19
+ caps.vertexHighpFloat.setSimulatedFloat(62, 16);
+ caps.vertexMediumpFloat.setSimulatedFloat(14, 10);
+ caps.vertexLowpFloat.setSimulatedFloat(1, 8);
+ caps.vertexHighpInt.setSimulatedInt(16);
+ caps.vertexMediumpInt.setSimulatedInt(10);
+ caps.vertexLowpInt.setSimulatedInt(8);
+ caps.fragmentHighpFloat.setSimulatedFloat(62, 16);
+ caps.fragmentMediumpFloat.setSimulatedFloat(14, 10);
+ caps.fragmentLowpFloat.setSimulatedFloat(1, 8);
+ caps.fragmentHighpInt.setSimulatedInt(16);
+ caps.fragmentMediumpInt.setSimulatedInt(10);
+ caps.fragmentLowpInt.setSimulatedInt(8);
+
+ // Table 6.20
+ caps.maxVertexAttributes = 8;
+ caps.maxVertexUniformVectors = 128;
+ caps.maxVaryingVectors = 8;
+ caps.maxCombinedTextureImageUnits = 8;
+ caps.maxShaderTextureImageUnits[ShaderType::Fragment] = 8;
+ caps.maxFragmentUniformVectors = 16;
+ caps.maxRenderbufferSize = 1;
+
+ // Table 3.35
+ caps.maxSamples = 4;
+ }
+
+ if (clientVersion >= Version(3, 0))
+ {
+ // Table 6.28
+ caps.maxElementIndex = (1 << 24) - 1;
+ caps.max3DTextureSize = 256;
+ caps.max2DTextureSize = 2048;
+ caps.maxArrayTextureLayers = 256;
+ caps.maxLODBias = 2.0f;
+ caps.maxCubeMapTextureSize = 2048;
+ caps.maxRenderbufferSize = 2048;
+ caps.maxDrawBuffers = 4;
+ caps.maxColorAttachments = 4;
+ caps.maxViewportWidth = caps.max2DTextureSize;
+ caps.maxViewportHeight = caps.max2DTextureSize;
+
+ // Table 6.29
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_R11_EAC);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_SIGNED_R11_EAC);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_RG11_EAC);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_SIGNED_RG11_EAC);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_RGB8_ETC2);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_SRGB8_ETC2);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_RGBA8_ETC2_EAC);
+ caps.compressedTextureFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
+ caps.vertexHighpFloat.setIEEEFloat();
+ caps.vertexHighpInt.setTwosComplementInt(32);
+ caps.vertexMediumpInt.setTwosComplementInt(16);
+ caps.vertexLowpInt.setTwosComplementInt(8);
+ caps.fragmentHighpFloat.setIEEEFloat();
+ caps.fragmentHighpInt.setSimulatedInt(32);
+ caps.fragmentMediumpInt.setTwosComplementInt(16);
+ caps.fragmentLowpInt.setTwosComplementInt(8);
+ caps.maxServerWaitTimeout = 0;
+
+ // Table 6.31
+ caps.maxVertexAttributes = 16;
+ caps.maxShaderUniformComponents[ShaderType::Vertex] = 1024;
+ caps.maxVertexUniformVectors = 256;
+ caps.maxShaderUniformBlocks[ShaderType::Vertex] = limits::kMinimumShaderUniformBlocks;
+ caps.maxVertexOutputComponents = limits::kMinimumVertexOutputComponents;
+ caps.maxShaderTextureImageUnits[ShaderType::Vertex] = 16;
+
+ // Table 6.32
+ caps.maxShaderUniformComponents[ShaderType::Fragment] = 896;
+ caps.maxFragmentUniformVectors = 224;
+ caps.maxShaderUniformBlocks[ShaderType::Fragment] = limits::kMinimumShaderUniformBlocks;
+ caps.maxFragmentInputComponents = 60;
+ caps.maxShaderTextureImageUnits[ShaderType::Fragment] = 16;
+ caps.minProgramTexelOffset = -8;
+ caps.maxProgramTexelOffset = 7;
+
+ // Table 6.33
+ caps.maxUniformBufferBindings = 24;
+ caps.maxUniformBlockSize = 16384;
+ caps.uniformBufferOffsetAlignment = 256;
+ caps.maxCombinedUniformBlocks = 24;
+ caps.maxVaryingComponents = 60;
+ caps.maxVaryingVectors = 15;
+ caps.maxCombinedTextureImageUnits = 32;
+
+ // Table 6.34
+ caps.maxTransformFeedbackInterleavedComponents = 64;
+ caps.maxTransformFeedbackSeparateAttributes = 4;
+ caps.maxTransformFeedbackSeparateComponents = 4;
+ }
+
+ if (clientVersion >= Version(3, 1))
+ {
+ // Table 20.40
+ caps.maxFramebufferWidth = 2048;
+ caps.maxFramebufferHeight = 2048;
+ caps.maxFramebufferSamples = 4;
+ caps.maxSampleMaskWords = 1;
+ caps.maxColorTextureSamples = 1;
+ caps.maxDepthTextureSamples = 1;
+ caps.maxIntegerSamples = 1;
+
+ // Table 20.41
+ caps.maxVertexAttribRelativeOffset = 2047;
+ caps.maxVertexAttribBindings = 16;
+ caps.maxVertexAttribStride = 2048;
+
+ // Table 20.43
+ caps.maxShaderAtomicCounterBuffers[ShaderType::Vertex] = 0;
+ caps.maxShaderAtomicCounters[ShaderType::Vertex] = 0;
+ caps.maxShaderImageUniforms[ShaderType::Vertex] = 0;
+ caps.maxShaderStorageBlocks[ShaderType::Vertex] = 0;
+
+ // Table 20.44
+ caps.maxShaderUniformComponents[ShaderType::Fragment] = 1024;
+ caps.maxFragmentUniformVectors = 256;
+ caps.maxShaderAtomicCounterBuffers[ShaderType::Fragment] = 0;
+ caps.maxShaderAtomicCounters[ShaderType::Fragment] = 0;
+ caps.maxShaderImageUniforms[ShaderType::Fragment] = 0;
+ caps.maxShaderStorageBlocks[ShaderType::Fragment] = 0;
+ caps.minProgramTextureGatherOffset = 0;
+ caps.maxProgramTextureGatherOffset = 0;
+
+ // Table 20.45
+ caps.maxComputeWorkGroupCount = {{65535, 65535, 65535}};
+ caps.maxComputeWorkGroupSize = {{128, 128, 64}};
+ caps.maxComputeWorkGroupInvocations = 12;
+ caps.maxShaderUniformBlocks[ShaderType::Compute] = limits::kMinimumShaderUniformBlocks;
+ caps.maxShaderTextureImageUnits[ShaderType::Compute] = 16;
+ caps.maxComputeSharedMemorySize = 16384;
+ caps.maxShaderUniformComponents[ShaderType::Compute] = 1024;
+ caps.maxShaderAtomicCounterBuffers[ShaderType::Compute] = 1;
+ caps.maxShaderAtomicCounters[ShaderType::Compute] = 8;
+ caps.maxShaderImageUniforms[ShaderType::Compute] = 4;
+ caps.maxShaderStorageBlocks[ShaderType::Compute] = 4;
+
+ // Table 20.46
+ caps.maxUniformBufferBindings = 36;
+ caps.maxCombinedTextureImageUnits = 48;
+ caps.maxCombinedShaderOutputResources = 4;
+
+ // Table 20.47
+ caps.maxUniformLocations = 1024;
+ caps.maxAtomicCounterBufferBindings = 1;
+ caps.maxAtomicCounterBufferSize = 32;
+ caps.maxCombinedAtomicCounterBuffers = 1;
+ caps.maxCombinedAtomicCounters = 8;
+ caps.maxImageUnits = 4;
+ caps.maxCombinedImageUniforms = 4;
+ caps.maxShaderStorageBufferBindings = 4;
+ caps.maxShaderStorageBlockSize = 1 << 27;
+ caps.maxCombinedShaderStorageBlocks = 4;
+ caps.shaderStorageBufferOffsetAlignment = 256;
+ }
+
+ if (extensions.textureRectangleANGLE)
+ {
+ caps.maxRectangleTextureSize = 64;
+ }
+
+ if (extensions.geometryShaderAny())
+ {
+ // Table 20.40 (GL_EXT_geometry_shader)
+ caps.maxFramebufferLayers = 256;
+ caps.layerProvokingVertex = GL_LAST_VERTEX_CONVENTION_EXT;
+
+ // Table 20.43gs (GL_EXT_geometry_shader)
+ caps.maxShaderUniformComponents[ShaderType::Geometry] = 1024;
+ caps.maxShaderUniformBlocks[ShaderType::Geometry] = limits::kMinimumShaderUniformBlocks;
+ caps.maxGeometryInputComponents = 64;
+ caps.maxGeometryOutputComponents = 64;
+ caps.maxGeometryOutputVertices = 256;
+ caps.maxGeometryTotalOutputComponents = 1024;
+ caps.maxShaderTextureImageUnits[ShaderType::Geometry] = 16;
+ caps.maxShaderAtomicCounterBuffers[ShaderType::Geometry] = 0;
+ caps.maxShaderAtomicCounters[ShaderType::Geometry] = 0;
+ caps.maxShaderStorageBlocks[ShaderType::Geometry] = 0;
+ caps.maxGeometryShaderInvocations = 32;
+
+ // Table 20.46 (GL_EXT_geometry_shader)
+ caps.maxShaderImageUniforms[ShaderType::Geometry] = 0;
+
+ // Table 20.46 (GL_EXT_geometry_shader)
+ caps.maxUniformBufferBindings = 48;
+ caps.maxCombinedUniformBlocks = 36;
+ caps.maxCombinedTextureImageUnits = 64;
+ }
+
+ if (extensions.tessellationShaderEXT)
+ {
+ // Table 20.43 "Implementation Dependent Tessellation Shader Limits"
+ caps.maxTessControlInputComponents = 64;
+ caps.maxTessControlOutputComponents = 64;
+ caps.maxShaderTextureImageUnits[ShaderType::TessControl] = 16;
+ caps.maxShaderUniformComponents[ShaderType::TessControl] = 1024;
+ caps.maxTessControlTotalOutputComponents = 2048;
+ caps.maxShaderImageUniforms[ShaderType::TessControl] = 0;
+ caps.maxShaderAtomicCounters[ShaderType::TessControl] = 0;
+ caps.maxShaderAtomicCounterBuffers[ShaderType::TessControl] = 0;
+
+ caps.maxTessPatchComponents = 120;
+ caps.maxPatchVertices = 32;
+ caps.maxTessGenLevel = 64;
+
+ caps.maxTessEvaluationInputComponents = 64;
+ caps.maxTessEvaluationOutputComponents = 64;
+ caps.maxShaderTextureImageUnits[ShaderType::TessEvaluation] = 16;
+ caps.maxShaderUniformComponents[ShaderType::TessEvaluation] = 1024;
+ caps.maxShaderImageUniforms[ShaderType::TessEvaluation] = 0;
+ caps.maxShaderAtomicCounters[ShaderType::TessEvaluation] = 0;
+ caps.maxShaderAtomicCounterBuffers[ShaderType::TessEvaluation] = 0;
+
+ // Table 20.46 "Implementation Dependent Aggregate Shader Limits"
+ caps.maxUniformBufferBindings = 72;
+ caps.maxCombinedUniformBlocks = 60;
+ caps.maxCombinedTextureImageUnits = 96;
+ }
+
+ for (ShaderType shaderType : AllShaderTypes())
+ {
+ caps.maxCombinedShaderUniformComponents[shaderType] =
+ caps.maxShaderUniformBlocks[shaderType] *
+ static_cast<GLuint>(caps.maxUniformBlockSize / 4) +
+ caps.maxShaderUniformComponents[shaderType];
+ }
+
+ return caps;
+}
+} // namespace gl
+
+namespace egl
+{
+
+Caps::Caps() = default;
+
+DisplayExtensions::DisplayExtensions() = default;
+
+std::vector<std::string> DisplayExtensions::getStrings() const
+{
+ std::vector<std::string> extensionStrings;
+
+ // clang-format off
+ // | Extension name | Supported flag | Output vector |
+ InsertExtensionString("EGL_EXT_create_context_robustness", createContextRobustness, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer", d3dShareHandleClientBuffer, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_d3d_texture_client_buffer", d3dTextureClientBuffer, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle", surfaceD3DTexture2DShareHandle, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_query_surface_pointer", querySurfacePointer, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_keyed_mutex", keyedMutex, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_surface_orientation", surfaceOrientation, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_direct_composition", directComposition, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_windows_ui_composition", windowsUIComposition, &extensionStrings);
+ InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings);
+ InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings);
+ InsertExtensionString("EGL_KHR_image", image, &extensionStrings);
+ InsertExtensionString("EGL_KHR_image_base", imageBase, &extensionStrings);
+ InsertExtensionString("EGL_KHR_image_pixmap", imagePixmap, &extensionStrings);
+ InsertExtensionString("EGL_EXT_image_gl_colorspace", imageGlColorspace, &extensionStrings);
+ InsertExtensionString("EGL_KHR_gl_colorspace", glColorspace, &extensionStrings);
+ InsertExtensionString("EGL_EXT_gl_colorspace_scrgb", glColorspaceScrgb, &extensionStrings);
+ InsertExtensionString("EGL_EXT_gl_colorspace_scrgb_linear", glColorspaceScrgbLinear, &extensionStrings);
+ InsertExtensionString("EGL_EXT_gl_colorspace_display_p3", glColorspaceDisplayP3, &extensionStrings);
+ InsertExtensionString("EGL_EXT_gl_colorspace_display_p3_linear", glColorspaceDisplayP3Linear, &extensionStrings);
+ InsertExtensionString("EGL_EXT_gl_colorspace_display_p3_passthrough", glColorspaceDisplayP3Passthrough, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_colorspace_attribute_passthrough", eglColorspaceAttributePassthroughANGLE, &extensionStrings);
+ InsertExtensionString("EGL_KHR_gl_texture_2D_image", glTexture2DImage, &extensionStrings);
+ InsertExtensionString("EGL_KHR_gl_texture_cubemap_image", glTextureCubemapImage, &extensionStrings);
+ InsertExtensionString("EGL_KHR_gl_texture_3D_image", glTexture3DImage, &extensionStrings);
+ InsertExtensionString("EGL_KHR_gl_renderbuffer_image", glRenderbufferImage, &extensionStrings);
+ InsertExtensionString("EGL_KHR_get_all_proc_addresses", getAllProcAddresses, &extensionStrings);
+ InsertExtensionString("EGL_KHR_stream", stream, &extensionStrings);
+ InsertExtensionString("EGL_KHR_stream_consumer_gltexture", streamConsumerGLTexture, &extensionStrings);
+ InsertExtensionString("EGL_NV_stream_consumer_gltexture_yuv", streamConsumerGLTextureYUV, &extensionStrings);
+ InsertExtensionString("EGL_KHR_fence_sync", fenceSync, &extensionStrings);
+ InsertExtensionString("EGL_KHR_wait_sync", waitSync, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_stream_producer_d3d_texture", streamProducerD3DTexture, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_create_context_webgl_compatibility", createContextWebGLCompatibility, &extensionStrings);
+ InsertExtensionString("EGL_CHROMIUM_create_context_bind_generates_resource", createContextBindGeneratesResource, &extensionStrings);
+ InsertExtensionString("EGL_CHROMIUM_sync_control", syncControlCHROMIUM, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_sync_control_rate", syncControlRateANGLE, &extensionStrings);
+ InsertExtensionString("EGL_KHR_swap_buffers_with_damage", swapBuffersWithDamage, &extensionStrings);
+ InsertExtensionString("EGL_EXT_pixel_format_float", pixelFormatFloat, &extensionStrings);
+ InsertExtensionString("EGL_KHR_surfaceless_context", surfacelessContext, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_display_texture_share_group", displayTextureShareGroup, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_display_semaphore_share_group", displaySemaphoreShareGroup, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_create_context_client_arrays", createContextClientArrays, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_program_cache_control", programCacheControlANGLE, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_robust_resource_initialization", robustResourceInitializationANGLE, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_iosurface_client_buffer", iosurfaceClientBuffer, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_metal_texture_client_buffer", mtlTextureClientBuffer, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_create_context_extensions_enabled", createContextExtensionsEnabled, &extensionStrings);
+ InsertExtensionString("EGL_ANDROID_presentation_time", presentationTime, &extensionStrings);
+ InsertExtensionString("EGL_ANDROID_blob_cache", blobCache, &extensionStrings);
+ InsertExtensionString("EGL_ANDROID_framebuffer_target", framebufferTargetANDROID, &extensionStrings);
+ InsertExtensionString("EGL_ANDROID_image_native_buffer", imageNativeBuffer, &extensionStrings);
+ InsertExtensionString("EGL_ANDROID_get_frame_timestamps", getFrameTimestamps, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_timestamp_surface_attribute", timestampSurfaceAttributeANGLE, &extensionStrings);
+ InsertExtensionString("EGL_ANDROID_recordable", recordable, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_power_preference", powerPreference, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_image_d3d11_texture", imageD3D11Texture, &extensionStrings);
+ InsertExtensionString("EGL_ANDROID_create_native_client_buffer", createNativeClientBufferANDROID, &extensionStrings);
+ InsertExtensionString("EGL_ANDROID_get_native_client_buffer", getNativeClientBufferANDROID, &extensionStrings);
+ InsertExtensionString("EGL_ANDROID_native_fence_sync", nativeFenceSyncANDROID, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_create_context_backwards_compatible", createContextBackwardsCompatible, &extensionStrings);
+ InsertExtensionString("EGL_KHR_no_config_context", noConfigContext, &extensionStrings);
+ InsertExtensionString("EGL_IMG_context_priority", contextPriority, &extensionStrings);
+ InsertExtensionString("EGL_KHR_create_context_no_error", createContextNoError, &extensionStrings);
+ InsertExtensionString("EGL_EXT_image_dma_buf_import", imageDmaBufImportEXT, &extensionStrings);
+ InsertExtensionString("EGL_EXT_image_dma_buf_import_modifiers", imageDmaBufImportModifiersEXT, &extensionStrings);
+ InsertExtensionString("EGL_NOK_texture_from_pixmap", textureFromPixmapNOK, &extensionStrings);
+ InsertExtensionString("EGL_NV_robustness_video_memory_purge", robustnessVideoMemoryPurgeNV, &extensionStrings);
+ InsertExtensionString("EGL_KHR_reusable_sync", reusableSyncKHR, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_external_context_and_surface", externalContextAndSurface, &extensionStrings);
+ InsertExtensionString("EGL_EXT_buffer_age", bufferAgeEXT, &extensionStrings);
+ InsertExtensionString("EGL_KHR_mutable_render_buffer", mutableRenderBufferKHR, &extensionStrings);
+ InsertExtensionString("EGL_EXT_protected_content", protectedContentEXT, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_create_surface_swap_interval", createSurfaceSwapIntervalANGLE, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_context_virtualization", contextVirtualizationANGLE, &extensionStrings);
+ InsertExtensionString("EGL_KHR_lock_surface3", lockSurface3KHR, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_vulkan_image", vulkanImageANGLE, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_metal_create_context_ownership_identity", metalCreateContextOwnershipIdentityANGLE, &extensionStrings);
+ InsertExtensionString("EGL_KHR_partial_update", partialUpdateKHR, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_metal_shared_event_sync", mtlSyncSharedEventANGLE, &extensionStrings);
+ // clang-format on
+
+ return extensionStrings;
+}
+
+DeviceExtensions::DeviceExtensions() = default;
+
+std::vector<std::string> DeviceExtensions::getStrings() const
+{
+ std::vector<std::string> extensionStrings;
+
+ // clang-format off
+ // | Extension name | Supported flag | Output vector |
+ InsertExtensionString("EGL_ANGLE_device_d3d", deviceD3D, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_device_cgl", deviceCGL, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_device_eagl", deviceEAGL, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_device_metal", deviceMetal, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_device_vulkan", deviceVulkan, &extensionStrings);
+
+ // clang-format on
+
+ return extensionStrings;
+}
+
+ClientExtensions::ClientExtensions() = default;
+ClientExtensions::ClientExtensions(const ClientExtensions &other) = default;
+
+std::vector<std::string> ClientExtensions::getStrings() const
+{
+ std::vector<std::string> extensionStrings;
+
+ // clang-format off
+ // | Extension name | Supported flag | Output vector |
+ InsertExtensionString("EGL_EXT_client_extensions", clientExtensions, &extensionStrings);
+ InsertExtensionString("EGL_EXT_device_query", deviceQueryEXT, &extensionStrings);
+ InsertExtensionString("EGL_EXT_platform_base", platformBase, &extensionStrings);
+ InsertExtensionString("EGL_EXT_platform_device", platformDevice, &extensionStrings);
+ InsertExtensionString("EGL_KHR_platform_gbm", platformGbmKHR, &extensionStrings);
+ InsertExtensionString("EGL_EXT_platform_wayland", platformWaylandEXT, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_d3d11on12", platformANGLED3D11ON12, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_device_type_egl_angle", platformANGLEDeviceTypeEGLANGLE, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_device_type_swiftshader", platformANGLEDeviceTypeSwiftShader, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_null", platformANGLENULL, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_vulkan", platformANGLEVulkan, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_metal", platformANGLEMetal, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_device_context_volatile_eagl", platformANGLEDeviceContextVolatileEagl, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_device_context_volatile_cgl", platformANGLEDeviceContextVolatileCgl, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_device_id", platformANGLEDeviceId, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_device_creation", deviceCreation, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_device_creation_d3d11", deviceCreationD3D11, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_x11_visual", x11Visual, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_experimental_present_path", experimentalPresentPath, &extensionStrings);
+ InsertExtensionString("EGL_KHR_client_get_all_proc_addresses", clientGetAllProcAddresses, &extensionStrings);
+ InsertExtensionString("EGL_KHR_debug", debug, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_feature_control", featureControlANGLE, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_display_power_preference", displayPowerPreferenceANGLE, &extensionStrings);
+ // clang-format on
+
+ return extensionStrings;
+}
+
+} // namespace egl
diff --git a/gfx/angle/checkout/src/libANGLE/Caps.h b/gfx/angle/checkout/src/libANGLE/Caps.h
new file mode 100644
index 0000000000..03b4ef8c9a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Caps.h
@@ -0,0 +1,786 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef LIBANGLE_CAPS_H_
+#define LIBANGLE_CAPS_H_
+
+#include "angle_gl.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/gles_extensions_autogen.h"
+#include "libANGLE/renderer/Format.h"
+
+#include <array>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+namespace gl
+{
+struct TextureCaps
+{
+ TextureCaps();
+ TextureCaps(const TextureCaps &other);
+ TextureCaps &operator=(const TextureCaps &other);
+
+ ~TextureCaps();
+
+ // Supports for basic texturing: glTexImage, glTexSubImage, etc
+ bool texturable = false;
+
+ // Support for linear or anisotropic filtering
+ bool filterable = false;
+
+ // Support for being used as a framebuffer attachment, i.e. glFramebufferTexture2D
+ bool textureAttachment = false;
+
+ // Support for being used as a renderbuffer format, i.e. glFramebufferRenderbuffer
+ bool renderbuffer = false;
+
+ // Support for blend modes while being used as a framebuffer attachment
+ bool blendable = false;
+
+ // Set of supported sample counts, only guaranteed to be valid in ES3.
+ SupportedSampleSet sampleCounts;
+
+ // Get the maximum number of samples supported
+ GLuint getMaxSamples() const;
+
+ // Get the number of supported samples that is at least as many as requested. Returns 0 if
+ // there are no sample counts available
+ GLuint getNearestSamples(GLuint requestedSamples) const;
+};
+
+TextureCaps GenerateMinimumTextureCaps(GLenum internalFormat,
+ const Version &clientVersion,
+ const Extensions &extensions);
+
+class TextureCapsMap final : angle::NonCopyable
+{
+ public:
+ TextureCapsMap();
+ ~TextureCapsMap();
+
+ // These methods are deprecated. Please use angle::Format for new features.
+ void insert(GLenum internalFormat, const TextureCaps &caps);
+ const TextureCaps &get(GLenum internalFormat) const;
+
+ void clear();
+
+ // Prefer using angle::Format methods.
+ const TextureCaps &get(angle::FormatID formatID) const;
+ void set(angle::FormatID formatID, const TextureCaps &caps);
+
+ private:
+ TextureCaps &get(angle::FormatID formatID);
+
+ // Indexed by angle::FormatID
+ angle::FormatMap<TextureCaps> mFormatData;
+};
+
+void InitMinimumTextureCapsMap(const Version &clientVersion,
+ const Extensions &extensions,
+ TextureCapsMap *capsMap);
+
+// Returns true if all the formats required to support GL_ANGLE_compressed_texture_etc are
+// present. Does not determine if they are natively supported without decompression.
+bool DetermineCompressedTextureETCSupport(const TextureCapsMap &textureCaps);
+
+// Pointer to a boolean member of the Extensions struct
+using ExtensionBool = bool Extensions::*;
+
+struct ExtensionInfo
+{
+ // If this extension can be enabled or disabled with glRequestExtension
+ // (GL_ANGLE_request_extension)
+ bool Requestable = false;
+ bool Disablable = false;
+
+ // Pointer to a boolean member of the Extensions struct
+ ExtensionBool ExtensionsMember = nullptr;
+};
+
+using ExtensionInfoMap = std::map<std::string, ExtensionInfo>;
+const ExtensionInfoMap &GetExtensionInfoMap();
+
+struct Limitations
+{
+ Limitations();
+ Limitations(const Limitations &other);
+
+ Limitations &operator=(const Limitations &other);
+
+ // Renderer doesn't support gl_FrontFacing in fragment shaders
+ bool noFrontFacingSupport = false;
+
+ // Renderer doesn't support GL_SAMPLE_ALPHA_TO_COVERAGE
+ bool noSampleAlphaToCoverageSupport = false;
+
+ // In glVertexAttribDivisorANGLE, attribute zero must have a zero divisor
+ bool attributeZeroRequiresZeroDivisorInEXT = false;
+
+ // Unable to support different values for front and back faces for stencil refs and masks
+ bool noSeparateStencilRefsAndMasks = false;
+
+ // Renderer doesn't support non-constant indexing loops in fragment shader
+ bool shadersRequireIndexedLoopValidation = false;
+
+ // Renderer doesn't support Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA
+ // and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR blend functions.
+ bool noSimultaneousConstantColorAndAlphaBlendFunc = false;
+
+ // Renderer always clamps constant blend color.
+ bool noUnclampedBlendColor = false;
+
+ // D3D9 does not support flexible varying register packing.
+ bool noFlexibleVaryingPacking = false;
+
+ // D3D does not support having multiple transform feedback outputs go to the same buffer.
+ bool noDoubleBoundTransformFeedbackBuffers = false;
+
+ // D3D does not support vertex attribute aliasing
+ bool noVertexAttributeAliasing = false;
+
+ // Renderer doesn't support GL_TEXTURE_COMPARE_MODE=GL_NONE on a shadow sampler.
+ // TODO(http://anglebug.com/5231): add validation code to front-end.
+ bool noShadowSamplerCompareModeNone = false;
+
+ // PVRTC1 textures must be squares.
+ bool squarePvrtc1 = false;
+
+ // ETC1 texture support is emulated.
+ bool emulatedEtc1 = false;
+
+ // ASTC texture support is emulated.
+ bool emulatedAstc = false;
+
+ // No compressed TEXTURE_3D support.
+ bool noCompressedTexture3D = false;
+
+ // D3D does not support compressed textures where the base mip level is not a multiple of 4
+ bool compressedBaseMipLevelMultipleOfFour = false;
+
+ bool limitWebglMaxTextureSizeTo4096 = false;
+};
+
+struct TypePrecision
+{
+ TypePrecision();
+ TypePrecision(const TypePrecision &other);
+
+ TypePrecision &operator=(const TypePrecision &other);
+
+ void setIEEEFloat();
+ void setIEEEHalfFloat();
+ void setTwosComplementInt(unsigned int bits);
+ void setSimulatedFloat(unsigned int range, unsigned int precision);
+ void setSimulatedInt(unsigned int range);
+
+ void get(GLint *returnRange, GLint *returnPrecision) const;
+
+ std::array<GLint, 2> range = {0, 0};
+ GLint precision = 0;
+};
+
+struct Caps
+{
+ Caps();
+ Caps(const Caps &other);
+ Caps &operator=(const Caps &other);
+
+ ~Caps();
+
+ // If the values could be got by using GetIntegeri_v, they should
+ // be GLint instead of GLuint and call LimitToInt() to ensure
+ // they will not overflow.
+
+ GLfloat minInterpolationOffset = 0;
+ GLfloat maxInterpolationOffset = 0;
+ GLint subPixelInterpolationOffsetBits = 0;
+
+ // ES 3.1 (April 29, 2015) 20.39: implementation dependent values
+ GLint64 maxElementIndex = 0;
+ GLint max3DTextureSize = 0;
+ GLint max2DTextureSize = 0;
+ GLint maxRectangleTextureSize = 0;
+ GLint maxArrayTextureLayers = 0;
+ GLfloat maxLODBias = 0.0f;
+ GLint maxCubeMapTextureSize = 0;
+ GLint maxRenderbufferSize = 0;
+ GLfloat minAliasedPointSize = 1.0f;
+ GLfloat maxAliasedPointSize = 1.0f;
+ GLfloat minAliasedLineWidth = 0.0f;
+ GLfloat maxAliasedLineWidth = 0.0f;
+
+ // ES 3.1 (April 29, 2015) 20.40: implementation dependent values (cont.)
+ GLint maxDrawBuffers = 0;
+ GLint maxFramebufferWidth = 0;
+ GLint maxFramebufferHeight = 0;
+ GLint maxFramebufferSamples = 0;
+ GLint maxColorAttachments = 0;
+ GLint maxViewportWidth = 0;
+ GLint maxViewportHeight = 0;
+ GLint maxSampleMaskWords = 0;
+ GLint maxColorTextureSamples = 0;
+ GLint maxDepthTextureSamples = 0;
+ GLint maxIntegerSamples = 0;
+ GLint64 maxServerWaitTimeout = 0;
+
+ // ES 3.1 (April 29, 2015) Table 20.41: Implementation dependent values (cont.)
+ GLint maxVertexAttribRelativeOffset = 0;
+ GLint maxVertexAttribBindings = 0;
+ GLint maxVertexAttribStride = 0;
+ GLint maxElementsIndices = 0;
+ GLint maxElementsVertices = 0;
+ std::vector<GLenum> compressedTextureFormats;
+ std::vector<GLenum> programBinaryFormats;
+ std::vector<GLenum> shaderBinaryFormats;
+ TypePrecision vertexHighpFloat;
+ TypePrecision vertexMediumpFloat;
+ TypePrecision vertexLowpFloat;
+ TypePrecision vertexHighpInt;
+ TypePrecision vertexMediumpInt;
+ TypePrecision vertexLowpInt;
+ TypePrecision fragmentHighpFloat;
+ TypePrecision fragmentMediumpFloat;
+ TypePrecision fragmentLowpFloat;
+ TypePrecision fragmentHighpInt;
+ TypePrecision fragmentMediumpInt;
+ TypePrecision fragmentLowpInt;
+
+ // Implementation dependent limits required on all shader types.
+ // TODO(jiawei.shao@intel.com): organize all such limits into ShaderMap.
+ // ES 3.1 (April 29, 2015) Table 20.43: Implementation dependent Vertex shader limits
+ // ES 3.1 (April 29, 2015) Table 20.44: Implementation dependent Fragment shader limits
+ // ES 3.1 (April 29, 2015) Table 20.45: implementation dependent compute shader limits
+ // GL_EXT_geometry_shader (May 31, 2016) Table 20.43gs: Implementation dependent geometry shader
+ // limits
+ // GL_EXT_geometry_shader (May 31, 2016) Table 20.46: Implementation dependent aggregate shader
+ // limits
+ ShaderMap<GLint> maxShaderUniformBlocks = {};
+ ShaderMap<GLint> maxShaderTextureImageUnits = {};
+ ShaderMap<GLint> maxShaderStorageBlocks = {};
+ ShaderMap<GLint> maxShaderUniformComponents = {};
+ ShaderMap<GLint> maxShaderAtomicCounterBuffers = {};
+ ShaderMap<GLint> maxShaderAtomicCounters = {};
+ ShaderMap<GLint> maxShaderImageUniforms = {};
+ // Note that we can query MAX_COMPUTE_UNIFORM_COMPONENTS and MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT
+ // by GetIntegerv, but we can only use GetInteger64v on MAX_VERTEX_UNIFORM_COMPONENTS and
+ // MAX_FRAGMENT_UNIFORM_COMPONENTS. Currently we use GLuint64 to store all these values so that
+ // we can put them together into one ShaderMap.
+ ShaderMap<GLint64> maxCombinedShaderUniformComponents = {};
+
+ // ES 3.1 (April 29, 2015) Table 20.43: Implementation dependent Vertex shader limits
+ GLint maxVertexAttributes = 0;
+ GLint maxVertexUniformVectors = 0;
+ GLint maxVertexOutputComponents = 0;
+
+ // ES 3.1 (April 29, 2015) Table 20.44: Implementation dependent Fragment shader limits
+ GLint maxFragmentUniformVectors = 0;
+ GLint maxFragmentInputComponents = 0;
+ GLint minProgramTextureGatherOffset = 0;
+ GLint maxProgramTextureGatherOffset = 0;
+ GLint minProgramTexelOffset = 0;
+ GLint maxProgramTexelOffset = 0;
+
+ // ES 3.1 (April 29, 2015) Table 20.45: implementation dependent compute shader limits
+ std::array<GLint, 3> maxComputeWorkGroupCount = {0, 0, 0};
+ std::array<GLint, 3> maxComputeWorkGroupSize = {0, 0, 0};
+ GLint maxComputeWorkGroupInvocations = 0;
+ GLint maxComputeSharedMemorySize = 0;
+
+ // ES 3.1 (April 29, 2015) Table 20.46: implementation dependent aggregate shader limits
+ GLint maxUniformBufferBindings = 0;
+ GLint64 maxUniformBlockSize = 0;
+ GLint uniformBufferOffsetAlignment = 0;
+ GLint maxCombinedUniformBlocks = 0;
+ GLint maxVaryingComponents = 0;
+ GLint maxVaryingVectors = 0;
+ GLint maxCombinedTextureImageUnits = 0;
+ GLint maxCombinedShaderOutputResources = 0;
+
+ // ES 3.1 (April 29, 2015) Table 20.47: implementation dependent aggregate shader limits (cont.)
+ GLint maxUniformLocations = 0;
+ GLint maxAtomicCounterBufferBindings = 0;
+ GLint maxAtomicCounterBufferSize = 0;
+ GLint maxCombinedAtomicCounterBuffers = 0;
+ GLint maxCombinedAtomicCounters = 0;
+ GLint maxImageUnits = 0;
+ GLint maxCombinedImageUniforms = 0;
+ GLint maxShaderStorageBufferBindings = 0;
+ GLint64 maxShaderStorageBlockSize = 0;
+ GLint maxCombinedShaderStorageBlocks = 0;
+ GLint shaderStorageBufferOffsetAlignment = 0;
+
+ // ES 3.1 (April 29, 2015) Table 20.48: implementation dependent transform feedback limits
+ GLint maxTransformFeedbackInterleavedComponents = 0;
+ GLint maxTransformFeedbackSeparateAttributes = 0;
+ GLint maxTransformFeedbackSeparateComponents = 0;
+
+ // ES 3.1 (April 29, 2015) Table 20.49: Framebuffer Dependent Values
+ GLint maxSamples = 0;
+
+ // GL_EXT_geometry_shader (May 31, 2016) Table 20.40: Implementation-Dependent Values (cont.)
+ GLint maxFramebufferLayers = 0;
+ GLint layerProvokingVertex = 0;
+
+ // GL_EXT_geometry_shader (May 31, 2016) Table 20.43gs: Implementation dependent geometry shader
+ // limits
+ GLint maxGeometryInputComponents = 0;
+ GLint maxGeometryOutputComponents = 0;
+ GLint maxGeometryOutputVertices = 0;
+ GLint maxGeometryTotalOutputComponents = 0;
+ GLint maxGeometryShaderInvocations = 0;
+
+ // GL_EXT_tessellation_shader
+ GLint maxTessControlInputComponents = 0;
+ GLint maxTessControlOutputComponents = 0;
+ GLint maxTessControlTotalOutputComponents = 0;
+
+ GLint maxTessPatchComponents = 0;
+ GLint maxPatchVertices = 0;
+ GLint maxTessGenLevel = 0;
+
+ GLint maxTessEvaluationInputComponents = 0;
+ GLint maxTessEvaluationOutputComponents = 0;
+
+ GLuint subPixelBits = 4;
+
+ // GL_EXT_blend_func_extended
+ GLuint maxDualSourceDrawBuffers = 0;
+
+ // GL_EXT_texture_filter_anisotropic
+ GLfloat maxTextureAnisotropy = 0.0f;
+
+ // GL_EXT_disjoint_timer_query
+ GLuint queryCounterBitsTimeElapsed = 0;
+ GLuint queryCounterBitsTimestamp = 0;
+
+ // OVR_multiview
+ GLuint maxViews = 1;
+
+ // GL_KHR_debug
+ GLuint maxDebugMessageLength = 0;
+ GLuint maxDebugLoggedMessages = 0;
+ GLuint maxDebugGroupStackDepth = 0;
+ GLuint maxLabelLength = 0;
+
+ // GL_APPLE_clip_distance/GL_EXT_clip_cull_distance
+ GLuint maxClipDistances = 0;
+ GLuint maxCullDistances = 0;
+ GLuint maxCombinedClipAndCullDistances = 0;
+
+ // GL_ANGLE_shader_pixel_local_storage
+ GLuint maxPixelLocalStoragePlanes = 0;
+ GLuint maxColorAttachmentsWithActivePixelLocalStorage = 0;
+ GLuint maxCombinedDrawBuffersAndPixelLocalStoragePlanes = 0;
+
+ // GLES1 emulation: Caps for ES 1.1. Taken from Table 6.20 / 6.22 in the OpenGL ES 1.1 spec.
+ GLuint maxMultitextureUnits = 0;
+ GLuint maxClipPlanes = 0;
+ GLuint maxLights = 0;
+ static constexpr int GlobalMatrixStackDepth = 16;
+ GLuint maxModelviewMatrixStackDepth = 0;
+ GLuint maxProjectionMatrixStackDepth = 0;
+ GLuint maxTextureMatrixStackDepth = 0;
+ GLfloat minSmoothPointSize = 0.0f;
+ GLfloat maxSmoothPointSize = 0.0f;
+ GLfloat minSmoothLineWidth = 0.0f;
+ GLfloat maxSmoothLineWidth = 0.0f;
+
+ // ES 3.2 Table 20.41: Implementation Dependent Values (cont.)
+ GLint maxTextureBufferSize = 0;
+ GLint textureBufferOffsetAlignment = 0;
+};
+
+Caps GenerateMinimumCaps(const Version &clientVersion, const Extensions &extensions);
+} // namespace gl
+
+namespace egl
+{
+
+struct Caps
+{
+ Caps();
+
+ // Support for NPOT surfaces
+ bool textureNPOT;
+
+ // Support for Stencil8 configs
+ bool stencil8;
+};
+
+struct DisplayExtensions
+{
+ DisplayExtensions();
+
+ // Generate a vector of supported extension strings
+ std::vector<std::string> getStrings() const;
+
+ // EGL_EXT_create_context_robustness
+ bool createContextRobustness = false;
+
+ // EGL_ANGLE_d3d_share_handle_client_buffer
+ bool d3dShareHandleClientBuffer = false;
+
+ // EGL_ANGLE_d3d_texture_client_buffer
+ bool d3dTextureClientBuffer = false;
+
+ // EGL_ANGLE_surface_d3d_texture_2d_share_handle
+ bool surfaceD3DTexture2DShareHandle = false;
+
+ // EGL_ANGLE_query_surface_pointer
+ bool querySurfacePointer = false;
+
+ // EGL_ANGLE_window_fixed_size
+ bool windowFixedSize = false;
+
+ // EGL_ANGLE_keyed_mutex
+ bool keyedMutex = false;
+
+ // EGL_ANGLE_surface_orientation
+ bool surfaceOrientation = false;
+
+ // EGL_NV_post_sub_buffer
+ bool postSubBuffer = false;
+
+ // EGL_KHR_create_context
+ bool createContext = false;
+
+ // EGL_KHR_image
+ bool image = false;
+
+ // EGL_KHR_image_base
+ bool imageBase = false;
+
+ // EGL_KHR_image_pixmap
+ bool imagePixmap = false;
+
+ // EGL_KHR_gl_texture_2D_image
+ bool glTexture2DImage = false;
+
+ // EGL_KHR_gl_texture_cubemap_image
+ bool glTextureCubemapImage = false;
+
+ // EGL_KHR_gl_texture_3D_image
+ bool glTexture3DImage = false;
+
+ // EGL_KHR_gl_renderbuffer_image
+ bool glRenderbufferImage = false;
+
+ // EGL_KHR_get_all_proc_addresses
+ bool getAllProcAddresses = false;
+
+ // EGL_ANGLE_direct_composition
+ bool directComposition = false;
+
+ // EGL_ANGLE_windows_ui_composition
+ bool windowsUIComposition = false;
+
+ // KHR_create_context_no_error
+ bool createContextNoError = false;
+
+ // EGL_KHR_stream
+ bool stream = false;
+
+ // EGL_KHR_stream_consumer_gltexture
+ bool streamConsumerGLTexture = false;
+
+ // EGL_NV_stream_consumer_gltexture_yuv
+ bool streamConsumerGLTextureYUV = false;
+
+ // EGL_ANGLE_stream_producer_d3d_texture
+ bool streamProducerD3DTexture = false;
+
+ // EGL_KHR_fence_sync
+ bool fenceSync = false;
+
+ // EGL_KHR_wait_sync
+ bool waitSync = false;
+
+ // EGL_ANGLE_create_context_webgl_compatibility
+ bool createContextWebGLCompatibility = false;
+
+ // EGL_CHROMIUM_create_context_bind_generates_resource
+ bool createContextBindGeneratesResource = false;
+
+ // EGL_CHROMIUM_sync_control
+ bool syncControlCHROMIUM = false;
+
+ // EGL_ANGLE_sync_control_rate
+ bool syncControlRateANGLE = false;
+
+ // EGL_KHR_swap_buffers_with_damage
+ bool swapBuffersWithDamage = false;
+
+ // EGL_EXT_pixel_format_float
+ bool pixelFormatFloat = false;
+
+ // EGL_KHR_surfaceless_context
+ bool surfacelessContext = false;
+
+ // EGL_ANGLE_display_texture_share_group
+ bool displayTextureShareGroup = false;
+
+ // EGL_ANGLE_display_semaphore_share_group
+ bool displaySemaphoreShareGroup = false;
+
+ // EGL_ANGLE_create_context_client_arrays
+ bool createContextClientArrays = false;
+
+ // EGL_ANGLE_program_cache_control
+ bool programCacheControlANGLE = false;
+
+ // EGL_ANGLE_robust_resource_initialization
+ bool robustResourceInitializationANGLE = false;
+
+ // EGL_ANGLE_iosurface_client_buffer
+ bool iosurfaceClientBuffer = false;
+
+ // EGL_ANGLE_metal_texture_client_buffer
+ bool mtlTextureClientBuffer = false;
+
+ // EGL_ANGLE_create_context_extensions_enabled
+ bool createContextExtensionsEnabled = false;
+
+ // EGL_ANDROID_presentation_time
+ bool presentationTime = false;
+
+ // EGL_ANDROID_blob_cache
+ bool blobCache = false;
+
+ // EGL_ANDROID_image_native_buffer
+ bool imageNativeBuffer = false;
+
+ // EGL_ANDROID_get_frame_timestamps
+ bool getFrameTimestamps = false;
+
+ // EGL_ANGLE_timestamp_surface_attribute
+ bool timestampSurfaceAttributeANGLE = false;
+
+ // EGL_ANDROID_recordable
+ bool recordable = false;
+
+ // EGL_ANGLE_power_preference
+ bool powerPreference = false;
+
+ // EGL_ANGLE_image_d3d11_texture
+ bool imageD3D11Texture = false;
+
+ // EGL_ANDROID_get_native_client_buffer
+ bool getNativeClientBufferANDROID = false;
+
+ // EGL_ANDROID_create_native_client_buffer
+ bool createNativeClientBufferANDROID = false;
+
+ // EGL_ANDROID_native_fence_sync
+ bool nativeFenceSyncANDROID = false;
+
+ // EGL_ANGLE_create_context_backwards_compatible
+ bool createContextBackwardsCompatible = false;
+
+ // EGL_KHR_no_config_context
+ bool noConfigContext = false;
+
+ // EGL_IMG_context_priority
+ bool contextPriority = false;
+
+ // EGL_ANGLE_ggp_stream_descriptor
+ bool ggpStreamDescriptor = false;
+
+ // EGL_ANGLE_swap_with_frame_token
+ bool swapWithFrameToken = false;
+
+ // EGL_KHR_gl_colorspace
+ bool glColorspace = false;
+
+ // EGL_EXT_gl_colorspace_display_p3_linear
+ bool glColorspaceDisplayP3Linear = false;
+
+ // EGL_EXT_gl_colorspace_display_p3
+ bool glColorspaceDisplayP3 = false;
+
+ // EGL_EXT_gl_colorspace_scrgb
+ bool glColorspaceScrgb = false;
+
+ // EGL_EXT_gl_colorspace_scrgb_linear
+ bool glColorspaceScrgbLinear = false;
+
+ // EGL_EXT_gl_colorspace_display_p3_passthrough
+ bool glColorspaceDisplayP3Passthrough = false;
+
+ // EGL_ANGLE_colorspace_attribute_passthrough
+ bool eglColorspaceAttributePassthroughANGLE = false;
+
+ // EGL_ANDROID_framebuffer_target
+ bool framebufferTargetANDROID = false;
+
+ // EGL_EXT_image_gl_colorspace
+ bool imageGlColorspace = false;
+
+ // EGL_EXT_image_dma_buf_import
+ bool imageDmaBufImportEXT = false;
+
+ // EGL_EXT_image_dma_buf_import_modifiers
+ bool imageDmaBufImportModifiersEXT = false;
+
+ // EGL_NOK_texture_from_pixmap
+ bool textureFromPixmapNOK = false;
+
+ // EGL_NV_robustness_video_memory_purge
+ bool robustnessVideoMemoryPurgeNV = false;
+
+ // EGL_KHR_reusable_sync
+ bool reusableSyncKHR = false;
+
+ // EGL_ANGLE_external_context_and_surface
+ bool externalContextAndSurface = false;
+
+ // EGL_EXT_buffer_age
+ bool bufferAgeEXT = false;
+
+ // EGL_KHR_mutable_render_buffer
+ bool mutableRenderBufferKHR = false;
+
+ // EGL_EXT_protected_content
+ bool protectedContentEXT = false;
+
+ // EGL_ANGLE_create_surface_swap_interval
+ bool createSurfaceSwapIntervalANGLE = false;
+
+ // EGL_ANGLE_context_virtualization
+ bool contextVirtualizationANGLE = false;
+
+ // EGL_KHR_lock_surface3
+ bool lockSurface3KHR = false;
+
+ // EGL_ANGLE_vulkan_image
+ bool vulkanImageANGLE = false;
+
+ // EGL_ANGLE_metal_create_context_ownership_identity
+ bool metalCreateContextOwnershipIdentityANGLE = false;
+
+ // EGL_KHR_partial_update
+ bool partialUpdateKHR = false;
+
+ // EGL_ANGLE_sync_mtl_shared_event
+ bool mtlSyncSharedEventANGLE = false;
+};
+
+struct DeviceExtensions
+{
+ DeviceExtensions();
+
+ // Generate a vector of supported extension strings
+ std::vector<std::string> getStrings() const;
+
+ // EGL_ANGLE_device_d3d
+ bool deviceD3D = false;
+
+ // EGL_ANGLE_device_cgl
+ bool deviceCGL = false;
+
+ // EGL_ANGLE_device_eagl
+ bool deviceEAGL = false;
+
+ // EGL_ANGLE_device_metal
+ bool deviceMetal = false;
+
+ // EGL_ANGLE_device_vulkan
+ bool deviceVulkan = false;
+};
+
+struct ClientExtensions
+{
+ ClientExtensions();
+ ClientExtensions(const ClientExtensions &other);
+
+ // Generate a vector of supported extension strings
+ std::vector<std::string> getStrings() const;
+
+ // EGL_EXT_client_extensions
+ bool clientExtensions = false;
+
+ // EGL_EXT_platform_base
+ bool platformBase = false;
+
+ // EGL_EXT_platform_device
+ bool platformDevice = false;
+
+ // EGL_KHR_platform_gbm
+ bool platformGbmKHR = false;
+
+ // EGL_EXT_platform_wayland
+ bool platformWaylandEXT = false;
+
+ // EGL_ANGLE_platform_angle
+ bool platformANGLE = false;
+
+ // EGL_ANGLE_platform_angle_d3d
+ bool platformANGLED3D = false;
+
+ // EGL_ANGLE_platform_angle_d3d11on12
+ bool platformANGLED3D11ON12 = false;
+
+ // EGL_ANGLE_platform_angle_opengl
+ bool platformANGLEOpenGL = false;
+
+ // EGL_ANGLE_platform_angle_null
+ bool platformANGLENULL = false;
+
+ // EGL_ANGLE_platform_angle_vulkan
+ bool platformANGLEVulkan = false;
+
+ // EGL_ANGLE_platform_angle_metal
+ bool platformANGLEMetal = false;
+
+ // EGL_ANGLE_platform_angle_device_context_volatile_eagl
+ bool platformANGLEDeviceContextVolatileEagl = false;
+
+ // EGL_ANGLE_platform_angle_device_context_volatile_cgl
+ bool platformANGLEDeviceContextVolatileCgl = false;
+
+ // EGL_ANGLE_platform_angle_device_id
+ bool platformANGLEDeviceId = false;
+
+ // EGL_ANGLE_device_creation
+ bool deviceCreation = false;
+
+ // EGL_ANGLE_device_creation_d3d11
+ bool deviceCreationD3D11 = false;
+
+ // EGL_ANGLE_x11_visual
+ bool x11Visual = false;
+
+ // EGL_ANGLE_experimental_present_path
+ bool experimentalPresentPath = false;
+
+ // EGL_KHR_client_get_all_proc_addresses
+ bool clientGetAllProcAddresses = false;
+
+ // EGL_KHR_debug
+ bool debug = false;
+
+ // EGL_ANGLE_feature_control
+ bool featureControlANGLE = false;
+
+ // EGL_ANGLE_platform_angle_device_type_swiftshader
+ bool platformANGLEDeviceTypeSwiftShader = false;
+
+ // EGL_ANGLE_platform_angle_device_type_egl_angle
+ bool platformANGLEDeviceTypeEGLANGLE = false;
+
+ // EGL_EXT_device_query
+ bool deviceQueryEXT = false;
+
+ // EGL_ANGLE_display_power_preference
+ bool displayPowerPreferenceANGLE = false;
+};
+
+} // namespace egl
+
+#endif // LIBANGLE_CAPS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Compiler.cpp b/gfx/angle/checkout/src/libANGLE/Compiler.cpp
new file mode 100644
index 0000000000..a838f27ed6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Compiler.cpp
@@ -0,0 +1,422 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Compiler.cpp: implements the gl::Compiler class.
+
+#include "libANGLE/Compiler.h"
+
+#include "common/debug.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/State.h"
+#include "libANGLE/renderer/CompilerImpl.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+
+namespace gl
+{
+
+namespace
+{
+
+// To know when to call sh::Initialize and sh::Finalize.
+size_t gActiveCompilers = 0;
+
+} // anonymous namespace
+
+Compiler::Compiler(rx::GLImplFactory *implFactory, const State &state, egl::Display *display)
+ : mImplementation(implFactory->createCompiler()),
+ mSpec(SelectShaderSpec(state)),
+ mOutputType(mImplementation->getTranslatorOutputType()),
+ mResources()
+{
+ // TODO(http://anglebug.com/3819): Update for GL version specific validation
+ ASSERT(state.getClientMajorVersion() == 1 || state.getClientMajorVersion() == 2 ||
+ state.getClientMajorVersion() == 3 || state.getClientMajorVersion() == 4);
+
+ {
+ std::lock_guard<std::mutex> lock(display->getDisplayGlobalMutex());
+ if (gActiveCompilers == 0)
+ {
+ sh::Initialize();
+ }
+ ++gActiveCompilers;
+ }
+
+ const Caps &caps = state.getCaps();
+ const Extensions &extensions = state.getExtensions();
+
+ sh::InitBuiltInResources(&mResources);
+ mResources.MaxVertexAttribs = caps.maxVertexAttributes;
+ mResources.MaxVertexUniformVectors = caps.maxVertexUniformVectors;
+ mResources.MaxVaryingVectors = caps.maxVaryingVectors;
+ mResources.MaxVertexTextureImageUnits = caps.maxShaderTextureImageUnits[ShaderType::Vertex];
+ mResources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
+ mResources.MaxTextureImageUnits = caps.maxShaderTextureImageUnits[ShaderType::Fragment];
+ mResources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors;
+ mResources.MaxDrawBuffers = caps.maxDrawBuffers;
+ mResources.OES_standard_derivatives = extensions.standardDerivativesOES;
+ mResources.EXT_draw_buffers = extensions.drawBuffersEXT;
+ mResources.EXT_shader_texture_lod = extensions.shaderTextureLodEXT;
+ mResources.EXT_shader_non_constant_global_initializers =
+ extensions.shaderNonConstantGlobalInitializersEXT;
+ mResources.OES_EGL_image_external = extensions.EGLImageExternalOES;
+ mResources.OES_EGL_image_external_essl3 = extensions.EGLImageExternalEssl3OES;
+ mResources.NV_EGL_stream_consumer_external = extensions.EGLStreamConsumerExternalNV;
+ mResources.NV_shader_noperspective_interpolation =
+ extensions.shaderNoperspectiveInterpolationNV;
+ mResources.ARB_texture_rectangle = extensions.textureRectangleANGLE;
+ mResources.EXT_gpu_shader5 = extensions.gpuShader5EXT;
+ mResources.OES_shader_io_blocks = extensions.shaderIoBlocksOES;
+ mResources.EXT_shader_io_blocks = extensions.shaderIoBlocksEXT;
+ mResources.OES_texture_storage_multisample_2d_array =
+ extensions.textureStorageMultisample2dArrayOES;
+ mResources.OES_texture_3D = extensions.texture3DOES;
+ mResources.ANGLE_base_vertex_base_instance_shader_builtin =
+ extensions.baseVertexBaseInstanceShaderBuiltinANGLE;
+ mResources.ANGLE_multi_draw = extensions.multiDrawANGLE;
+ mResources.ANGLE_shader_pixel_local_storage = extensions.shaderPixelLocalStorageANGLE;
+ mResources.ANGLE_texture_multisample = extensions.textureMultisampleANGLE;
+ mResources.APPLE_clip_distance = extensions.clipDistanceAPPLE;
+ // OES_shader_multisample_interpolation
+ mResources.OES_shader_multisample_interpolation = extensions.shaderMultisampleInterpolationOES;
+ mResources.OES_shader_image_atomic = extensions.shaderImageAtomicOES;
+ // TODO: use shader precision caps to determine if high precision is supported?
+ mResources.FragmentPrecisionHigh = 1;
+ mResources.EXT_frag_depth = extensions.fragDepthEXT;
+
+ // OVR_multiview state
+ mResources.OVR_multiview = extensions.multiviewOVR;
+
+ // OVR_multiview2 state
+ mResources.OVR_multiview2 = extensions.multiview2OVR;
+ mResources.MaxViewsOVR = caps.maxViews;
+
+ // EXT_multisampled_render_to_texture and EXT_multisampled_render_to_texture2
+ mResources.EXT_multisampled_render_to_texture = extensions.multisampledRenderToTextureEXT;
+ mResources.EXT_multisampled_render_to_texture2 = extensions.multisampledRenderToTexture2EXT;
+
+ // WEBGL_video_texture
+ mResources.WEBGL_video_texture = extensions.videoTextureWEBGL;
+
+ // OES_texture_cube_map_array
+ mResources.OES_texture_cube_map_array = extensions.textureCubeMapArrayOES;
+ mResources.EXT_texture_cube_map_array = extensions.textureCubeMapArrayEXT;
+
+ // EXT_shadow_samplers
+ mResources.EXT_shadow_samplers = extensions.shadowSamplersEXT;
+
+ // OES_texture_buffer
+ mResources.OES_texture_buffer = extensions.textureBufferOES;
+ mResources.EXT_texture_buffer = extensions.textureBufferEXT;
+
+ // GL_EXT_YUV_target
+ mResources.EXT_YUV_target = extensions.YUVTargetEXT;
+
+ mResources.EXT_shader_framebuffer_fetch_non_coherent =
+ extensions.shaderFramebufferFetchNonCoherentEXT;
+
+ mResources.EXT_shader_framebuffer_fetch = extensions.shaderFramebufferFetchEXT;
+
+ // GL_EXT_clip_cull_distance
+ mResources.EXT_clip_cull_distance = extensions.clipCullDistanceEXT;
+
+ // GL_EXT_primitive_bounding_box
+ mResources.EXT_primitive_bounding_box = extensions.primitiveBoundingBoxEXT;
+
+ // GL_OES_primitive_bounding_box
+ mResources.OES_primitive_bounding_box = extensions.primitiveBoundingBoxOES;
+
+ // GLSL ES 3.0 constants
+ mResources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4;
+ mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4;
+ mResources.MinProgramTexelOffset = caps.minProgramTexelOffset;
+ mResources.MaxProgramTexelOffset = caps.maxProgramTexelOffset;
+
+ // EXT_blend_func_extended
+ mResources.EXT_blend_func_extended = extensions.blendFuncExtendedEXT;
+ mResources.MaxDualSourceDrawBuffers = caps.maxDualSourceDrawBuffers;
+
+ // APPLE_clip_distance/EXT_clip_cull_distance
+ mResources.MaxClipDistances = caps.maxClipDistances;
+ mResources.MaxCullDistances = caps.maxCullDistances;
+ mResources.MaxCombinedClipAndCullDistances = caps.maxCombinedClipAndCullDistances;
+
+ // ANGLE_shader_pixel_local_storage.
+ mResources.MaxPixelLocalStoragePlanes = caps.maxPixelLocalStoragePlanes;
+ mResources.MaxColorAttachmentsWithActivePixelLocalStorage =
+ caps.maxColorAttachmentsWithActivePixelLocalStorage;
+ mResources.MaxCombinedDrawBuffersAndPixelLocalStoragePlanes =
+ caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes;
+
+ // OES_sample_variables
+ mResources.OES_sample_variables = extensions.sampleVariablesOES;
+ mResources.MaxSamples = caps.maxSamples;
+
+ // ANDROID_extension_pack_es31a
+ mResources.ANDROID_extension_pack_es31a = extensions.extensionPackEs31aANDROID;
+
+ // KHR_blend_equation_advanced
+ mResources.KHR_blend_equation_advanced = extensions.blendEquationAdvancedKHR;
+
+ // GLSL ES 3.1 constants
+ mResources.MaxProgramTextureGatherOffset = caps.maxProgramTextureGatherOffset;
+ mResources.MinProgramTextureGatherOffset = caps.minProgramTextureGatherOffset;
+ mResources.MaxImageUnits = caps.maxImageUnits;
+ mResources.MaxVertexImageUniforms = caps.maxShaderImageUniforms[ShaderType::Vertex];
+ mResources.MaxFragmentImageUniforms = caps.maxShaderImageUniforms[ShaderType::Fragment];
+ mResources.MaxComputeImageUniforms = caps.maxShaderImageUniforms[ShaderType::Compute];
+ mResources.MaxCombinedImageUniforms = caps.maxCombinedImageUniforms;
+ mResources.MaxCombinedShaderOutputResources = caps.maxCombinedShaderOutputResources;
+ mResources.MaxUniformLocations = caps.maxUniformLocations;
+
+ for (size_t index = 0u; index < 3u; ++index)
+ {
+ mResources.MaxComputeWorkGroupCount[index] = caps.maxComputeWorkGroupCount[index];
+ mResources.MaxComputeWorkGroupSize[index] = caps.maxComputeWorkGroupSize[index];
+ }
+
+ mResources.MaxComputeUniformComponents = caps.maxShaderUniformComponents[ShaderType::Compute];
+ mResources.MaxComputeTextureImageUnits = caps.maxShaderTextureImageUnits[ShaderType::Compute];
+
+ mResources.MaxComputeAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Compute];
+ mResources.MaxComputeAtomicCounterBuffers =
+ caps.maxShaderAtomicCounterBuffers[ShaderType::Compute];
+
+ mResources.MaxVertexAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Vertex];
+ mResources.MaxFragmentAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Fragment];
+ mResources.MaxCombinedAtomicCounters = caps.maxCombinedAtomicCounters;
+ mResources.MaxAtomicCounterBindings = caps.maxAtomicCounterBufferBindings;
+ mResources.MaxVertexAtomicCounterBuffers =
+ caps.maxShaderAtomicCounterBuffers[ShaderType::Vertex];
+ mResources.MaxFragmentAtomicCounterBuffers =
+ caps.maxShaderAtomicCounterBuffers[ShaderType::Fragment];
+ mResources.MaxCombinedAtomicCounterBuffers = caps.maxCombinedAtomicCounterBuffers;
+ mResources.MaxAtomicCounterBufferSize = caps.maxAtomicCounterBufferSize;
+
+ mResources.MaxUniformBufferBindings = caps.maxUniformBufferBindings;
+ mResources.MaxShaderStorageBufferBindings = caps.maxShaderStorageBufferBindings;
+
+ // Needed by point size clamping workaround
+ mResources.MaxPointSize = caps.maxAliasedPointSize;
+
+ if (state.getClientMajorVersion() == 2 && !extensions.drawBuffersEXT)
+ {
+ mResources.MaxDrawBuffers = 1;
+ }
+
+ // Geometry Shader constants
+ mResources.EXT_geometry_shader = extensions.geometryShaderEXT;
+ mResources.OES_geometry_shader = extensions.geometryShaderOES;
+ mResources.MaxGeometryUniformComponents = caps.maxShaderUniformComponents[ShaderType::Geometry];
+ mResources.MaxGeometryUniformBlocks = caps.maxShaderUniformBlocks[ShaderType::Geometry];
+ mResources.MaxGeometryInputComponents = caps.maxGeometryInputComponents;
+ mResources.MaxGeometryOutputComponents = caps.maxGeometryOutputComponents;
+ mResources.MaxGeometryOutputVertices = caps.maxGeometryOutputVertices;
+ mResources.MaxGeometryTotalOutputComponents = caps.maxGeometryTotalOutputComponents;
+ mResources.MaxGeometryTextureImageUnits = caps.maxShaderTextureImageUnits[ShaderType::Geometry];
+
+ mResources.MaxGeometryAtomicCounterBuffers =
+ caps.maxShaderAtomicCounterBuffers[ShaderType::Geometry];
+ mResources.MaxGeometryAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::Geometry];
+ mResources.MaxGeometryShaderStorageBlocks = caps.maxShaderStorageBlocks[ShaderType::Geometry];
+ mResources.MaxGeometryShaderInvocations = caps.maxGeometryShaderInvocations;
+ mResources.MaxGeometryImageUniforms = caps.maxShaderImageUniforms[ShaderType::Geometry];
+
+ // Tessellation Shader constants
+ mResources.EXT_tessellation_shader = extensions.tessellationShaderEXT;
+ mResources.MaxTessControlInputComponents = caps.maxTessControlInputComponents;
+ mResources.MaxTessControlOutputComponents = caps.maxTessControlOutputComponents;
+ mResources.MaxTessControlTextureImageUnits =
+ caps.maxShaderTextureImageUnits[ShaderType::TessControl];
+ mResources.MaxTessControlUniformComponents =
+ caps.maxShaderUniformComponents[ShaderType::TessControl];
+ mResources.MaxTessControlTotalOutputComponents = caps.maxTessControlTotalOutputComponents;
+ mResources.MaxTessControlImageUniforms = caps.maxShaderImageUniforms[ShaderType::TessControl];
+ mResources.MaxTessControlAtomicCounters = caps.maxShaderAtomicCounters[ShaderType::TessControl];
+ mResources.MaxTessControlAtomicCounterBuffers =
+ caps.maxShaderAtomicCounterBuffers[ShaderType::TessControl];
+
+ mResources.MaxTessPatchComponents = caps.maxTessPatchComponents;
+ mResources.MaxPatchVertices = caps.maxPatchVertices;
+ mResources.MaxTessGenLevel = caps.maxTessGenLevel;
+
+ mResources.MaxTessEvaluationInputComponents = caps.maxTessEvaluationInputComponents;
+ mResources.MaxTessEvaluationOutputComponents = caps.maxTessEvaluationOutputComponents;
+ mResources.MaxTessEvaluationTextureImageUnits =
+ caps.maxShaderTextureImageUnits[ShaderType::TessEvaluation];
+ mResources.MaxTessEvaluationUniformComponents =
+ caps.maxShaderUniformComponents[ShaderType::TessEvaluation];
+ mResources.MaxTessEvaluationImageUniforms =
+ caps.maxShaderImageUniforms[ShaderType::TessEvaluation];
+ mResources.MaxTessEvaluationAtomicCounters =
+ caps.maxShaderAtomicCounters[ShaderType::TessEvaluation];
+ mResources.MaxTessEvaluationAtomicCounterBuffers =
+ caps.maxShaderAtomicCounterBuffers[ShaderType::TessEvaluation];
+
+ // Subpixel bits.
+ mResources.SubPixelBits = static_cast<int>(caps.subPixelBits);
+}
+
+Compiler::~Compiler() = default;
+
+void Compiler::onDestroy(const Context *context)
+{
+ std::lock_guard<std::mutex> lock(context->getDisplay()->getDisplayGlobalMutex());
+ for (auto &pool : mPools)
+ {
+ for (ShCompilerInstance &instance : pool)
+ {
+ instance.destroy();
+ }
+ }
+ --gActiveCompilers;
+ if (gActiveCompilers == 0)
+ {
+ sh::Finalize();
+ }
+}
+
+ShCompilerInstance Compiler::getInstance(ShaderType type)
+{
+ ASSERT(type != ShaderType::InvalidEnum);
+ auto &pool = mPools[type];
+ if (pool.empty())
+ {
+ ShHandle handle = sh::ConstructCompiler(ToGLenum(type), mSpec, mOutputType, &mResources);
+ ASSERT(handle);
+ return ShCompilerInstance(handle, mOutputType, type);
+ }
+ else
+ {
+ ShCompilerInstance instance = std::move(pool.back());
+ pool.pop_back();
+ return instance;
+ }
+}
+
+void Compiler::putInstance(ShCompilerInstance &&instance)
+{
+ static constexpr size_t kMaxPoolSize = 32;
+ auto &pool = mPools[instance.getShaderType()];
+ if (pool.size() < kMaxPoolSize)
+ {
+ pool.push_back(std::move(instance));
+ }
+ else
+ {
+ instance.destroy();
+ }
+}
+
+ShShaderSpec Compiler::SelectShaderSpec(const State &state)
+{
+ const EGLenum clientType = state.getClientType();
+ const EGLint profileMask = state.getProfileMask();
+ const GLint majorVersion = state.getClientMajorVersion();
+ const GLint minorVersion = state.getClientMinorVersion();
+ bool isWebGL = state.isWebGL();
+
+ // For Desktop GL
+ if (clientType == EGL_OPENGL_API)
+ {
+ if ((profileMask & EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT) != 0)
+ {
+ return SH_GL_CORE_SPEC;
+ }
+ else
+ {
+ return SH_GL_COMPATIBILITY_SPEC;
+ }
+ }
+
+ if (majorVersion >= 3)
+ {
+ switch (minorVersion)
+ {
+ case 2:
+ ASSERT(!isWebGL);
+ return SH_GLES3_2_SPEC;
+ case 1:
+ return isWebGL ? SH_WEBGL3_SPEC : SH_GLES3_1_SPEC;
+ case 0:
+ return isWebGL ? SH_WEBGL2_SPEC : SH_GLES3_SPEC;
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ // GLES1 emulation: Use GLES3 shader spec.
+ if (!isWebGL && majorVersion == 1)
+ {
+ return SH_GLES3_SPEC;
+ }
+
+ return isWebGL ? SH_WEBGL_SPEC : SH_GLES2_SPEC;
+}
+
+ShCompilerInstance::ShCompilerInstance() : mHandle(nullptr) {}
+
+ShCompilerInstance::ShCompilerInstance(ShHandle handle,
+ ShShaderOutput outputType,
+ ShaderType shaderType)
+ : mHandle(handle), mOutputType(outputType), mShaderType(shaderType)
+{}
+
+ShCompilerInstance::~ShCompilerInstance()
+{
+ ASSERT(mHandle == nullptr);
+}
+
+void ShCompilerInstance::destroy()
+{
+ if (mHandle != nullptr)
+ {
+ sh::Destruct(mHandle);
+ mHandle = nullptr;
+ }
+}
+
+ShCompilerInstance::ShCompilerInstance(ShCompilerInstance &&other)
+ : mHandle(other.mHandle), mOutputType(other.mOutputType), mShaderType(other.mShaderType)
+{
+ other.mHandle = nullptr;
+}
+
+ShCompilerInstance &ShCompilerInstance::operator=(ShCompilerInstance &&other)
+{
+ mHandle = other.mHandle;
+ mOutputType = other.mOutputType;
+ mShaderType = other.mShaderType;
+ other.mHandle = nullptr;
+ return *this;
+}
+
+ShHandle ShCompilerInstance::getHandle()
+{
+ return mHandle;
+}
+
+ShaderType ShCompilerInstance::getShaderType() const
+{
+ return mShaderType;
+}
+
+ShBuiltInResources ShCompilerInstance::getBuiltInResources() const
+{
+ return sh::GetBuiltInResources(mHandle);
+}
+
+const std::string &ShCompilerInstance::getBuiltinResourcesString() const
+{
+ return sh::GetBuiltInResourcesString(mHandle);
+}
+
+ShShaderOutput ShCompilerInstance::getShaderOutputType() const
+{
+ return mOutputType;
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Compiler.h b/gfx/angle/checkout/src/libANGLE/Compiler.h
new file mode 100644
index 0000000000..01428f36da
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Compiler.h
@@ -0,0 +1,78 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Compiler.h: Defines the gl::Compiler class, abstracting the ESSL compiler
+// that a GL context holds.
+
+#ifndef LIBANGLE_COMPILER_H_
+#define LIBANGLE_COMPILER_H_
+
+#include <vector>
+
+#include "GLSLANG/ShaderLang.h"
+#include "common/PackedEnums.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+namespace rx
+{
+class CompilerImpl;
+class GLImplFactory;
+} // namespace rx
+
+namespace gl
+{
+class ShCompilerInstance;
+class State;
+
+class Compiler final : public RefCountObjectNoID
+{
+ public:
+ Compiler(rx::GLImplFactory *implFactory, const State &data, egl::Display *display);
+
+ void onDestroy(const Context *context) override;
+
+ ShCompilerInstance getInstance(ShaderType shaderType);
+ void putInstance(ShCompilerInstance &&instance);
+ ShShaderOutput getShaderOutputType() const { return mOutputType; }
+
+ static ShShaderSpec SelectShaderSpec(const State &state);
+
+ private:
+ ~Compiler() override;
+ std::unique_ptr<rx::CompilerImpl> mImplementation;
+ ShShaderSpec mSpec;
+ ShShaderOutput mOutputType;
+ ShBuiltInResources mResources;
+ ShaderMap<std::vector<ShCompilerInstance>> mPools;
+};
+
+class ShCompilerInstance final : public angle::NonCopyable
+{
+ public:
+ ShCompilerInstance();
+ ShCompilerInstance(ShHandle handle, ShShaderOutput outputType, ShaderType shaderType);
+ ~ShCompilerInstance();
+ void destroy();
+
+ ShCompilerInstance(ShCompilerInstance &&other);
+ ShCompilerInstance &operator=(ShCompilerInstance &&other);
+
+ ShHandle getHandle();
+ ShaderType getShaderType() const;
+ ShBuiltInResources getBuiltInResources() const;
+ const std::string &getBuiltinResourcesString() const;
+ ShShaderOutput getShaderOutputType() const;
+
+ private:
+ ShHandle mHandle;
+ ShShaderOutput mOutputType;
+ ShaderType mShaderType;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_COMPILER_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Config.cpp b/gfx/angle/checkout/src/libANGLE/Config.cpp
new file mode 100644
index 0000000000..127480db1f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Config.cpp
@@ -0,0 +1,416 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Config.cpp: Implements the egl::Config class, describing the format, type
+// and size for an egl::Surface. Implements EGLConfig and related functionality.
+// [EGL 1.5] section 3.4 page 19.
+
+#include "libANGLE/Config.h"
+#include "libANGLE/AttributeMap.h"
+
+#include <algorithm>
+#include <vector>
+
+#include <EGL/eglext.h>
+#include "angle_gl.h"
+
+#include "common/debug.h"
+
+namespace egl
+{
+
+Config::Config()
+ : renderTargetFormat(GL_NONE),
+ depthStencilFormat(GL_NONE),
+ bufferSize(0),
+ redSize(0),
+ greenSize(0),
+ blueSize(0),
+ luminanceSize(0),
+ alphaSize(0),
+ alphaMaskSize(0),
+ bindToTextureRGB(EGL_FALSE),
+ bindToTextureRGBA(EGL_FALSE),
+ bindToTextureTarget(EGL_TEXTURE_2D),
+ colorBufferType(EGL_RGB_BUFFER),
+ configCaveat(EGL_NONE),
+ configID(0),
+ conformant(0),
+ depthSize(0),
+ level(0),
+ matchNativePixmap(EGL_FALSE),
+ maxPBufferWidth(0),
+ maxPBufferHeight(0),
+ maxPBufferPixels(0),
+ maxSwapInterval(0),
+ minSwapInterval(0),
+ nativeRenderable(EGL_FALSE),
+ nativeVisualID(0),
+ nativeVisualType(0),
+ renderableType(0),
+ sampleBuffers(0),
+ samples(0),
+ stencilSize(0),
+ surfaceType(0),
+ transparentType(EGL_NONE),
+ transparentRedValue(0),
+ transparentGreenValue(0),
+ transparentBlueValue(0),
+ optimalOrientation(0),
+ colorComponentType(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT),
+ recordable(EGL_FALSE),
+ framebufferTarget(EGL_FALSE), // TODO: http://anglebug.com/4208
+ yInverted(EGL_FALSE)
+{}
+
+Config::~Config() {}
+
+Config::Config(const Config &other) = default;
+
+Config &Config::operator=(const Config &other) = default;
+
+ConfigSet::ConfigSet() = default;
+
+ConfigSet::ConfigSet(const ConfigSet &other) = default;
+
+ConfigSet &ConfigSet::operator=(const ConfigSet &other) = default;
+
+ConfigSet::~ConfigSet() = default;
+
+EGLint ConfigSet::add(const Config &config)
+{
+ // Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4)
+ EGLint id = static_cast<EGLint>(mConfigs.size()) + 1;
+
+ Config copyConfig(config);
+ copyConfig.configID = id;
+ mConfigs.insert(std::make_pair(id, copyConfig));
+
+ return id;
+}
+
+const Config &ConfigSet::get(EGLint id) const
+{
+ ASSERT(mConfigs.find(id) != mConfigs.end());
+ return mConfigs.find(id)->second;
+}
+
+void ConfigSet::clear()
+{
+ mConfigs.clear();
+}
+
+size_t ConfigSet::size() const
+{
+ return mConfigs.size();
+}
+
+bool ConfigSet::contains(const Config *config) const
+{
+ for (auto i = mConfigs.begin(); i != mConfigs.end(); i++)
+ {
+ const Config &item = i->second;
+ if (config == &item)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Function object used by STL sorting routines for ordering Configs according to [EGL 1.5]
+// section 3.4.1.2 page 28.
+class ConfigSorter
+{
+ public:
+ explicit ConfigSorter(const AttributeMap &attributeMap)
+ : mWantRed(false),
+ mWantGreen(false),
+ mWantBlue(false),
+ mWantAlpha(false),
+ mWantLuminance(false)
+ {
+ scanForWantedComponents(attributeMap);
+ }
+
+ bool operator()(const Config *x, const Config *y) const { return (*this)(*x, *y); }
+
+ bool operator()(const Config &x, const Config &y) const
+ {
+#define SORT(attribute) \
+ do \
+ { \
+ if (x.attribute != y.attribute) \
+ return x.attribute < y.attribute; \
+ } while (0)
+
+ static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG,
+ "Unexpected EGL enum value.");
+ SORT(configCaveat);
+
+ static_assert(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT < EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
+ "Unexpected order of EGL enums.");
+ SORT(colorComponentType);
+
+ static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "Unexpected EGL enum value.");
+ SORT(colorBufferType);
+
+ // By larger total number of color bits, only considering those that are requested to be >
+ // 0.
+ EGLint xComponentsSize = wantedComponentsSize(x);
+ EGLint yComponentsSize = wantedComponentsSize(y);
+ if (xComponentsSize != yComponentsSize)
+ {
+ return xComponentsSize > yComponentsSize;
+ }
+
+ SORT(bufferSize);
+ SORT(sampleBuffers);
+ SORT(samples);
+ SORT(depthSize);
+ SORT(stencilSize);
+ SORT(alphaMaskSize);
+ SORT(nativeVisualType);
+ SORT(configID);
+
+#undef SORT
+
+ return false;
+ }
+
+ private:
+ static bool wantsComponent(const AttributeMap &attributeMap, EGLAttrib component)
+ {
+ // [EGL 1.5] section 3.4.1.2 page 30
+ // Sorting rule #3: by larger total number of color bits, not considering
+ // components that are 0 or don't-care.
+ EGLAttrib value = attributeMap.get(component, 0);
+ return value != 0 && value != EGL_DONT_CARE;
+ }
+
+ void scanForWantedComponents(const AttributeMap &attributeMap)
+ {
+ mWantRed = wantsComponent(attributeMap, EGL_RED_SIZE);
+ mWantGreen = wantsComponent(attributeMap, EGL_GREEN_SIZE);
+ mWantBlue = wantsComponent(attributeMap, EGL_BLUE_SIZE);
+ mWantAlpha = wantsComponent(attributeMap, EGL_ALPHA_SIZE);
+ mWantLuminance = wantsComponent(attributeMap, EGL_LUMINANCE_SIZE);
+ }
+
+ EGLint wantedComponentsSize(const Config &config) const
+ {
+ EGLint total = 0;
+
+ if (mWantRed)
+ total += config.redSize;
+ if (mWantGreen)
+ total += config.greenSize;
+ if (mWantBlue)
+ total += config.blueSize;
+ if (mWantAlpha)
+ total += config.alphaSize;
+ if (mWantLuminance)
+ total += config.luminanceSize;
+
+ return total;
+ }
+
+ bool mWantRed;
+ bool mWantGreen;
+ bool mWantBlue;
+ bool mWantAlpha;
+ bool mWantLuminance;
+};
+
+std::vector<const Config *> ConfigSet::filter(const AttributeMap &attributeMap) const
+{
+ std::vector<const Config *> result;
+ result.reserve(mConfigs.size());
+
+ for (auto configIter = mConfigs.begin(); configIter != mConfigs.end(); configIter++)
+ {
+ const Config &config = configIter->second;
+ bool match = true;
+
+ for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
+ {
+ EGLAttrib attributeKey = attribIter->first;
+ EGLAttrib attributeValue = attribIter->second;
+
+ if (attributeValue == EGL_DONT_CARE)
+ {
+ continue;
+ }
+
+ switch (attributeKey)
+ {
+ case EGL_BUFFER_SIZE:
+ match = config.bufferSize >= attributeValue;
+ break;
+ case EGL_ALPHA_SIZE:
+ match = config.alphaSize >= attributeValue;
+ break;
+ case EGL_BLUE_SIZE:
+ match = config.blueSize >= attributeValue;
+ break;
+ case EGL_GREEN_SIZE:
+ match = config.greenSize >= attributeValue;
+ break;
+ case EGL_RED_SIZE:
+ match = config.redSize >= attributeValue;
+ break;
+ case EGL_DEPTH_SIZE:
+ match = config.depthSize >= attributeValue;
+ break;
+ case EGL_STENCIL_SIZE:
+ match = config.stencilSize >= attributeValue;
+ break;
+ case EGL_CONFIG_CAVEAT:
+ match = config.configCaveat == static_cast<EGLenum>(attributeValue);
+ break;
+ case EGL_CONFIG_ID:
+ match = config.configID == attributeValue;
+ break;
+ case EGL_LEVEL:
+ match = config.level == attributeValue;
+ break;
+ case EGL_NATIVE_RENDERABLE:
+ match = config.nativeRenderable == static_cast<EGLBoolean>(attributeValue);
+ break;
+ case EGL_NATIVE_VISUAL_TYPE:
+ match = config.nativeVisualType == attributeValue;
+ break;
+ case EGL_SAMPLES:
+ match = config.samples >= attributeValue;
+ break;
+ case EGL_SAMPLE_BUFFERS:
+ match = config.sampleBuffers >= attributeValue;
+ break;
+ case EGL_SURFACE_TYPE:
+ match = (config.surfaceType & attributeValue) == attributeValue;
+ break;
+ case EGL_TRANSPARENT_TYPE:
+ match = config.transparentType == static_cast<EGLenum>(attributeValue);
+ break;
+ case EGL_TRANSPARENT_BLUE_VALUE:
+ if (attributeMap.get(EGL_TRANSPARENT_TYPE, EGL_NONE) != EGL_NONE)
+ {
+ match = config.transparentBlueValue == attributeValue;
+ }
+ break;
+ case EGL_TRANSPARENT_GREEN_VALUE:
+ if (attributeMap.get(EGL_TRANSPARENT_TYPE, EGL_NONE) != EGL_NONE)
+ {
+ match = config.transparentGreenValue == attributeValue;
+ }
+ break;
+ case EGL_TRANSPARENT_RED_VALUE:
+ if (attributeMap.get(EGL_TRANSPARENT_TYPE, EGL_NONE) != EGL_NONE)
+ {
+ match = config.transparentRedValue == attributeValue;
+ }
+ break;
+ case EGL_BIND_TO_TEXTURE_RGB:
+ match = config.bindToTextureRGB == static_cast<EGLBoolean>(attributeValue);
+ break;
+ case EGL_BIND_TO_TEXTURE_RGBA:
+ match = config.bindToTextureRGBA == static_cast<EGLBoolean>(attributeValue);
+ break;
+ case EGL_BIND_TO_TEXTURE_TARGET_ANGLE:
+ match = config.bindToTextureTarget == static_cast<EGLenum>(attributeValue);
+ break;
+ case EGL_MIN_SWAP_INTERVAL:
+ match = config.minSwapInterval == attributeValue;
+ break;
+ case EGL_MAX_SWAP_INTERVAL:
+ match = config.maxSwapInterval == attributeValue;
+ break;
+ case EGL_LUMINANCE_SIZE:
+ match = config.luminanceSize >= attributeValue;
+ break;
+ case EGL_ALPHA_MASK_SIZE:
+ match = config.alphaMaskSize >= attributeValue;
+ break;
+ case EGL_COLOR_BUFFER_TYPE:
+ match = config.colorBufferType == static_cast<EGLenum>(attributeValue);
+ break;
+ case EGL_RENDERABLE_TYPE:
+ match = (config.renderableType & attributeValue) == attributeValue;
+ break;
+ case EGL_MATCH_NATIVE_PIXMAP:
+ match = false;
+ UNIMPLEMENTED();
+ break;
+ case EGL_CONFORMANT:
+ match = (config.conformant & attributeValue) == attributeValue;
+ break;
+ case EGL_MAX_PBUFFER_WIDTH:
+ match = config.maxPBufferWidth >= attributeValue;
+ break;
+ case EGL_MAX_PBUFFER_HEIGHT:
+ match = config.maxPBufferHeight >= attributeValue;
+ break;
+ case EGL_MAX_PBUFFER_PIXELS:
+ match = config.maxPBufferPixels >= attributeValue;
+ break;
+ case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
+ match = config.optimalOrientation == attributeValue;
+ break;
+ case EGL_COLOR_COMPONENT_TYPE_EXT:
+ match = config.colorComponentType == static_cast<EGLenum>(attributeValue);
+ break;
+ case EGL_RECORDABLE_ANDROID:
+ match = config.recordable == static_cast<EGLBoolean>(attributeValue);
+ break;
+ case EGL_FRAMEBUFFER_TARGET_ANDROID:
+ match = config.framebufferTarget == static_cast<EGLBoolean>(attributeValue);
+ break;
+ case EGL_Y_INVERTED_NOK:
+ match = config.yInverted == static_cast<EGLBoolean>(attributeValue);
+ break;
+ case EGL_MATCH_FORMAT_KHR:
+ if (attributeValue == EGL_NONE)
+ {
+ match = (config.surfaceType & EGL_LOCK_SURFACE_BIT_KHR) == 0;
+ }
+ else
+ {
+ match = config.matchFormat == attributeValue;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ if (!match)
+ {
+ break;
+ }
+ }
+
+ if (match)
+ {
+ result.push_back(&config);
+ }
+ }
+
+ // Sort the result
+ std::sort(result.begin(), result.end(), ConfigSorter(attributeMap));
+
+ return result;
+}
+
+ConfigSet::ConfigMap::iterator ConfigSet::begin()
+{
+ return mConfigs.begin();
+}
+
+ConfigSet::ConfigMap::iterator ConfigSet::end()
+{
+ return mConfigs.end();
+}
+} // namespace egl
diff --git a/gfx/angle/checkout/src/libANGLE/Config.h b/gfx/angle/checkout/src/libANGLE/Config.h
new file mode 100644
index 0000000000..7901c793ee
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Config.h
@@ -0,0 +1,115 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Config.h: Defines the egl::Config class, describing the format, type
+// and size for an egl::Surface. Implements EGLConfig and related functionality.
+// [EGL 1.5] section 3.4 page 19.
+
+#ifndef INCLUDE_CONFIG_H_
+#define INCLUDE_CONFIG_H_
+
+#include "libANGLE/AttributeMap.h"
+
+#include "common/angleutils.h"
+
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+
+#include <map>
+#include <vector>
+
+namespace egl
+{
+
+struct Config
+{
+ Config();
+ ~Config();
+ Config(const Config &other);
+ Config &operator=(const Config &other);
+
+ GLenum renderTargetFormat; // TODO(geofflang): remove this
+ GLenum depthStencilFormat; // TODO(geofflang): remove this
+
+ EGLint bufferSize; // Depth of the color buffer
+ EGLint redSize; // Bits of Red in the color buffer
+ EGLint greenSize; // Bits of Green in the color buffer
+ EGLint blueSize; // Bits of Blue in the color buffer
+ EGLint luminanceSize; // Bits of Luminance in the color buffer
+ EGLint alphaSize; // Bits of Alpha in the color buffer
+ EGLint alphaMaskSize; // Bits of Alpha Mask in the mask buffer
+ EGLBoolean bindToTextureRGB; // True if bindable to RGB textures.
+ EGLBoolean bindToTextureRGBA; // True if bindable to RGBA textures.
+ EGLenum bindToTextureTarget; // Which texture target should be used for pbuffers
+ EGLenum colorBufferType; // Color buffer type
+ EGLenum configCaveat; // Any caveats for the configuration
+ EGLint configID; // Unique EGLConfig identifier
+ EGLint conformant; // Whether contexts created with this config are conformant
+ EGLint depthSize; // Bits of Z in the depth buffer
+ EGLint level; // Frame buffer level
+ EGLBoolean matchNativePixmap; // Match the native pixmap format
+ EGLint maxPBufferWidth; // Maximum width of pbuffer
+ EGLint maxPBufferHeight; // Maximum height of pbuffer
+ EGLint maxPBufferPixels; // Maximum size of pbuffer
+ EGLint maxSwapInterval; // Maximum swap interval
+ EGLint minSwapInterval; // Minimum swap interval
+ EGLBoolean nativeRenderable; // EGL_TRUE if native rendering APIs can render to surface
+ EGLint nativeVisualID; // Handle of corresponding native visual
+ EGLint nativeVisualType; // Native visual type of the associated visual
+ EGLint renderableType; // Which client rendering APIs are supported.
+ EGLint sampleBuffers; // Number of multisample buffers
+ EGLint samples; // Number of samples per pixel
+ EGLint stencilSize; // Bits of Stencil in the stencil buffer
+ EGLint surfaceType; // Which types of EGL surfaces are supported.
+ EGLenum transparentType; // Type of transparency supported
+ EGLint transparentRedValue; // Transparent red value
+ EGLint transparentGreenValue; // Transparent green value
+ EGLint transparentBlueValue; // Transparent blue value
+ EGLint optimalOrientation; // Optimal window surface orientation
+ EGLenum colorComponentType; // Color component type
+ EGLBoolean recordable; // EGL_TRUE if a surface can support recording on Android
+ EGLBoolean framebufferTarget; // EGL_TRUE if the config supports rendering to a ANativeWindow
+ // for which the buffers are passed to the HWComposer HAL as a
+ // framebuffer target layer.
+ EGLBoolean yInverted; // True if the drawable's framebuffer is y-inverted. This can be used to
+ // determine if y-inverted texture coordinates need to be used when
+ // texturing from this drawable when it is bound to a texture target.
+ EGLint matchFormat; // LockSurface match format.
+};
+
+class ConfigSet
+{
+ private:
+ typedef std::map<EGLint, Config> ConfigMap;
+
+ public:
+ ConfigSet();
+ ConfigSet(const ConfigSet &other);
+ ~ConfigSet();
+ ConfigSet &operator=(const ConfigSet &other);
+
+ EGLint add(const Config &config);
+ const Config &get(EGLint id) const;
+
+ void clear();
+
+ size_t size() const;
+
+ bool contains(const Config *config) const;
+
+ // Filter configurations based on the table in [EGL 1.5] section 3.4.1.2 page 29
+ std::vector<const Config *> filter(const AttributeMap &attributeMap) const;
+
+ ConfigMap::iterator begin();
+ ConfigMap::iterator end();
+
+ private:
+ ConfigMap mConfigs;
+};
+
+} // namespace egl
+
+#endif // INCLUDE_CONFIG_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Constants.h b/gfx/angle/checkout/src/libANGLE/Constants.h
new file mode 100644
index 0000000000..36152825e4
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Constants.h
@@ -0,0 +1,125 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Contants.h: Defines some implementation specific and gl constants
+
+#ifndef LIBANGLE_CONSTANTS_H_
+#define LIBANGLE_CONSTANTS_H_
+
+#include "common/platform.h"
+
+#include <stdint.h>
+
+namespace gl
+{
+
+// The binary cache is currently left disable by default, and the application can enable it.
+const size_t kDefaultMaxProgramCacheMemoryBytes = 0;
+
+enum
+{
+ // Implementation upper limits, real maximums depend on the hardware
+
+ // Only up to 32x MSAA supported.
+ IMPLEMENTATION_MAX_SAMPLE_MASK_WORDS = 1,
+ IMPLEMENTATION_MAX_SAMPLES = 32,
+
+ MAX_VERTEX_ATTRIBS = 16,
+ MAX_VERTEX_ATTRIB_BINDINGS = 16,
+
+ IMPLEMENTATION_MAX_VARYING_VECTORS = 32,
+ IMPLEMENTATION_MAX_DRAW_BUFFERS = 8,
+ IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS =
+ IMPLEMENTATION_MAX_DRAW_BUFFERS + 2, // 2 extra for depth and/or stencil buffers
+
+ // The vast majority of devices support only one dual-source draw buffer
+ IMPLEMENTATION_MAX_DUAL_SOURCE_DRAW_BUFFERS = 1,
+
+ IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS = 16,
+ IMPLEMENTATION_MAX_GEOMETRY_SHADER_UNIFORM_BUFFERS = 16,
+ IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS = 16,
+ IMPLEMENTATION_MAX_COMPUTE_SHADER_UNIFORM_BUFFERS = 16,
+
+ // GL_EXT_geometry_shader increases the minimum value of GL_MAX_COMBINED_UNIFORM_BLOCKS to 36.
+ // GL_EXT_tessellation_shader increases the minimum value to 60.
+ IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS = 60,
+
+ // GL_EXT_geometry_shader increases the minimum value of GL_MAX_UNIFORM_BUFFER_BINDINGS to 48.
+ // GL_EXT_tessellation_shader increases the minimum value to 72.
+ IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS = 72,
+
+ // Transform feedback limits set to the minimum required by the spec.
+ IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS = 128,
+ IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = 4,
+ IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS = 4,
+ IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS = 4,
+
+ // Maximum number of views which are supported by the implementation of ANGLE_multiview.
+ IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS = 4,
+
+ // These are the maximums the implementation can support
+ // The actual GL caps are limited by the device caps
+ // and should be queried from the Context
+ IMPLEMENTATION_MAX_2D_TEXTURE_SIZE = 32768,
+ IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 32768,
+ IMPLEMENTATION_MAX_3D_TEXTURE_SIZE = 16384,
+ IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS = 2048,
+
+ // 1+log2 of max of MAX_*_TEXTURE_SIZE
+ IMPLEMENTATION_MAX_TEXTURE_LEVELS = 16,
+
+ IMPLEMENTATION_MAX_SHADER_TEXTURES = 32,
+
+ // In ES 3.1 and below, the limit for active textures is 64.
+ IMPLEMENTATION_MAX_ES31_ACTIVE_TEXTURES = 64,
+
+ // In ES 3.2 we need to support a minimum of 96 maximum textures.
+ IMPLEMENTATION_MAX_ACTIVE_TEXTURES = 96,
+ IMPLEMENTATION_MAX_IMAGE_UNITS = IMPLEMENTATION_MAX_ACTIVE_TEXTURES,
+
+ // Maximum number of slots allocated for atomic counter buffers.
+ IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS = 8,
+
+ // Implementation upper limits, real maximums depend on the hardware.
+ IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS = 64,
+
+ // Implementation upper limits of max number of clip distances (minimum required per spec)
+ IMPLEMENTATION_MAX_CLIP_DISTANCES = 8,
+
+ // Implementation upper limit for layered framebuffer layer count
+ IMPLEMENTATION_MAX_FRAMEBUFFER_LAYERS = 256,
+
+ // ANGLE_shader_pixel_local_storage: keep the maximum number of supported planes reasonably
+ // similar on all platforms.
+ IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES = 8,
+};
+
+namespace limits
+{
+// Almost all drivers use 2048 (the minimum value) as GL_MAX_VERTEX_ATTRIB_STRIDE. ANGLE advertizes
+// the same limit.
+constexpr uint32_t kMaxVertexAttribStride = 2048;
+
+// Some of the minimums required by GL, used to detect if the backend meets the minimum requirement.
+// Currently, there's no need to separate these values per spec version.
+constexpr uint32_t kMinimumComputeStorageBuffers = 4;
+
+// OpenGL ES 3.0+ Minimum Values
+// Table 6.31 MAX_VERTEX_UNIFORM_BLOCKS minimum value = 12
+// Table 6.32 MAX_FRAGMENT_UNIFORM_BLOCKS minimum value = 12
+constexpr uint32_t kMinimumShaderUniformBlocks = 12;
+// Table 6.31 MAX_VERTEX_OUTPUT_COMPONENTS minimum value = 64
+constexpr uint32_t kMinimumVertexOutputComponents = 64;
+
+// OpenGL ES 3.2+ Minimum Values
+// Table 21.42 TEXTURE_BUFFER_OFFSET_ALIGNMENT minimum value = 256
+constexpr uint32_t kMinTextureBufferOffsetAlignment = 256;
+
+} // namespace limits
+
+} // namespace gl
+
+#endif // LIBANGLE_CONSTANTS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Context.cpp b/gfx/angle/checkout/src/libANGLE/Context.cpp
new file mode 100644
index 0000000000..bfd490ab29
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Context.cpp
@@ -0,0 +1,10472 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Context.cpp: Implements the gl::Context class, managing all GL state and performing
+// rendering operations. It is the GLES2 specific implementation of EGLContext.
+#include "libANGLE/Context.inl.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <iterator>
+#include <sstream>
+#include <vector>
+
+#include "common/PackedEnums.h"
+#include "common/angle_version_info.h"
+#include "common/matrix_utils.h"
+#include "common/platform.h"
+#include "common/system_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/MemoryObject.h"
+#include "libANGLE/PixelLocalStorage.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/ProgramPipeline.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/Sampler.h"
+#include "libANGLE/Semaphore.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/capture/FrameCapture.h"
+#include "libANGLE/capture/frame_capture_utils.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/queryutils.h"
+#include "libANGLE/renderer/DisplayImpl.h"
+#include "libANGLE/renderer/Format.h"
+#include "libANGLE/validationES.h"
+
+#if defined(ANGLE_PLATFORM_APPLE)
+# include <dispatch/dispatch.h>
+# include "common/tls.h"
+#endif
+
+namespace gl
+{
+namespace
+{
+
+egl::ShareGroup *AllocateOrGetShareGroup(egl::Display *display, const gl::Context *shareContext)
+{
+ if (shareContext)
+ {
+ egl::ShareGroup *shareGroup = shareContext->getState().getShareGroup();
+ shareGroup->addRef();
+ return shareGroup;
+ }
+ else
+ {
+ return new egl::ShareGroup(display->getImplementation());
+ }
+}
+
+template <typename T>
+angle::Result GetQueryObjectParameter(const Context *context, Query *query, GLenum pname, T *params)
+{
+ if (!query)
+ {
+ // Some applications call into glGetQueryObjectuiv(...) prior to calling glBeginQuery(...)
+ // This wouldn't be an issue since the validation layer will handle such a usecases but when
+ // the app enables EGL_KHR_create_context_no_error extension, we skip the validation layer.
+ switch (pname)
+ {
+ case GL_QUERY_RESULT_EXT:
+ *params = 0;
+ break;
+ case GL_QUERY_RESULT_AVAILABLE_EXT:
+ *params = GL_FALSE;
+ break;
+ default:
+ UNREACHABLE();
+ return angle::Result::Stop;
+ }
+ return angle::Result::Continue;
+ }
+
+ switch (pname)
+ {
+ case GL_QUERY_RESULT_EXT:
+ return query->getResult(context, params);
+ case GL_QUERY_RESULT_AVAILABLE_EXT:
+ {
+ bool available = false;
+ if (context->isContextLost())
+ {
+ available = true;
+ }
+ else
+ {
+ ANGLE_TRY(query->isResultAvailable(context, &available));
+ }
+ *params = CastFromStateValue<T>(pname, static_cast<GLuint>(available));
+ return angle::Result::Continue;
+ }
+ default:
+ UNREACHABLE();
+ return angle::Result::Stop;
+ }
+}
+
+// Attribute map queries.
+EGLint GetClientMajorVersion(const egl::AttributeMap &attribs)
+{
+ return static_cast<EGLint>(attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1));
+}
+
+EGLint GetClientMinorVersion(const egl::AttributeMap &attribs)
+{
+ return static_cast<EGLint>(attribs.get(EGL_CONTEXT_MINOR_VERSION, 0));
+}
+
+bool GetBackwardCompatibleContext(const egl::AttributeMap &attribs)
+{
+ return attribs.get(EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE, EGL_TRUE) == EGL_TRUE;
+}
+
+bool GetWebGLContext(const egl::AttributeMap &attribs)
+{
+ return (attribs.get(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE, EGL_FALSE) == EGL_TRUE);
+}
+
+Version GetClientVersion(egl::Display *display,
+ const egl::AttributeMap &attribs,
+ const EGLenum clientType)
+{
+ Version requestedVersion =
+ Version(GetClientMajorVersion(attribs), GetClientMinorVersion(attribs));
+ if (GetBackwardCompatibleContext(attribs))
+ {
+ if (clientType == EGL_OPENGL_API)
+ {
+ Optional<gl::Version> maxSupportedDesktopVersion =
+ display->getImplementation()->getMaxSupportedDesktopVersion();
+ if (maxSupportedDesktopVersion.valid())
+ return std::max(maxSupportedDesktopVersion.value(), requestedVersion);
+ else
+ return requestedVersion;
+ }
+ else if (requestedVersion.major == 1)
+ {
+ // If the user requests an ES1 context, we cannot return an ES 2+ context.
+ return Version(1, 1);
+ }
+ else
+ {
+ // Always up the version to at least the max conformant version this display supports.
+ // Only return a higher client version if requested.
+ const Version conformantVersion = std::max(
+ display->getImplementation()->getMaxConformantESVersion(), requestedVersion);
+ // Limit the WebGL context to at most version 3.1
+ const bool isWebGL = GetWebGLContext(attribs);
+ return isWebGL ? std::min(conformantVersion, Version(3, 1)) : conformantVersion;
+ }
+ }
+ else
+ {
+ return requestedVersion;
+ }
+}
+
+EGLint GetProfileMask(const egl::AttributeMap &attribs)
+{
+ return attribs.getAsInt(EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT);
+}
+
+GLenum GetResetStrategy(const egl::AttributeMap &attribs)
+{
+ EGLAttrib resetStrategyExt =
+ attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION);
+ EGLAttrib resetStrategyCore =
+ attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY, resetStrategyExt);
+
+ switch (resetStrategyCore)
+ {
+ case EGL_NO_RESET_NOTIFICATION:
+ return GL_NO_RESET_NOTIFICATION_EXT;
+ case EGL_LOSE_CONTEXT_ON_RESET:
+ return GL_LOSE_CONTEXT_ON_RESET_EXT;
+ default:
+ UNREACHABLE();
+ return GL_NONE;
+ }
+}
+
+bool GetRobustAccess(const egl::AttributeMap &attribs)
+{
+ EGLAttrib robustAccessExt = attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE);
+ EGLAttrib robustAccessCore = attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS, robustAccessExt);
+
+ bool attribRobustAccess = (robustAccessCore == EGL_TRUE);
+ bool contextFlagsRobustAccess =
+ ((attribs.get(EGL_CONTEXT_FLAGS_KHR, 0) & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) != 0);
+
+ return (attribRobustAccess || contextFlagsRobustAccess);
+}
+
+bool GetDebug(const egl::AttributeMap &attribs)
+{
+ return (attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE) ||
+ ((attribs.get(EGL_CONTEXT_FLAGS_KHR, 0) & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) != 0);
+}
+
+bool GetNoError(const egl::AttributeMap &attribs)
+{
+ return (attribs.get(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, EGL_FALSE) == EGL_TRUE);
+}
+
+bool GetExtensionsEnabled(const egl::AttributeMap &attribs, bool webGLContext)
+{
+ // If the context is WebGL, extensions are disabled by default
+ EGLAttrib defaultValue = webGLContext ? EGL_FALSE : EGL_TRUE;
+ return (attribs.get(EGL_EXTENSIONS_ENABLED_ANGLE, defaultValue) == EGL_TRUE);
+}
+
+bool GetBindGeneratesResource(const egl::AttributeMap &attribs)
+{
+ return (attribs.get(EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM, EGL_TRUE) == EGL_TRUE);
+}
+
+bool GetClientArraysEnabled(const egl::AttributeMap &attribs)
+{
+ return (attribs.get(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE, EGL_TRUE) == EGL_TRUE);
+}
+
+bool GetRobustResourceInit(egl::Display *display, const egl::AttributeMap &attribs)
+{
+ const angle::FrontendFeatures &frontendFeatures = display->getFrontendFeatures();
+ return (frontendFeatures.forceRobustResourceInit.enabled ||
+ attribs.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE);
+}
+
+EGLenum GetContextPriority(const egl::AttributeMap &attribs)
+{
+ return static_cast<EGLenum>(
+ attribs.getAsInt(EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_MEDIUM_IMG));
+}
+
+bool GetProtectedContent(const egl::AttributeMap &attribs)
+{
+ return static_cast<bool>(attribs.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE));
+}
+
+std::string GetObjectLabelFromPointer(GLsizei length, const GLchar *label)
+{
+ std::string labelName;
+ if (label != nullptr)
+ {
+ size_t labelLength = length < 0 ? strlen(label) : length;
+ labelName = std::string(label, labelLength);
+ }
+ return labelName;
+}
+
+void GetObjectLabelBase(const std::string &objectLabel,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label)
+{
+ size_t writeLength = objectLabel.length();
+ if (label != nullptr && bufSize > 0)
+ {
+ writeLength = std::min(static_cast<size_t>(bufSize) - 1, objectLabel.length());
+ std::copy(objectLabel.begin(), objectLabel.begin() + writeLength, label);
+ label[writeLength] = '\0';
+ }
+
+ if (length != nullptr)
+ {
+ *length = static_cast<GLsizei>(writeLength);
+ }
+}
+
+enum SubjectIndexes : angle::SubjectIndex
+{
+ kTexture0SubjectIndex = 0,
+ kTextureMaxSubjectIndex = kTexture0SubjectIndex + IMPLEMENTATION_MAX_ACTIVE_TEXTURES,
+ kImage0SubjectIndex = kTextureMaxSubjectIndex,
+ kImageMaxSubjectIndex = kImage0SubjectIndex + IMPLEMENTATION_MAX_IMAGE_UNITS,
+ kUniformBuffer0SubjectIndex = kImageMaxSubjectIndex,
+ kUniformBufferMaxSubjectIndex =
+ kUniformBuffer0SubjectIndex + IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS,
+ kAtomicCounterBuffer0SubjectIndex = kUniformBufferMaxSubjectIndex,
+ kAtomicCounterBufferMaxSubjectIndex =
+ kAtomicCounterBuffer0SubjectIndex + IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS,
+ kShaderStorageBuffer0SubjectIndex = kAtomicCounterBufferMaxSubjectIndex,
+ kShaderStorageBufferMaxSubjectIndex =
+ kShaderStorageBuffer0SubjectIndex + IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS,
+ kSampler0SubjectIndex = kShaderStorageBufferMaxSubjectIndex,
+ kSamplerMaxSubjectIndex = kSampler0SubjectIndex + IMPLEMENTATION_MAX_ACTIVE_TEXTURES,
+ kVertexArraySubjectIndex = kSamplerMaxSubjectIndex,
+ kReadFramebufferSubjectIndex,
+ kDrawFramebufferSubjectIndex,
+ kProgramPipelineSubjectIndex,
+};
+
+bool IsClearBufferEnabled(const FramebufferState &fbState, GLenum buffer, GLint drawbuffer)
+{
+ return buffer != GL_COLOR || fbState.getEnabledDrawBuffers()[drawbuffer];
+}
+
+bool IsEmptyScissor(const State &glState)
+{
+ if (!glState.isScissorTestEnabled())
+ {
+ return false;
+ }
+
+ const Extents &dimensions = glState.getDrawFramebuffer()->getExtents();
+ Rectangle framebufferArea(0, 0, dimensions.width, dimensions.height);
+ return !ClipRectangle(framebufferArea, glState.getScissor(), nullptr);
+}
+
+bool IsColorMaskedOut(const BlendStateExt &blendStateExt, const GLint drawbuffer)
+{
+ ASSERT(static_cast<size_t>(drawbuffer) < blendStateExt.getDrawBufferCount());
+ return blendStateExt.getColorMaskIndexed(static_cast<size_t>(drawbuffer)) == 0;
+}
+
+bool GetIsExternal(const egl::AttributeMap &attribs)
+{
+ return (attribs.get(EGL_EXTERNAL_CONTEXT_ANGLE, EGL_FALSE) == EGL_TRUE);
+}
+
+bool GetSaveAndRestoreState(const egl::AttributeMap &attribs)
+{
+ return (attribs.get(EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE, EGL_FALSE) == EGL_TRUE);
+}
+
+void GetPerfMonitorString(const std::string &name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *stringOut)
+{
+ GLsizei numCharsWritten = std::min(bufSize, static_cast<GLsizei>(name.size()));
+
+ if (length)
+ {
+ if (bufSize == 0)
+ {
+ *length = static_cast<GLsizei>(name.size());
+ }
+ else
+ {
+ // Excludes null terminator.
+ ASSERT(numCharsWritten > 0);
+ *length = numCharsWritten - 1;
+ }
+ }
+
+ if (stringOut)
+ {
+ memcpy(stringOut, name.c_str(), numCharsWritten);
+ }
+}
+
+bool CanSupportAEP(const gl::Version &version, const gl::Extensions &extensions)
+{
+ // From the GL_ANDROID_extension_pack_es31a extension spec:
+ // OpenGL ES 3.1 and GLSL ES 3.10 are required.
+ // The following extensions are required:
+ // * KHR_debug
+ // * KHR_texture_compression_astc_ldr
+ // * KHR_blend_equation_advanced
+ // * OES_sample_shading
+ // * OES_sample_variables
+ // * OES_shader_image_atomic
+ // * OES_shader_multisample_interpolation
+ // * OES_texture_stencil8
+ // * OES_texture_storage_multisample_2d_array
+ // * EXT_copy_image
+ // * EXT_draw_buffers_indexed
+ // * EXT_geometry_shader
+ // * EXT_gpu_shader5
+ // * EXT_primitive_bounding_box
+ // * EXT_shader_io_blocks
+ // * EXT_tessellation_shader
+ // * EXT_texture_border_clamp
+ // * EXT_texture_buffer
+ // * EXT_texture_cube_map_array
+ // * EXT_texture_sRGB_decode
+ return (version >= ES_3_1 && extensions.debugKHR && extensions.textureCompressionAstcLdrKHR &&
+ extensions.blendEquationAdvancedKHR && extensions.sampleShadingOES &&
+ extensions.sampleVariablesOES && extensions.shaderImageAtomicOES &&
+ extensions.shaderMultisampleInterpolationOES && extensions.textureStencil8OES &&
+ extensions.textureStorageMultisample2dArrayOES && extensions.copyImageEXT &&
+ extensions.drawBuffersIndexedEXT && extensions.geometryShaderEXT &&
+ extensions.gpuShader5EXT && extensions.primitiveBoundingBoxEXT &&
+ extensions.shaderIoBlocksEXT && extensions.tessellationShaderEXT &&
+ extensions.textureBorderClampEXT && extensions.textureBufferEXT &&
+ extensions.textureCubeMapArrayEXT && extensions.textureSRGBDecodeEXT);
+}
+} // anonymous namespace
+
+#if defined(ANGLE_PLATFORM_APPLE)
+// TODO(angleproject:6479): Due to a bug in Apple's dyld loader, `thread_local` will cause
+// excessive memory use. Temporarily avoid it by using pthread's thread
+// local storage instead.
+static TLSIndex GetCurrentValidContextTLSIndex()
+{
+ static TLSIndex CurrentValidContextIndex = TLS_INVALID_INDEX;
+ static dispatch_once_t once;
+ dispatch_once(&once, ^{
+ ASSERT(CurrentValidContextIndex == TLS_INVALID_INDEX);
+ CurrentValidContextIndex = CreateTLSIndex(nullptr);
+ });
+ return CurrentValidContextIndex;
+}
+Context *GetCurrentValidContextTLS()
+{
+ TLSIndex CurrentValidContextIndex = GetCurrentValidContextTLSIndex();
+ ASSERT(CurrentValidContextIndex != TLS_INVALID_INDEX);
+ return static_cast<Context *>(GetTLSValue(CurrentValidContextIndex));
+}
+void SetCurrentValidContextTLS(Context *context)
+{
+ TLSIndex CurrentValidContextIndex = GetCurrentValidContextTLSIndex();
+ ASSERT(CurrentValidContextIndex != TLS_INVALID_INDEX);
+ SetTLSValue(CurrentValidContextIndex, context);
+}
+#else
+thread_local Context *gCurrentValidContext = nullptr;
+#endif
+
+Context::Context(egl::Display *display,
+ const egl::Config *config,
+ const Context *shareContext,
+ TextureManager *shareTextures,
+ SemaphoreManager *shareSemaphores,
+ MemoryProgramCache *memoryProgramCache,
+ MemoryShaderCache *memoryShaderCache,
+ const EGLenum clientType,
+ const egl::AttributeMap &attribs,
+ const egl::DisplayExtensions &displayExtensions,
+ const egl::ClientExtensions &clientExtensions)
+ : mState(shareContext ? &shareContext->mState : nullptr,
+ AllocateOrGetShareGroup(display, shareContext),
+ shareTextures,
+ shareSemaphores,
+ &mOverlay,
+ clientType,
+ GetClientVersion(display, attribs, clientType),
+ GetProfileMask(attribs),
+ GetDebug(attribs),
+ GetBindGeneratesResource(attribs),
+ GetClientArraysEnabled(attribs),
+ GetRobustResourceInit(display, attribs),
+ memoryProgramCache != nullptr,
+ GetContextPriority(attribs),
+ GetRobustAccess(attribs),
+ GetProtectedContent(attribs)),
+ mShared(shareContext != nullptr || shareTextures != nullptr || shareSemaphores != nullptr),
+ mSkipValidation(GetNoError(attribs)),
+ mDisplayTextureShareGroup(shareTextures != nullptr),
+ mDisplaySemaphoreShareGroup(shareSemaphores != nullptr),
+ mErrors(this),
+ mImplementation(display->getImplementation()
+ ->createContext(mState, &mErrors, config, shareContext, attribs)),
+ mLabel(nullptr),
+ mCompiler(),
+ mConfig(config),
+ mHasBeenCurrent(false),
+ mContextLost(false),
+ mResetStatus(GraphicsResetStatus::NoError),
+ mContextLostForced(false),
+ mResetStrategy(GetResetStrategy(attribs)),
+ mSurfacelessSupported(displayExtensions.surfacelessContext),
+ mCurrentDrawSurface(static_cast<egl::Surface *>(EGL_NO_SURFACE)),
+ mCurrentReadSurface(static_cast<egl::Surface *>(EGL_NO_SURFACE)),
+ mDisplay(display),
+ mWebGLContext(GetWebGLContext(attribs)),
+ mBufferAccessValidationEnabled(false),
+ mExtensionsEnabled(GetExtensionsEnabled(attribs, mWebGLContext)),
+ mMemoryProgramCache(memoryProgramCache),
+ mMemoryShaderCache(memoryShaderCache),
+ mVertexArrayObserverBinding(this, kVertexArraySubjectIndex),
+ mDrawFramebufferObserverBinding(this, kDrawFramebufferSubjectIndex),
+ mReadFramebufferObserverBinding(this, kReadFramebufferSubjectIndex),
+ mProgramPipelineObserverBinding(this, kProgramPipelineSubjectIndex),
+ mSingleThreadPool(nullptr),
+ mMultiThreadPool(nullptr),
+ mFrameCapture(new angle::FrameCapture),
+ mRefCount(0),
+ mOverlay(mImplementation.get()),
+ mIsExternal(GetIsExternal(attribs)),
+ mSaveAndRestoreState(GetSaveAndRestoreState(attribs)),
+ mIsDestroyed(false)
+{
+ for (angle::SubjectIndex uboIndex = kUniformBuffer0SubjectIndex;
+ uboIndex < kUniformBufferMaxSubjectIndex; ++uboIndex)
+ {
+ mUniformBufferObserverBindings.emplace_back(this, uboIndex);
+ }
+
+ for (angle::SubjectIndex acbIndex = kAtomicCounterBuffer0SubjectIndex;
+ acbIndex < kAtomicCounterBufferMaxSubjectIndex; ++acbIndex)
+ {
+ mAtomicCounterBufferObserverBindings.emplace_back(this, acbIndex);
+ }
+
+ for (angle::SubjectIndex ssboIndex = kShaderStorageBuffer0SubjectIndex;
+ ssboIndex < kShaderStorageBufferMaxSubjectIndex; ++ssboIndex)
+ {
+ mShaderStorageBufferObserverBindings.emplace_back(this, ssboIndex);
+ }
+
+ for (angle::SubjectIndex samplerIndex = kSampler0SubjectIndex;
+ samplerIndex < kSamplerMaxSubjectIndex; ++samplerIndex)
+ {
+ mSamplerObserverBindings.emplace_back(this, samplerIndex);
+ }
+
+ for (angle::SubjectIndex imageIndex = kImage0SubjectIndex; imageIndex < kImageMaxSubjectIndex;
+ ++imageIndex)
+ {
+ mImageObserverBindings.emplace_back(this, imageIndex);
+ }
+
+ // Implementations now require the display to be set at context creation.
+ ASSERT(mDisplay);
+}
+
+egl::Error Context::initialize()
+{
+ if (!mImplementation)
+ return egl::Error(EGL_NOT_INITIALIZED, "native context creation failed");
+ return egl::NoError();
+}
+
+void Context::initializeDefaultResources()
+{
+ mImplementation->setMemoryProgramCache(mMemoryProgramCache);
+
+ initCaps();
+
+ mState.initialize(this);
+
+ mDefaultFramebuffer = std::make_unique<Framebuffer>(this, mImplementation.get());
+
+ mFenceNVHandleAllocator.setBaseHandle(0);
+
+ // [OpenGL ES 2.0.24] section 3.7 page 83:
+ // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have two-dimensional
+ // and cube map texture state vectors respectively associated with them.
+ // In order that access to these initial textures not be lost, they are treated as texture
+ // objects all of whose names are 0.
+
+ Texture *zeroTexture2D = new Texture(mImplementation.get(), {0}, TextureType::_2D);
+ mZeroTextures[TextureType::_2D].set(this, zeroTexture2D);
+
+ Texture *zeroTextureCube = new Texture(mImplementation.get(), {0}, TextureType::CubeMap);
+ mZeroTextures[TextureType::CubeMap].set(this, zeroTextureCube);
+
+ if (getClientVersion() >= Version(3, 0) || mSupportedExtensions.texture3DOES)
+ {
+ Texture *zeroTexture3D = new Texture(mImplementation.get(), {0}, TextureType::_3D);
+ mZeroTextures[TextureType::_3D].set(this, zeroTexture3D);
+ }
+ if (getClientVersion() >= Version(3, 0))
+ {
+ Texture *zeroTexture2DArray =
+ new Texture(mImplementation.get(), {0}, TextureType::_2DArray);
+ mZeroTextures[TextureType::_2DArray].set(this, zeroTexture2DArray);
+ }
+ if (getClientVersion() >= Version(3, 1) || mSupportedExtensions.textureMultisampleANGLE)
+ {
+ Texture *zeroTexture2DMultisample =
+ new Texture(mImplementation.get(), {0}, TextureType::_2DMultisample);
+ mZeroTextures[TextureType::_2DMultisample].set(this, zeroTexture2DMultisample);
+ }
+ if (getClientVersion() >= Version(3, 1))
+ {
+ Texture *zeroTexture2DMultisampleArray =
+ new Texture(mImplementation.get(), {0}, TextureType::_2DMultisampleArray);
+ mZeroTextures[TextureType::_2DMultisampleArray].set(this, zeroTexture2DMultisampleArray);
+
+ for (int i = 0; i < mState.mCaps.maxAtomicCounterBufferBindings; i++)
+ {
+ bindBufferRange(BufferBinding::AtomicCounter, i, {0}, 0, 0);
+ }
+
+ for (int i = 0; i < mState.mCaps.maxShaderStorageBufferBindings; i++)
+ {
+ bindBufferRange(BufferBinding::ShaderStorage, i, {0}, 0, 0);
+ }
+ }
+
+ if ((getClientType() != EGL_OPENGL_API && getClientVersion() >= Version(3, 2)) ||
+ mSupportedExtensions.textureCubeMapArrayAny())
+ {
+ Texture *zeroTextureCubeMapArray =
+ new Texture(mImplementation.get(), {0}, TextureType::CubeMapArray);
+ mZeroTextures[TextureType::CubeMapArray].set(this, zeroTextureCubeMapArray);
+ }
+
+ if ((getClientType() != EGL_OPENGL_API && getClientVersion() >= Version(3, 2)) ||
+ mSupportedExtensions.textureBufferAny())
+ {
+ Texture *zeroTextureBuffer = new Texture(mImplementation.get(), {0}, TextureType::Buffer);
+ mZeroTextures[TextureType::Buffer].set(this, zeroTextureBuffer);
+ }
+
+ if (mSupportedExtensions.textureRectangleANGLE)
+ {
+ Texture *zeroTextureRectangle =
+ new Texture(mImplementation.get(), {0}, TextureType::Rectangle);
+ mZeroTextures[TextureType::Rectangle].set(this, zeroTextureRectangle);
+ }
+
+ if (mSupportedExtensions.EGLImageExternalOES ||
+ mSupportedExtensions.EGLStreamConsumerExternalNV)
+ {
+ Texture *zeroTextureExternal =
+ new Texture(mImplementation.get(), {0}, TextureType::External);
+ mZeroTextures[TextureType::External].set(this, zeroTextureExternal);
+ }
+
+ // This may change native TEXTURE_2D, TEXTURE_EXTERNAL_OES and TEXTURE_RECTANGLE,
+ // binding states. Ensure state manager is aware of this when binding
+ // this texture type.
+ if (mSupportedExtensions.videoTextureWEBGL)
+ {
+ Texture *zeroTextureVideoImage =
+ new Texture(mImplementation.get(), {0}, TextureType::VideoImage);
+ mZeroTextures[TextureType::VideoImage].set(this, zeroTextureVideoImage);
+ }
+
+ mState.initializeZeroTextures(this, mZeroTextures);
+
+ ANGLE_CONTEXT_TRY(mImplementation->initialize());
+
+ // Add context into the share group
+ mState.getShareGroup()->addSharedContext(this);
+
+ bindVertexArray({0});
+
+ if (getClientVersion() >= Version(3, 0))
+ {
+ // [OpenGL ES 3.0.2] section 2.14.1 pg 85:
+ // In the initial state, a default transform feedback object is bound and treated as
+ // a transform feedback object with a name of zero. That object is bound any time
+ // BindTransformFeedback is called with id of zero
+ bindTransformFeedback(GL_TRANSFORM_FEEDBACK, {0});
+ }
+
+ for (auto type : angle::AllEnums<BufferBinding>())
+ {
+ bindBuffer(type, {0});
+ }
+
+ bindRenderbuffer(GL_RENDERBUFFER, {0});
+
+ for (int i = 0; i < mState.mCaps.maxUniformBufferBindings; i++)
+ {
+ bindBufferRange(BufferBinding::Uniform, i, {0}, 0, -1);
+ }
+
+ // Initialize GLES1 renderer if appropriate.
+ if (getClientVersion() < Version(2, 0))
+ {
+ mGLES1Renderer.reset(new GLES1Renderer());
+ }
+
+ // Initialize dirty bit masks
+ mAllDirtyBits.set();
+
+ mDrawDirtyObjects.set(State::DIRTY_OBJECT_ACTIVE_TEXTURES);
+ mDrawDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+ mDrawDirtyObjects.set(State::DIRTY_OBJECT_VERTEX_ARRAY);
+ mDrawDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES);
+ mDrawDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM);
+ mDrawDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT);
+ mDrawDirtyObjects.set(State::DIRTY_OBJECT_SAMPLERS);
+ mDrawDirtyObjects.set(State::DIRTY_OBJECT_IMAGES);
+
+ mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_STATE);
+ mTexImageDirtyBits.set(State::DIRTY_BIT_UNPACK_BUFFER_BINDING);
+ mTexImageDirtyBits.set(State::DIRTY_BIT_EXTENDED);
+ // No dirty objects.
+
+ // Readpixels uses the pack state and read FBO
+ mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_STATE);
+ mReadPixelsDirtyBits.set(State::DIRTY_BIT_PACK_BUFFER_BINDING);
+ mReadPixelsDirtyBits.set(State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
+ mReadPixelsDirtyObjects.set(State::DIRTY_OBJECT_READ_FRAMEBUFFER);
+
+ mClearDirtyBits.set(State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
+ mClearDirtyBits.set(State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
+ mClearDirtyBits.set(State::DIRTY_BIT_SCISSOR);
+ mClearDirtyBits.set(State::DIRTY_BIT_VIEWPORT);
+ mClearDirtyBits.set(State::DIRTY_BIT_CLEAR_COLOR);
+ mClearDirtyBits.set(State::DIRTY_BIT_CLEAR_DEPTH);
+ mClearDirtyBits.set(State::DIRTY_BIT_CLEAR_STENCIL);
+ mClearDirtyBits.set(State::DIRTY_BIT_COLOR_MASK);
+ mClearDirtyBits.set(State::DIRTY_BIT_DEPTH_MASK);
+ mClearDirtyBits.set(State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+ mClearDirtyBits.set(State::DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+ mClearDirtyBits.set(State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
+ mClearDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+
+ // We sync the draw Framebuffer manually in prepareForClear to allow the clear calls to do
+ // more custom handling for robust resource init.
+
+ mBlitDirtyBits.set(State::DIRTY_BIT_SCISSOR_TEST_ENABLED);
+ mBlitDirtyBits.set(State::DIRTY_BIT_SCISSOR);
+ mBlitDirtyBits.set(State::DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE);
+ mBlitDirtyBits.set(State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
+ mBlitDirtyBits.set(State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
+ mBlitDirtyObjects.set(State::DIRTY_OBJECT_READ_FRAMEBUFFER);
+ mBlitDirtyObjects.set(State::DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+
+ mComputeDirtyBits.set(State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
+ mComputeDirtyBits.set(State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
+ mComputeDirtyBits.set(State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
+ mComputeDirtyBits.set(State::DIRTY_BIT_PROGRAM_BINDING);
+ mComputeDirtyBits.set(State::DIRTY_BIT_PROGRAM_EXECUTABLE);
+ mComputeDirtyBits.set(State::DIRTY_BIT_TEXTURE_BINDINGS);
+ mComputeDirtyBits.set(State::DIRTY_BIT_SAMPLER_BINDINGS);
+ mComputeDirtyBits.set(State::DIRTY_BIT_IMAGE_BINDINGS);
+ mComputeDirtyBits.set(State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING);
+ mComputeDirtyObjects.set(State::DIRTY_OBJECT_ACTIVE_TEXTURES);
+ mComputeDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES);
+ mComputeDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM);
+ mComputeDirtyObjects.set(State::DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT);
+ mComputeDirtyObjects.set(State::DIRTY_OBJECT_IMAGES);
+ mComputeDirtyObjects.set(State::DIRTY_OBJECT_SAMPLERS);
+
+ mCopyImageDirtyBits.set(State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
+ mCopyImageDirtyObjects.set(State::DIRTY_OBJECT_READ_FRAMEBUFFER);
+
+ mReadInvalidateDirtyBits.set(State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
+ mDrawInvalidateDirtyBits.set(State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
+
+ mOverlay.init();
+}
+
+egl::Error Context::onDestroy(const egl::Display *display)
+{
+ if (!mHasBeenCurrent)
+ {
+ // The context is never current, so default resources are not allocated.
+ return egl::NoError();
+ }
+
+ // eglDestoryContext() must have been called for this Context and there must not be any Threads
+ // that still have it current.
+ ASSERT(mIsDestroyed == true && mRefCount == 0);
+
+ // Dump frame capture if enabled.
+ getShareGroup()->getFrameCaptureShared()->onDestroyContext(this);
+
+ // Remove context from the capture share group
+ getShareGroup()->removeSharedContext(this);
+
+ if (mGLES1Renderer)
+ {
+ mGLES1Renderer->onDestroy(this, &mState);
+ }
+
+ ANGLE_TRY(unMakeCurrent(display));
+
+ mDefaultFramebuffer->onDestroy(this);
+ mDefaultFramebuffer.reset();
+
+ for (auto fence : mFenceNVMap)
+ {
+ if (fence.second)
+ {
+ fence.second->onDestroy(this);
+ }
+ SafeDelete(fence.second);
+ }
+ mFenceNVMap.clear();
+
+ for (auto query : mQueryMap)
+ {
+ if (query.second != nullptr)
+ {
+ query.second->release(this);
+ }
+ }
+ mQueryMap.clear();
+
+ for (auto vertexArray : mVertexArrayMap)
+ {
+ if (vertexArray.second)
+ {
+ vertexArray.second->onDestroy(this);
+ }
+ }
+ mVertexArrayMap.clear();
+
+ for (auto transformFeedback : mTransformFeedbackMap)
+ {
+ if (transformFeedback.second != nullptr)
+ {
+ transformFeedback.second->release(this);
+ }
+ }
+ mTransformFeedbackMap.clear();
+
+ for (BindingPointer<Texture> &zeroTexture : mZeroTextures)
+ {
+ if (zeroTexture.get() != nullptr)
+ {
+ zeroTexture.set(this, nullptr);
+ }
+ }
+
+ releaseShaderCompiler();
+
+ mState.reset(this);
+
+ mState.mBufferManager->release(this);
+ // mProgramPipelineManager must be before mShaderProgramManager to give each
+ // PPO the chance to release any references they have to the Programs that
+ // are bound to them before the Programs are released()'ed.
+ mState.mProgramPipelineManager->release(this);
+ mState.mShaderProgramManager->release(this);
+ mState.mTextureManager->release(this);
+ mState.mRenderbufferManager->release(this);
+ mState.mSamplerManager->release(this);
+ mState.mSyncManager->release(this);
+ mState.mFramebufferManager->release(this);
+ mState.mMemoryObjectManager->release(this);
+ mState.mSemaphoreManager->release(this);
+
+ mSingleThreadPool.reset();
+ mMultiThreadPool.reset();
+
+ mImplementation->onDestroy(this);
+
+ // Backend requires implementation to be destroyed first to close down all the objects
+ mState.mShareGroup->release(display);
+
+ mOverlay.destroy(this);
+
+ return egl::NoError();
+}
+
+Context::~Context() {}
+
+void Context::setLabel(EGLLabelKHR label)
+{
+ mLabel = label;
+}
+
+EGLLabelKHR Context::getLabel() const
+{
+ return mLabel;
+}
+
+egl::Error Context::makeCurrent(egl::Display *display,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface)
+{
+ mDisplay = display;
+
+ if (!mHasBeenCurrent)
+ {
+ initializeDefaultResources();
+ initRendererString();
+ initVersionStrings();
+ initExtensionStrings();
+
+ int width = 0;
+ int height = 0;
+ if (drawSurface != nullptr)
+ {
+ width = drawSurface->getWidth();
+ height = drawSurface->getHeight();
+ }
+
+ mState.setViewportParams(0, 0, width, height);
+ mState.setScissorParams(0, 0, width, height);
+
+ mHasBeenCurrent = true;
+ }
+
+ ANGLE_TRY(unsetDefaultFramebuffer());
+
+ getShareGroup()->getFrameCaptureShared()->onMakeCurrent(this, drawSurface);
+
+ // TODO(jmadill): Rework this when we support ContextImpl
+ mState.setAllDirtyBits();
+ mState.setAllDirtyObjects();
+
+ ANGLE_TRY(setDefaultFramebuffer(drawSurface, readSurface));
+
+ // Notify the renderer of a context switch.
+ angle::Result implResult = mImplementation->onMakeCurrent(this);
+
+ // If the implementation fails onMakeCurrent, unset the default framebuffer.
+ if (implResult != angle::Result::Continue)
+ {
+ ANGLE_TRY(unsetDefaultFramebuffer());
+ return angle::ResultToEGL(implResult);
+ }
+
+ return egl::NoError();
+}
+
+egl::Error Context::unMakeCurrent(const egl::Display *display)
+{
+ ANGLE_TRY(angle::ResultToEGL(mImplementation->onUnMakeCurrent(this)));
+
+ ANGLE_TRY(unsetDefaultFramebuffer());
+
+ // Return the scratch buffers to the display so they can be shared with other contexts while
+ // this one is not current.
+ if (mScratchBuffer.valid())
+ {
+ mDisplay->returnScratchBuffer(mScratchBuffer.release());
+ }
+ if (mZeroFilledBuffer.valid())
+ {
+ mDisplay->returnZeroFilledBuffer(mZeroFilledBuffer.release());
+ }
+
+ return egl::NoError();
+}
+
+BufferID Context::createBuffer()
+{
+ return mState.mBufferManager->createBuffer();
+}
+
+GLuint Context::createProgram()
+{
+ return mState.mShaderProgramManager->createProgram(mImplementation.get()).value;
+}
+
+GLuint Context::createShader(ShaderType type)
+{
+ return mState.mShaderProgramManager
+ ->createShader(mImplementation.get(), mState.mLimitations, type)
+ .value;
+}
+
+TextureID Context::createTexture()
+{
+ return mState.mTextureManager->createTexture();
+}
+
+RenderbufferID Context::createRenderbuffer()
+{
+ return mState.mRenderbufferManager->createRenderbuffer();
+}
+
+// Returns an unused framebuffer name
+FramebufferID Context::createFramebuffer()
+{
+ return mState.mFramebufferManager->createFramebuffer();
+}
+
+void Context::genFencesNV(GLsizei n, FenceNVID *fences)
+{
+ for (int i = 0; i < n; i++)
+ {
+ GLuint handle = mFenceNVHandleAllocator.allocate();
+ mFenceNVMap.assign({handle}, new FenceNV(mImplementation.get()));
+ fences[i] = {handle};
+ }
+}
+
+ProgramPipelineID Context::createProgramPipeline()
+{
+ return mState.mProgramPipelineManager->createProgramPipeline();
+}
+
+GLuint Context::createShaderProgramv(ShaderType type, GLsizei count, const GLchar *const *strings)
+{
+ const ShaderProgramID shaderID = PackParam<ShaderProgramID>(createShader(type));
+ if (shaderID.value)
+ {
+ Shader *shaderObject = getShader(shaderID);
+ ASSERT(shaderObject);
+ shaderObject->setSource(count, strings, nullptr);
+ shaderObject->compile(this);
+ const ShaderProgramID programID = PackParam<ShaderProgramID>(createProgram());
+ if (programID.value)
+ {
+ gl::Program *programObject = getProgramNoResolveLink(programID);
+ ASSERT(programObject);
+
+ if (shaderObject->isCompiled(this))
+ {
+ // As per Khronos issue 2261:
+ // https://gitlab.khronos.org/Tracker/vk-gl-cts/issues/2261
+ // We must wait to mark the program separable until it's successfully compiled.
+ programObject->setSeparable(true);
+
+ programObject->attachShader(shaderObject);
+
+ if (programObject->link(this) != angle::Result::Continue)
+ {
+ deleteShader(shaderID);
+ deleteProgram(programID);
+ return 0u;
+ }
+ if (onProgramLink(programObject) != angle::Result::Continue)
+ {
+ deleteShader(shaderID);
+ deleteProgram(programID);
+ return 0u;
+ }
+
+ programObject->detachShader(this, shaderObject);
+ }
+
+ InfoLog &programInfoLog = programObject->getExecutable().getInfoLog();
+ programInfoLog << shaderObject->getInfoLogString();
+ }
+
+ deleteShader(shaderID);
+
+ return programID.value;
+ }
+
+ return 0u;
+}
+
+MemoryObjectID Context::createMemoryObject()
+{
+ return mState.mMemoryObjectManager->createMemoryObject(mImplementation.get());
+}
+
+SemaphoreID Context::createSemaphore()
+{
+ return mState.mSemaphoreManager->createSemaphore(mImplementation.get());
+}
+
+void Context::deleteBuffer(BufferID bufferName)
+{
+ Buffer *buffer = mState.mBufferManager->getBuffer(bufferName);
+ if (buffer)
+ {
+ detachBuffer(buffer);
+ }
+
+ mState.mBufferManager->deleteObject(this, bufferName);
+}
+
+void Context::deleteShader(ShaderProgramID shader)
+{
+ mState.mShaderProgramManager->deleteShader(this, shader);
+}
+
+void Context::deleteProgram(ShaderProgramID program)
+{
+ mState.mShaderProgramManager->deleteProgram(this, program);
+}
+
+void Context::deleteTexture(TextureID texture)
+{
+ if (mState.mTextureManager->getTexture(texture))
+ {
+ detachTexture(texture);
+ }
+
+ mState.mTextureManager->deleteObject(this, texture);
+}
+
+void Context::deleteRenderbuffer(RenderbufferID renderbuffer)
+{
+ if (mState.mRenderbufferManager->getRenderbuffer(renderbuffer))
+ {
+ detachRenderbuffer(renderbuffer);
+ }
+
+ mState.mRenderbufferManager->deleteObject(this, renderbuffer);
+}
+
+void Context::deleteSync(GLsync sync)
+{
+ // The spec specifies the underlying Fence object is not deleted until all current
+ // wait commands finish. However, since the name becomes invalid, we cannot query the fence,
+ // and since our API is currently designed for being called from a single thread, we can delete
+ // the fence immediately.
+ mState.mSyncManager->deleteObject(this, static_cast<GLuint>(reinterpret_cast<uintptr_t>(sync)));
+}
+
+void Context::deleteProgramPipeline(ProgramPipelineID pipelineID)
+{
+ ProgramPipeline *pipeline = mState.mProgramPipelineManager->getProgramPipeline(pipelineID);
+ if (pipeline)
+ {
+ detachProgramPipeline(pipelineID);
+ }
+
+ mState.mProgramPipelineManager->deleteObject(this, pipelineID);
+}
+
+void Context::deleteMemoryObject(MemoryObjectID memoryObject)
+{
+ mState.mMemoryObjectManager->deleteMemoryObject(this, memoryObject);
+}
+
+void Context::deleteSemaphore(SemaphoreID semaphore)
+{
+ mState.mSemaphoreManager->deleteSemaphore(this, semaphore);
+}
+
+// GL_CHROMIUM_lose_context
+void Context::loseContext(GraphicsResetStatus current, GraphicsResetStatus other)
+{
+ // TODO(geofflang): mark the rest of the share group lost. Requires access to the entire share
+ // group from a context. http://anglebug.com/3379
+ markContextLost(current);
+}
+
+void Context::deleteFramebuffer(FramebufferID framebufferID)
+{
+ // We are responsible for deleting the GL objects from the Framebuffer's pixel local storage.
+ std::unique_ptr<PixelLocalStorage> plsToDelete;
+
+ Framebuffer *framebuffer = mState.mFramebufferManager->getFramebuffer(framebufferID);
+ if (framebuffer)
+ {
+ plsToDelete = framebuffer->detachPixelLocalStorage();
+ detachFramebuffer(framebufferID);
+ }
+
+ mState.mFramebufferManager->deleteObject(this, framebufferID);
+
+ // Delete the pixel local storage GL objects after the framebuffer, in order to avoid any
+ // potential trickyness with orphaning.
+ if (plsToDelete)
+ {
+ plsToDelete->deleteContextObjects(this);
+ }
+}
+
+void Context::deleteFencesNV(GLsizei n, const FenceNVID *fences)
+{
+ for (int i = 0; i < n; i++)
+ {
+ FenceNVID fence = fences[i];
+
+ FenceNV *fenceObject = nullptr;
+ if (mFenceNVMap.erase(fence, &fenceObject))
+ {
+ mFenceNVHandleAllocator.release(fence.value);
+ if (fenceObject)
+ {
+ fenceObject->onDestroy(this);
+ }
+ delete fenceObject;
+ }
+ }
+}
+
+Buffer *Context::getBuffer(BufferID handle) const
+{
+ return mState.mBufferManager->getBuffer(handle);
+}
+
+Renderbuffer *Context::getRenderbuffer(RenderbufferID handle) const
+{
+ return mState.mRenderbufferManager->getRenderbuffer(handle);
+}
+
+EGLenum Context::getContextPriority() const
+{
+ return egl::ToEGLenum(mImplementation->getContextPriority());
+}
+
+Sync *Context::getSync(GLsync handle) const
+{
+ return mState.mSyncManager->getSync(static_cast<GLuint>(reinterpret_cast<uintptr_t>(handle)));
+}
+
+VertexArray *Context::getVertexArray(VertexArrayID handle) const
+{
+ return mVertexArrayMap.query(handle);
+}
+
+Sampler *Context::getSampler(SamplerID handle) const
+{
+ return mState.mSamplerManager->getSampler(handle);
+}
+
+TransformFeedback *Context::getTransformFeedback(TransformFeedbackID handle) const
+{
+ return mTransformFeedbackMap.query(handle);
+}
+
+ProgramPipeline *Context::getProgramPipeline(ProgramPipelineID handle) const
+{
+ return mState.mProgramPipelineManager->getProgramPipeline(handle);
+}
+
+gl::LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const
+{
+ switch (identifier)
+ {
+ case GL_BUFFER:
+ case GL_BUFFER_OBJECT_EXT:
+ return getBuffer({name});
+ case GL_SHADER:
+ case GL_SHADER_OBJECT_EXT:
+ return getShader({name});
+ case GL_PROGRAM:
+ case GL_PROGRAM_OBJECT_EXT:
+ return getProgramNoResolveLink({name});
+ case GL_VERTEX_ARRAY:
+ case GL_VERTEX_ARRAY_OBJECT_EXT:
+ return getVertexArray({name});
+ case GL_QUERY:
+ case GL_QUERY_OBJECT_EXT:
+ return getQuery({name});
+ case GL_TRANSFORM_FEEDBACK:
+ return getTransformFeedback({name});
+ case GL_SAMPLER:
+ return getSampler({name});
+ case GL_TEXTURE:
+ return getTexture({name});
+ case GL_RENDERBUFFER:
+ return getRenderbuffer({name});
+ case GL_FRAMEBUFFER:
+ return getFramebuffer({name});
+ case GL_PROGRAM_PIPELINE:
+ case GL_PROGRAM_PIPELINE_OBJECT_EXT:
+ return getProgramPipeline({name});
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+
+gl::LabeledObject *Context::getLabeledObjectFromPtr(const void *ptr) const
+{
+ return getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr)));
+}
+
+void Context::objectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar *label)
+{
+ gl::LabeledObject *object = getLabeledObject(identifier, name);
+ ASSERT(object != nullptr);
+
+ std::string labelName = GetObjectLabelFromPointer(length, label);
+ ANGLE_CONTEXT_TRY(object->setLabel(this, labelName));
+
+ // TODO(jmadill): Determine if the object is dirty based on 'name'. Conservatively assume the
+ // specified object is active until we do this.
+ mState.setObjectDirty(identifier);
+}
+
+void Context::labelObject(GLenum type, GLuint object, GLsizei length, const GLchar *label)
+{
+ gl::LabeledObject *obj = getLabeledObject(type, object);
+ ASSERT(obj != nullptr);
+
+ std::string labelName = "";
+ if (label != nullptr)
+ {
+ size_t labelLength = length == 0 ? strlen(label) : length;
+ labelName = std::string(label, labelLength);
+ }
+ ANGLE_CONTEXT_TRY(obj->setLabel(this, labelName));
+ mState.setObjectDirty(type);
+}
+
+void Context::objectPtrLabel(const void *ptr, GLsizei length, const GLchar *label)
+{
+ gl::LabeledObject *object = getLabeledObjectFromPtr(ptr);
+ ASSERT(object != nullptr);
+
+ std::string labelName = GetObjectLabelFromPointer(length, label);
+ ANGLE_CONTEXT_TRY(object->setLabel(this, labelName));
+}
+
+void Context::getObjectLabel(GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label)
+{
+ gl::LabeledObject *object = getLabeledObject(identifier, name);
+ ASSERT(object != nullptr);
+
+ const std::string &objectLabel = object->getLabel();
+ GetObjectLabelBase(objectLabel, bufSize, length, label);
+}
+
+void Context::getObjectPtrLabel(const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label)
+{
+ gl::LabeledObject *object = getLabeledObjectFromPtr(ptr);
+ ASSERT(object != nullptr);
+
+ const std::string &objectLabel = object->getLabel();
+ GetObjectLabelBase(objectLabel, bufSize, length, label);
+}
+
+GLboolean Context::isSampler(SamplerID samplerName) const
+{
+ return mState.mSamplerManager->isSampler(samplerName);
+}
+
+void Context::bindTexture(TextureType target, TextureID handle)
+{
+ // Some apps enable KHR_create_context_no_error but pass in an invalid texture type.
+ // Workaround this by silently returning in such situations.
+ if (target == TextureType::InvalidEnum)
+ {
+ return;
+ }
+
+ Texture *texture = nullptr;
+ if (handle.value == 0)
+ {
+ texture = mZeroTextures[target].get();
+ }
+ else
+ {
+ texture =
+ mState.mTextureManager->checkTextureAllocation(mImplementation.get(), handle, target);
+ }
+
+ ASSERT(texture);
+ // Early return if rebinding the same texture
+ if (texture == mState.getTargetTexture(target))
+ {
+ return;
+ }
+
+ mState.setSamplerTexture(this, target, texture);
+ mStateCache.onActiveTextureChange(this);
+}
+
+void Context::bindReadFramebuffer(FramebufferID framebufferHandle)
+{
+ Framebuffer *framebuffer = mState.mFramebufferManager->checkFramebufferAllocation(
+ mImplementation.get(), this, framebufferHandle);
+ mState.setReadFramebufferBinding(framebuffer);
+ mReadFramebufferObserverBinding.bind(framebuffer);
+}
+
+void Context::bindDrawFramebuffer(FramebufferID framebufferHandle)
+{
+ Framebuffer *framebuffer = mState.mFramebufferManager->checkFramebufferAllocation(
+ mImplementation.get(), this, framebufferHandle);
+ mState.setDrawFramebufferBinding(framebuffer);
+ mDrawFramebufferObserverBinding.bind(framebuffer);
+ mStateCache.onDrawFramebufferChange(this);
+}
+
+void Context::bindVertexArray(VertexArrayID vertexArrayHandle)
+{
+ VertexArray *vertexArray = checkVertexArrayAllocation(vertexArrayHandle);
+ mState.setVertexArrayBinding(this, vertexArray);
+ mVertexArrayObserverBinding.bind(vertexArray);
+ mStateCache.onVertexArrayBindingChange(this);
+}
+
+void Context::bindVertexBuffer(GLuint bindingIndex,
+ BufferID bufferHandle,
+ GLintptr offset,
+ GLsizei stride)
+{
+ Buffer *buffer =
+ mState.mBufferManager->checkBufferAllocation(mImplementation.get(), bufferHandle);
+ mState.bindVertexBuffer(this, bindingIndex, buffer, offset, stride);
+ mStateCache.onVertexArrayStateChange(this);
+}
+
+void Context::bindSampler(GLuint textureUnit, SamplerID samplerHandle)
+{
+ ASSERT(textureUnit < static_cast<GLuint>(mState.mCaps.maxCombinedTextureImageUnits));
+ Sampler *sampler =
+ mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), samplerHandle);
+
+ // Early return if rebinding the same sampler
+ if (sampler == mState.getSampler(textureUnit))
+ {
+ return;
+ }
+
+ mState.setSamplerBinding(this, textureUnit, sampler);
+ mSamplerObserverBindings[textureUnit].bind(sampler);
+ mStateCache.onActiveTextureChange(this);
+}
+
+void Context::bindImageTexture(GLuint unit,
+ TextureID texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format)
+{
+ Texture *tex = mState.mTextureManager->getTexture(texture);
+ mState.setImageUnit(this, unit, tex, level, layered, layer, access, format);
+ mImageObserverBindings[unit].bind(tex);
+}
+
+void Context::useProgram(ShaderProgramID program)
+{
+ ANGLE_CONTEXT_TRY(mState.setProgram(this, getProgramResolveLink(program)));
+ mStateCache.onProgramExecutableChange(this);
+}
+
+void Context::useProgramStages(ProgramPipelineID pipeline,
+ GLbitfield stages,
+ ShaderProgramID program)
+{
+ Program *shaderProgram = getProgramNoResolveLink(program);
+ ProgramPipeline *programPipeline =
+ mState.mProgramPipelineManager->checkProgramPipelineAllocation(mImplementation.get(),
+ pipeline);
+
+ ASSERT(programPipeline);
+ ANGLE_CONTEXT_TRY(programPipeline->useProgramStages(this, stages, shaderProgram));
+}
+
+void Context::bindTransformFeedback(GLenum target, TransformFeedbackID transformFeedbackHandle)
+{
+ ASSERT(target == GL_TRANSFORM_FEEDBACK);
+ TransformFeedback *transformFeedback =
+ checkTransformFeedbackAllocation(transformFeedbackHandle);
+ mState.setTransformFeedbackBinding(this, transformFeedback);
+ mStateCache.onActiveTransformFeedbackChange(this);
+}
+
+void Context::bindProgramPipeline(ProgramPipelineID pipelineHandle)
+{
+ ProgramPipeline *pipeline = mState.mProgramPipelineManager->checkProgramPipelineAllocation(
+ mImplementation.get(), pipelineHandle);
+ ANGLE_CONTEXT_TRY(mState.setProgramPipelineBinding(this, pipeline));
+ mStateCache.onProgramExecutableChange(this);
+ mProgramPipelineObserverBinding.bind(pipeline);
+}
+
+void Context::beginQuery(QueryType target, QueryID query)
+{
+ Query *queryObject = getOrCreateQuery(query, target);
+ ASSERT(queryObject);
+
+ // begin query
+ ANGLE_CONTEXT_TRY(queryObject->begin(this));
+
+ // set query as active for specified target only if begin succeeded
+ mState.setActiveQuery(this, target, queryObject);
+ mStateCache.onQueryChange(this);
+}
+
+void Context::endQuery(QueryType target)
+{
+ Query *queryObject = mState.getActiveQuery(target);
+ ASSERT(queryObject);
+
+ // Intentionally don't call try here. We don't want an early return.
+ (void)(queryObject->end(this));
+
+ // Always unbind the query, even if there was an error. This may delete the query object.
+ mState.setActiveQuery(this, target, nullptr);
+ mStateCache.onQueryChange(this);
+}
+
+void Context::queryCounter(QueryID id, QueryType target)
+{
+ ASSERT(target == QueryType::Timestamp);
+
+ Query *queryObject = getOrCreateQuery(id, target);
+ ASSERT(queryObject);
+
+ ANGLE_CONTEXT_TRY(queryObject->queryCounter(this));
+}
+
+void Context::getQueryiv(QueryType target, GLenum pname, GLint *params)
+{
+ switch (pname)
+ {
+ case GL_CURRENT_QUERY_EXT:
+ params[0] = mState.getActiveQueryId(target).value;
+ break;
+ case GL_QUERY_COUNTER_BITS_EXT:
+ switch (target)
+ {
+ case QueryType::TimeElapsed:
+ params[0] = getCaps().queryCounterBitsTimeElapsed;
+ break;
+ case QueryType::Timestamp:
+ params[0] = getCaps().queryCounterBitsTimestamp;
+ break;
+ default:
+ UNREACHABLE();
+ params[0] = 0;
+ break;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+void Context::getQueryivRobust(QueryType target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ getQueryiv(target, pname, params);
+}
+
+void Context::getUnsignedBytev(GLenum pname, GLubyte *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getUnsignedBytei_v(GLenum target, GLuint index, GLubyte *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getQueryObjectiv(QueryID id, GLenum pname, GLint *params)
+{
+ ANGLE_CONTEXT_TRY(GetQueryObjectParameter(this, getQuery(id), pname, params));
+}
+
+void Context::getQueryObjectivRobust(QueryID id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ getQueryObjectiv(id, pname, params);
+}
+
+void Context::getQueryObjectuiv(QueryID id, GLenum pname, GLuint *params)
+{
+ ANGLE_CONTEXT_TRY(GetQueryObjectParameter(this, getQuery(id), pname, params));
+}
+
+void Context::getQueryObjectuivRobust(QueryID id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ getQueryObjectuiv(id, pname, params);
+}
+
+void Context::getQueryObjecti64v(QueryID id, GLenum pname, GLint64 *params)
+{
+ ANGLE_CONTEXT_TRY(GetQueryObjectParameter(this, getQuery(id), pname, params));
+}
+
+void Context::getQueryObjecti64vRobust(QueryID id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params)
+{
+ getQueryObjecti64v(id, pname, params);
+}
+
+void Context::getQueryObjectui64v(QueryID id, GLenum pname, GLuint64 *params)
+{
+ ANGLE_CONTEXT_TRY(GetQueryObjectParameter(this, getQuery(id), pname, params));
+}
+
+void Context::getQueryObjectui64vRobust(QueryID id,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint64 *params)
+{
+ getQueryObjectui64v(id, pname, params);
+}
+
+Framebuffer *Context::getFramebuffer(FramebufferID handle) const
+{
+ return mState.mFramebufferManager->getFramebuffer(handle);
+}
+
+FenceNV *Context::getFenceNV(FenceNVID handle) const
+{
+ return mFenceNVMap.query(handle);
+}
+
+Query *Context::getOrCreateQuery(QueryID handle, QueryType type)
+{
+ if (!mQueryMap.contains(handle))
+ {
+ return nullptr;
+ }
+
+ Query *query = mQueryMap.query(handle);
+ if (!query)
+ {
+ ASSERT(type != QueryType::InvalidEnum);
+ query = new Query(mImplementation.get(), type, handle);
+ query->addRef();
+ mQueryMap.assign(handle, query);
+ }
+ return query;
+}
+
+Query *Context::getQuery(QueryID handle) const
+{
+ return mQueryMap.query(handle);
+}
+
+Texture *Context::getTextureByType(TextureType type) const
+{
+ ASSERT(ValidTextureTarget(this, type) || ValidTextureExternalTarget(this, type));
+ return mState.getTargetTexture(type);
+}
+
+Texture *Context::getTextureByTarget(TextureTarget target) const
+{
+ return getTextureByType(TextureTargetToType(target));
+}
+
+Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) const
+{
+ return mState.getSamplerTexture(sampler, type);
+}
+
+Compiler *Context::getCompiler() const
+{
+ if (mCompiler.get() == nullptr)
+ {
+ mCompiler.set(this, new Compiler(mImplementation.get(), mState, mDisplay));
+ }
+ return mCompiler.get();
+}
+
+void Context::getBooleanvImpl(GLenum pname, GLboolean *params) const
+{
+ switch (pname)
+ {
+ case GL_SHADER_COMPILER:
+ *params = GL_TRUE;
+ break;
+ case GL_CONTEXT_ROBUST_ACCESS_EXT:
+ *params = ConvertToGLBoolean(mState.hasRobustAccess());
+ break;
+
+ default:
+ mState.getBooleanv(pname, params);
+ break;
+ }
+}
+
+void Context::getFloatvImpl(GLenum pname, GLfloat *params) const
+{
+ // Queries about context capabilities and maximums are answered by Context.
+ // Queries about current GL state values are answered by State.
+ switch (pname)
+ {
+ case GL_ALIASED_LINE_WIDTH_RANGE:
+ params[0] = mState.mCaps.minAliasedLineWidth;
+ params[1] = mState.mCaps.maxAliasedLineWidth;
+ break;
+ case GL_ALIASED_POINT_SIZE_RANGE:
+ params[0] = mState.mCaps.minAliasedPointSize;
+ params[1] = mState.mCaps.maxAliasedPointSize;
+ break;
+ case GL_SMOOTH_POINT_SIZE_RANGE:
+ params[0] = mState.mCaps.minSmoothPointSize;
+ params[1] = mState.mCaps.maxSmoothPointSize;
+ break;
+ case GL_SMOOTH_LINE_WIDTH_RANGE:
+ params[0] = mState.mCaps.minSmoothLineWidth;
+ params[1] = mState.mCaps.maxSmoothLineWidth;
+ break;
+ case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+ ASSERT(mState.mExtensions.textureFilterAnisotropicEXT);
+ *params = mState.mCaps.maxTextureAnisotropy;
+ break;
+ case GL_MAX_TEXTURE_LOD_BIAS:
+ *params = mState.mCaps.maxLODBias;
+ break;
+ case GL_MIN_FRAGMENT_INTERPOLATION_OFFSET:
+ *params = mState.mCaps.minInterpolationOffset;
+ break;
+ case GL_MAX_FRAGMENT_INTERPOLATION_OFFSET:
+ *params = mState.mCaps.maxInterpolationOffset;
+ break;
+ case GL_PRIMITIVE_BOUNDING_BOX:
+ params[0] = mState.mBoundingBoxMinX;
+ params[1] = mState.mBoundingBoxMinY;
+ params[2] = mState.mBoundingBoxMinZ;
+ params[3] = mState.mBoundingBoxMinW;
+ params[4] = mState.mBoundingBoxMaxX;
+ params[5] = mState.mBoundingBoxMaxY;
+ params[6] = mState.mBoundingBoxMaxZ;
+ params[7] = mState.mBoundingBoxMaxW;
+ break;
+ default:
+ mState.getFloatv(pname, params);
+ break;
+ }
+}
+
+void Context::getIntegervImpl(GLenum pname, GLint *params) const
+{
+ // Queries about context capabilities and maximums are answered by Context.
+ // Queries about current GL state values are answered by State.
+
+ switch (pname)
+ {
+ case GL_MAX_VERTEX_ATTRIBS:
+ *params = mState.mCaps.maxVertexAttributes;
+ break;
+ case GL_MAX_VERTEX_UNIFORM_VECTORS:
+ *params = mState.mCaps.maxVertexUniformVectors;
+ break;
+ case GL_MAX_VERTEX_UNIFORM_COMPONENTS:
+ *params = mState.mCaps.maxShaderUniformComponents[ShaderType::Vertex];
+ break;
+ case GL_MAX_VARYING_VECTORS:
+ *params = mState.mCaps.maxVaryingVectors;
+ break;
+ case GL_MAX_VARYING_COMPONENTS:
+ *params = mState.mCaps.maxVaryingVectors * 4;
+ break;
+ case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+ *params = mState.mCaps.maxCombinedTextureImageUnits;
+ break;
+ case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
+ *params = mState.mCaps.maxShaderTextureImageUnits[ShaderType::Vertex];
+ break;
+ case GL_MAX_TEXTURE_IMAGE_UNITS:
+ *params = mState.mCaps.maxShaderTextureImageUnits[ShaderType::Fragment];
+ break;
+ case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
+ *params = mState.mCaps.maxFragmentUniformVectors;
+ break;
+ case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
+ *params = mState.mCaps.maxShaderUniformComponents[ShaderType::Fragment];
+ break;
+ case GL_MAX_RENDERBUFFER_SIZE:
+ *params = mState.mCaps.maxRenderbufferSize;
+ break;
+ case GL_MAX_COLOR_ATTACHMENTS_EXT:
+ *params = mState.mCaps.maxColorAttachments;
+ break;
+ case GL_MAX_DRAW_BUFFERS_EXT:
+ *params = mState.mCaps.maxDrawBuffers;
+ break;
+ case GL_SUBPIXEL_BITS:
+ *params = mState.mCaps.subPixelBits;
+ break;
+ case GL_MAX_TEXTURE_SIZE:
+ *params = mState.mCaps.max2DTextureSize;
+ break;
+ case GL_MAX_RECTANGLE_TEXTURE_SIZE_ANGLE:
+ *params = mState.mCaps.maxRectangleTextureSize;
+ break;
+ case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
+ *params = mState.mCaps.maxCubeMapTextureSize;
+ break;
+ case GL_MAX_3D_TEXTURE_SIZE:
+ *params = mState.mCaps.max3DTextureSize;
+ break;
+ case GL_MAX_ARRAY_TEXTURE_LAYERS:
+ *params = mState.mCaps.maxArrayTextureLayers;
+ break;
+ case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
+ *params = mState.mCaps.uniformBufferOffsetAlignment;
+ break;
+ case GL_MAX_UNIFORM_BUFFER_BINDINGS:
+ *params = mState.mCaps.maxUniformBufferBindings;
+ break;
+ case GL_MAX_VERTEX_UNIFORM_BLOCKS:
+ *params = mState.mCaps.maxShaderUniformBlocks[ShaderType::Vertex];
+ break;
+ case GL_MAX_FRAGMENT_UNIFORM_BLOCKS:
+ *params = mState.mCaps.maxShaderUniformBlocks[ShaderType::Fragment];
+ break;
+ case GL_MAX_COMBINED_UNIFORM_BLOCKS:
+ *params = mState.mCaps.maxCombinedUniformBlocks;
+ break;
+ case GL_MAX_VERTEX_OUTPUT_COMPONENTS:
+ *params = mState.mCaps.maxVertexOutputComponents;
+ break;
+ case GL_MAX_FRAGMENT_INPUT_COMPONENTS:
+ *params = mState.mCaps.maxFragmentInputComponents;
+ break;
+ case GL_MIN_PROGRAM_TEXEL_OFFSET:
+ *params = mState.mCaps.minProgramTexelOffset;
+ break;
+ case GL_MAX_PROGRAM_TEXEL_OFFSET:
+ *params = mState.mCaps.maxProgramTexelOffset;
+ break;
+ case GL_MAJOR_VERSION:
+ *params = getClientVersion().major;
+ break;
+ case GL_MINOR_VERSION:
+ *params = getClientVersion().minor;
+ break;
+ case GL_MAX_ELEMENTS_INDICES:
+ *params = mState.mCaps.maxElementsIndices;
+ break;
+ case GL_MAX_ELEMENTS_VERTICES:
+ *params = mState.mCaps.maxElementsVertices;
+ break;
+ case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
+ *params = mState.mCaps.maxTransformFeedbackInterleavedComponents;
+ break;
+ case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
+ *params = mState.mCaps.maxTransformFeedbackSeparateAttributes;
+ break;
+ case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
+ *params = mState.mCaps.maxTransformFeedbackSeparateComponents;
+ break;
+ case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
+ *params = static_cast<GLint>(mState.mCaps.compressedTextureFormats.size());
+ break;
+ case GL_MAX_SAMPLES_ANGLE:
+ *params = mState.mCaps.maxSamples;
+ break;
+ case GL_MAX_VIEWPORT_DIMS:
+ {
+ params[0] = mState.mCaps.maxViewportWidth;
+ params[1] = mState.mCaps.maxViewportHeight;
+ }
+ break;
+ case GL_COMPRESSED_TEXTURE_FORMATS:
+ std::copy(mState.mCaps.compressedTextureFormats.begin(),
+ mState.mCaps.compressedTextureFormats.end(), params);
+ break;
+ case GL_RESET_NOTIFICATION_STRATEGY_EXT:
+ *params = mResetStrategy;
+ break;
+ case GL_NUM_SHADER_BINARY_FORMATS:
+ *params = static_cast<GLint>(mState.mCaps.shaderBinaryFormats.size());
+ break;
+ case GL_SHADER_BINARY_FORMATS:
+ std::copy(mState.mCaps.shaderBinaryFormats.begin(),
+ mState.mCaps.shaderBinaryFormats.end(), params);
+ break;
+ case GL_NUM_PROGRAM_BINARY_FORMATS:
+ *params = static_cast<GLint>(mState.mCaps.programBinaryFormats.size());
+ break;
+ case GL_PROGRAM_BINARY_FORMATS:
+ std::copy(mState.mCaps.programBinaryFormats.begin(),
+ mState.mCaps.programBinaryFormats.end(), params);
+ break;
+ case GL_NUM_EXTENSIONS:
+ *params = static_cast<GLint>(mExtensionStrings.size());
+ break;
+
+ // Desktop client flags
+ case GL_CONTEXT_FLAGS:
+ {
+ GLint contextFlags = 0;
+ if (mState.hasProtectedContent())
+ {
+ contextFlags |= GL_CONTEXT_FLAG_PROTECTED_CONTENT_BIT_EXT;
+ }
+
+ if (mState.isDebugContext())
+ {
+ contextFlags |= GL_CONTEXT_FLAG_DEBUG_BIT_KHR;
+ }
+
+ if (mState.hasRobustAccess())
+ {
+ contextFlags |= GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT;
+ }
+ *params = contextFlags;
+ }
+ break;
+ case GL_CONTEXT_PROFILE_MASK:
+ ASSERT(getClientType() == EGL_OPENGL_API);
+ *params = mState.getProfileMask();
+ break;
+
+ // GL_ANGLE_request_extension
+ case GL_NUM_REQUESTABLE_EXTENSIONS_ANGLE:
+ *params = static_cast<GLint>(mRequestableExtensionStrings.size());
+ break;
+
+ // GL_KHR_debug
+ case GL_MAX_DEBUG_MESSAGE_LENGTH:
+ *params = mState.mCaps.maxDebugMessageLength;
+ break;
+ case GL_MAX_DEBUG_LOGGED_MESSAGES:
+ *params = mState.mCaps.maxDebugLoggedMessages;
+ break;
+ case GL_MAX_DEBUG_GROUP_STACK_DEPTH:
+ *params = mState.mCaps.maxDebugGroupStackDepth;
+ break;
+ case GL_MAX_LABEL_LENGTH:
+ *params = mState.mCaps.maxLabelLength;
+ break;
+
+ // GL_OVR_multiview2
+ case GL_MAX_VIEWS_OVR:
+ *params = mState.mCaps.maxViews;
+ break;
+
+ // GL_EXT_disjoint_timer_query
+ case GL_GPU_DISJOINT_EXT:
+ *params = mImplementation->getGPUDisjoint();
+ break;
+ case GL_MAX_FRAMEBUFFER_WIDTH:
+ *params = mState.mCaps.maxFramebufferWidth;
+ break;
+ case GL_MAX_FRAMEBUFFER_HEIGHT:
+ *params = mState.mCaps.maxFramebufferHeight;
+ break;
+ case GL_MAX_FRAMEBUFFER_SAMPLES:
+ *params = mState.mCaps.maxFramebufferSamples;
+ break;
+ case GL_MAX_SAMPLE_MASK_WORDS:
+ *params = mState.mCaps.maxSampleMaskWords;
+ break;
+ case GL_MAX_COLOR_TEXTURE_SAMPLES:
+ *params = mState.mCaps.maxColorTextureSamples;
+ break;
+ case GL_MAX_DEPTH_TEXTURE_SAMPLES:
+ *params = mState.mCaps.maxDepthTextureSamples;
+ break;
+ case GL_MAX_INTEGER_SAMPLES:
+ *params = mState.mCaps.maxIntegerSamples;
+ break;
+ case GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET:
+ *params = mState.mCaps.maxVertexAttribRelativeOffset;
+ break;
+ case GL_MAX_VERTEX_ATTRIB_BINDINGS:
+ *params = mState.mCaps.maxVertexAttribBindings;
+ break;
+ case GL_MAX_VERTEX_ATTRIB_STRIDE:
+ *params = mState.mCaps.maxVertexAttribStride;
+ break;
+ case GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS:
+ *params = mState.mCaps.maxShaderAtomicCounterBuffers[ShaderType::Vertex];
+ break;
+ case GL_MAX_VERTEX_ATOMIC_COUNTERS:
+ *params = mState.mCaps.maxShaderAtomicCounters[ShaderType::Vertex];
+ break;
+ case GL_MAX_VERTEX_IMAGE_UNIFORMS:
+ *params = mState.mCaps.maxShaderImageUniforms[ShaderType::Vertex];
+ break;
+ case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
+ *params = mState.mCaps.maxShaderStorageBlocks[ShaderType::Vertex];
+ break;
+ case GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS:
+ *params = mState.mCaps.maxShaderAtomicCounterBuffers[ShaderType::Fragment];
+ break;
+ case GL_MAX_FRAGMENT_ATOMIC_COUNTERS:
+ *params = mState.mCaps.maxShaderAtomicCounters[ShaderType::Fragment];
+ break;
+ case GL_MAX_FRAGMENT_IMAGE_UNIFORMS:
+ *params = mState.mCaps.maxShaderImageUniforms[ShaderType::Fragment];
+ break;
+ case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
+ *params = mState.mCaps.maxShaderStorageBlocks[ShaderType::Fragment];
+ break;
+ case GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET:
+ *params = mState.mCaps.minProgramTextureGatherOffset;
+ break;
+ case GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET:
+ *params = mState.mCaps.maxProgramTextureGatherOffset;
+ break;
+ case GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS:
+ *params = mState.mCaps.maxComputeWorkGroupInvocations;
+ break;
+ case GL_MAX_COMPUTE_UNIFORM_BLOCKS:
+ *params = mState.mCaps.maxShaderUniformBlocks[ShaderType::Compute];
+ break;
+ case GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS:
+ *params = mState.mCaps.maxShaderTextureImageUnits[ShaderType::Compute];
+ break;
+ case GL_MAX_COMPUTE_SHARED_MEMORY_SIZE:
+ *params = mState.mCaps.maxComputeSharedMemorySize;
+ break;
+ case GL_MAX_COMPUTE_UNIFORM_COMPONENTS:
+ *params = mState.mCaps.maxShaderUniformComponents[ShaderType::Compute];
+ break;
+ case GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS:
+ *params = mState.mCaps.maxShaderAtomicCounterBuffers[ShaderType::Compute];
+ break;
+ case GL_MAX_COMPUTE_ATOMIC_COUNTERS:
+ *params = mState.mCaps.maxShaderAtomicCounters[ShaderType::Compute];
+ break;
+ case GL_MAX_COMPUTE_IMAGE_UNIFORMS:
+ *params = mState.mCaps.maxShaderImageUniforms[ShaderType::Compute];
+ break;
+ case GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS:
+ *params = static_cast<GLint>(
+ mState.mCaps.maxCombinedShaderUniformComponents[ShaderType::Compute]);
+ break;
+ case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
+ *params = mState.mCaps.maxShaderStorageBlocks[ShaderType::Compute];
+ break;
+ case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
+ *params = mState.mCaps.maxCombinedShaderOutputResources;
+ break;
+ case GL_MAX_UNIFORM_LOCATIONS:
+ *params = mState.mCaps.maxUniformLocations;
+ break;
+ case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
+ *params = mState.mCaps.maxAtomicCounterBufferBindings;
+ break;
+ case GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE:
+ *params = mState.mCaps.maxAtomicCounterBufferSize;
+ break;
+ case GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS:
+ *params = mState.mCaps.maxCombinedAtomicCounterBuffers;
+ break;
+ case GL_MAX_COMBINED_ATOMIC_COUNTERS:
+ *params = mState.mCaps.maxCombinedAtomicCounters;
+ break;
+ case GL_MAX_IMAGE_UNITS:
+ *params = mState.mCaps.maxImageUnits;
+ break;
+ case GL_MAX_COMBINED_IMAGE_UNIFORMS:
+ *params = mState.mCaps.maxCombinedImageUniforms;
+ break;
+ case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
+ *params = mState.mCaps.maxShaderStorageBufferBindings;
+ break;
+ case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
+ *params = mState.mCaps.maxCombinedShaderStorageBlocks;
+ break;
+ case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
+ *params = mState.mCaps.shaderStorageBufferOffsetAlignment;
+ break;
+
+ // GL_EXT_geometry_shader
+ case GL_MAX_FRAMEBUFFER_LAYERS_EXT:
+ *params = mState.mCaps.maxFramebufferLayers;
+ break;
+ case GL_LAYER_PROVOKING_VERTEX_EXT:
+ *params = mState.mCaps.layerProvokingVertex;
+ break;
+ case GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT:
+ *params = mState.mCaps.maxShaderUniformComponents[ShaderType::Geometry];
+ break;
+ case GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT:
+ *params = mState.mCaps.maxShaderUniformBlocks[ShaderType::Geometry];
+ break;
+ case GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT:
+ *params = static_cast<GLint>(
+ mState.mCaps.maxCombinedShaderUniformComponents[ShaderType::Geometry]);
+ break;
+ case GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT:
+ *params = mState.mCaps.maxGeometryInputComponents;
+ break;
+ case GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT:
+ *params = mState.mCaps.maxGeometryOutputComponents;
+ break;
+ case GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT:
+ *params = mState.mCaps.maxGeometryOutputVertices;
+ break;
+ case GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT:
+ *params = mState.mCaps.maxGeometryTotalOutputComponents;
+ break;
+ case GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT:
+ *params = mState.mCaps.maxGeometryShaderInvocations;
+ break;
+ case GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT:
+ *params = mState.mCaps.maxShaderTextureImageUnits[ShaderType::Geometry];
+ break;
+ case GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT:
+ *params = mState.mCaps.maxShaderAtomicCounterBuffers[ShaderType::Geometry];
+ break;
+ case GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT:
+ *params = mState.mCaps.maxShaderAtomicCounters[ShaderType::Geometry];
+ break;
+ case GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT:
+ *params = mState.mCaps.maxShaderImageUniforms[ShaderType::Geometry];
+ break;
+ case GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT:
+ *params = mState.mCaps.maxShaderStorageBlocks[ShaderType::Geometry];
+ break;
+ // GL_EXT_tessellation_shader
+ case GL_MAX_PATCH_VERTICES_EXT:
+ *params = mState.mCaps.maxPatchVertices;
+ break;
+ case GL_MAX_TESS_GEN_LEVEL_EXT:
+ *params = mState.mCaps.maxTessGenLevel;
+ break;
+ case GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT:
+ *params = mState.mCaps.maxShaderUniformComponents[ShaderType::TessControl];
+ break;
+ case GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT:
+ *params = mState.mCaps.maxShaderUniformComponents[ShaderType::TessEvaluation];
+ break;
+ case GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT:
+ *params = mState.mCaps.maxShaderTextureImageUnits[ShaderType::TessControl];
+ break;
+ case GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT:
+ *params = mState.mCaps.maxShaderTextureImageUnits[ShaderType::TessEvaluation];
+ break;
+ case GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT:
+ *params = mState.mCaps.maxTessControlOutputComponents;
+ break;
+ case GL_MAX_TESS_PATCH_COMPONENTS_EXT:
+ *params = mState.mCaps.maxTessPatchComponents;
+ break;
+ case GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT:
+ *params = mState.mCaps.maxTessControlTotalOutputComponents;
+ break;
+ case GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT:
+ *params = mState.mCaps.maxTessEvaluationOutputComponents;
+ break;
+ case GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT:
+ *params = mState.mCaps.maxShaderUniformBlocks[ShaderType::TessControl];
+ break;
+ case GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT:
+ *params = mState.mCaps.maxShaderUniformBlocks[ShaderType::TessEvaluation];
+ break;
+ case GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT:
+ *params = mState.mCaps.maxTessControlInputComponents;
+ break;
+ case GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT:
+ *params = mState.mCaps.maxTessEvaluationInputComponents;
+ break;
+ case GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT:
+ *params = static_cast<GLint>(
+ mState.mCaps.maxCombinedShaderUniformComponents[ShaderType::TessControl]);
+ break;
+ case GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT:
+ *params = static_cast<GLint>(
+ mState.mCaps.maxCombinedShaderUniformComponents[ShaderType::TessEvaluation]);
+ break;
+ case GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT:
+ *params = mState.mCaps.maxShaderAtomicCounterBuffers[ShaderType::TessControl];
+ break;
+ case GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT:
+ *params = mState.mCaps.maxShaderAtomicCounterBuffers[ShaderType::TessEvaluation];
+ break;
+ case GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT:
+ *params = mState.mCaps.maxShaderAtomicCounters[ShaderType::TessControl];
+ break;
+ case GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT:
+ *params = mState.mCaps.maxShaderAtomicCounters[ShaderType::TessEvaluation];
+ break;
+ case GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT:
+ *params = mState.mCaps.maxShaderImageUniforms[ShaderType::TessControl];
+ break;
+ case GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT:
+ *params = mState.mCaps.maxShaderImageUniforms[ShaderType::TessEvaluation];
+ break;
+ case GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT:
+ *params = mState.mCaps.maxShaderStorageBlocks[ShaderType::TessControl];
+ break;
+ case GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT:
+ *params = mState.mCaps.maxShaderStorageBlocks[ShaderType::TessEvaluation];
+ break;
+ // GLES1 emulation: Caps queries
+ case GL_MAX_TEXTURE_UNITS:
+ *params = mState.mCaps.maxMultitextureUnits;
+ break;
+ case GL_MAX_MODELVIEW_STACK_DEPTH:
+ *params = mState.mCaps.maxModelviewMatrixStackDepth;
+ break;
+ case GL_MAX_PROJECTION_STACK_DEPTH:
+ *params = mState.mCaps.maxProjectionMatrixStackDepth;
+ break;
+ case GL_MAX_TEXTURE_STACK_DEPTH:
+ *params = mState.mCaps.maxTextureMatrixStackDepth;
+ break;
+ case GL_MAX_LIGHTS:
+ *params = mState.mCaps.maxLights;
+ break;
+
+ // case GL_MAX_CLIP_DISTANCES_EXT: Conflict enum value
+ case GL_MAX_CLIP_PLANES:
+ if (getClientVersion().major >= 2)
+ {
+ // GL_APPLE_clip_distance/GL_EXT_clip_cull_distance
+ *params = mState.mCaps.maxClipDistances;
+ }
+ else
+ {
+ *params = mState.mCaps.maxClipPlanes;
+ }
+ break;
+ case GL_MAX_CULL_DISTANCES_EXT:
+ *params = mState.mCaps.maxCullDistances;
+ break;
+ case GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT:
+ *params = mState.mCaps.maxCombinedClipAndCullDistances;
+ break;
+ // GLES1 emulation: Vertex attribute queries
+ case GL_VERTEX_ARRAY_BUFFER_BINDING:
+ case GL_NORMAL_ARRAY_BUFFER_BINDING:
+ case GL_COLOR_ARRAY_BUFFER_BINDING:
+ case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
+ case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
+ getIntegerVertexAttribImpl(pname, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, params);
+ break;
+ case GL_VERTEX_ARRAY_STRIDE:
+ case GL_NORMAL_ARRAY_STRIDE:
+ case GL_COLOR_ARRAY_STRIDE:
+ case GL_POINT_SIZE_ARRAY_STRIDE_OES:
+ case GL_TEXTURE_COORD_ARRAY_STRIDE:
+ getIntegerVertexAttribImpl(pname, GL_VERTEX_ATTRIB_ARRAY_STRIDE, params);
+ break;
+ case GL_VERTEX_ARRAY_SIZE:
+ case GL_COLOR_ARRAY_SIZE:
+ case GL_TEXTURE_COORD_ARRAY_SIZE:
+ getIntegerVertexAttribImpl(pname, GL_VERTEX_ATTRIB_ARRAY_SIZE, params);
+ break;
+ case GL_VERTEX_ARRAY_TYPE:
+ case GL_COLOR_ARRAY_TYPE:
+ case GL_NORMAL_ARRAY_TYPE:
+ case GL_POINT_SIZE_ARRAY_TYPE_OES:
+ case GL_TEXTURE_COORD_ARRAY_TYPE:
+ getIntegerVertexAttribImpl(pname, GL_VERTEX_ATTRIB_ARRAY_TYPE, params);
+ break;
+
+ // GL_KHR_parallel_shader_compile
+ case GL_MAX_SHADER_COMPILER_THREADS_KHR:
+ *params = mState.getMaxShaderCompilerThreads();
+ break;
+
+ // GL_EXT_blend_func_extended
+ case GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT:
+ *params = mState.mCaps.maxDualSourceDrawBuffers;
+ break;
+
+ // OES_shader_multisample_interpolation
+ case GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES:
+ *params = mState.mCaps.subPixelInterpolationOffsetBits;
+ break;
+
+ // GL_OES_texture_buffer
+ case GL_MAX_TEXTURE_BUFFER_SIZE:
+ *params = mState.mCaps.maxTextureBufferSize;
+ break;
+ case GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
+ *params = mState.mCaps.textureBufferOffsetAlignment;
+ break;
+
+ // GL_EXT_clip_control
+ case GL_CLIP_ORIGIN_EXT:
+ *params = mState.mClipControlOrigin;
+ break;
+ case GL_CLIP_DEPTH_MODE_EXT:
+ *params = mState.mClipControlDepth;
+ break;
+
+ // ANGLE_shader_pixel_local_storage
+ case GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE:
+ *params = mState.mCaps.maxPixelLocalStoragePlanes;
+ break;
+ case GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE:
+ *params = mState.mCaps.maxColorAttachmentsWithActivePixelLocalStorage;
+ break;
+ case GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE:
+ *params = mState.mCaps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes;
+ break;
+
+ default:
+ ANGLE_CONTEXT_TRY(mState.getIntegerv(this, pname, params));
+ break;
+ }
+}
+
+void Context::getIntegerVertexAttribImpl(GLenum pname, GLenum attribpname, GLint *params) const
+{
+ getVertexAttribivImpl(static_cast<GLuint>(vertexArrayIndex(ParamToVertexArrayType(pname))),
+ attribpname, params);
+}
+
+void Context::getInteger64vImpl(GLenum pname, GLint64 *params) const
+{
+ // Queries about context capabilities and maximums are answered by Context.
+ // Queries about current GL state values are answered by State.
+ switch (pname)
+ {
+ case GL_MAX_ELEMENT_INDEX:
+ *params = mState.mCaps.maxElementIndex;
+ break;
+ case GL_MAX_UNIFORM_BLOCK_SIZE:
+ *params = mState.mCaps.maxUniformBlockSize;
+ break;
+ case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
+ *params = mState.mCaps.maxCombinedShaderUniformComponents[ShaderType::Vertex];
+ break;
+ case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
+ *params = mState.mCaps.maxCombinedShaderUniformComponents[ShaderType::Fragment];
+ break;
+ case GL_MAX_SERVER_WAIT_TIMEOUT:
+ *params = mState.mCaps.maxServerWaitTimeout;
+ break;
+
+ // GL_EXT_disjoint_timer_query
+ case GL_TIMESTAMP_EXT:
+ *params = mImplementation->getTimestamp();
+ break;
+
+ case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
+ *params = mState.mCaps.maxShaderStorageBlockSize;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void Context::getPointerv(GLenum pname, void **params)
+{
+ mState.getPointerv(this, pname, params);
+}
+
+void Context::getPointervRobustANGLERobust(GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getIntegeri_v(GLenum target, GLuint index, GLint *data)
+{
+ // Queries about context capabilities and maximums are answered by Context.
+ // Queries about current GL state values are answered by State.
+
+ GLenum nativeType;
+ unsigned int numParams;
+ bool queryStatus = getIndexedQueryParameterInfo(target, &nativeType, &numParams);
+ ASSERT(queryStatus);
+
+ if (nativeType == GL_INT)
+ {
+ switch (target)
+ {
+ case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
+ ASSERT(index < 3u);
+ *data = mState.mCaps.maxComputeWorkGroupCount[index];
+ break;
+ case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
+ ASSERT(index < 3u);
+ *data = mState.mCaps.maxComputeWorkGroupSize[index];
+ break;
+ default:
+ mState.getIntegeri_v(this, target, index, data);
+ }
+ }
+ else
+ {
+ CastIndexedStateValues(this, nativeType, target, index, numParams, data);
+ }
+}
+
+void Context::getIntegeri_vRobust(GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *data)
+{
+ getIntegeri_v(target, index, data);
+}
+
+void Context::getInteger64i_v(GLenum target, GLuint index, GLint64 *data)
+{
+ // Queries about context capabilities and maximums are answered by Context.
+ // Queries about current GL state values are answered by State.
+
+ GLenum nativeType;
+ unsigned int numParams;
+ bool queryStatus = getIndexedQueryParameterInfo(target, &nativeType, &numParams);
+ ASSERT(queryStatus);
+
+ if (nativeType == GL_INT_64_ANGLEX)
+ {
+ mState.getInteger64i_v(target, index, data);
+ }
+ else
+ {
+ CastIndexedStateValues(this, nativeType, target, index, numParams, data);
+ }
+}
+
+void Context::getInteger64i_vRobust(GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data)
+{
+ getInteger64i_v(target, index, data);
+}
+
+void Context::getBooleani_v(GLenum target, GLuint index, GLboolean *data)
+{
+ // Queries about context capabilities and maximums are answered by Context.
+ // Queries about current GL state values are answered by State.
+
+ GLenum nativeType;
+ unsigned int numParams;
+ bool queryStatus = getIndexedQueryParameterInfo(target, &nativeType, &numParams);
+ ASSERT(queryStatus);
+
+ if (nativeType == GL_BOOL)
+ {
+ mState.getBooleani_v(target, index, data);
+ }
+ else
+ {
+ CastIndexedStateValues(this, nativeType, target, index, numParams, data);
+ }
+}
+
+void Context::getBooleani_vRobust(GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *data)
+{
+ getBooleani_v(target, index, data);
+}
+
+void Context::getBufferParameteriv(BufferBinding target, GLenum pname, GLint *params)
+{
+ Buffer *buffer = mState.getTargetBuffer(target);
+ QueryBufferParameteriv(buffer, pname, params);
+}
+
+void Context::getBufferParameterivRobust(BufferBinding target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ getBufferParameteriv(target, pname, params);
+}
+
+void Context::getFramebufferAttachmentParameteriv(GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params)
+{
+ const Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ QueryFramebufferAttachmentParameteriv(this, framebuffer, attachment, pname, params);
+}
+
+void Context::getFramebufferAttachmentParameterivRobust(GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ getFramebufferAttachmentParameteriv(target, attachment, pname, params);
+}
+
+void Context::getRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ Renderbuffer *renderbuffer = mState.getCurrentRenderbuffer();
+ QueryRenderbufferiv(this, renderbuffer, pname, params);
+}
+
+void Context::getRenderbufferParameterivRobust(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ getRenderbufferParameteriv(target, pname, params);
+}
+
+void Context::texBuffer(TextureType target, GLenum internalformat, BufferID buffer)
+{
+ ASSERT(target == TextureType::Buffer);
+
+ Texture *texture = getTextureByType(target);
+ Buffer *bufferObj = mState.mBufferManager->getBuffer(buffer);
+ ANGLE_CONTEXT_TRY(texture->setBuffer(this, bufferObj, internalformat));
+}
+
+void Context::texBufferRange(TextureType target,
+ GLenum internalformat,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ ASSERT(target == TextureType::Buffer);
+
+ Texture *texture = getTextureByType(target);
+ Buffer *bufferObj = mState.mBufferManager->getBuffer(buffer);
+ ANGLE_CONTEXT_TRY(texture->setBufferRange(this, bufferObj, internalformat, offset, size));
+}
+
+void Context::getTexParameterfv(TextureType target, GLenum pname, GLfloat *params)
+{
+ const Texture *const texture = getTextureByType(target);
+ QueryTexParameterfv(this, texture, pname, params);
+}
+
+void Context::getTexParameterfvRobust(TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ getTexParameterfv(target, pname, params);
+}
+
+void Context::getTexParameteriv(TextureType target, GLenum pname, GLint *params)
+{
+ const Texture *const texture = getTextureByType(target);
+ QueryTexParameteriv(this, texture, pname, params);
+}
+
+void Context::getTexParameterIiv(TextureType target, GLenum pname, GLint *params)
+{
+ const Texture *const texture = getTextureByType(target);
+ QueryTexParameterIiv(this, texture, pname, params);
+}
+
+void Context::getTexParameterIuiv(TextureType target, GLenum pname, GLuint *params)
+{
+ const Texture *const texture = getTextureByType(target);
+ QueryTexParameterIuiv(this, texture, pname, params);
+}
+
+void Context::getTexParameterivRobust(TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ getTexParameteriv(target, pname, params);
+}
+
+void Context::getTexParameterIivRobust(TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTexParameterIuivRobust(TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTexLevelParameteriv(TextureTarget target, GLint level, GLenum pname, GLint *params)
+{
+ Texture *texture = getTextureByTarget(target);
+ QueryTexLevelParameteriv(texture, target, level, pname, params);
+}
+
+void Context::getTexLevelParameterivRobust(TextureTarget target,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTexLevelParameterfv(TextureTarget target,
+ GLint level,
+ GLenum pname,
+ GLfloat *params)
+{
+ Texture *texture = getTextureByTarget(target);
+ QueryTexLevelParameterfv(texture, target, level, pname, params);
+}
+
+void Context::getTexLevelParameterfvRobust(TextureTarget target,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texParameterf(TextureType target, GLenum pname, GLfloat param)
+{
+ Texture *const texture = getTextureByType(target);
+ SetTexParameterf(this, texture, pname, param);
+}
+
+void Context::texParameterfv(TextureType target, GLenum pname, const GLfloat *params)
+{
+ Texture *const texture = getTextureByType(target);
+ SetTexParameterfv(this, texture, pname, params);
+}
+
+void Context::texParameterfvRobust(TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params)
+{
+ texParameterfv(target, pname, params);
+}
+
+void Context::texParameteri(TextureType target, GLenum pname, GLint param)
+{
+ // Some apps enable KHR_create_context_no_error but pass in an invalid texture type.
+ // Workaround this by silently returning in such situations.
+ if (target == TextureType::InvalidEnum)
+ {
+ return;
+ }
+
+ Texture *const texture = getTextureByType(target);
+ SetTexParameteri(this, texture, pname, param);
+}
+
+void Context::texParameteriv(TextureType target, GLenum pname, const GLint *params)
+{
+ Texture *const texture = getTextureByType(target);
+ SetTexParameteriv(this, texture, pname, params);
+}
+
+void Context::texParameterIiv(TextureType target, GLenum pname, const GLint *params)
+{
+ Texture *const texture = getTextureByType(target);
+ SetTexParameterIiv(this, texture, pname, params);
+}
+
+void Context::texParameterIuiv(TextureType target, GLenum pname, const GLuint *params)
+{
+ Texture *const texture = getTextureByType(target);
+ SetTexParameterIuiv(this, texture, pname, params);
+}
+
+void Context::texParameterivRobust(TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params)
+{
+ texParameteriv(target, pname, params);
+}
+
+void Context::texParameterIivRobust(TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texParameterIuivRobust(TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLuint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::drawArraysInstanced(PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount)
+{
+ // No-op if count draws no primitives for given mode
+ if (noopDrawInstanced(mode, count, instanceCount))
+ {
+ ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(
+ mImplementation->drawArraysInstanced(this, mode, first, count, instanceCount));
+ MarkTransformFeedbackBufferUsage(this, count, instanceCount);
+ MarkShaderStorageUsage(this);
+}
+
+void Context::drawElementsInstanced(PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei instances)
+{
+ // No-op if count draws no primitives for given mode
+ if (noopDrawInstanced(mode, count, instances))
+ {
+ ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(
+ mImplementation->drawElementsInstanced(this, mode, count, type, indices, instances));
+ MarkShaderStorageUsage(this);
+}
+
+void Context::drawElementsBaseVertex(PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLint basevertex)
+{
+ // No-op if count draws no primitives for given mode
+ if (noopDraw(mode, count))
+ {
+ ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(
+ mImplementation->drawElementsBaseVertex(this, mode, count, type, indices, basevertex));
+ MarkShaderStorageUsage(this);
+}
+
+void Context::drawElementsInstancedBaseVertex(PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex)
+{
+ // No-op if count draws no primitives for given mode
+ if (noopDrawInstanced(mode, count, instancecount))
+ {
+ ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(mImplementation->drawElementsInstancedBaseVertex(
+ this, mode, count, type, indices, instancecount, basevertex));
+ MarkShaderStorageUsage(this);
+}
+
+void Context::drawRangeElements(PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices)
+{
+ // No-op if count draws no primitives for given mode
+ if (noopDraw(mode, count))
+ {
+ ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(
+ mImplementation->drawRangeElements(this, mode, start, end, count, type, indices));
+ MarkShaderStorageUsage(this);
+}
+
+void Context::drawRangeElementsBaseVertex(PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLint basevertex)
+{
+ // No-op if count draws no primitives for given mode
+ if (noopDraw(mode, count))
+ {
+ ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(mImplementation->drawRangeElementsBaseVertex(this, mode, start, end, count,
+ type, indices, basevertex));
+ MarkShaderStorageUsage(this);
+}
+
+void Context::drawArraysIndirect(PrimitiveMode mode, const void *indirect)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(mImplementation->drawArraysIndirect(this, mode, indirect));
+ MarkShaderStorageUsage(this);
+}
+
+void Context::drawElementsIndirect(PrimitiveMode mode, DrawElementsType type, const void *indirect)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(mImplementation->drawElementsIndirect(this, mode, type, indirect));
+ MarkShaderStorageUsage(this);
+}
+
+void Context::flush()
+{
+ ANGLE_CONTEXT_TRY(mImplementation->flush(this));
+}
+
+void Context::finish()
+{
+ ANGLE_CONTEXT_TRY(mImplementation->finish(this));
+}
+
+void Context::insertEventMarker(GLsizei length, const char *marker)
+{
+ ASSERT(mImplementation);
+ ANGLE_CONTEXT_TRY(mImplementation->insertEventMarker(length, marker));
+}
+
+void Context::pushGroupMarker(GLsizei length, const char *marker)
+{
+ ASSERT(mImplementation);
+
+ if (marker == nullptr)
+ {
+ // From the EXT_debug_marker spec,
+ // "If <marker> is null then an empty string is pushed on the stack."
+ ANGLE_CONTEXT_TRY(mImplementation->pushGroupMarker(length, ""));
+ }
+ else
+ {
+ ANGLE_CONTEXT_TRY(mImplementation->pushGroupMarker(length, marker));
+ }
+}
+
+void Context::popGroupMarker()
+{
+ ASSERT(mImplementation);
+ ANGLE_CONTEXT_TRY(mImplementation->popGroupMarker());
+}
+
+void Context::bindUniformLocation(ShaderProgramID program,
+ UniformLocation location,
+ const GLchar *name)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+
+ programObject->bindUniformLocation(location, name);
+}
+
+void Context::coverageModulation(GLenum components)
+{
+ mState.setCoverageModulation(components);
+}
+
+GLuint Context::getProgramResourceIndex(ShaderProgramID program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ const Program *programObject = getProgramResolveLink(program);
+ return QueryProgramResourceIndex(programObject, programInterface, name);
+}
+
+void Context::getProgramResourceName(ShaderProgramID program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name)
+{
+ const Program *programObject = getProgramResolveLink(program);
+ QueryProgramResourceName(this, programObject, programInterface, index, bufSize, length, name);
+}
+
+GLint Context::getProgramResourceLocation(ShaderProgramID program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ const Program *programObject = getProgramResolveLink(program);
+ return QueryProgramResourceLocation(programObject, programInterface, name);
+}
+
+void Context::getProgramResourceiv(ShaderProgramID program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ const Program *programObject = getProgramResolveLink(program);
+ QueryProgramResourceiv(programObject, programInterface, {index}, propCount, props, bufSize,
+ length, params);
+}
+
+void Context::getProgramInterfaceiv(ShaderProgramID program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint *params)
+{
+ const Program *programObject = getProgramResolveLink(program);
+ QueryProgramInterfaceiv(programObject, programInterface, pname, params);
+}
+
+void Context::getProgramInterfaceivRobust(ShaderProgramID program,
+ GLenum programInterface,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::handleError(GLenum errorCode,
+ const char *message,
+ const char *file,
+ const char *function,
+ unsigned int line)
+{
+ mErrors.handleError(errorCode, message, file, function, line);
+}
+
+void Context::validationError(angle::EntryPoint entryPoint,
+ GLenum errorCode,
+ const char *message) const
+{
+ const_cast<Context *>(this)->mErrors.validationError(entryPoint, errorCode, message);
+}
+
+void Context::validationErrorF(angle::EntryPoint entryPoint,
+ GLenum errorCode,
+ const char *format,
+ ...) const
+{
+ va_list vargs;
+ va_start(vargs, format);
+ constexpr size_t kMessageSize = 256;
+ char message[kMessageSize];
+ int r = vsnprintf(message, kMessageSize, format, vargs);
+ va_end(vargs);
+
+ if (r > 0)
+ {
+ validationError(entryPoint, errorCode, message);
+ }
+ else
+ {
+ validationError(entryPoint, errorCode, format);
+ }
+}
+
+// Get one of the recorded errors and clear its flag, if any.
+// [OpenGL ES 2.0.24] section 2.5 page 13.
+GLenum Context::getError()
+{
+ if (mErrors.empty())
+ {
+ return GL_NO_ERROR;
+ }
+ else
+ {
+ return mErrors.popError();
+ }
+}
+
+// NOTE: this function should not assume that this context is current!
+void Context::markContextLost(GraphicsResetStatus status)
+{
+ ASSERT(status != GraphicsResetStatus::NoError);
+ if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
+ {
+ mResetStatus = status;
+ mContextLostForced = true;
+ }
+ setContextLost();
+}
+
+void Context::setContextLost()
+{
+ mContextLost = true;
+
+ // Stop skipping validation, since many implementation entrypoint assume they can't
+ // be called when lost, or with null object arguments, etc.
+ mSkipValidation = false;
+
+ // Make sure we update TLS.
+#if defined(ANGLE_PLATFORM_APPLE)
+ SetCurrentValidContextTLS(nullptr);
+#else
+ gCurrentValidContext = nullptr;
+#endif
+}
+
+GLenum Context::getGraphicsResetStatus()
+{
+ // Even if the application doesn't want to know about resets, we want to know
+ // as it will allow us to skip all the calls.
+ if (mResetStrategy == GL_NO_RESET_NOTIFICATION_EXT)
+ {
+ if (!isContextLost() && mImplementation->getResetStatus() != GraphicsResetStatus::NoError)
+ {
+ setContextLost();
+ }
+
+ // EXT_robustness, section 2.6: If the reset notification behavior is
+ // NO_RESET_NOTIFICATION_EXT, then the implementation will never deliver notification of
+ // reset events, and GetGraphicsResetStatusEXT will always return NO_ERROR.
+ return GL_NO_ERROR;
+ }
+
+ // The GL_EXT_robustness spec says that if a reset is encountered, a reset
+ // status should be returned at least once, and GL_NO_ERROR should be returned
+ // once the device has finished resetting.
+ if (!isContextLost())
+ {
+ ASSERT(mResetStatus == GraphicsResetStatus::NoError);
+ mResetStatus = mImplementation->getResetStatus();
+
+ if (mResetStatus != GraphicsResetStatus::NoError)
+ {
+ setContextLost();
+ }
+ }
+ else if (!mContextLostForced && mResetStatus != GraphicsResetStatus::NoError)
+ {
+ // If markContextLost was used to mark the context lost then
+ // assume that is not recoverable, and continue to report the
+ // lost reset status for the lifetime of this context.
+ mResetStatus = mImplementation->getResetStatus();
+ }
+
+ return ToGLenum(mResetStatus);
+}
+
+bool Context::isResetNotificationEnabled() const
+{
+ return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT);
+}
+
+bool Context::isRobustnessEnabled() const
+{
+ return mState.hasRobustAccess();
+}
+
+const egl::Config *Context::getConfig() const
+{
+ return mConfig;
+}
+
+EGLenum Context::getClientType() const
+{
+ return mState.getClientType();
+}
+
+EGLenum Context::getRenderBuffer() const
+{
+ const Framebuffer *framebuffer =
+ mState.mFramebufferManager->getFramebuffer(Framebuffer::kDefaultDrawFramebufferHandle);
+ if (framebuffer == nullptr)
+ {
+ return EGL_NONE;
+ }
+
+ const FramebufferAttachment *backAttachment = framebuffer->getAttachment(this, GL_BACK);
+ ASSERT(backAttachment != nullptr);
+ return backAttachment->getSurface()->getRenderBuffer();
+}
+
+VertexArray *Context::checkVertexArrayAllocation(VertexArrayID vertexArrayHandle)
+{
+ // Only called after a prior call to Gen.
+ VertexArray *vertexArray = getVertexArray(vertexArrayHandle);
+ if (!vertexArray)
+ {
+ vertexArray =
+ new VertexArray(mImplementation.get(), vertexArrayHandle,
+ mState.mCaps.maxVertexAttributes, mState.mCaps.maxVertexAttribBindings);
+ vertexArray->setBufferAccessValidationEnabled(mBufferAccessValidationEnabled);
+
+ mVertexArrayMap.assign(vertexArrayHandle, vertexArray);
+ }
+
+ return vertexArray;
+}
+
+TransformFeedback *Context::checkTransformFeedbackAllocation(
+ TransformFeedbackID transformFeedbackHandle)
+{
+ // Only called after a prior call to Gen.
+ TransformFeedback *transformFeedback = getTransformFeedback(transformFeedbackHandle);
+ if (!transformFeedback)
+ {
+ transformFeedback =
+ new TransformFeedback(mImplementation.get(), transformFeedbackHandle, mState.mCaps);
+ transformFeedback->addRef();
+ mTransformFeedbackMap.assign(transformFeedbackHandle, transformFeedback);
+ }
+
+ return transformFeedback;
+}
+
+bool Context::isVertexArrayGenerated(VertexArrayID vertexArray) const
+{
+ ASSERT(mVertexArrayMap.contains({0}));
+ return mVertexArrayMap.contains(vertexArray);
+}
+
+bool Context::isTransformFeedbackGenerated(TransformFeedbackID transformFeedback) const
+{
+ ASSERT(mTransformFeedbackMap.contains({0}));
+ return mTransformFeedbackMap.contains(transformFeedback);
+}
+
+void Context::detachTexture(TextureID texture)
+{
+ // The State cannot unbind image observers itself, they are owned by the Context
+ Texture *tex = mState.mTextureManager->getTexture(texture);
+ for (auto &imageBinding : mImageObserverBindings)
+ {
+ if (imageBinding.getSubject() == tex)
+ {
+ imageBinding.reset();
+ }
+ }
+
+ // Simple pass-through to State's detachTexture method, as textures do not require
+ // allocation map management either here or in the resource manager at detach time.
+ // Zero textures are held by the Context, and we don't attempt to request them from
+ // the State.
+ mState.detachTexture(this, mZeroTextures, texture);
+}
+
+void Context::detachBuffer(Buffer *buffer)
+{
+ // Simple pass-through to State's detachBuffer method, since
+ // only buffer attachments to container objects that are bound to the current context
+ // should be detached. And all those are available in State.
+
+ // [OpenGL ES 3.2] section 5.1.2 page 45:
+ // Attachments to unbound container objects, such as
+ // deletion of a buffer attached to a vertex array object which is not bound to the context,
+ // are not affected and continue to act as references on the deleted object
+ ANGLE_CONTEXT_TRY(mState.detachBuffer(this, buffer));
+}
+
+void Context::detachFramebuffer(FramebufferID framebuffer)
+{
+ // Framebuffer detachment is handled by Context, because 0 is a valid
+ // Framebuffer object, and a pointer to it must be passed from Context
+ // to State at binding time.
+
+ // [OpenGL ES 2.0.24] section 4.4 page 107:
+ // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as
+ // though BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of
+ // zero.
+
+ if (mState.removeReadFramebufferBinding(framebuffer) && framebuffer.value != 0)
+ {
+ bindReadFramebuffer({0});
+ }
+
+ if (mState.removeDrawFramebufferBinding(framebuffer) && framebuffer.value != 0)
+ {
+ bindDrawFramebuffer({0});
+ }
+}
+
+void Context::detachRenderbuffer(RenderbufferID renderbuffer)
+{
+ mState.detachRenderbuffer(this, renderbuffer);
+}
+
+void Context::detachVertexArray(VertexArrayID vertexArray)
+{
+ // Vertex array detachment is handled by Context, because 0 is a valid
+ // VAO, and a pointer to it must be passed from Context to State at
+ // binding time.
+
+ // [OpenGL ES 3.0.2] section 2.10 page 43:
+ // If a vertex array object that is currently bound is deleted, the binding
+ // for that object reverts to zero and the default vertex array becomes current.
+ if (mState.removeVertexArrayBinding(this, vertexArray))
+ {
+ bindVertexArray({0});
+ }
+}
+
+void Context::detachTransformFeedback(TransformFeedbackID transformFeedback)
+{
+ // Transform feedback detachment is handled by Context, because 0 is a valid
+ // transform feedback, and a pointer to it must be passed from Context to State at
+ // binding time.
+
+ // The OpenGL specification doesn't mention what should happen when the currently bound
+ // transform feedback object is deleted. Since it is a container object, we treat it like
+ // VAOs and FBOs and set the current bound transform feedback back to 0.
+ if (mState.removeTransformFeedbackBinding(this, transformFeedback))
+ {
+ bindTransformFeedback(GL_TRANSFORM_FEEDBACK, {0});
+ mStateCache.onActiveTransformFeedbackChange(this);
+ }
+}
+
+void Context::detachSampler(SamplerID sampler)
+{
+ mState.detachSampler(this, sampler);
+}
+
+void Context::detachProgramPipeline(ProgramPipelineID pipeline)
+{
+ mState.detachProgramPipeline(this, pipeline);
+}
+
+void Context::vertexAttribDivisor(GLuint index, GLuint divisor)
+{
+ mState.setVertexAttribDivisor(this, index, divisor);
+ mStateCache.onVertexArrayStateChange(this);
+}
+
+void Context::samplerParameteri(SamplerID sampler, GLenum pname, GLint param)
+{
+ Sampler *const samplerObject =
+ mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ SetSamplerParameteri(this, samplerObject, pname, param);
+}
+
+void Context::samplerParameteriv(SamplerID sampler, GLenum pname, const GLint *param)
+{
+ Sampler *const samplerObject =
+ mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ SetSamplerParameteriv(this, samplerObject, pname, param);
+}
+
+void Context::samplerParameterIiv(SamplerID sampler, GLenum pname, const GLint *param)
+{
+ Sampler *const samplerObject =
+ mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ SetSamplerParameterIiv(this, samplerObject, pname, param);
+}
+
+void Context::samplerParameterIuiv(SamplerID sampler, GLenum pname, const GLuint *param)
+{
+ Sampler *const samplerObject =
+ mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ SetSamplerParameterIuiv(this, samplerObject, pname, param);
+}
+
+void Context::samplerParameterivRobust(SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *param)
+{
+ samplerParameteriv(sampler, pname, param);
+}
+
+void Context::samplerParameterIivRobust(SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::samplerParameterIuivRobust(SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLuint *param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::samplerParameterf(SamplerID sampler, GLenum pname, GLfloat param)
+{
+ Sampler *const samplerObject =
+ mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ SetSamplerParameterf(this, samplerObject, pname, param);
+}
+
+void Context::samplerParameterfv(SamplerID sampler, GLenum pname, const GLfloat *param)
+{
+ Sampler *const samplerObject =
+ mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ SetSamplerParameterfv(this, samplerObject, pname, param);
+}
+
+void Context::samplerParameterfvRobust(SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *param)
+{
+ samplerParameterfv(sampler, pname, param);
+}
+
+void Context::getSamplerParameteriv(SamplerID sampler, GLenum pname, GLint *params)
+{
+ const Sampler *const samplerObject =
+ mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ QuerySamplerParameteriv(samplerObject, pname, params);
+}
+
+void Context::getSamplerParameterIiv(SamplerID sampler, GLenum pname, GLint *params)
+{
+ const Sampler *const samplerObject =
+ mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ QuerySamplerParameterIiv(samplerObject, pname, params);
+}
+
+void Context::getSamplerParameterIuiv(SamplerID sampler, GLenum pname, GLuint *params)
+{
+ const Sampler *const samplerObject =
+ mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ QuerySamplerParameterIuiv(samplerObject, pname, params);
+}
+
+void Context::getSamplerParameterivRobust(SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ getSamplerParameteriv(sampler, pname, params);
+}
+
+void Context::getSamplerParameterIivRobust(SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getSamplerParameterIuivRobust(SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getSamplerParameterfv(SamplerID sampler, GLenum pname, GLfloat *params)
+{
+ const Sampler *const samplerObject =
+ mState.mSamplerManager->checkSamplerAllocation(mImplementation.get(), sampler);
+ QuerySamplerParameterfv(samplerObject, pname, params);
+}
+
+void Context::getSamplerParameterfvRobust(SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ getSamplerParameterfv(sampler, pname, params);
+}
+
+void Context::programParameteri(ShaderProgramID program, GLenum pname, GLint value)
+{
+ gl::Program *programObject = getProgramResolveLink(program);
+ SetProgramParameteri(programObject, pname, value);
+}
+
+void Context::initRendererString()
+{
+ std::ostringstream frontendRendererString;
+ std::string vendorString(mDisplay->getBackendVendorString());
+ std::string rendererString(mDisplay->getBackendRendererDescription());
+ std::string versionString(mDisplay->getBackendVersionString(!isWebGL()));
+ // Commas are used as a separator in ANGLE's renderer string, so remove commas from each
+ // element.
+ vendorString.erase(std::remove(vendorString.begin(), vendorString.end(), ','),
+ vendorString.end());
+ rendererString.erase(std::remove(rendererString.begin(), rendererString.end(), ','),
+ rendererString.end());
+ versionString.erase(std::remove(versionString.begin(), versionString.end(), ','),
+ versionString.end());
+ frontendRendererString << "ANGLE (";
+ frontendRendererString << vendorString;
+ frontendRendererString << ", ";
+ frontendRendererString << rendererString;
+ frontendRendererString << ", ";
+ frontendRendererString << versionString;
+ frontendRendererString << ")";
+
+ mRendererString = MakeStaticString(frontendRendererString.str());
+}
+
+void Context::initVersionStrings()
+{
+ const Version &clientVersion = getClientVersion();
+
+ std::ostringstream versionString;
+ if (getClientType() == EGL_OPENGL_ES_API)
+ {
+ versionString << "OpenGL ES ";
+ }
+ versionString << clientVersion.major << "." << clientVersion.minor << ".0 (ANGLE "
+ << angle::GetANGLEVersionString() << ")";
+ mVersionString = MakeStaticString(versionString.str());
+
+ std::ostringstream shadingLanguageVersionString;
+ if (getClientType() == EGL_OPENGL_ES_API)
+ {
+ shadingLanguageVersionString << "OpenGL ES GLSL ES ";
+ }
+ else
+ {
+ ASSERT(getClientType() == EGL_OPENGL_API);
+ shadingLanguageVersionString << "OpenGL GLSL ";
+ }
+ shadingLanguageVersionString << (clientVersion.major == 2 ? 1 : clientVersion.major) << "."
+ << clientVersion.minor << "0 (ANGLE "
+ << angle::GetANGLEVersionString() << ")";
+ mShadingLanguageString = MakeStaticString(shadingLanguageVersionString.str());
+}
+
+void Context::initExtensionStrings()
+{
+ auto mergeExtensionStrings = [](const std::vector<const char *> &strings) {
+ std::ostringstream combinedStringStream;
+ std::copy(strings.begin(), strings.end(),
+ std::ostream_iterator<const char *>(combinedStringStream, " "));
+ return MakeStaticString(combinedStringStream.str());
+ };
+
+ mExtensionStrings.clear();
+ for (const auto &extensionString : mState.mExtensions.getStrings())
+ {
+ mExtensionStrings.push_back(MakeStaticString(extensionString));
+ }
+ mExtensionString = mergeExtensionStrings(mExtensionStrings);
+
+ mRequestableExtensionStrings.clear();
+ for (const auto &extensionInfo : GetExtensionInfoMap())
+ {
+ if (extensionInfo.second.Requestable &&
+ !(mState.mExtensions.*(extensionInfo.second.ExtensionsMember)) &&
+ mSupportedExtensions.*(extensionInfo.second.ExtensionsMember))
+ {
+ mRequestableExtensionStrings.push_back(MakeStaticString(extensionInfo.first));
+ }
+ }
+ mRequestableExtensionString = mergeExtensionStrings(mRequestableExtensionStrings);
+}
+
+const GLubyte *Context::getString(GLenum name)
+{
+ return static_cast<const Context *>(this)->getString(name);
+}
+
+const GLubyte *Context::getStringi(GLenum name, GLuint index)
+{
+ return static_cast<const Context *>(this)->getStringi(name, index);
+}
+
+const GLubyte *Context::getString(GLenum name) const
+{
+ switch (name)
+ {
+ case GL_VENDOR:
+ return reinterpret_cast<const GLubyte *>(mDisplay->getVendorString().c_str());
+
+ case GL_RENDERER:
+ return reinterpret_cast<const GLubyte *>(mRendererString);
+
+ case GL_VERSION:
+ return reinterpret_cast<const GLubyte *>(mVersionString);
+
+ case GL_SHADING_LANGUAGE_VERSION:
+ return reinterpret_cast<const GLubyte *>(mShadingLanguageString);
+
+ case GL_EXTENSIONS:
+ return reinterpret_cast<const GLubyte *>(mExtensionString);
+
+ case GL_REQUESTABLE_EXTENSIONS_ANGLE:
+ return reinterpret_cast<const GLubyte *>(mRequestableExtensionString);
+
+ case GL_SERIALIZED_CONTEXT_STRING_ANGLE:
+ if (angle::SerializeContextToString(this, &mCachedSerializedStateString) ==
+ angle::Result::Continue)
+ {
+ return reinterpret_cast<const GLubyte *>(mCachedSerializedStateString.c_str());
+ }
+ else
+ {
+ return nullptr;
+ }
+
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+
+const GLubyte *Context::getStringi(GLenum name, GLuint index) const
+{
+ switch (name)
+ {
+ case GL_EXTENSIONS:
+ return reinterpret_cast<const GLubyte *>(mExtensionStrings[index]);
+
+ case GL_REQUESTABLE_EXTENSIONS_ANGLE:
+ return reinterpret_cast<const GLubyte *>(mRequestableExtensionStrings[index]);
+
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+
+size_t Context::getExtensionStringCount() const
+{
+ return mExtensionStrings.size();
+}
+
+bool Context::isExtensionRequestable(const char *name) const
+{
+ const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
+ auto extension = extensionInfos.find(name);
+
+ return extension != extensionInfos.end() && extension->second.Requestable &&
+ mSupportedExtensions.*(extension->second.ExtensionsMember);
+}
+
+bool Context::isExtensionDisablable(const char *name) const
+{
+ const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
+ auto extension = extensionInfos.find(name);
+
+ return extension != extensionInfos.end() && extension->second.Disablable &&
+ mSupportedExtensions.*(extension->second.ExtensionsMember);
+}
+
+void Context::requestExtension(const char *name)
+{
+ setExtensionEnabled(name, true);
+}
+void Context::disableExtension(const char *name)
+{
+ setExtensionEnabled(name, false);
+}
+
+void Context::setExtensionEnabled(const char *name, bool enabled)
+{
+ // OVR_multiview is implicitly enabled when OVR_multiview2 is enabled
+ if (strcmp(name, "GL_OVR_multiview2") == 0)
+ {
+ setExtensionEnabled("GL_OVR_multiview", enabled);
+ }
+ const ExtensionInfoMap &extensionInfos = GetExtensionInfoMap();
+ ASSERT(extensionInfos.find(name) != extensionInfos.end());
+ const auto &extension = extensionInfos.at(name);
+ ASSERT(extension.Requestable);
+ ASSERT(isExtensionRequestable(name));
+
+ if (mState.mExtensions.*(extension.ExtensionsMember) == enabled)
+ {
+ // No change
+ return;
+ }
+
+ mState.mExtensions.*(extension.ExtensionsMember) = enabled;
+
+ reinitializeAfterExtensionsChanged();
+}
+
+void Context::reinitializeAfterExtensionsChanged()
+{
+ updateCaps();
+ initExtensionStrings();
+
+ // Release the shader compiler so it will be re-created with the requested extensions enabled.
+ releaseShaderCompiler();
+
+ // Invalidate all textures and framebuffer. Some extensions make new formats renderable or
+ // sampleable.
+ mState.mTextureManager->signalAllTexturesDirty();
+ for (auto &zeroTexture : mZeroTextures)
+ {
+ if (zeroTexture.get() != nullptr)
+ {
+ zeroTexture->signalDirtyStorage(InitState::Initialized);
+ }
+ }
+
+ mState.mFramebufferManager->invalidateFramebufferCompletenessCache();
+}
+
+size_t Context::getRequestableExtensionStringCount() const
+{
+ return mRequestableExtensionStrings.size();
+}
+
+void Context::beginTransformFeedback(PrimitiveMode primitiveMode)
+{
+ TransformFeedback *transformFeedback = mState.getCurrentTransformFeedback();
+ ASSERT(transformFeedback != nullptr);
+ ASSERT(!transformFeedback->isPaused());
+
+ // TODO: http://anglebug.com/7232: Handle PPOs
+ ANGLE_CONTEXT_TRY(transformFeedback->begin(this, primitiveMode, mState.getProgram()));
+ mStateCache.onActiveTransformFeedbackChange(this);
+}
+
+bool Context::hasActiveTransformFeedback(ShaderProgramID program) const
+{
+ for (auto pair : mTransformFeedbackMap)
+ {
+ if (pair.second != nullptr && pair.second->hasBoundProgram(program))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+Extensions Context::generateSupportedExtensions() const
+{
+ Extensions supportedExtensions = mImplementation->getNativeExtensions();
+
+ if (getClientVersion() < ES_2_0)
+ {
+ // Default extensions for GLES1
+ supportedExtensions.pointSizeArrayOES = true;
+ supportedExtensions.textureCubeMapOES = true;
+ supportedExtensions.pointSpriteOES = true;
+ supportedExtensions.drawTextureOES = true;
+ supportedExtensions.framebufferObjectOES = true;
+ supportedExtensions.parallelShaderCompileKHR = false;
+ supportedExtensions.texture3DOES = false;
+ supportedExtensions.clipDistanceAPPLE = false;
+ }
+
+ if (getClientVersion() < ES_3_0)
+ {
+ // Disable ES3+ extensions
+ supportedExtensions.colorBufferFloatEXT = false;
+ supportedExtensions.EGLImageExternalEssl3OES = false;
+ supportedExtensions.multiviewOVR = false;
+ supportedExtensions.multiview2OVR = false;
+ supportedExtensions.multiviewMultisampleANGLE = false;
+ supportedExtensions.copyTexture3dANGLE = false;
+ supportedExtensions.textureMultisampleANGLE = false;
+ supportedExtensions.drawBuffersIndexedEXT = false;
+ supportedExtensions.drawBuffersIndexedOES = false;
+ supportedExtensions.EGLImageArrayEXT = false;
+ supportedExtensions.textureFormatSRGBOverrideEXT = false;
+
+ // Support GL_EXT_texture_norm16 on non-WebGL ES2 contexts. This is needed for R16/RG16
+ // texturing for HDR video playback in Chromium which uses ES2 for compositor contexts.
+ // Remove this workaround after Chromium migrates to ES3 for compositor contexts.
+ if (mWebGLContext || getClientVersion() < ES_2_0)
+ {
+ supportedExtensions.textureNorm16EXT = false;
+ }
+
+ // Requires immutable textures
+ supportedExtensions.yuvInternalFormatANGLE = false;
+
+ // Require ESSL 3.0
+ supportedExtensions.shaderMultisampleInterpolationOES = false;
+ supportedExtensions.shaderNoperspectiveInterpolationNV = false;
+ supportedExtensions.sampleVariablesOES = false;
+
+ // Require ES 3.1 but could likely be exposed on 3.0
+ supportedExtensions.textureCubeMapArrayEXT = false;
+ supportedExtensions.textureCubeMapArrayOES = false;
+
+ // Require RED and RG formats
+ supportedExtensions.textureSRGBR8EXT = false;
+ supportedExtensions.textureSRGBRG8EXT = false;
+
+ // Requires glCompressedTexImage3D
+ supportedExtensions.textureCompressionAstcOES = false;
+
+ // Don't expose GL_EXT_texture_sRGB_decode without sRGB texture support
+ if (!supportedExtensions.sRGBEXT)
+ {
+ supportedExtensions.textureSRGBDecodeEXT = false;
+ }
+
+ // Don't expose GL_OES_texture_float_linear without full legacy float texture support
+ // The renderer may report OES_texture_float_linear without OES_texture_float
+ // This is valid in a GLES 3.0 context, but not in a GLES 2.0 context
+ if (!(supportedExtensions.textureFloatOES && supportedExtensions.textureHalfFloatOES))
+ {
+ supportedExtensions.textureFloatLinearOES = false;
+ supportedExtensions.textureHalfFloatLinearOES = false;
+ }
+
+ // Because of the difference in the SNORM to FLOAT conversion formula
+ // between GLES 2.0 and 3.0, vertex type 10_10_10_2 is disabled
+ // when the context version is lower than 3.0
+ supportedExtensions.vertexType1010102OES = false;
+
+ // GL_EXT_EGL_image_storage requires ESSL3
+ supportedExtensions.EGLImageStorageEXT = false;
+
+ // GL_EXT_YUV_target requires ESSL3
+ supportedExtensions.YUVTargetEXT = false;
+
+ // GL_EXT_clip_cull_distance requires ESSL3
+ supportedExtensions.clipCullDistanceEXT = false;
+
+ // ANGLE_shader_pixel_local_storage requires ES3
+ supportedExtensions.shaderPixelLocalStorageANGLE = false;
+ supportedExtensions.shaderPixelLocalStorageCoherentANGLE = false;
+ }
+
+ if (getClientVersion() < ES_3_1)
+ {
+ // Disable ES3.1+ extensions
+ supportedExtensions.geometryShaderEXT = false;
+ supportedExtensions.geometryShaderOES = false;
+ supportedExtensions.gpuShader5EXT = false;
+ supportedExtensions.primitiveBoundingBoxEXT = false;
+ supportedExtensions.shaderImageAtomicOES = false;
+ supportedExtensions.shaderIoBlocksEXT = false;
+ supportedExtensions.shaderIoBlocksOES = false;
+ supportedExtensions.tessellationShaderEXT = false;
+ supportedExtensions.textureBufferEXT = false;
+ supportedExtensions.textureBufferOES = false;
+
+ // TODO(http://anglebug.com/2775): Multisample arrays could be supported on ES 3.0 as well
+ // once 2D multisample texture extension is exposed there.
+ supportedExtensions.textureStorageMultisample2dArrayOES = false;
+ }
+
+ if (getClientVersion() > ES_2_0)
+ {
+ // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts
+ // supportedExtensions.sRGB = false;
+
+ // If colorBufferFloatEXT is disabled but colorBufferHalfFloatEXT is enabled, then we will
+ // expose some floating-point formats as color buffer targets but reject blits between
+ // fixed-point and floating-point formats (this behavior is only enabled in
+ // colorBufferFloatEXT, and must be rejected if only colorBufferHalfFloatEXT is enabled).
+ // dEQP does not check for this, and will assume that floating-point and fixed-point formats
+ // can be blit onto each other if the format is available.
+ // We require colorBufferFloatEXT to be present in order to enable colorBufferHalfFloatEXT,
+ // so that blitting is always allowed if the requested formats are exposed and have the
+ // correct feature capabilities. WebGL 2 wants to support colorBufferHalfFloatEXT without
+ // colorBufferFloatEXT.
+ if (!supportedExtensions.colorBufferFloatEXT && !mWebGLContext)
+ {
+ supportedExtensions.colorBufferHalfFloatEXT = false;
+ }
+
+ // Disable support for CHROMIUM_color_buffer_float_rgb[a] in ES 3.0+, these extensions are
+ // non-conformant in ES 3.0 and superseded by EXT_color_buffer_float.
+ supportedExtensions.colorBufferFloatRgbCHROMIUM = false;
+ supportedExtensions.colorBufferFloatRgbaCHROMIUM = false;
+ }
+
+ if (getFrontendFeatures().disableDrawBuffersIndexed.enabled)
+ {
+ supportedExtensions.drawBuffersIndexedEXT = false;
+ supportedExtensions.drawBuffersIndexedOES = false;
+ }
+
+ if (getFrontendFeatures().disableAnisotropicFiltering.enabled)
+ {
+ supportedExtensions.textureFilterAnisotropicEXT = false;
+ }
+
+ if (!getFrontendFeatures().emulatePixelLocalStorage.enabled)
+ {
+ supportedExtensions.shaderPixelLocalStorageANGLE = false;
+ supportedExtensions.shaderPixelLocalStorageCoherentANGLE = false;
+ }
+
+ // Some extensions are always available because they are implemented in the GL layer.
+ supportedExtensions.bindUniformLocationCHROMIUM = true;
+ supportedExtensions.vertexArrayObjectOES = true;
+ supportedExtensions.bindGeneratesResourceCHROMIUM = true;
+ supportedExtensions.clientArraysANGLE = true;
+ supportedExtensions.requestExtensionANGLE = true;
+ supportedExtensions.multiDrawANGLE = true;
+
+ // Enable the no error extension if the context was created with the flag.
+ supportedExtensions.noErrorKHR = mSkipValidation;
+
+ // Enable surfaceless to advertise we'll have the correct behavior when there is no default FBO
+ supportedExtensions.surfacelessContextOES = mSurfacelessSupported;
+
+ // Explicitly enable GL_KHR_debug
+ supportedExtensions.debugKHR = true;
+
+ // Explicitly enable GL_EXT_debug_label
+ supportedExtensions.debugLabelEXT = true;
+
+ // Explicitly enable GL_ANGLE_robust_client_memory if the context supports validation.
+ supportedExtensions.robustClientMemoryANGLE = !mSkipValidation;
+
+ // Determine robust resource init availability from EGL.
+ supportedExtensions.robustResourceInitializationANGLE = mState.isRobustResourceInitEnabled();
+
+ // mState.mExtensions.robustBufferAccessBehaviorKHR is true only if robust access is true and
+ // the backend supports it.
+ supportedExtensions.robustBufferAccessBehaviorKHR =
+ mState.hasRobustAccess() && supportedExtensions.robustBufferAccessBehaviorKHR;
+
+ // Enable the cache control query unconditionally.
+ supportedExtensions.programCacheControlANGLE = true;
+
+ // If EGL_KHR_fence_sync is not enabled, don't expose GL_OES_EGL_sync.
+ ASSERT(mDisplay);
+ if (!mDisplay->getExtensions().fenceSync)
+ {
+ supportedExtensions.EGLSyncOES = false;
+ }
+
+ if (mDisplay->getExtensions().robustnessVideoMemoryPurgeNV)
+ {
+ supportedExtensions.robustnessVideoMemoryPurgeNV = true;
+ }
+
+ supportedExtensions.memorySizeANGLE = true;
+
+ // GL_CHROMIUM_lose_context is implemented in the frontend
+ supportedExtensions.loseContextCHROMIUM = true;
+
+ // The ASTC texture extensions have dependency requirements.
+ if (supportedExtensions.textureCompressionAstcHdrKHR ||
+ supportedExtensions.textureCompressionAstcSliced3dKHR)
+ {
+ // GL_KHR_texture_compression_astc_hdr cannot be exposed without also exposing
+ // GL_KHR_texture_compression_astc_ldr
+ ASSERT(supportedExtensions.textureCompressionAstcLdrKHR);
+ }
+
+ if (supportedExtensions.textureCompressionAstcOES)
+ {
+ // GL_OES_texture_compression_astc cannot be exposed without also exposing
+ // GL_KHR_texture_compression_astc_ldr and GL_KHR_texture_compression_astc_hdr
+ ASSERT(supportedExtensions.textureCompressionAstcLdrKHR);
+ ASSERT(supportedExtensions.textureCompressionAstcHdrKHR);
+ }
+
+ // GL_KHR_protected_textures
+ // If EGL_KHR_protected_content is not supported then GL_EXT_protected_texture
+ // can not be supported.
+ if (!mDisplay->getExtensions().protectedContentEXT)
+ {
+ supportedExtensions.protectedTexturesEXT = false;
+ }
+
+ // GL_ANGLE_get_tex_level_parameter is implemented in the front-end
+ supportedExtensions.getTexLevelParameterANGLE = true;
+
+ // Always enabled. Will return a default string if capture is not enabled.
+ supportedExtensions.getSerializedContextStringANGLE = true;
+
+ // Performance counter queries are always supported. Different groups exist on each back-end.
+ supportedExtensions.performanceMonitorAMD = true;
+
+ // GL_ANDROID_extension_pack_es31a
+ supportedExtensions.extensionPackEs31aANDROID =
+ CanSupportAEP(getClientVersion(), supportedExtensions);
+
+ return supportedExtensions;
+}
+
+void Context::initCaps()
+{
+ mState.mCaps = mImplementation->getNativeCaps();
+
+ // TODO (http://anglebug.com/6010): mSupportedExtensions should not be modified here
+ mSupportedExtensions = generateSupportedExtensions();
+
+ if (!mDisplay->getFrontendFeatures().allowCompressedFormats.enabled)
+ {
+ INFO() << "Limiting compressed format support.\n";
+
+ mSupportedExtensions.compressedEACR11SignedTextureOES = false;
+ mSupportedExtensions.compressedEACR11UnsignedTextureOES = false;
+ mSupportedExtensions.compressedEACRG11SignedTextureOES = false;
+ mSupportedExtensions.compressedEACRG11UnsignedTextureOES = false;
+ mSupportedExtensions.compressedETC1RGB8SubTextureEXT = false;
+ mSupportedExtensions.compressedETC1RGB8TextureOES = false;
+ mSupportedExtensions.compressedETC2PunchthroughARGBA8TextureOES = false;
+ mSupportedExtensions.compressedETC2PunchthroughASRGB8AlphaTextureOES = false;
+ mSupportedExtensions.compressedETC2RGB8TextureOES = false;
+ mSupportedExtensions.compressedETC2RGBA8TextureOES = false;
+ mSupportedExtensions.compressedETC2SRGB8Alpha8TextureOES = false;
+ mSupportedExtensions.compressedETC2SRGB8TextureOES = false;
+ mSupportedExtensions.compressedTextureEtcANGLE = false;
+ mSupportedExtensions.textureCompressionPvrtcIMG = false;
+ mSupportedExtensions.pvrtcSRGBEXT = false;
+ mSupportedExtensions.copyCompressedTextureCHROMIUM = false;
+ mSupportedExtensions.textureCompressionAstcHdrKHR = false;
+ mSupportedExtensions.textureCompressionAstcLdrKHR = false;
+ mSupportedExtensions.textureCompressionAstcOES = false;
+ mSupportedExtensions.textureCompressionBptcEXT = false;
+ mSupportedExtensions.textureCompressionDxt1EXT = false;
+ mSupportedExtensions.textureCompressionDxt3ANGLE = false;
+ mSupportedExtensions.textureCompressionDxt5ANGLE = false;
+ mSupportedExtensions.textureCompressionRgtcEXT = false;
+ mSupportedExtensions.textureCompressionS3tcSrgbEXT = false;
+ mSupportedExtensions.textureCompressionAstcSliced3dKHR = false;
+ mSupportedExtensions.textureFilteringHintCHROMIUM = false;
+
+ mState.mCaps.compressedTextureFormats.clear();
+ }
+
+ mState.mExtensions = mSupportedExtensions;
+
+ mState.mLimitations = mImplementation->getNativeLimitations();
+
+ // GLES1 emulation: Initialize caps (Table 6.20 / 6.22 in the ES 1.1 spec)
+ if (getClientType() == EGL_OPENGL_API || getClientVersion() < Version(2, 0))
+ {
+ mState.mCaps.maxMultitextureUnits = 4;
+ mState.mCaps.maxClipPlanes = 6;
+ mState.mCaps.maxLights = 8;
+ mState.mCaps.maxModelviewMatrixStackDepth = Caps::GlobalMatrixStackDepth;
+ mState.mCaps.maxProjectionMatrixStackDepth = Caps::GlobalMatrixStackDepth;
+ mState.mCaps.maxTextureMatrixStackDepth = Caps::GlobalMatrixStackDepth;
+ mState.mCaps.minSmoothPointSize = 1.0f;
+ mState.mCaps.maxSmoothPointSize = 1.0f;
+ mState.mCaps.minSmoothLineWidth = 1.0f;
+ mState.mCaps.maxSmoothLineWidth = 1.0f;
+ }
+
+ mState.mCaps.maxDebugMessageLength = 1024;
+ mState.mCaps.maxDebugLoggedMessages = 1024;
+ mState.mCaps.maxDebugGroupStackDepth = 1024;
+ mState.mCaps.maxLabelLength = 1024;
+
+ if (getClientVersion() < Version(3, 0))
+ {
+ mState.mCaps.maxViews = 1u;
+ }
+
+#if 0
+// This logging can generate a lot of spam in test suites that create many contexts
+# define ANGLE_LOG_LIMITED_CAP(cap, limit) \
+ INFO() << "Limiting " << #cap << " to implementation limit " << (limit) << " (was " \
+ << (cap) << ")."
+#else
+# define ANGLE_LOG_LIMITED_CAP(cap, limit)
+#endif
+
+#define ANGLE_LIMIT_CAP(cap, limit) \
+ do \
+ { \
+ if ((cap) > (limit)) \
+ { \
+ ANGLE_LOG_LIMITED_CAP(cap, limit); \
+ (cap) = (limit); \
+ } \
+ } while (0)
+
+ // Apply/Verify implementation limits
+ ANGLE_LIMIT_CAP(mState.mCaps.maxDrawBuffers, IMPLEMENTATION_MAX_DRAW_BUFFERS);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxColorAttachments, IMPLEMENTATION_MAX_DRAW_BUFFERS);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxVertexAttribStride,
+ static_cast<GLint>(limits::kMaxVertexAttribStride));
+
+ ASSERT(mState.mCaps.minAliasedPointSize >= 1.0f);
+
+ if (getClientVersion() < ES_3_1)
+ {
+ mState.mCaps.maxVertexAttribBindings = mState.mCaps.maxVertexAttributes;
+ }
+ else
+ {
+ ANGLE_LIMIT_CAP(mState.mCaps.maxVertexAttribBindings, MAX_VERTEX_ATTRIB_BINDINGS);
+ }
+
+ if (mWebGLContext && getLimitations().limitWebglMaxTextureSizeTo4096)
+ {
+ constexpr GLint kMaxTextureSize = 4096;
+ ANGLE_LIMIT_CAP(mState.mCaps.max2DTextureSize, kMaxTextureSize);
+ ANGLE_LIMIT_CAP(mState.mCaps.max3DTextureSize, kMaxTextureSize);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxCubeMapTextureSize, kMaxTextureSize);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxArrayTextureLayers, kMaxTextureSize);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxRectangleTextureSize, kMaxTextureSize);
+ }
+
+ ANGLE_LIMIT_CAP(mState.mCaps.max2DTextureSize, IMPLEMENTATION_MAX_2D_TEXTURE_SIZE);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxCubeMapTextureSize, IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE);
+ ANGLE_LIMIT_CAP(mState.mCaps.max3DTextureSize, IMPLEMENTATION_MAX_3D_TEXTURE_SIZE);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxArrayTextureLayers, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxRectangleTextureSize, IMPLEMENTATION_MAX_2D_TEXTURE_SIZE);
+
+ ANGLE_LIMIT_CAP(mState.mCaps.maxShaderUniformBlocks[ShaderType::Vertex],
+ IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxShaderUniformBlocks[ShaderType::Geometry],
+ IMPLEMENTATION_MAX_GEOMETRY_SHADER_UNIFORM_BUFFERS);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxShaderUniformBlocks[ShaderType::Fragment],
+ IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxShaderUniformBlocks[ShaderType::Compute],
+ IMPLEMENTATION_MAX_COMPUTE_SHADER_UNIFORM_BUFFERS);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxCombinedUniformBlocks,
+ IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxUniformBufferBindings,
+ IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS);
+
+ ANGLE_LIMIT_CAP(mState.mCaps.maxVertexOutputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxFragmentInputComponents,
+ IMPLEMENTATION_MAX_VARYING_VECTORS * 4);
+
+ ANGLE_LIMIT_CAP(mState.mCaps.maxTransformFeedbackInterleavedComponents,
+ IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxTransformFeedbackSeparateAttributes,
+ IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxTransformFeedbackSeparateComponents,
+ IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS);
+
+ if (getClientVersion() < ES_3_2 && !mState.mExtensions.tessellationShaderEXT)
+ {
+ ANGLE_LIMIT_CAP(mState.mCaps.maxCombinedTextureImageUnits,
+ IMPLEMENTATION_MAX_ES31_ACTIVE_TEXTURES);
+ }
+ else
+ {
+ ANGLE_LIMIT_CAP(mState.mCaps.maxCombinedTextureImageUnits,
+ IMPLEMENTATION_MAX_ACTIVE_TEXTURES);
+ }
+
+ for (ShaderType shaderType : AllShaderTypes())
+ {
+ ANGLE_LIMIT_CAP(mState.mCaps.maxShaderTextureImageUnits[shaderType],
+ IMPLEMENTATION_MAX_SHADER_TEXTURES);
+ }
+
+ ANGLE_LIMIT_CAP(mState.mCaps.maxImageUnits, IMPLEMENTATION_MAX_IMAGE_UNITS);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxCombinedImageUniforms, IMPLEMENTATION_MAX_IMAGE_UNITS);
+ for (ShaderType shaderType : AllShaderTypes())
+ {
+ ANGLE_LIMIT_CAP(mState.mCaps.maxShaderImageUniforms[shaderType],
+ IMPLEMENTATION_MAX_IMAGE_UNITS);
+ }
+
+ for (ShaderType shaderType : AllShaderTypes())
+ {
+ ANGLE_LIMIT_CAP(mState.mCaps.maxShaderAtomicCounterBuffers[shaderType],
+ IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS);
+ }
+ ANGLE_LIMIT_CAP(mState.mCaps.maxAtomicCounterBufferBindings,
+ IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxCombinedAtomicCounterBuffers,
+ IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS);
+
+ for (ShaderType shaderType : AllShaderTypes())
+ {
+ ANGLE_LIMIT_CAP(mState.mCaps.maxShaderStorageBlocks[shaderType],
+ IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
+ }
+ ANGLE_LIMIT_CAP(mState.mCaps.maxShaderStorageBufferBindings,
+ IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxCombinedShaderStorageBlocks,
+ IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS);
+
+ ANGLE_LIMIT_CAP(mState.mCaps.maxClipDistances, IMPLEMENTATION_MAX_CLIP_DISTANCES);
+
+ ANGLE_LIMIT_CAP(mState.mCaps.maxFramebufferLayers, IMPLEMENTATION_MAX_FRAMEBUFFER_LAYERS);
+
+ ANGLE_LIMIT_CAP(mState.mCaps.maxSampleMaskWords, IMPLEMENTATION_MAX_SAMPLE_MASK_WORDS);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxSamples, IMPLEMENTATION_MAX_SAMPLES);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxFramebufferSamples, IMPLEMENTATION_MAX_SAMPLES);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxColorTextureSamples, IMPLEMENTATION_MAX_SAMPLES);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxDepthTextureSamples, IMPLEMENTATION_MAX_SAMPLES);
+ ANGLE_LIMIT_CAP(mState.mCaps.maxIntegerSamples, IMPLEMENTATION_MAX_SAMPLES);
+
+ ANGLE_LIMIT_CAP(mState.mCaps.maxViews, IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS);
+
+ ANGLE_LIMIT_CAP(mState.mCaps.maxDualSourceDrawBuffers,
+ IMPLEMENTATION_MAX_DUAL_SOURCE_DRAW_BUFFERS);
+
+ // WebGL compatibility
+ mState.mExtensions.webglCompatibilityANGLE = mWebGLContext;
+ for (const auto &extensionInfo : GetExtensionInfoMap())
+ {
+ // If the user has requested that extensions start disabled and they are requestable,
+ // disable them.
+ if (!mExtensionsEnabled && extensionInfo.second.Requestable)
+ {
+ mState.mExtensions.*(extensionInfo.second.ExtensionsMember) = false;
+ }
+ }
+
+ // Hide emulated ETC1 extension from WebGL contexts.
+ if (mWebGLContext && getLimitations().emulatedEtc1)
+ {
+ mSupportedExtensions.compressedETC1RGB8SubTextureEXT = false;
+ mSupportedExtensions.compressedETC1RGB8TextureOES = false;
+ }
+
+ if (getLimitations().emulatedAstc)
+ {
+ // Hide emulated ASTC extension from WebGL contexts.
+ if (mWebGLContext)
+ {
+ mSupportedExtensions.textureCompressionAstcLdrKHR = false;
+ mState.mExtensions.textureCompressionAstcLdrKHR = false;
+ }
+#if !defined(ANGLE_HAS_ASTCENC)
+ // Don't expose emulated ASTC when it's not built.
+ mSupportedExtensions.textureCompressionAstcLdrKHR = false;
+ mState.mExtensions.textureCompressionAstcLdrKHR = false;
+#endif
+ }
+
+ // If we're capturing application calls for replay, apply some feature limits to increase
+ // portability of the trace.
+ if (getShareGroup()->getFrameCaptureShared()->enabled() ||
+ getFrontendFeatures().enableCaptureLimits.enabled)
+ {
+ INFO() << "Limit some features because "
+ << (getShareGroup()->getFrameCaptureShared()->enabled()
+ ? "FrameCapture is enabled"
+ : "FrameCapture limits were forced")
+ << std::endl;
+
+ if (!getFrontendFeatures().enableProgramBinaryForCapture.enabled)
+ {
+ // Some apps insist on being able to use glProgramBinary. For those, we'll allow the
+ // extension to remain on. Otherwise, force the extension off.
+ INFO() << "Disabling GL_OES_get_program_binary for trace portability";
+ mDisplay->overrideFrontendFeatures({"disable_program_binary"}, true);
+ }
+
+ // Set to the most common limit per gpuinfo.org. Required for several platforms we test.
+ constexpr GLint maxImageUnits = 8;
+ INFO() << "Limiting image unit count to " << maxImageUnits;
+ ANGLE_LIMIT_CAP(mState.mCaps.maxImageUnits, maxImageUnits);
+ for (ShaderType shaderType : AllShaderTypes())
+ {
+ ANGLE_LIMIT_CAP(mState.mCaps.maxShaderImageUniforms[shaderType], maxImageUnits);
+ }
+
+ // Set a large uniform buffer offset alignment that works on multiple platforms.
+ // The offset used by the trace needs to be divisible by the device's actual value.
+ // Values seen during development: ARM (16), Intel (32), Qualcomm (128), Nvidia (256)
+ constexpr GLint uniformBufferOffsetAlignment = 256;
+ ASSERT(uniformBufferOffsetAlignment % mState.mCaps.uniformBufferOffsetAlignment == 0);
+ INFO() << "Setting uniform buffer offset alignment to " << uniformBufferOffsetAlignment;
+ mState.mCaps.uniformBufferOffsetAlignment = uniformBufferOffsetAlignment;
+
+ // Also limit texture buffer offset alignment, if enabled
+ if (mState.mExtensions.textureBufferAny())
+ {
+ constexpr GLint textureBufferOffsetAlignment =
+ gl::limits::kMinTextureBufferOffsetAlignment;
+ ASSERT(textureBufferOffsetAlignment % mState.mCaps.textureBufferOffsetAlignment == 0);
+ INFO() << "Setting texture buffer offset alignment to " << textureBufferOffsetAlignment;
+ mState.mCaps.textureBufferOffsetAlignment = textureBufferOffsetAlignment;
+ }
+
+ INFO() << "Disabling GL_EXT_map_buffer_range and GL_OES_mapbuffer during capture, which "
+ "are not supported on some native drivers";
+ mState.mExtensions.mapBufferRangeEXT = false;
+ mState.mExtensions.mapbufferOES = false;
+
+ INFO() << "Disabling GL_CHROMIUM_bind_uniform_location during capture, which is not "
+ "supported on native drivers";
+ mState.mExtensions.bindUniformLocationCHROMIUM = false;
+
+ INFO() << "Disabling GL_NV_shader_noperspective_interpolation during capture, which is not "
+ "supported on some native drivers";
+ mState.mExtensions.shaderNoperspectiveInterpolationNV = false;
+
+ INFO() << "Disabling GL_NV_framebuffer_blit during capture, which is not "
+ "supported on some native drivers";
+ mState.mExtensions.framebufferBlitNV = false;
+
+ // NVIDIA's Vulkan driver only supports 4 draw buffers
+ constexpr GLint maxDrawBuffers = 4;
+ INFO() << "Limiting draw buffer count to " << maxDrawBuffers;
+ ANGLE_LIMIT_CAP(mState.mCaps.maxDrawBuffers, maxDrawBuffers);
+
+ // Unity based applications are sending down GL streams with undefined behavior.
+ // Disabling EGL_KHR_create_context_no_error (which enables a new EGL attrib) prevents that,
+ // but we don't have the infrastructure for disabling EGL extensions yet.
+ // Instead, disable GL_KHR_no_error (which disables exposing the GL extension), which
+ // prevents writing invalid calls to the capture.
+ INFO() << "Enabling validation to prevent invalid calls from being captured. This "
+ "effectively disables GL_KHR_no_error and enables GL_ANGLE_robust_client_memory.";
+ mSkipValidation = false;
+ mState.mExtensions.noErrorKHR = mSkipValidation;
+ mState.mExtensions.robustClientMemoryANGLE = !mSkipValidation;
+
+ INFO() << "Disabling GL_OES_depth32 during capture, which is not widely supported on "
+ "mobile";
+ mState.mExtensions.depth32OES = false;
+
+ // Pixel 4 (Qualcomm) only supports 6 atomic counter buffer bindings.
+ constexpr GLint maxAtomicCounterBufferBindings = 6;
+ INFO() << "Limiting max atomic counter buffer bindings to "
+ << maxAtomicCounterBufferBindings;
+ ANGLE_LIMIT_CAP(mState.mCaps.maxAtomicCounterBufferBindings,
+ maxAtomicCounterBufferBindings);
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ ANGLE_LIMIT_CAP(mState.mCaps.maxShaderAtomicCounterBuffers[shaderType],
+ maxAtomicCounterBufferBindings);
+ }
+
+ // SwiftShader only supports 12 shader storage buffer bindings.
+ constexpr GLint maxShaderStorageBufferBindings = 12;
+ INFO() << "Limiting max shader storage buffer bindings to "
+ << maxShaderStorageBufferBindings;
+ ANGLE_LIMIT_CAP(mState.mCaps.maxShaderStorageBufferBindings,
+ maxShaderStorageBufferBindings);
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ ANGLE_LIMIT_CAP(mState.mCaps.maxShaderStorageBlocks[shaderType],
+ maxShaderStorageBufferBindings);
+ }
+
+ // Pixel 4 only supports GL_MAX_SAMPLES of 4
+ constexpr GLint maxSamples = 4;
+ INFO() << "Limiting GL_MAX_SAMPLES to " << maxSamples;
+ ANGLE_LIMIT_CAP(mState.mCaps.maxSamples, maxSamples);
+ }
+
+ // Disable support for OES_get_program_binary
+ if (mDisplay->getFrontendFeatures().disableProgramBinary.enabled)
+ {
+ mState.mExtensions.getProgramBinaryOES = false;
+ mState.mCaps.shaderBinaryFormats.clear();
+ mState.mCaps.programBinaryFormats.clear();
+ mMemoryProgramCache = nullptr;
+ }
+
+ if (mSupportedExtensions.shaderPixelLocalStorageANGLE)
+ {
+ int maxDrawableAttachments =
+ std::min(mState.mCaps.maxDrawBuffers, mState.mCaps.maxColorAttachments);
+ ShPixelLocalStorageType plsType = mImplementation->getNativePixelLocalStorageType();
+ if (ShPixelLocalStorageTypeUsesImages(plsType))
+ {
+ mState.mCaps.maxPixelLocalStoragePlanes =
+ mState.mCaps.maxShaderImageUniforms[ShaderType::Fragment];
+ ANGLE_LIMIT_CAP(mState.mCaps.maxPixelLocalStoragePlanes,
+ IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES);
+ mState.mCaps.maxColorAttachmentsWithActivePixelLocalStorage =
+ mState.mCaps.maxColorAttachments;
+ mState.mCaps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes = std::min<GLint>(
+ mState.mCaps.maxPixelLocalStoragePlanes +
+ std::min(mState.mCaps.maxDrawBuffers, mState.mCaps.maxColorAttachments),
+ mState.mCaps.maxCombinedShaderOutputResources);
+ }
+ else
+ {
+ ASSERT(plsType == ShPixelLocalStorageType::FramebufferFetch);
+ mState.mCaps.maxPixelLocalStoragePlanes = maxDrawableAttachments;
+ ANGLE_LIMIT_CAP(mState.mCaps.maxPixelLocalStoragePlanes,
+ IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES);
+ if (!mSupportedExtensions.drawBuffersIndexedAny())
+ {
+ // When pixel local storage is implemented as framebuffer attachments, we need to
+ // disable color masks and blending to its attachments. If the backend context
+ // doesn't have indexed blend and color mask support, then we will have have to
+ // disable them globally. This also means the application can't have its own draw
+ // buffers while PLS is active.
+ mState.mCaps.maxColorAttachmentsWithActivePixelLocalStorage = 0;
+ }
+ else
+ {
+ mState.mCaps.maxColorAttachmentsWithActivePixelLocalStorage =
+ maxDrawableAttachments - 1;
+ }
+ mState.mCaps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes = maxDrawableAttachments;
+ }
+ }
+
+#undef ANGLE_LIMIT_CAP
+#undef ANGLE_LOG_CAP_LIMIT
+
+ // Generate texture caps
+ updateCaps();
+}
+
+void Context::updateCaps()
+{
+ mState.mCaps.compressedTextureFormats.clear();
+ mState.mTextureCaps.clear();
+
+ for (GLenum sizedInternalFormat : GetAllSizedInternalFormats())
+ {
+ TextureCaps formatCaps = mImplementation->getNativeTextureCaps().get(sizedInternalFormat);
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(sizedInternalFormat);
+
+ // Update the format caps based on the client version and extensions.
+ // Caps are AND'd with the renderer caps because some core formats are still unsupported in
+ // ES3.
+ formatCaps.texturable = formatCaps.texturable &&
+ formatInfo.textureSupport(getClientVersion(), mState.mExtensions);
+ formatCaps.filterable = formatCaps.filterable &&
+ formatInfo.filterSupport(getClientVersion(), mState.mExtensions);
+ formatCaps.textureAttachment =
+ formatCaps.textureAttachment &&
+ formatInfo.textureAttachmentSupport(getClientVersion(), mState.mExtensions);
+ formatCaps.renderbuffer =
+ formatCaps.renderbuffer &&
+ formatInfo.renderbufferSupport(getClientVersion(), mState.mExtensions);
+ formatCaps.blendable =
+ formatCaps.blendable && formatInfo.blendSupport(getClientVersion(), mState.mExtensions);
+
+ // OpenGL ES does not support multisampling with non-rendererable formats
+ // OpenGL ES 3.0 or prior does not support multisampling with integer formats
+ if (!formatCaps.renderbuffer ||
+ (getClientVersion() < ES_3_1 && !mState.mExtensions.textureMultisampleANGLE &&
+ formatInfo.isInt()))
+ {
+ formatCaps.sampleCounts.clear();
+ }
+ else
+ {
+ // We may have limited the max samples for some required renderbuffer formats due to
+ // non-conformant formats. In this case MAX_SAMPLES needs to be lowered accordingly.
+ GLuint formatMaxSamples = formatCaps.getMaxSamples();
+
+ // GLES 3.0.5 section 4.4.2.2: "Implementations must support creation of renderbuffers
+ // in these required formats with up to the value of MAX_SAMPLES multisamples, with the
+ // exception of signed and unsigned integer formats."
+ if (!formatInfo.isInt() && formatInfo.isRequiredRenderbufferFormat(getClientVersion()))
+ {
+ ASSERT(getClientVersion() < ES_3_0 || formatMaxSamples >= 4);
+ mState.mCaps.maxSamples =
+ std::min(static_cast<GLuint>(mState.mCaps.maxSamples), formatMaxSamples);
+ }
+
+ // Handle GLES 3.1 MAX_*_SAMPLES values similarly to MAX_SAMPLES.
+ if (getClientVersion() >= ES_3_1 || mState.mExtensions.textureMultisampleANGLE)
+ {
+ // GLES 3.1 section 9.2.5: "Implementations must support creation of renderbuffers
+ // in these required formats with up to the value of MAX_SAMPLES multisamples, with
+ // the exception that the signed and unsigned integer formats are required only to
+ // support creation of renderbuffers with up to the value of MAX_INTEGER_SAMPLES
+ // multisamples, which must be at least one."
+ if (formatInfo.isInt())
+ {
+ mState.mCaps.maxIntegerSamples = std::min(
+ static_cast<GLuint>(mState.mCaps.maxIntegerSamples), formatMaxSamples);
+ }
+
+ // GLES 3.1 section 19.3.1.
+ if (formatCaps.texturable)
+ {
+ if (formatInfo.depthBits > 0)
+ {
+ mState.mCaps.maxDepthTextureSamples =
+ std::min(static_cast<GLuint>(mState.mCaps.maxDepthTextureSamples),
+ formatMaxSamples);
+ }
+ else if (formatInfo.redBits > 0)
+ {
+ mState.mCaps.maxColorTextureSamples =
+ std::min(static_cast<GLuint>(mState.mCaps.maxColorTextureSamples),
+ formatMaxSamples);
+ }
+ }
+ }
+ }
+
+ if (formatCaps.texturable && (formatInfo.compressed || formatInfo.paletted))
+ {
+ mState.mCaps.compressedTextureFormats.push_back(sizedInternalFormat);
+ }
+
+ mState.mTextureCaps.insert(sizedInternalFormat, formatCaps);
+ }
+
+ // If program binary is disabled, blank out the memory cache pointer.
+ if (!mSupportedExtensions.getProgramBinaryOES)
+ {
+ mMemoryProgramCache = nullptr;
+ }
+
+ // Compute which buffer types are allowed
+ mValidBufferBindings.reset();
+ mValidBufferBindings.set(BufferBinding::ElementArray);
+ mValidBufferBindings.set(BufferBinding::Array);
+
+ if (mState.mExtensions.pixelBufferObjectNV || getClientVersion() >= ES_3_0)
+ {
+ mValidBufferBindings.set(BufferBinding::PixelPack);
+ mValidBufferBindings.set(BufferBinding::PixelUnpack);
+ }
+
+ if (getClientVersion() >= ES_3_0)
+ {
+ mValidBufferBindings.set(BufferBinding::CopyRead);
+ mValidBufferBindings.set(BufferBinding::CopyWrite);
+ mValidBufferBindings.set(BufferBinding::TransformFeedback);
+ mValidBufferBindings.set(BufferBinding::Uniform);
+ }
+
+ if (getClientVersion() >= ES_3_1)
+ {
+ mValidBufferBindings.set(BufferBinding::AtomicCounter);
+ mValidBufferBindings.set(BufferBinding::ShaderStorage);
+ mValidBufferBindings.set(BufferBinding::DrawIndirect);
+ mValidBufferBindings.set(BufferBinding::DispatchIndirect);
+ }
+
+ if (getClientVersion() >= ES_3_2 || mState.mExtensions.textureBufferAny())
+ {
+ mValidBufferBindings.set(BufferBinding::Texture);
+ }
+
+ if (!mState.mExtensions.parallelShaderCompileKHR)
+ {
+ mSingleThreadPool = angle::WorkerThreadPool::Create(false);
+ }
+ mMultiThreadPool = angle::WorkerThreadPool::Create(
+ mState.mExtensions.parallelShaderCompileKHR ||
+ getFrontendFeatures().enableCompressingPipelineCacheInThreadPool.enabled);
+
+ // Reinitialize some dirty bits that depend on extensions.
+ if (mState.isRobustResourceInitEnabled())
+ {
+ mDrawDirtyObjects.set(State::DIRTY_OBJECT_DRAW_ATTACHMENTS);
+ mDrawDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES_INIT);
+ mDrawDirtyObjects.set(State::DIRTY_OBJECT_IMAGES_INIT);
+ mBlitDirtyObjects.set(State::DIRTY_OBJECT_DRAW_ATTACHMENTS);
+ mBlitDirtyObjects.set(State::DIRTY_OBJECT_READ_ATTACHMENTS);
+ mComputeDirtyObjects.set(State::DIRTY_OBJECT_TEXTURES_INIT);
+ mComputeDirtyObjects.set(State::DIRTY_OBJECT_IMAGES_INIT);
+ mReadPixelsDirtyObjects.set(State::DIRTY_OBJECT_READ_ATTACHMENTS);
+ mCopyImageDirtyBits.set(State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
+ mCopyImageDirtyObjects.set(State::DIRTY_OBJECT_READ_ATTACHMENTS);
+ }
+
+ // We need to validate buffer bounds if we are in a WebGL or robust access context and the
+ // back-end does not support robust buffer access behaviour.
+ mBufferAccessValidationEnabled = (!mSupportedExtensions.robustBufferAccessBehaviorKHR &&
+ (mState.isWebGL() || mState.hasRobustAccess()));
+
+ // Cache this in the VertexArrays. They need to check it in state change notifications.
+ for (auto vaoIter : mVertexArrayMap)
+ {
+ VertexArray *vao = vaoIter.second;
+ vao->setBufferAccessValidationEnabled(mBufferAccessValidationEnabled);
+ }
+
+ // Reinitialize state cache after extension changes.
+ mStateCache.initialize(this);
+}
+
+bool Context::noopDrawInstanced(PrimitiveMode mode, GLsizei count, GLsizei instanceCount) const
+{
+ return (instanceCount == 0) || noopDraw(mode, count);
+}
+
+angle::Result Context::prepareForClear(GLbitfield mask)
+{
+ // Sync the draw framebuffer manually after the clear attachments.
+ ANGLE_TRY(mState.getDrawFramebuffer()->ensureClearAttachmentsInitialized(this, mask));
+ return syncStateForClear();
+}
+
+angle::Result Context::prepareForClearBuffer(GLenum buffer, GLint drawbuffer)
+{
+ // Sync the draw framebuffer manually after the clear attachments.
+ ANGLE_TRY(mState.getDrawFramebuffer()->ensureClearBufferAttachmentsInitialized(this, buffer,
+ drawbuffer));
+ return syncStateForClear();
+}
+
+ANGLE_INLINE angle::Result Context::prepareForCopyImage()
+{
+ ANGLE_TRY(syncDirtyObjects(mCopyImageDirtyObjects, Command::CopyImage));
+ return syncDirtyBits(mCopyImageDirtyBits, Command::CopyImage);
+}
+
+ANGLE_INLINE angle::Result Context::prepareForDispatch()
+{
+ // Converting a PPO from graphics to compute requires re-linking it.
+ // The compute shader must have successfully linked before being included in the PPO, so no link
+ // errors that would have been caught during validation should be possible when re-linking the
+ // PPO with the compute shader.
+ Program *program = mState.getProgram();
+ ProgramPipeline *pipeline = mState.getProgramPipeline();
+ if (!program && pipeline)
+ {
+ // Linking the PPO can't fail due to a validation error within the compute program,
+ // since it successfully linked already in order to become part of the PPO in the first
+ // place.
+ pipeline->resolveLink(this);
+ ANGLE_CHECK(this, pipeline->isLinked(), "Program pipeline link failed",
+ GL_INVALID_OPERATION);
+ }
+
+ ANGLE_TRY(syncDirtyObjects(mComputeDirtyObjects, Command::Dispatch));
+ return syncDirtyBits(mComputeDirtyBits, Command::Dispatch);
+}
+
+angle::Result Context::prepareForInvalidate(GLenum target)
+{
+ // Only sync the FBO that's being invalidated. Per the GLES3 spec, GL_FRAMEBUFFER is equivalent
+ // to GL_DRAW_FRAMEBUFFER for the purposes of invalidation.
+ GLenum effectiveTarget = target;
+ if (effectiveTarget == GL_FRAMEBUFFER)
+ {
+ effectiveTarget = GL_DRAW_FRAMEBUFFER;
+ }
+ ANGLE_TRY(mState.syncDirtyObject(this, effectiveTarget));
+ return syncDirtyBits(effectiveTarget == GL_READ_FRAMEBUFFER ? mReadInvalidateDirtyBits
+ : mDrawInvalidateDirtyBits,
+ Command::Invalidate);
+}
+
+angle::Result Context::syncState(const State::DirtyBits &bitMask,
+ const State::DirtyObjects &objectMask,
+ Command command)
+{
+ ANGLE_TRY(syncDirtyObjects(objectMask, command));
+ ANGLE_TRY(syncDirtyBits(bitMask, command));
+ return angle::Result::Continue;
+}
+
+void Context::blitFramebuffer(GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter)
+{
+ if (mask == 0)
+ {
+ // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
+ // buffers are copied.
+ return;
+ }
+
+ Framebuffer *drawFramebuffer = mState.getDrawFramebuffer();
+ ASSERT(drawFramebuffer);
+
+ // Note that blitting is called against draw framebuffer.
+ // See the code in gl::Context::blitFramebuffer.
+ if ((mask & GL_COLOR_BUFFER_BIT) && !drawFramebuffer->hasEnabledDrawBuffer())
+ {
+ mask &= ~GL_COLOR_BUFFER_BIT;
+ }
+
+ if ((mask & GL_STENCIL_BUFFER_BIT) &&
+ drawFramebuffer->getState().getStencilAttachment() == nullptr)
+ {
+ mask &= ~GL_STENCIL_BUFFER_BIT;
+ }
+
+ if ((mask & GL_DEPTH_BUFFER_BIT) && drawFramebuffer->getState().getDepthAttachment() == nullptr)
+ {
+ mask &= ~GL_DEPTH_BUFFER_BIT;
+ }
+
+ // Early out if none of the specified attachments exist or are enabled.
+ if (mask == 0)
+ {
+ ANGLE_PERF_WARNING(mState.getDebug(), GL_DEBUG_SEVERITY_LOW,
+ "BlitFramebuffer called for non-existing buffers");
+ return;
+ }
+
+ Rectangle srcArea(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
+ Rectangle dstArea(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
+
+ if (dstArea.width == 0 || dstArea.height == 0)
+ {
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(syncStateForBlit(mask));
+ ANGLE_CONTEXT_TRY(drawFramebuffer->blit(this, srcArea, dstArea, mask, filter));
+}
+
+void Context::blitFramebufferNV(GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter)
+{
+ blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+}
+
+void Context::clear(GLbitfield mask)
+{
+ if (mState.isRasterizerDiscardEnabled())
+ {
+ return;
+ }
+
+ // Noop empty scissors.
+ if (IsEmptyScissor(mState))
+ {
+ return;
+ }
+
+ // Remove clear bits that are ineffective. An effective clear changes at least one fragment. If
+ // color/depth/stencil masks make the clear ineffective we skip it altogether.
+
+ // If all color channels in all draw buffers are masked, don't attempt to clear color.
+ if (mState.allActiveDrawBufferChannelsMasked())
+ {
+ mask &= ~GL_COLOR_BUFFER_BIT;
+ }
+
+ // If depth write is disabled, don't attempt to clear depth.
+ if (mState.getDrawFramebuffer()->getDepthAttachment() == nullptr ||
+ !mState.getDepthStencilState().depthMask)
+ {
+ mask &= ~GL_DEPTH_BUFFER_BIT;
+ }
+
+ // If all stencil bits are masked, don't attempt to clear stencil.
+ if (mState.getDrawFramebuffer()->getStencilAttachment() == nullptr ||
+ (angle::BitMask<uint32_t>(
+ mState.getDrawFramebuffer()->getStencilAttachment()->getStencilSize()) &
+ mState.getDepthStencilState().stencilWritemask) == 0)
+ {
+ mask &= ~GL_STENCIL_BUFFER_BIT;
+ }
+
+ if (mask == 0)
+ {
+ ANGLE_PERF_WARNING(mState.getDebug(), GL_DEBUG_SEVERITY_LOW,
+ "Clear called for non-existing buffers");
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForClear(mask));
+ ANGLE_CONTEXT_TRY(mState.getDrawFramebuffer()->clear(this, mask));
+}
+
+bool Context::isClearBufferMaskedOut(GLenum buffer, GLint drawbuffer) const
+{
+ switch (buffer)
+ {
+ case GL_COLOR:
+ return IsColorMaskedOut(mState.getBlendStateExt(), drawbuffer);
+ case GL_DEPTH:
+ return mState.getDepthStencilState().isDepthMaskedOut();
+ case GL_STENCIL:
+ return mState.getDepthStencilState().isStencilMaskedOut();
+ case GL_DEPTH_STENCIL:
+ return mState.getDepthStencilState().isDepthMaskedOut() &&
+ mState.getDepthStencilState().isStencilMaskedOut();
+ default:
+ UNREACHABLE();
+ return true;
+ }
+}
+
+bool Context::noopClearBuffer(GLenum buffer, GLint drawbuffer) const
+{
+ Framebuffer *framebufferObject = mState.getDrawFramebuffer();
+
+ return !IsClearBufferEnabled(framebufferObject->getState(), buffer, drawbuffer) ||
+ mState.isRasterizerDiscardEnabled() || isClearBufferMaskedOut(buffer, drawbuffer) ||
+ IsEmptyScissor(mState);
+}
+
+void Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values)
+{
+ if (noopClearBuffer(buffer, drawbuffer))
+ {
+ return;
+ }
+
+ Framebuffer *framebufferObject = mState.getDrawFramebuffer();
+ const FramebufferAttachment *attachment = nullptr;
+ if (buffer == GL_DEPTH)
+ {
+ attachment = framebufferObject->getDepthAttachment();
+ }
+ else if (buffer == GL_COLOR &&
+ static_cast<size_t>(drawbuffer) < framebufferObject->getNumColorAttachments())
+ {
+ attachment = framebufferObject->getColorAttachment(drawbuffer);
+ }
+ // It's not an error to try to clear a non-existent buffer, but it's a no-op. We early out so
+ // that the backend doesn't need to take this case into account.
+ if (!attachment)
+ {
+ return;
+ }
+ ANGLE_CONTEXT_TRY(prepareForClearBuffer(buffer, drawbuffer));
+ ANGLE_CONTEXT_TRY(framebufferObject->clearBufferfv(this, buffer, drawbuffer, values));
+}
+
+void Context::clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values)
+{
+ if (noopClearBuffer(buffer, drawbuffer))
+ {
+ return;
+ }
+
+ Framebuffer *framebufferObject = mState.getDrawFramebuffer();
+ const FramebufferAttachment *attachment = nullptr;
+ if (buffer == GL_COLOR &&
+ static_cast<size_t>(drawbuffer) < framebufferObject->getNumColorAttachments())
+ {
+ attachment = framebufferObject->getColorAttachment(drawbuffer);
+ }
+ // It's not an error to try to clear a non-existent buffer, but it's a no-op. We early out so
+ // that the backend doesn't need to take this case into account.
+ if (!attachment)
+ {
+ return;
+ }
+ ANGLE_CONTEXT_TRY(prepareForClearBuffer(buffer, drawbuffer));
+ ANGLE_CONTEXT_TRY(framebufferObject->clearBufferuiv(this, buffer, drawbuffer, values));
+}
+
+void Context::clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values)
+{
+ if (noopClearBuffer(buffer, drawbuffer))
+ {
+ return;
+ }
+
+ Framebuffer *framebufferObject = mState.getDrawFramebuffer();
+ const FramebufferAttachment *attachment = nullptr;
+ if (buffer == GL_STENCIL)
+ {
+ attachment = framebufferObject->getStencilAttachment();
+ }
+ else if (buffer == GL_COLOR &&
+ static_cast<size_t>(drawbuffer) < framebufferObject->getNumColorAttachments())
+ {
+ attachment = framebufferObject->getColorAttachment(drawbuffer);
+ }
+ // It's not an error to try to clear a non-existent buffer, but it's a no-op. We early out so
+ // that the backend doesn't need to take this case into account.
+ if (!attachment)
+ {
+ return;
+ }
+ ANGLE_CONTEXT_TRY(prepareForClearBuffer(buffer, drawbuffer));
+ ANGLE_CONTEXT_TRY(framebufferObject->clearBufferiv(this, buffer, drawbuffer, values));
+}
+
+void Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+{
+ if (noopClearBuffer(buffer, drawbuffer))
+ {
+ return;
+ }
+
+ Framebuffer *framebufferObject = mState.getDrawFramebuffer();
+ ASSERT(framebufferObject);
+
+ // If a buffer is not present, the clear has no effect
+ if (framebufferObject->getDepthAttachment() == nullptr &&
+ framebufferObject->getStencilAttachment() == nullptr)
+ {
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForClearBuffer(buffer, drawbuffer));
+ ANGLE_CONTEXT_TRY(framebufferObject->clearBufferfi(this, buffer, drawbuffer, depth, stencil));
+}
+
+void Context::readPixels(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ void *pixels)
+{
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(syncStateForReadPixels());
+
+ Framebuffer *readFBO = mState.getReadFramebuffer();
+ ASSERT(readFBO);
+
+ Rectangle area(x, y, width, height);
+ PixelPackState packState = mState.getPackState();
+ Buffer *packBuffer = mState.getTargetBuffer(gl::BufferBinding::PixelPack);
+ ANGLE_CONTEXT_TRY(readFBO->readPixels(this, area, format, type, packState, packBuffer, pixels));
+}
+
+void Context::readPixelsRobust(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *pixels)
+{
+ readPixels(x, y, width, height, format, type, pixels);
+}
+
+void Context::readnPixelsRobust(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *data)
+{
+ readPixels(x, y, width, height, format, type, data);
+}
+
+void Context::copyTexImage2D(TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ ANGLE_CONTEXT_TRY(prepareForCopyImage());
+
+ Rectangle sourceArea(x, y, width, height);
+
+ Framebuffer *framebuffer = mState.getReadFramebuffer();
+ Texture *texture = getTextureByTarget(target);
+ ANGLE_CONTEXT_TRY(
+ texture->copyImage(this, target, level, sourceArea, internalformat, framebuffer));
+}
+
+void Context::copyTexSubImage2D(TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForCopyImage());
+
+ Offset destOffset(xoffset, yoffset, 0);
+ Rectangle sourceArea(x, y, width, height);
+
+ ImageIndex index = ImageIndex::MakeFromTarget(target, level, 1);
+
+ Framebuffer *framebuffer = mState.getReadFramebuffer();
+ Texture *texture = getTextureByTarget(target);
+ ANGLE_CONTEXT_TRY(texture->copySubImage(this, index, destOffset, sourceArea, framebuffer));
+}
+
+void Context::copyTexSubImage3D(TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForCopyImage());
+
+ Offset destOffset(xoffset, yoffset, zoffset);
+ Rectangle sourceArea(x, y, width, height);
+
+ ImageIndex index = ImageIndex::MakeFromType(TextureTargetToType(target), level, zoffset);
+
+ Framebuffer *framebuffer = mState.getReadFramebuffer();
+ Texture *texture = getTextureByTarget(target);
+ ANGLE_CONTEXT_TRY(texture->copySubImage(this, index, destOffset, sourceArea, framebuffer));
+}
+
+void Context::copyImageSubData(GLuint srcName,
+ GLenum srcTarget,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLuint dstName,
+ GLenum dstTarget,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth)
+{
+ // if copy region is zero, the copy is a successful no-op
+ if ((srcWidth == 0) || (srcHeight == 0) || (srcDepth == 0))
+ {
+ return;
+ }
+
+ if (srcTarget == GL_RENDERBUFFER)
+ {
+ // Source target is a Renderbuffer
+ Renderbuffer *readBuffer = getRenderbuffer(PackParam<RenderbufferID>(srcName));
+ if (dstTarget == GL_RENDERBUFFER)
+ {
+ // Destination target is a Renderbuffer
+ Renderbuffer *writeBuffer = getRenderbuffer(PackParam<RenderbufferID>(dstName));
+
+ // Copy Renderbuffer to Renderbuffer
+ ANGLE_CONTEXT_TRY(writeBuffer->copyRenderbufferSubData(
+ this, readBuffer, srcLevel, srcX, srcY, srcZ, dstLevel, dstX, dstY, dstZ, srcWidth,
+ srcHeight, srcDepth));
+ }
+ else
+ {
+ // Destination target is a Texture
+ ASSERT(dstTarget == GL_TEXTURE_2D || dstTarget == GL_TEXTURE_2D_ARRAY ||
+ dstTarget == GL_TEXTURE_3D || dstTarget == GL_TEXTURE_CUBE_MAP);
+
+ Texture *writeTexture = getTexture(PackParam<TextureID>(dstName));
+ ANGLE_CONTEXT_TRY(syncTextureForCopy(writeTexture));
+
+ // Copy Renderbuffer to Texture
+ ANGLE_CONTEXT_TRY(writeTexture->copyRenderbufferSubData(
+ this, readBuffer, srcLevel, srcX, srcY, srcZ, dstLevel, dstX, dstY, dstZ, srcWidth,
+ srcHeight, srcDepth));
+ }
+ }
+ else
+ {
+ // Source target is a Texture
+ ASSERT(srcTarget == GL_TEXTURE_2D || srcTarget == GL_TEXTURE_2D_ARRAY ||
+ srcTarget == GL_TEXTURE_3D || srcTarget == GL_TEXTURE_CUBE_MAP);
+
+ Texture *readTexture = getTexture(PackParam<TextureID>(srcName));
+ ANGLE_CONTEXT_TRY(syncTextureForCopy(readTexture));
+
+ if (dstTarget == GL_RENDERBUFFER)
+ {
+ // Destination target is a Renderbuffer
+ Renderbuffer *writeBuffer = getRenderbuffer(PackParam<RenderbufferID>(dstName));
+
+ // Copy Texture to Renderbuffer
+ ANGLE_CONTEXT_TRY(writeBuffer->copyTextureSubData(this, readTexture, srcLevel, srcX,
+ srcY, srcZ, dstLevel, dstX, dstY,
+ dstZ, srcWidth, srcHeight, srcDepth));
+ }
+ else
+ {
+ // Destination target is a Texture
+ ASSERT(dstTarget == GL_TEXTURE_2D || dstTarget == GL_TEXTURE_2D_ARRAY ||
+ dstTarget == GL_TEXTURE_3D || dstTarget == GL_TEXTURE_CUBE_MAP);
+
+ Texture *writeTexture = getTexture(PackParam<TextureID>(dstName));
+ ANGLE_CONTEXT_TRY(syncTextureForCopy(writeTexture));
+
+ // Copy Texture to Texture
+ ANGLE_CONTEXT_TRY(writeTexture->copyTextureSubData(
+ this, readTexture, srcLevel, srcX, srcY, srcZ, dstLevel, dstX, dstY, dstZ, srcWidth,
+ srcHeight, srcDepth));
+ }
+ }
+}
+
+void Context::framebufferTexture2D(GLenum target,
+ GLenum attachment,
+ TextureTarget textarget,
+ TextureID texture,
+ GLint level)
+{
+ Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (texture.value != 0)
+ {
+ Texture *textureObj = getTexture(texture);
+ ImageIndex index = ImageIndex::MakeFromTarget(textarget, level, 1);
+ framebuffer->setAttachment(this, GL_TEXTURE, attachment, index, textureObj);
+ }
+ else
+ {
+ framebuffer->resetAttachment(this, attachment);
+ }
+
+ mState.setObjectDirty(target);
+}
+
+void Context::framebufferTexture3D(GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texture,
+ GLint level,
+ GLint zoffset)
+{
+ Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (texture.value != 0)
+ {
+ Texture *textureObj = getTexture(texture);
+ ImageIndex index = ImageIndex::Make3D(level, zoffset);
+ framebuffer->setAttachment(this, GL_TEXTURE, attachment, index, textureObj);
+ }
+ else
+ {
+ framebuffer->resetAttachment(this, attachment);
+ }
+
+ mState.setObjectDirty(target);
+}
+
+void Context::framebufferRenderbuffer(GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ RenderbufferID renderbuffer)
+{
+ Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (renderbuffer.value != 0)
+ {
+ Renderbuffer *renderbufferObject = getRenderbuffer(renderbuffer);
+ GLsizei rbSamples = renderbufferObject->getState().getSamples();
+
+ framebuffer->setAttachmentMultisample(this, GL_RENDERBUFFER, attachment, gl::ImageIndex(),
+ renderbufferObject, rbSamples);
+ }
+ else
+ {
+ framebuffer->resetAttachment(this, attachment);
+ }
+
+ mState.setObjectDirty(target);
+}
+
+void Context::framebufferTextureLayer(GLenum target,
+ GLenum attachment,
+ TextureID texture,
+ GLint level,
+ GLint layer)
+{
+ Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (texture.value != 0)
+ {
+ Texture *textureObject = getTexture(texture);
+ ImageIndex index = ImageIndex::MakeFromType(textureObject->getType(), level, layer);
+ framebuffer->setAttachment(this, GL_TEXTURE, attachment, index, textureObject);
+ }
+ else
+ {
+ framebuffer->resetAttachment(this, attachment);
+ }
+
+ mState.setObjectDirty(target);
+}
+
+void Context::framebufferTextureMultiview(GLenum target,
+ GLenum attachment,
+ TextureID texture,
+ GLint level,
+ GLint baseViewIndex,
+ GLsizei numViews)
+{
+ Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (texture.value != 0)
+ {
+ Texture *textureObj = getTexture(texture);
+
+ ImageIndex index;
+ if (textureObj->getType() == TextureType::_2DArray)
+ {
+ index = ImageIndex::Make2DArrayRange(level, baseViewIndex, numViews);
+ }
+ else
+ {
+ ASSERT(textureObj->getType() == TextureType::_2DMultisampleArray);
+ ASSERT(level == 0);
+ index = ImageIndex::Make2DMultisampleArrayRange(baseViewIndex, numViews);
+ }
+ framebuffer->setAttachmentMultiview(this, GL_TEXTURE, attachment, index, textureObj,
+ numViews, baseViewIndex);
+ }
+ else
+ {
+ framebuffer->resetAttachment(this, attachment);
+ }
+
+ mState.setObjectDirty(target);
+}
+
+void Context::framebufferTexture(GLenum target, GLenum attachment, TextureID texture, GLint level)
+{
+ Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (texture.value != 0)
+ {
+ Texture *textureObj = getTexture(texture);
+
+ ImageIndex index = ImageIndex::MakeFromType(
+ textureObj->getType(), level, ImageIndex::kEntireLevel, ImageIndex::kEntireLevel);
+ framebuffer->setAttachment(this, GL_TEXTURE, attachment, index, textureObj);
+ }
+ else
+ {
+ framebuffer->resetAttachment(this, attachment);
+ }
+
+ mState.setObjectDirty(target);
+}
+
+void Context::drawBuffers(GLsizei n, const GLenum *bufs)
+{
+ Framebuffer *framebuffer = mState.getDrawFramebuffer();
+ ASSERT(framebuffer);
+ framebuffer->setDrawBuffers(n, bufs);
+ mState.setDrawFramebufferDirty();
+ mStateCache.onDrawFramebufferChange(this);
+}
+
+void Context::readBuffer(GLenum mode)
+{
+ Framebuffer *readFBO = mState.getReadFramebuffer();
+ readFBO->setReadBuffer(mode);
+ mState.setObjectDirty(GL_READ_FRAMEBUFFER);
+}
+
+void Context::discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments)
+{
+ // The specification isn't clear what should be done when the framebuffer isn't complete.
+ // We threat it the same way as GLES3 glInvalidateFramebuffer.
+ invalidateFramebuffer(target, numAttachments, attachments);
+}
+
+void Context::invalidateFramebuffer(GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments)
+{
+ Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ // No-op incomplete FBOs.
+ if (!framebuffer->isComplete(this))
+ {
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForInvalidate(target));
+ ANGLE_CONTEXT_TRY(framebuffer->invalidate(this, numAttachments, attachments));
+}
+
+void Context::invalidateSubFramebuffer(GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (!framebuffer->isComplete(this))
+ {
+ return;
+ }
+
+ Rectangle area(x, y, width, height);
+ ANGLE_CONTEXT_TRY(prepareForInvalidate(target));
+ ANGLE_CONTEXT_TRY(framebuffer->invalidateSub(this, numAttachments, attachments, area));
+}
+
+void Context::texImage2D(TextureTarget target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ ANGLE_CONTEXT_TRY(syncStateForTexImage());
+
+ gl::Buffer *unpackBuffer = mState.getTargetBuffer(gl::BufferBinding::PixelUnpack);
+
+ Extents size(width, height, 1);
+ Texture *texture = getTextureByTarget(target);
+ ANGLE_CONTEXT_TRY(texture->setImage(this, mState.getUnpackState(), unpackBuffer, target, level,
+ internalformat, size, format, type,
+ static_cast<const uint8_t *>(pixels)));
+}
+
+void Context::texImage2DRobust(TextureTarget target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
+}
+
+void Context::texImage3D(TextureTarget target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ ANGLE_CONTEXT_TRY(syncStateForTexImage());
+
+ gl::Buffer *unpackBuffer = mState.getTargetBuffer(gl::BufferBinding::PixelUnpack);
+
+ Extents size(width, height, depth);
+ Texture *texture = getTextureByTarget(target);
+ ANGLE_CONTEXT_TRY(texture->setImage(this, mState.getUnpackState(), unpackBuffer, target, level,
+ internalformat, size, format, type,
+ static_cast<const uint8_t *>(pixels)));
+}
+
+void Context::texImage3DRobust(TextureTarget target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ texImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels);
+}
+
+void Context::texSubImage2D(TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ // Zero sized uploads are valid but no-ops
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(syncStateForTexImage());
+
+ Box area(xoffset, yoffset, 0, width, height, 1);
+ Texture *texture = getTextureByTarget(target);
+
+ gl::Buffer *unpackBuffer = mState.getTargetBuffer(gl::BufferBinding::PixelUnpack);
+
+ ANGLE_CONTEXT_TRY(texture->setSubImage(this, mState.getUnpackState(), unpackBuffer, target,
+ level, area, format, type,
+ static_cast<const uint8_t *>(pixels)));
+}
+
+void Context::texSubImage2DRobust(TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
+}
+
+void Context::texSubImage3D(TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ // Zero sized uploads are valid but no-ops
+ if (width == 0 || height == 0 || depth == 0)
+ {
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(syncStateForTexImage());
+
+ Box area(xoffset, yoffset, zoffset, width, height, depth);
+ Texture *texture = getTextureByTarget(target);
+
+ gl::Buffer *unpackBuffer = mState.getTargetBuffer(gl::BufferBinding::PixelUnpack);
+
+ ANGLE_CONTEXT_TRY(texture->setSubImage(this, mState.getUnpackState(), unpackBuffer, target,
+ level, area, format, type,
+ static_cast<const uint8_t *>(pixels)));
+}
+
+void Context::texSubImage3DRobust(TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type,
+ pixels);
+}
+
+void Context::compressedTexImage2D(TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const void *data)
+{
+ ANGLE_CONTEXT_TRY(syncStateForTexImage());
+
+ Extents size(width, height, 1);
+ Texture *texture = getTextureByTarget(target);
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
+ // image. So we use an empty PixelUnpackState.
+ ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, PixelUnpackState(), target, level,
+ internalformat, size, imageSize,
+ static_cast<const uint8_t *>(data)));
+}
+
+void Context::compressedTexImage2DRobust(TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data)
+{
+ compressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
+}
+
+void Context::compressedTexImage3D(TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const void *data)
+{
+ ANGLE_CONTEXT_TRY(syncStateForTexImage());
+
+ Extents size(width, height, depth);
+ Texture *texture = getTextureByTarget(target);
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
+ // image. So we use an empty PixelUnpackState.
+ ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, PixelUnpackState(), target, level,
+ internalformat, size, imageSize,
+ static_cast<const uint8_t *>(data)));
+}
+
+void Context::compressedTexImage3DRobust(TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data)
+{
+ compressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize,
+ data);
+}
+
+void Context::compressedTexSubImage2D(TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ ANGLE_CONTEXT_TRY(syncStateForTexImage());
+
+ Box area(xoffset, yoffset, 0, width, height, 1);
+ Texture *texture = getTextureByTarget(target);
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
+ // image. So we use an empty PixelUnpackState.
+ ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, PixelUnpackState(), target, level, area,
+ format, imageSize,
+ static_cast<const uint8_t *>(data)));
+}
+
+void Context::compressedTexSubImage2DRobust(TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data)
+{
+ compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize,
+ data);
+}
+
+void Context::compressedTexSubImage3D(TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ // Zero sized uploads are valid but no-ops
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(syncStateForTexImage());
+
+ Box area(xoffset, yoffset, zoffset, width, height, depth);
+ Texture *texture = getTextureByTarget(target);
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
+ // image. So we use an empty PixelUnpackState.
+ ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, PixelUnpackState(), target, level, area,
+ format, imageSize,
+ static_cast<const uint8_t *>(data)));
+}
+
+void Context::compressedTexSubImage3DRobust(TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data)
+{
+ compressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format,
+ imageSize, data);
+}
+
+void Context::generateMipmap(TextureType target)
+{
+ Texture *texture = getTextureByType(target);
+ ANGLE_CONTEXT_TRY(texture->generateMipmap(this));
+}
+
+void Context::copyTexture(TextureID sourceId,
+ GLint sourceLevel,
+ TextureTarget destTarget,
+ TextureID destId,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ ANGLE_CONTEXT_TRY(syncStateForTexImage());
+
+ gl::Texture *sourceTexture = getTexture(sourceId);
+ gl::Texture *destTexture = getTexture(destId);
+ ANGLE_CONTEXT_TRY(
+ destTexture->copyTexture(this, destTarget, destLevel, internalFormat, destType, sourceLevel,
+ ConvertToBool(unpackFlipY), ConvertToBool(unpackPremultiplyAlpha),
+ ConvertToBool(unpackUnmultiplyAlpha), sourceTexture));
+}
+
+void Context::copySubTexture(TextureID sourceId,
+ GLint sourceLevel,
+ TextureTarget destTarget,
+ TextureID destId,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ // Zero sized copies are valid but no-ops
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(syncStateForTexImage());
+
+ gl::Texture *sourceTexture = getTexture(sourceId);
+ gl::Texture *destTexture = getTexture(destId);
+ Offset offset(xoffset, yoffset, 0);
+ Box box(x, y, 0, width, height, 1);
+ ANGLE_CONTEXT_TRY(destTexture->copySubTexture(
+ this, destTarget, destLevel, offset, sourceLevel, box, ConvertToBool(unpackFlipY),
+ ConvertToBool(unpackPremultiplyAlpha), ConvertToBool(unpackUnmultiplyAlpha),
+ sourceTexture));
+}
+
+void Context::copyTexture3D(TextureID sourceId,
+ GLint sourceLevel,
+ TextureTarget destTarget,
+ TextureID destId,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ ANGLE_CONTEXT_TRY(syncStateForTexImage());
+
+ Texture *sourceTexture = getTexture(sourceId);
+ Texture *destTexture = getTexture(destId);
+ ANGLE_CONTEXT_TRY(
+ destTexture->copyTexture(this, destTarget, destLevel, internalFormat, destType, sourceLevel,
+ ConvertToBool(unpackFlipY), ConvertToBool(unpackPremultiplyAlpha),
+ ConvertToBool(unpackUnmultiplyAlpha), sourceTexture));
+}
+
+void Context::copySubTexture3D(TextureID sourceId,
+ GLint sourceLevel,
+ TextureTarget destTarget,
+ TextureID destId,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ // Zero sized copies are valid but no-ops
+ if (width == 0 || height == 0 || depth == 0)
+ {
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(syncStateForTexImage());
+
+ Texture *sourceTexture = getTexture(sourceId);
+ Texture *destTexture = getTexture(destId);
+ Offset offset(xoffset, yoffset, zoffset);
+ Box box(x, y, z, width, height, depth);
+ ANGLE_CONTEXT_TRY(destTexture->copySubTexture(
+ this, destTarget, destLevel, offset, sourceLevel, box, ConvertToBool(unpackFlipY),
+ ConvertToBool(unpackPremultiplyAlpha), ConvertToBool(unpackUnmultiplyAlpha),
+ sourceTexture));
+}
+
+void Context::compressedCopyTexture(TextureID sourceId, TextureID destId)
+{
+ ANGLE_CONTEXT_TRY(syncStateForTexImage());
+
+ gl::Texture *sourceTexture = getTexture(sourceId);
+ gl::Texture *destTexture = getTexture(destId);
+ ANGLE_CONTEXT_TRY(destTexture->copyCompressedTexture(this, sourceTexture));
+}
+
+void Context::getBufferPointerv(BufferBinding target, GLenum pname, void **params)
+{
+ Buffer *buffer = mState.getTargetBuffer(target);
+ ASSERT(buffer);
+
+ QueryBufferPointerv(buffer, pname, params);
+}
+
+void Context::getBufferPointervRobust(BufferBinding target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **params)
+{
+ getBufferPointerv(target, pname, params);
+}
+
+void *Context::mapBuffer(BufferBinding target, GLenum access)
+{
+ Buffer *buffer = mState.getTargetBuffer(target);
+ ASSERT(buffer);
+
+ if (buffer->map(this, access) == angle::Result::Stop)
+ {
+ return nullptr;
+ }
+
+ return buffer->getMapPointer();
+}
+
+GLboolean Context::unmapBuffer(BufferBinding target)
+{
+ Buffer *buffer = mState.getTargetBuffer(target);
+ ASSERT(buffer);
+
+ GLboolean result;
+ if (buffer->unmap(this, &result) == angle::Result::Stop)
+ {
+ return GL_FALSE;
+ }
+
+ return result;
+}
+
+void *Context::mapBufferRange(BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ Buffer *buffer = mState.getTargetBuffer(target);
+ ASSERT(buffer);
+
+ if (buffer->mapRange(this, offset, length, access) == angle::Result::Stop)
+ {
+ return nullptr;
+ }
+
+ return buffer->getMapPointer();
+}
+
+void Context::flushMappedBufferRange(BufferBinding /*target*/,
+ GLintptr /*offset*/,
+ GLsizeiptr /*length*/)
+{
+ // We do not currently support a non-trivial implementation of FlushMappedBufferRange
+}
+
+angle::Result Context::syncStateForReadPixels()
+{
+ return syncState(mReadPixelsDirtyBits, mReadPixelsDirtyObjects, Command::ReadPixels);
+}
+
+angle::Result Context::syncStateForTexImage()
+{
+ return syncState(mTexImageDirtyBits, mTexImageDirtyObjects, Command::TexImage);
+}
+
+angle::Result Context::syncStateForBlit(GLbitfield mask)
+{
+ uint32_t commandMask = 0;
+ if ((mask & GL_COLOR_BUFFER_BIT) != 0)
+ {
+ commandMask |= CommandBlitBufferColor;
+ }
+ if ((mask & GL_DEPTH_BUFFER_BIT) != 0)
+ {
+ commandMask |= CommandBlitBufferDepth;
+ }
+ if ((mask & GL_STENCIL_BUFFER_BIT) != 0)
+ {
+ commandMask |= CommandBlitBufferStencil;
+ }
+
+ Command command = static_cast<Command>(static_cast<uint32_t>(Command::Blit) + commandMask);
+
+ return syncState(mBlitDirtyBits, mBlitDirtyObjects, command);
+}
+
+angle::Result Context::syncStateForClear()
+{
+ return syncState(mClearDirtyBits, mClearDirtyObjects, Command::Clear);
+}
+
+angle::Result Context::syncTextureForCopy(Texture *texture)
+{
+ ASSERT(texture);
+ // Sync texture not active but scheduled for a copy
+ if (texture->hasAnyDirtyBit())
+ {
+ return texture->syncState(this, Command::Other);
+ }
+
+ return angle::Result::Continue;
+}
+
+void Context::activeShaderProgram(ProgramPipelineID pipeline, ShaderProgramID program)
+{
+ Program *shaderProgram = getProgramNoResolveLink(program);
+ ProgramPipeline *programPipeline =
+ mState.mProgramPipelineManager->checkProgramPipelineAllocation(mImplementation.get(),
+ pipeline);
+ ASSERT(programPipeline);
+
+ programPipeline->activeShaderProgram(shaderProgram);
+}
+
+void Context::activeTexture(GLenum texture)
+{
+ mState.setActiveSampler(texture - GL_TEXTURE0);
+}
+
+void Context::blendBarrier()
+{
+ mImplementation->blendBarrier();
+}
+
+void Context::blendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+ mState.setBlendColor(red, green, blue, alpha);
+}
+
+void Context::blendEquation(GLenum mode)
+{
+ mState.setBlendEquation(mode, mode);
+
+ mStateCache.onBlendEquationChange(this);
+}
+
+void Context::blendEquationi(GLuint buf, GLenum mode)
+{
+ mState.setBlendEquationIndexed(mode, mode, buf);
+
+ mStateCache.onBlendEquationChange(this);
+}
+
+void Context::blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+{
+ mState.setBlendEquation(modeRGB, modeAlpha);
+}
+
+void Context::blendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeAlpha)
+{
+ mState.setBlendEquationIndexed(modeRGB, modeAlpha, buf);
+}
+
+void Context::blendFunc(GLenum sfactor, GLenum dfactor)
+{
+ mState.setBlendFactors(sfactor, dfactor, sfactor, dfactor);
+}
+
+void Context::blendFunci(GLuint buf, GLenum src, GLenum dst)
+{
+ mState.setBlendFactorsIndexed(src, dst, src, dst, buf);
+
+ if (mState.noSimultaneousConstantColorAndAlphaBlendFunc())
+ {
+ mStateCache.onBlendFuncIndexedChange(this);
+ }
+}
+
+void Context::blendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+ mState.setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+void Context::blendFuncSeparatei(GLuint buf,
+ GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha)
+{
+ mState.setBlendFactorsIndexed(srcRGB, dstRGB, srcAlpha, dstAlpha, buf);
+
+ if (mState.noSimultaneousConstantColorAndAlphaBlendFunc())
+ {
+ mStateCache.onBlendFuncIndexedChange(this);
+ }
+}
+
+void Context::clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+ mState.setColorClearValue(red, green, blue, alpha);
+}
+
+void Context::clearDepthf(GLfloat depth)
+{
+ mState.setDepthClearValue(clamp01(depth));
+}
+
+void Context::clearStencil(GLint s)
+{
+ mState.setStencilClearValue(s);
+}
+
+void Context::colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+{
+ mState.setColorMask(ConvertToBool(red), ConvertToBool(green), ConvertToBool(blue),
+ ConvertToBool(alpha));
+ mStateCache.onColorMaskChange(this);
+}
+
+void Context::colorMaski(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)
+{
+ mState.setColorMaskIndexed(ConvertToBool(r), ConvertToBool(g), ConvertToBool(b),
+ ConvertToBool(a), index);
+ mStateCache.onColorMaskChange(this);
+}
+
+void Context::cullFace(CullFaceMode mode)
+{
+ mState.setCullMode(mode);
+}
+
+void Context::depthFunc(GLenum func)
+{
+ mState.setDepthFunc(func);
+}
+
+void Context::depthMask(GLboolean flag)
+{
+ mState.setDepthMask(ConvertToBool(flag));
+}
+
+void Context::depthRangef(GLfloat zNear, GLfloat zFar)
+{
+ mState.setDepthRange(clamp01(zNear), clamp01(zFar));
+}
+
+void Context::clipControl(GLenum origin, GLenum depth)
+{
+ mState.setClipControl(origin, depth);
+}
+
+void Context::disable(GLenum cap)
+{
+ mState.setEnableFeature(cap, false);
+ mStateCache.onContextCapChange(this);
+}
+
+void Context::disablei(GLenum target, GLuint index)
+{
+ mState.setEnableFeatureIndexed(target, false, index);
+ mStateCache.onContextCapChange(this);
+}
+
+void Context::disableVertexAttribArray(GLuint index)
+{
+ mState.setEnableVertexAttribArray(index, false);
+ mStateCache.onVertexArrayStateChange(this);
+}
+
+void Context::enable(GLenum cap)
+{
+ mState.setEnableFeature(cap, true);
+ mStateCache.onContextCapChange(this);
+}
+
+void Context::enablei(GLenum target, GLuint index)
+{
+ mState.setEnableFeatureIndexed(target, true, index);
+ mStateCache.onContextCapChange(this);
+}
+
+void Context::enableVertexAttribArray(GLuint index)
+{
+ mState.setEnableVertexAttribArray(index, true);
+ mStateCache.onVertexArrayStateChange(this);
+}
+
+void Context::frontFace(GLenum mode)
+{
+ mState.setFrontFace(mode);
+}
+
+void Context::hint(GLenum target, GLenum mode)
+{
+ switch (target)
+ {
+ case GL_GENERATE_MIPMAP_HINT:
+ mState.setGenerateMipmapHint(mode);
+ break;
+
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
+ mState.setFragmentShaderDerivativeHint(mode);
+ break;
+
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ case GL_POINT_SMOOTH_HINT:
+ case GL_LINE_SMOOTH_HINT:
+ case GL_FOG_HINT:
+ mState.gles1().setHint(target, mode);
+ break;
+ case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
+ mState.setTextureFilteringHint(mode);
+ break;
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+void Context::lineWidth(GLfloat width)
+{
+ mState.setLineWidth(width);
+}
+
+void Context::pixelStorei(GLenum pname, GLint param)
+{
+ switch (pname)
+ {
+ case GL_UNPACK_ALIGNMENT:
+ mState.setUnpackAlignment(param);
+ break;
+
+ case GL_PACK_ALIGNMENT:
+ mState.setPackAlignment(param);
+ break;
+
+ case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+ mState.setPackReverseRowOrder(param != 0);
+ break;
+
+ case GL_UNPACK_ROW_LENGTH:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().unpackSubimageEXT);
+ mState.setUnpackRowLength(param);
+ break;
+
+ case GL_UNPACK_IMAGE_HEIGHT:
+ ASSERT(getClientMajorVersion() >= 3);
+ mState.setUnpackImageHeight(param);
+ break;
+
+ case GL_UNPACK_SKIP_IMAGES:
+ ASSERT(getClientMajorVersion() >= 3);
+ mState.setUnpackSkipImages(param);
+ break;
+
+ case GL_UNPACK_SKIP_ROWS:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().unpackSubimageEXT);
+ mState.setUnpackSkipRows(param);
+ break;
+
+ case GL_UNPACK_SKIP_PIXELS:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().unpackSubimageEXT);
+ mState.setUnpackSkipPixels(param);
+ break;
+
+ case GL_PACK_ROW_LENGTH:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().packSubimageNV);
+ mState.setPackRowLength(param);
+ break;
+
+ case GL_PACK_SKIP_ROWS:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().packSubimageNV);
+ mState.setPackSkipRows(param);
+ break;
+
+ case GL_PACK_SKIP_PIXELS:
+ ASSERT((getClientMajorVersion() >= 3) || getExtensions().packSubimageNV);
+ mState.setPackSkipPixels(param);
+ break;
+
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+void Context::polygonOffset(GLfloat factor, GLfloat units)
+{
+ mState.setPolygonOffsetParams(factor, units);
+}
+
+void Context::sampleCoverage(GLfloat value, GLboolean invert)
+{
+ mState.setSampleCoverageParams(clamp01(value), ConvertToBool(invert));
+}
+
+void Context::sampleMaski(GLuint maskNumber, GLbitfield mask)
+{
+ mState.setSampleMaskParams(maskNumber, mask);
+}
+
+void Context::scissor(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ mState.setScissorParams(x, y, width, height);
+}
+
+void Context::shadingRateQCOM(GLenum rate)
+{
+ mState.setShadingRate(rate);
+}
+
+void Context::stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+ GLint clampedRef = gl::clamp(ref, 0, std::numeric_limits<uint8_t>::max());
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+ {
+ mState.setStencilParams(func, clampedRef, mask);
+ }
+
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ mState.setStencilBackParams(func, clampedRef, mask);
+ }
+
+ mStateCache.onStencilStateChange(this);
+}
+
+void Context::stencilMaskSeparate(GLenum face, GLuint mask)
+{
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+ {
+ mState.setStencilWritemask(mask);
+ }
+
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ mState.setStencilBackWritemask(mask);
+ }
+
+ mStateCache.onStencilStateChange(this);
+}
+
+void Context::stencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+ {
+ mState.setStencilOperations(fail, zfail, zpass);
+ }
+
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ mState.setStencilBackOperations(fail, zfail, zpass);
+ }
+}
+
+void Context::vertexAttrib1f(GLuint index, GLfloat x)
+{
+ GLfloat vals[4] = {x, 0, 0, 1};
+ mState.setVertexAttribf(index, vals);
+ mStateCache.onDefaultVertexAttributeChange(this);
+}
+
+void Context::vertexAttrib1fv(GLuint index, const GLfloat *values)
+{
+ GLfloat vals[4] = {values[0], 0, 0, 1};
+ mState.setVertexAttribf(index, vals);
+ mStateCache.onDefaultVertexAttributeChange(this);
+}
+
+void Context::vertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
+{
+ GLfloat vals[4] = {x, y, 0, 1};
+ mState.setVertexAttribf(index, vals);
+ mStateCache.onDefaultVertexAttributeChange(this);
+}
+
+void Context::vertexAttrib2fv(GLuint index, const GLfloat *values)
+{
+ GLfloat vals[4] = {values[0], values[1], 0, 1};
+ mState.setVertexAttribf(index, vals);
+ mStateCache.onDefaultVertexAttributeChange(this);
+}
+
+void Context::vertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLfloat vals[4] = {x, y, z, 1};
+ mState.setVertexAttribf(index, vals);
+ mStateCache.onDefaultVertexAttributeChange(this);
+}
+
+void Context::vertexAttrib3fv(GLuint index, const GLfloat *values)
+{
+ GLfloat vals[4] = {values[0], values[1], values[2], 1};
+ mState.setVertexAttribf(index, vals);
+ mStateCache.onDefaultVertexAttributeChange(this);
+}
+
+void Context::vertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GLfloat vals[4] = {x, y, z, w};
+ mState.setVertexAttribf(index, vals);
+ mStateCache.onDefaultVertexAttributeChange(this);
+}
+
+void Context::vertexAttrib4fv(GLuint index, const GLfloat *values)
+{
+ mState.setVertexAttribf(index, values);
+ mStateCache.onDefaultVertexAttributeChange(this);
+}
+
+void Context::vertexAttribPointer(GLuint index,
+ GLint size,
+ VertexAttribType type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *ptr)
+{
+ mState.setVertexAttribPointer(this, index, mState.getTargetBuffer(BufferBinding::Array), size,
+ type, ConvertToBool(normalized), stride, ptr);
+ mStateCache.onVertexArrayStateChange(this);
+}
+
+void Context::vertexAttribFormat(GLuint attribIndex,
+ GLint size,
+ VertexAttribType type,
+ GLboolean normalized,
+ GLuint relativeOffset)
+{
+ mState.setVertexAttribFormat(attribIndex, size, type, ConvertToBool(normalized), false,
+ relativeOffset);
+ mStateCache.onVertexArrayFormatChange(this);
+}
+
+void Context::vertexAttribIFormat(GLuint attribIndex,
+ GLint size,
+ VertexAttribType type,
+ GLuint relativeOffset)
+{
+ mState.setVertexAttribFormat(attribIndex, size, type, false, true, relativeOffset);
+ mStateCache.onVertexArrayFormatChange(this);
+}
+
+void Context::vertexAttribBinding(GLuint attribIndex, GLuint bindingIndex)
+{
+ mState.setVertexAttribBinding(this, attribIndex, bindingIndex);
+ mStateCache.onVertexArrayStateChange(this);
+}
+
+void Context::vertexBindingDivisor(GLuint bindingIndex, GLuint divisor)
+{
+ mState.setVertexBindingDivisor(this, bindingIndex, divisor);
+ mStateCache.onVertexArrayFormatChange(this);
+}
+
+void Context::viewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ mState.setViewportParams(x, y, width, height);
+}
+
+void Context::vertexAttribIPointer(GLuint index,
+ GLint size,
+ VertexAttribType type,
+ GLsizei stride,
+ const void *pointer)
+{
+ mState.setVertexAttribIPointer(this, index, mState.getTargetBuffer(BufferBinding::Array), size,
+ type, stride, pointer);
+ mStateCache.onVertexArrayStateChange(this);
+}
+
+void Context::vertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
+{
+ GLint vals[4] = {x, y, z, w};
+ mState.setVertexAttribi(index, vals);
+ mStateCache.onDefaultVertexAttributeChange(this);
+}
+
+void Context::vertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
+{
+ GLuint vals[4] = {x, y, z, w};
+ mState.setVertexAttribu(index, vals);
+ mStateCache.onDefaultVertexAttributeChange(this);
+}
+
+void Context::vertexAttribI4iv(GLuint index, const GLint *v)
+{
+ mState.setVertexAttribi(index, v);
+ mStateCache.onDefaultVertexAttributeChange(this);
+}
+
+void Context::vertexAttribI4uiv(GLuint index, const GLuint *v)
+{
+ mState.setVertexAttribu(index, v);
+ mStateCache.onDefaultVertexAttributeChange(this);
+}
+
+void Context::getVertexAttribivImpl(GLuint index, GLenum pname, GLint *params) const
+{
+ const VertexAttribCurrentValueData &currentValues =
+ getState().getVertexAttribCurrentValue(index);
+ const VertexArray *vao = getState().getVertexArray();
+ QueryVertexAttribiv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
+ currentValues, pname, params);
+}
+
+void Context::getVertexAttribiv(GLuint index, GLenum pname, GLint *params)
+{
+ return getVertexAttribivImpl(index, pname, params);
+}
+
+void Context::getVertexAttribivRobust(GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ getVertexAttribiv(index, pname, params);
+}
+
+void Context::getVertexAttribfv(GLuint index, GLenum pname, GLfloat *params)
+{
+ const VertexAttribCurrentValueData &currentValues =
+ getState().getVertexAttribCurrentValue(index);
+ const VertexArray *vao = getState().getVertexArray();
+ QueryVertexAttribfv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
+ currentValues, pname, params);
+}
+
+void Context::getVertexAttribfvRobust(GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ getVertexAttribfv(index, pname, params);
+}
+
+void Context::getVertexAttribIiv(GLuint index, GLenum pname, GLint *params)
+{
+ const VertexAttribCurrentValueData &currentValues =
+ getState().getVertexAttribCurrentValue(index);
+ const VertexArray *vao = getState().getVertexArray();
+ QueryVertexAttribIiv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
+ currentValues, pname, params);
+}
+
+void Context::getVertexAttribIivRobust(GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ getVertexAttribIiv(index, pname, params);
+}
+
+void Context::getVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params)
+{
+ const VertexAttribCurrentValueData &currentValues =
+ getState().getVertexAttribCurrentValue(index);
+ const VertexArray *vao = getState().getVertexArray();
+ QueryVertexAttribIuiv(vao->getVertexAttribute(index), vao->getBindingFromAttribIndex(index),
+ currentValues, pname, params);
+}
+
+void Context::getVertexAttribIuivRobust(GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ getVertexAttribIuiv(index, pname, params);
+}
+
+void Context::getVertexAttribPointerv(GLuint index, GLenum pname, void **pointer)
+{
+ const VertexAttribute &attrib = getState().getVertexArray()->getVertexAttribute(index);
+ QueryVertexAttribPointerv(attrib, pname, pointer);
+}
+
+void Context::getVertexAttribPointervRobust(GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **pointer)
+{
+ getVertexAttribPointerv(index, pname, pointer);
+}
+
+void Context::debugMessageControl(GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled)
+{
+ std::vector<GLuint> idVector(ids, ids + count);
+ mState.getDebug().setMessageControl(source, type, severity, std::move(idVector),
+ ConvertToBool(enabled));
+}
+
+void Context::debugMessageInsert(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *buf)
+{
+ std::string msg(buf, (length > 0) ? static_cast<size_t>(length) : strlen(buf));
+ mState.getDebug().insertMessage(source, type, id, severity, std::move(msg), gl::LOG_INFO,
+ angle::EntryPoint::GLDebugMessageInsert);
+}
+
+void Context::debugMessageCallback(GLDEBUGPROCKHR callback, const void *userParam)
+{
+ mState.getDebug().setCallback(callback, userParam);
+}
+
+GLuint Context::getDebugMessageLog(GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog)
+{
+ return static_cast<GLuint>(mState.getDebug().getMessages(count, bufSize, sources, types, ids,
+ severities, lengths, messageLog));
+}
+
+void Context::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar *message)
+{
+ std::string msg(message, (length > 0) ? static_cast<size_t>(length) : strlen(message));
+ ANGLE_CONTEXT_TRY(mImplementation->pushDebugGroup(this, source, id, msg));
+ mState.getDebug().pushGroup(source, id, std::move(msg));
+}
+
+angle::Result Context::handleNoopDrawEvent()
+{
+ return (mImplementation->handleNoopDrawEvent());
+}
+
+void Context::popDebugGroup()
+{
+ mState.getDebug().popGroup();
+ ANGLE_CONTEXT_TRY(mImplementation->popDebugGroup(this));
+}
+
+void Context::primitiveBoundingBox(GLfloat minX,
+ GLfloat minY,
+ GLfloat minZ,
+ GLfloat minW,
+ GLfloat maxX,
+ GLfloat maxY,
+ GLfloat maxZ,
+ GLfloat maxW)
+{
+ mState.mBoundingBoxMinX = minX;
+ mState.mBoundingBoxMinY = minY;
+ mState.mBoundingBoxMinZ = minZ;
+ mState.mBoundingBoxMinW = minW;
+ mState.mBoundingBoxMaxX = maxX;
+ mState.mBoundingBoxMaxY = maxY;
+ mState.mBoundingBoxMaxZ = maxZ;
+ mState.mBoundingBoxMaxW = maxW;
+}
+
+void Context::bufferStorage(BufferBinding target,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags)
+{
+ Buffer *buffer = mState.getTargetBuffer(target);
+ ASSERT(buffer);
+ ANGLE_CONTEXT_TRY(buffer->bufferStorage(this, target, size, data, flags));
+}
+
+void Context::bufferStorageExternal(BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLeglClientBufferEXT clientBuffer,
+ GLbitfield flags)
+{
+ Buffer *buffer = mState.getTargetBuffer(target);
+ ASSERT(buffer);
+
+ ANGLE_CONTEXT_TRY(buffer->bufferStorageExternal(this, target, size, clientBuffer, flags));
+}
+
+void Context::namedBufferStorageExternal(GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLeglClientBufferEXT clientBuffer,
+ GLbitfield flags)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::bufferData(BufferBinding target, GLsizeiptr size, const void *data, BufferUsage usage)
+{
+ Buffer *buffer = mState.getTargetBuffer(target);
+ ASSERT(buffer);
+ ANGLE_CONTEXT_TRY(buffer->bufferData(this, target, data, size, usage));
+}
+
+void Context::bufferSubData(BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data)
+{
+ if (data == nullptr || size == 0)
+ {
+ return;
+ }
+
+ Buffer *buffer = mState.getTargetBuffer(target);
+ ASSERT(buffer);
+ ANGLE_CONTEXT_TRY(buffer->bufferSubData(this, target, data, size, offset));
+}
+
+void Context::attachShader(ShaderProgramID program, ShaderProgramID shader)
+{
+ Program *programObject = mState.mShaderProgramManager->getProgram(program);
+ Shader *shaderObject = mState.mShaderProgramManager->getShader(shader);
+ ASSERT(programObject && shaderObject);
+ programObject->attachShader(shaderObject);
+}
+
+void Context::copyBufferSubData(BufferBinding readTarget,
+ BufferBinding writeTarget,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ // if size is zero, the copy is a successful no-op
+ if (size == 0)
+ {
+ return;
+ }
+
+ // TODO(jmadill): cache these.
+ Buffer *readBuffer = mState.getTargetBuffer(readTarget);
+ Buffer *writeBuffer = mState.getTargetBuffer(writeTarget);
+
+ ANGLE_CONTEXT_TRY(
+ writeBuffer->copyBufferSubData(this, readBuffer, readOffset, writeOffset, size));
+}
+
+void Context::bindAttribLocation(ShaderProgramID program, GLuint index, const GLchar *name)
+{
+ // Ideally we could share the program query with the validation layer if possible.
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->bindAttributeLocation(index, name);
+}
+
+void Context::bindBufferBase(BufferBinding target, GLuint index, BufferID buffer)
+{
+ bindBufferRange(target, index, buffer, 0, 0);
+}
+
+void Context::bindBufferRange(BufferBinding target,
+ GLuint index,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ Buffer *object = mState.mBufferManager->checkBufferAllocation(mImplementation.get(), buffer);
+ ANGLE_CONTEXT_TRY(mState.setIndexedBufferBinding(this, target, index, object, offset, size));
+ if (target == BufferBinding::Uniform)
+ {
+ mUniformBufferObserverBindings[index].bind(object);
+ mStateCache.onUniformBufferStateChange(this);
+ }
+ else if (target == BufferBinding::AtomicCounter)
+ {
+ mAtomicCounterBufferObserverBindings[index].bind(object);
+ mStateCache.onAtomicCounterBufferStateChange(this);
+ }
+ else if (target == BufferBinding::ShaderStorage)
+ {
+ mShaderStorageBufferObserverBindings[index].bind(object);
+ mStateCache.onShaderStorageBufferStateChange(this);
+ }
+ else
+ {
+ mStateCache.onBufferBindingChange(this);
+ }
+}
+
+void Context::bindFramebuffer(GLenum target, FramebufferID framebuffer)
+{
+ if (target == GL_READ_FRAMEBUFFER || target == GL_FRAMEBUFFER)
+ {
+ bindReadFramebuffer(framebuffer);
+ }
+
+ if (target == GL_DRAW_FRAMEBUFFER || target == GL_FRAMEBUFFER)
+ {
+ bindDrawFramebuffer(framebuffer);
+ }
+}
+
+void Context::bindRenderbuffer(GLenum target, RenderbufferID renderbuffer)
+{
+ ASSERT(target == GL_RENDERBUFFER);
+ Renderbuffer *object = mState.mRenderbufferManager->checkRenderbufferAllocation(
+ mImplementation.get(), renderbuffer);
+ mState.setRenderbufferBinding(this, object);
+}
+
+void Context::texStorage2DMultisample(TextureType target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations)
+{
+ Extents size(width, height, 1);
+ Texture *texture = getTextureByType(target);
+ ANGLE_CONTEXT_TRY(texture->setStorageMultisample(this, target, samples, internalformat, size,
+ ConvertToBool(fixedsamplelocations)));
+}
+
+void Context::texStorage3DMultisample(TextureType target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedsamplelocations)
+{
+ Extents size(width, height, depth);
+ Texture *texture = getTextureByType(target);
+ ANGLE_CONTEXT_TRY(texture->setStorageMultisample(this, target, samples, internalformat, size,
+ ConvertToBool(fixedsamplelocations)));
+}
+
+void Context::texImage2DExternal(TextureTarget target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type)
+{
+ Extents size(width, height, 1);
+ Texture *texture = getTextureByTarget(target);
+ ANGLE_CONTEXT_TRY(
+ texture->setImageExternal(this, target, level, internalformat, size, format, type));
+}
+
+void Context::invalidateTexture(TextureType target)
+{
+ mImplementation->invalidateTexture(target);
+ mState.invalidateTextureBindings(target);
+}
+
+void Context::getMultisamplefv(GLenum pname, GLuint index, GLfloat *val)
+{
+ // According to spec 3.1 Table 20.49: Framebuffer Dependent Values,
+ // the sample position should be queried by DRAW_FRAMEBUFFER.
+ ANGLE_CONTEXT_TRY(mState.syncDirtyObject(this, GL_DRAW_FRAMEBUFFER));
+ const Framebuffer *framebuffer = mState.getDrawFramebuffer();
+
+ switch (pname)
+ {
+ case GL_SAMPLE_POSITION:
+ ANGLE_CONTEXT_TRY(framebuffer->getSamplePosition(this, index, val));
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+void Context::getMultisamplefvRobust(GLenum pname,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *val)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::renderbufferStorage(GLenum target,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
+ GLenum convertedInternalFormat = getConvertedRenderbufferFormat(internalformat);
+
+ Renderbuffer *renderbuffer = mState.getCurrentRenderbuffer();
+ ANGLE_CONTEXT_TRY(renderbuffer->setStorage(this, convertedInternalFormat, width, height));
+}
+
+void Context::renderbufferStorageMultisample(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ renderbufferStorageMultisampleImpl(target, samples, internalformat, width, height,
+ MultisamplingMode::Regular);
+}
+
+void Context::renderbufferStorageMultisampleEXT(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ renderbufferStorageMultisampleImpl(target, samples, internalformat, width, height,
+ MultisamplingMode::MultisampledRenderToTexture);
+}
+
+void Context::renderbufferStorageMultisampleImpl(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ MultisamplingMode mode)
+{
+ // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
+ GLenum convertedInternalFormat = getConvertedRenderbufferFormat(internalformat);
+
+ Renderbuffer *renderbuffer = mState.getCurrentRenderbuffer();
+ ANGLE_CONTEXT_TRY(renderbuffer->setStorageMultisample(this, samples, convertedInternalFormat,
+ width, height, mode));
+}
+
+void Context::framebufferTexture2DMultisample(GLenum target,
+ GLenum attachment,
+ TextureTarget textarget,
+ TextureID texture,
+ GLint level,
+ GLsizei samples)
+{
+ Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (texture.value != 0)
+ {
+ Texture *textureObj = getTexture(texture);
+ ImageIndex index = ImageIndex::MakeFromTarget(textarget, level, 1);
+ framebuffer->setAttachmentMultisample(this, GL_TEXTURE, attachment, index, textureObj,
+ samples);
+ }
+ else
+ {
+ framebuffer->resetAttachment(this, attachment);
+ }
+
+ mState.setObjectDirty(target);
+}
+
+void Context::getSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values)
+{
+ const Sync *syncObject = nullptr;
+ if (!isContextLost())
+ {
+ syncObject = getSync(sync);
+ }
+ ANGLE_CONTEXT_TRY(QuerySynciv(this, syncObject, pname, bufSize, length, values));
+}
+
+void Context::getFramebufferParameteriv(GLenum target, GLenum pname, GLint *params)
+{
+ Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ QueryFramebufferParameteriv(framebuffer, pname, params);
+}
+
+void Context::getFramebufferParameterivRobust(GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::framebufferParameteri(GLenum target, GLenum pname, GLint param)
+{
+ Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ SetFramebufferParameteri(this, framebuffer, pname, param);
+}
+
+bool Context::getScratchBuffer(size_t requstedSizeBytes,
+ angle::MemoryBuffer **scratchBufferOut) const
+{
+ if (!mScratchBuffer.valid())
+ {
+ mScratchBuffer = mDisplay->requestScratchBuffer();
+ }
+
+ ASSERT(mScratchBuffer.valid());
+ return mScratchBuffer.value().get(requstedSizeBytes, scratchBufferOut);
+}
+
+angle::ScratchBuffer *Context::getScratchBuffer() const
+{
+ if (!mScratchBuffer.valid())
+ {
+ mScratchBuffer = mDisplay->requestScratchBuffer();
+ }
+
+ ASSERT(mScratchBuffer.valid());
+ return &mScratchBuffer.value();
+}
+
+bool Context::getZeroFilledBuffer(size_t requstedSizeBytes,
+ angle::MemoryBuffer **zeroBufferOut) const
+{
+ if (!mZeroFilledBuffer.valid())
+ {
+ mZeroFilledBuffer = mDisplay->requestZeroFilledBuffer();
+ }
+
+ ASSERT(mZeroFilledBuffer.valid());
+ return mZeroFilledBuffer.value().getInitialized(requstedSizeBytes, zeroBufferOut, 0);
+}
+
+void Context::dispatchCompute(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ)
+{
+ if (numGroupsX == 0u || numGroupsY == 0u || numGroupsZ == 0u)
+ {
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForDispatch());
+
+ angle::Result result =
+ mImplementation->dispatchCompute(this, numGroupsX, numGroupsY, numGroupsZ);
+
+ // This must be called before convertPpoToComputeOrDraw() so it uses the PPO's compute values
+ // before convertPpoToComputeOrDraw() reverts the PPO back to graphics.
+ MarkShaderStorageUsage(this);
+
+ if (ANGLE_UNLIKELY(IsError(result)))
+ {
+ return;
+ }
+}
+
+void Context::dispatchComputeIndirect(GLintptr indirect)
+{
+ ANGLE_CONTEXT_TRY(prepareForDispatch());
+ ANGLE_CONTEXT_TRY(mImplementation->dispatchComputeIndirect(this, indirect));
+
+ MarkShaderStorageUsage(this);
+}
+
+void Context::texStorage2D(TextureType target,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height)
+{
+ Extents size(width, height, 1);
+ Texture *texture = getTextureByType(target);
+ ANGLE_CONTEXT_TRY(texture->setStorage(this, target, levels, internalFormat, size));
+}
+
+void Context::texStorage3D(TextureType target,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ Extents size(width, height, depth);
+ Texture *texture = getTextureByType(target);
+ ANGLE_CONTEXT_TRY(texture->setStorage(this, target, levels, internalFormat, size));
+}
+
+void Context::memoryBarrier(GLbitfield barriers)
+{
+ ANGLE_CONTEXT_TRY(mImplementation->memoryBarrier(this, barriers));
+}
+
+void Context::memoryBarrierByRegion(GLbitfield barriers)
+{
+ ANGLE_CONTEXT_TRY(mImplementation->memoryBarrierByRegion(this, barriers));
+}
+
+void Context::multiDrawArrays(PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ GLsizei drawcount)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(mImplementation->multiDrawArrays(this, mode, firsts, counts, drawcount));
+}
+
+void Context::multiDrawArraysInstanced(PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(mImplementation->multiDrawArraysInstanced(this, mode, firsts, counts,
+ instanceCounts, drawcount));
+}
+
+void Context::multiDrawArraysIndirect(PrimitiveMode mode,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(
+ mImplementation->multiDrawArraysIndirect(this, mode, indirect, drawcount, stride));
+ MarkShaderStorageUsage(this);
+}
+
+void Context::multiDrawElements(PrimitiveMode mode,
+ const GLsizei *counts,
+ DrawElementsType type,
+ const GLvoid *const *indices,
+ GLsizei drawcount)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(
+ mImplementation->multiDrawElements(this, mode, counts, type, indices, drawcount));
+}
+
+void Context::multiDrawElementsInstanced(PrimitiveMode mode,
+ const GLsizei *counts,
+ DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(mImplementation->multiDrawElementsInstanced(this, mode, counts, type, indices,
+ instanceCounts, drawcount));
+}
+
+void Context::multiDrawElementsIndirect(PrimitiveMode mode,
+ DrawElementsType type,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(
+ mImplementation->multiDrawElementsIndirect(this, mode, type, indirect, drawcount, stride));
+ MarkShaderStorageUsage(this);
+}
+
+void Context::drawArraysInstancedBaseInstance(PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount,
+ GLuint baseInstance)
+{
+ if (noopDrawInstanced(mode, count, instanceCount))
+ {
+ ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ Program *programObject = mState.getLinkedProgram(this);
+
+ const bool hasBaseInstance = programObject && programObject->hasBaseInstanceUniform();
+ if (hasBaseInstance)
+ {
+ programObject->setBaseInstanceUniform(baseInstance);
+ }
+
+ rx::ResetBaseVertexBaseInstance resetUniforms(programObject, false, hasBaseInstance);
+
+ // The input gl_InstanceID does not follow the baseinstance. gl_InstanceID always falls on
+ // the half-open range [0, instancecount). No need to set other stuff. Except for Vulkan.
+
+ ANGLE_CONTEXT_TRY(mImplementation->drawArraysInstancedBaseInstance(
+ this, mode, first, count, instanceCount, baseInstance));
+ MarkTransformFeedbackBufferUsage(this, count, 1);
+}
+
+void Context::drawArraysInstancedBaseInstanceANGLE(PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount,
+ GLuint baseInstance)
+{
+ drawArraysInstancedBaseInstance(mode, first, count, instanceCount, baseInstance);
+}
+
+void Context::drawElementsInstancedBaseInstance(PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei instanceCount,
+ GLuint baseInstance)
+{
+ drawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, instanceCount, 0,
+ baseInstance);
+}
+
+void Context::drawElementsInstancedBaseVertexBaseInstance(PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const GLvoid *indices,
+ GLsizei instanceCount,
+ GLint baseVertex,
+ GLuint baseInstance)
+{
+ if (noopDrawInstanced(mode, count, instanceCount))
+ {
+ ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ Program *programObject = mState.getLinkedProgram(this);
+
+ const bool hasBaseVertex = programObject && programObject->hasBaseVertexUniform();
+ if (hasBaseVertex)
+ {
+ programObject->setBaseVertexUniform(baseVertex);
+ }
+
+ const bool hasBaseInstance = programObject && programObject->hasBaseInstanceUniform();
+ if (hasBaseInstance)
+ {
+ programObject->setBaseInstanceUniform(baseInstance);
+ }
+
+ rx::ResetBaseVertexBaseInstance resetUniforms(programObject, hasBaseVertex, hasBaseInstance);
+
+ ANGLE_CONTEXT_TRY(mImplementation->drawElementsInstancedBaseVertexBaseInstance(
+ this, mode, count, type, indices, instanceCount, baseVertex, baseInstance));
+}
+
+void Context::drawElementsInstancedBaseVertexBaseInstanceANGLE(PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const GLvoid *indices,
+ GLsizei instanceCount,
+ GLint baseVertex,
+ GLuint baseInstance)
+{
+ drawElementsInstancedBaseVertexBaseInstance(mode, count, type, indices, instanceCount,
+ baseVertex, baseInstance);
+}
+
+void Context::multiDrawArraysInstancedBaseInstance(PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ const GLuint *baseInstances,
+ GLsizei drawcount)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(mImplementation->multiDrawArraysInstancedBaseInstance(
+ this, mode, firsts, counts, instanceCounts, baseInstances, drawcount));
+}
+
+void Context::multiDrawElementsInstancedBaseVertexBaseInstance(PrimitiveMode mode,
+ const GLsizei *counts,
+ DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount)
+{
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(mImplementation->multiDrawElementsInstancedBaseVertexBaseInstance(
+ this, mode, counts, type, indices, instanceCounts, baseVertices, baseInstances, drawcount));
+}
+
+void Context::provokingVertex(ProvokingVertexConvention provokeMode)
+{
+ mState.setProvokingVertex(provokeMode);
+}
+
+GLenum Context::checkFramebufferStatus(GLenum target)
+{
+ Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+ return framebuffer->checkStatus(this).status;
+}
+
+void Context::compileShader(ShaderProgramID shader)
+{
+ Shader *shaderObject = GetValidShader(this, angle::EntryPoint::GLCompileShader, shader);
+ if (!shaderObject)
+ {
+ return;
+ }
+ shaderObject->compile(this);
+}
+
+void Context::deleteBuffers(GLsizei n, const BufferID *buffers)
+{
+ for (int i = 0; i < n; i++)
+ {
+ deleteBuffer(buffers[i]);
+ }
+}
+
+void Context::deleteFramebuffers(GLsizei n, const FramebufferID *framebuffers)
+{
+ for (int i = 0; i < n; i++)
+ {
+ if (framebuffers[i].value != 0)
+ {
+ deleteFramebuffer(framebuffers[i]);
+ }
+ }
+}
+
+void Context::deleteRenderbuffers(GLsizei n, const RenderbufferID *renderbuffers)
+{
+ for (int i = 0; i < n; i++)
+ {
+ deleteRenderbuffer(renderbuffers[i]);
+ }
+}
+
+void Context::deleteTextures(GLsizei n, const TextureID *textures)
+{
+ for (int i = 0; i < n; i++)
+ {
+ if (textures[i].value != 0)
+ {
+ deleteTexture(textures[i]);
+ }
+ }
+}
+
+void Context::detachShader(ShaderProgramID program, ShaderProgramID shader)
+{
+ Program *programObject = getProgramNoResolveLink(program);
+ ASSERT(programObject);
+
+ Shader *shaderObject = getShader(shader);
+ ASSERT(shaderObject);
+
+ programObject->detachShader(this, shaderObject);
+}
+
+void Context::genBuffers(GLsizei n, BufferID *buffers)
+{
+ for (int i = 0; i < n; i++)
+ {
+ buffers[i] = createBuffer();
+ }
+}
+
+void Context::genFramebuffers(GLsizei n, FramebufferID *framebuffers)
+{
+ for (int i = 0; i < n; i++)
+ {
+ framebuffers[i] = createFramebuffer();
+ }
+}
+
+void Context::genRenderbuffers(GLsizei n, RenderbufferID *renderbuffers)
+{
+ for (int i = 0; i < n; i++)
+ {
+ renderbuffers[i] = createRenderbuffer();
+ }
+}
+
+void Context::genTextures(GLsizei n, TextureID *textures)
+{
+ for (int i = 0; i < n; i++)
+ {
+ textures[i] = createTexture();
+ }
+}
+
+void Context::getActiveAttrib(ShaderProgramID program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->getActiveAttribute(index, bufsize, length, size, type, name);
+}
+
+void Context::getActiveUniform(ShaderProgramID program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->getActiveUniform(index, bufsize, length, size, type, name);
+}
+
+void Context::getAttachedShaders(ShaderProgramID program,
+ GLsizei maxcount,
+ GLsizei *count,
+ ShaderProgramID *shaders)
+{
+ Program *programObject = getProgramNoResolveLink(program);
+ ASSERT(programObject);
+ programObject->getAttachedShaders(maxcount, count, shaders);
+}
+
+GLint Context::getAttribLocation(ShaderProgramID program, const GLchar *name)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ return programObject->getAttributeLocation(name);
+}
+
+void Context::getBooleanv(GLenum pname, GLboolean *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ getQueryParameterInfo(pname, &nativeType, &numParams);
+
+ if (nativeType == GL_BOOL)
+ {
+ getBooleanvImpl(pname, params);
+ }
+ else
+ {
+ CastStateValues(this, nativeType, pname, numParams, params);
+ }
+}
+
+void Context::getBooleanvRobust(GLenum pname, GLsizei bufSize, GLsizei *length, GLboolean *params)
+{
+ getBooleanv(pname, params);
+}
+
+void Context::getFloatv(GLenum pname, GLfloat *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ getQueryParameterInfo(pname, &nativeType, &numParams);
+
+ if (nativeType == GL_FLOAT)
+ {
+ getFloatvImpl(pname, params);
+ }
+ else
+ {
+ CastStateValues(this, nativeType, pname, numParams, params);
+ }
+}
+
+void Context::getFloatvRobust(GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params)
+{
+ getFloatv(pname, params);
+}
+
+void Context::getIntegerv(GLenum pname, GLint *params)
+{
+ GLenum nativeType = GL_NONE;
+ unsigned int numParams = 0;
+ getQueryParameterInfo(pname, &nativeType, &numParams);
+
+ if (nativeType == GL_INT)
+ {
+ getIntegervImpl(pname, params);
+ }
+ else
+ {
+ CastStateValues(this, nativeType, pname, numParams, params);
+ }
+}
+
+void Context::getIntegervRobust(GLenum pname, GLsizei bufSize, GLsizei *length, GLint *data)
+{
+ getIntegerv(pname, data);
+}
+
+void Context::getProgramiv(ShaderProgramID program, GLenum pname, GLint *params)
+{
+ // Don't resolve link if checking the link completion status.
+ Program *programObject = getProgramNoResolveLink(program);
+ if (!isContextLost() && pname != GL_COMPLETION_STATUS_KHR)
+ {
+ programObject = getProgramResolveLink(program);
+ }
+ ASSERT(programObject);
+ QueryProgramiv(this, programObject, pname, params);
+}
+
+void Context::getProgramivRobust(ShaderProgramID program,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ getProgramiv(program, pname, params);
+}
+
+void Context::getProgramPipelineiv(ProgramPipelineID pipeline, GLenum pname, GLint *params)
+{
+ ProgramPipeline *programPipeline = nullptr;
+ if (!mContextLost)
+ {
+ programPipeline = getProgramPipeline(pipeline);
+ }
+ QueryProgramPipelineiv(this, programPipeline, pname, params);
+}
+
+MemoryObject *Context::getMemoryObject(MemoryObjectID handle) const
+{
+ return mState.mMemoryObjectManager->getMemoryObject(handle);
+}
+
+Semaphore *Context::getSemaphore(SemaphoreID handle) const
+{
+ return mState.mSemaphoreManager->getSemaphore(handle);
+}
+
+void Context::getProgramInfoLog(ShaderProgramID program,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *infolog)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->getExecutable().getInfoLog(bufsize, length, infolog);
+}
+
+void Context::getProgramPipelineInfoLog(ProgramPipelineID pipeline,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog)
+{
+ ProgramPipeline *programPipeline = getProgramPipeline(pipeline);
+ if (programPipeline)
+ {
+ programPipeline->getExecutable().getInfoLog(bufSize, length, infoLog);
+ }
+ else
+ {
+ *length = 0;
+ *infoLog = '\0';
+ }
+}
+
+void Context::getShaderiv(ShaderProgramID shader, GLenum pname, GLint *params)
+{
+ Shader *shaderObject = nullptr;
+ if (!isContextLost())
+ {
+ shaderObject = getShader(shader);
+ ASSERT(shaderObject);
+ }
+ QueryShaderiv(this, shaderObject, pname, params);
+}
+
+void Context::getShaderivRobust(ShaderProgramID shader,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ getShaderiv(shader, pname, params);
+}
+
+void Context::getShaderInfoLog(ShaderProgramID shader,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *infolog)
+{
+ Shader *shaderObject = getShader(shader);
+ ASSERT(shaderObject);
+ shaderObject->getInfoLog(this, bufsize, length, infolog);
+}
+
+void Context::getShaderPrecisionFormat(GLenum shadertype,
+ GLenum precisiontype,
+ GLint *range,
+ GLint *precision)
+{
+ // TODO(jmadill): Compute shaders.
+
+ switch (shadertype)
+ {
+ case GL_VERTEX_SHADER:
+ switch (precisiontype)
+ {
+ case GL_LOW_FLOAT:
+ mState.mCaps.vertexLowpFloat.get(range, precision);
+ break;
+ case GL_MEDIUM_FLOAT:
+ mState.mCaps.vertexMediumpFloat.get(range, precision);
+ break;
+ case GL_HIGH_FLOAT:
+ mState.mCaps.vertexHighpFloat.get(range, precision);
+ break;
+
+ case GL_LOW_INT:
+ mState.mCaps.vertexLowpInt.get(range, precision);
+ break;
+ case GL_MEDIUM_INT:
+ mState.mCaps.vertexMediumpInt.get(range, precision);
+ break;
+ case GL_HIGH_INT:
+ mState.mCaps.vertexHighpInt.get(range, precision);
+ break;
+
+ default:
+ UNREACHABLE();
+ return;
+ }
+ break;
+
+ case GL_FRAGMENT_SHADER:
+ switch (precisiontype)
+ {
+ case GL_LOW_FLOAT:
+ mState.mCaps.fragmentLowpFloat.get(range, precision);
+ break;
+ case GL_MEDIUM_FLOAT:
+ mState.mCaps.fragmentMediumpFloat.get(range, precision);
+ break;
+ case GL_HIGH_FLOAT:
+ mState.mCaps.fragmentHighpFloat.get(range, precision);
+ break;
+
+ case GL_LOW_INT:
+ mState.mCaps.fragmentLowpInt.get(range, precision);
+ break;
+ case GL_MEDIUM_INT:
+ mState.mCaps.fragmentMediumpInt.get(range, precision);
+ break;
+ case GL_HIGH_INT:
+ mState.mCaps.fragmentHighpInt.get(range, precision);
+ break;
+
+ default:
+ UNREACHABLE();
+ return;
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ return;
+ }
+}
+
+void Context::getShaderSource(ShaderProgramID shader,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *source)
+{
+ Shader *shaderObject = getShader(shader);
+ ASSERT(shaderObject);
+ shaderObject->getSource(bufsize, length, source);
+}
+
+void Context::getUniformfv(ShaderProgramID program, UniformLocation location, GLfloat *params)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->getUniformfv(this, location, params);
+}
+
+void Context::getUniformfvRobust(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ getUniformfv(program, location, params);
+}
+
+void Context::getUniformiv(ShaderProgramID program, UniformLocation location, GLint *params)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->getUniformiv(this, location, params);
+}
+
+void Context::getUniformivRobust(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ getUniformiv(program, location, params);
+}
+
+GLint Context::getUniformLocation(ShaderProgramID program, const GLchar *name)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ return programObject->getUniformLocation(name).value;
+}
+
+GLboolean Context::isBuffer(BufferID buffer) const
+{
+ if (buffer.value == 0)
+ {
+ return GL_FALSE;
+ }
+
+ return ConvertToGLBoolean(getBuffer(buffer));
+}
+
+GLboolean Context::isEnabled(GLenum cap) const
+{
+ return mState.getEnableFeature(cap);
+}
+
+GLboolean Context::isEnabledi(GLenum target, GLuint index) const
+{
+ return mState.getEnableFeatureIndexed(target, index);
+}
+
+GLboolean Context::isFramebuffer(FramebufferID framebuffer) const
+{
+ if (framebuffer.value == 0)
+ {
+ return GL_FALSE;
+ }
+
+ return ConvertToGLBoolean(getFramebuffer(framebuffer));
+}
+
+GLboolean Context::isProgram(ShaderProgramID program) const
+{
+ if (program.value == 0)
+ {
+ return GL_FALSE;
+ }
+
+ return ConvertToGLBoolean(getProgramNoResolveLink(program));
+}
+
+GLboolean Context::isRenderbuffer(RenderbufferID renderbuffer) const
+{
+ if (renderbuffer.value == 0)
+ {
+ return GL_FALSE;
+ }
+
+ return ConvertToGLBoolean(getRenderbuffer(renderbuffer));
+}
+
+GLboolean Context::isShader(ShaderProgramID shader) const
+{
+ if (shader.value == 0)
+ {
+ return GL_FALSE;
+ }
+
+ return ConvertToGLBoolean(getShader(shader));
+}
+
+GLboolean Context::isTexture(TextureID texture) const
+{
+ if (texture.value == 0)
+ {
+ return GL_FALSE;
+ }
+
+ return ConvertToGLBoolean(getTexture(texture));
+}
+
+void Context::linkProgram(ShaderProgramID program)
+{
+ Program *programObject = getProgramNoResolveLink(program);
+ ASSERT(programObject);
+ ANGLE_CONTEXT_TRY(programObject->link(this));
+ ANGLE_CONTEXT_TRY(onProgramLink(programObject));
+}
+
+void Context::releaseShaderCompiler()
+{
+ mCompiler.set(this, nullptr);
+}
+
+void Context::shaderBinary(GLsizei n,
+ const ShaderProgramID *shaders,
+ GLenum binaryformat,
+ const void *binary,
+ GLsizei length)
+{
+ // No binary shader formats are supported.
+ UNIMPLEMENTED();
+}
+
+void Context::bindFragDataLocationIndexed(ShaderProgramID program,
+ GLuint colorNumber,
+ GLuint index,
+ const char *name)
+{
+ Program *programObject = getProgramNoResolveLink(program);
+ programObject->bindFragmentOutputLocation(colorNumber, name);
+ programObject->bindFragmentOutputIndex(index, name);
+}
+
+void Context::bindFragDataLocation(ShaderProgramID program, GLuint colorNumber, const char *name)
+{
+ bindFragDataLocationIndexed(program, colorNumber, 0u, name);
+}
+
+int Context::getFragDataIndex(ShaderProgramID program, const char *name)
+{
+ Program *programObject = getProgramResolveLink(program);
+ return programObject->getFragDataIndex(name);
+}
+
+int Context::getProgramResourceLocationIndex(ShaderProgramID program,
+ GLenum programInterface,
+ const char *name)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programInterface == GL_PROGRAM_OUTPUT);
+ return programObject->getFragDataIndex(name);
+}
+
+void Context::shaderSource(ShaderProgramID shader,
+ GLsizei count,
+ const GLchar *const *string,
+ const GLint *length)
+{
+ Shader *shaderObject = getShader(shader);
+ ASSERT(shaderObject);
+ shaderObject->setSource(count, string, length);
+}
+
+void Context::stencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+ stencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
+}
+
+void Context::stencilMask(GLuint mask)
+{
+ stencilMaskSeparate(GL_FRONT_AND_BACK, mask);
+}
+
+void Context::stencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+{
+ stencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
+}
+
+void Context::patchParameteri(GLenum pname, GLint value)
+{
+ switch (pname)
+ {
+ case GL_PATCH_VERTICES:
+ mState.setPatchVertices(value);
+ break;
+ default:
+ break;
+ }
+}
+
+Program *Context::getActiveLinkedProgram() const
+{
+ Program *program = mState.getLinkedProgram(this);
+ if (!program)
+ {
+ ProgramPipeline *programPipelineObject = mState.getProgramPipeline();
+ if (programPipelineObject)
+ {
+ program = programPipelineObject->getLinkedActiveShaderProgram(this);
+ }
+ }
+
+ return program;
+}
+
+void Context::uniform1f(UniformLocation location, GLfloat x)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniform1fv(location, 1, &x);
+}
+
+void Context::uniform1fv(UniformLocation location, GLsizei count, const GLfloat *v)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniform1fv(location, count, v);
+}
+
+void Context::setUniform1iImpl(Program *program,
+ UniformLocation location,
+ GLsizei count,
+ const GLint *v)
+{
+ program->setUniform1iv(this, location, count, v);
+}
+
+void Context::onSamplerUniformChange(size_t textureUnitIndex)
+{
+ mState.onActiveTextureChange(this, textureUnitIndex);
+ mStateCache.onActiveTextureChange(this);
+}
+
+void Context::uniform1i(UniformLocation location, GLint x)
+{
+ Program *program = getActiveLinkedProgram();
+ setUniform1iImpl(program, location, 1, &x);
+}
+
+void Context::uniform1iv(UniformLocation location, GLsizei count, const GLint *v)
+{
+ Program *program = getActiveLinkedProgram();
+ setUniform1iImpl(program, location, count, v);
+}
+
+void Context::uniform2f(UniformLocation location, GLfloat x, GLfloat y)
+{
+ GLfloat xy[2] = {x, y};
+ Program *program = getActiveLinkedProgram();
+ program->setUniform2fv(location, 1, xy);
+}
+
+void Context::uniform2fv(UniformLocation location, GLsizei count, const GLfloat *v)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniform2fv(location, count, v);
+}
+
+void Context::uniform2i(UniformLocation location, GLint x, GLint y)
+{
+ GLint xy[2] = {x, y};
+ Program *program = getActiveLinkedProgram();
+ program->setUniform2iv(location, 1, xy);
+}
+
+void Context::uniform2iv(UniformLocation location, GLsizei count, const GLint *v)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniform2iv(location, count, v);
+}
+
+void Context::uniform3f(UniformLocation location, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLfloat xyz[3] = {x, y, z};
+ Program *program = getActiveLinkedProgram();
+ program->setUniform3fv(location, 1, xyz);
+}
+
+void Context::uniform3fv(UniformLocation location, GLsizei count, const GLfloat *v)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniform3fv(location, count, v);
+}
+
+void Context::uniform3i(UniformLocation location, GLint x, GLint y, GLint z)
+{
+ GLint xyz[3] = {x, y, z};
+ Program *program = getActiveLinkedProgram();
+ program->setUniform3iv(location, 1, xyz);
+}
+
+void Context::uniform3iv(UniformLocation location, GLsizei count, const GLint *v)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniform3iv(location, count, v);
+}
+
+void Context::uniform4f(UniformLocation location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GLfloat xyzw[4] = {x, y, z, w};
+ Program *program = getActiveLinkedProgram();
+ program->setUniform4fv(location, 1, xyzw);
+}
+
+void Context::uniform4fv(UniformLocation location, GLsizei count, const GLfloat *v)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniform4fv(location, count, v);
+}
+
+void Context::uniform4i(UniformLocation location, GLint x, GLint y, GLint z, GLint w)
+{
+ GLint xyzw[4] = {x, y, z, w};
+ Program *program = getActiveLinkedProgram();
+ program->setUniform4iv(location, 1, xyzw);
+}
+
+void Context::uniform4iv(UniformLocation location, GLsizei count, const GLint *v)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniform4iv(location, count, v);
+}
+
+void Context::uniformMatrix2fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniformMatrix2fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix3fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniformMatrix3fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix4fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniformMatrix4fv(location, count, transpose, value);
+}
+
+void Context::validateProgram(ShaderProgramID program)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->validate(mState.mCaps);
+}
+
+void Context::validateProgramPipeline(ProgramPipelineID pipeline)
+{
+ // GLES spec 3.2, Section 7.4 "Program Pipeline Objects"
+ // If pipeline is a name that has been generated (without subsequent deletion) by
+ // GenProgramPipelines, but refers to a program pipeline object that has not been
+ // previously bound, the GL first creates a new state vector in the same manner as
+ // when BindProgramPipeline creates a new program pipeline object.
+ //
+ // void BindProgramPipeline( uint pipeline );
+ // pipeline is the program pipeline object name. The resulting program pipeline
+ // object is a new state vector, comprising all the state and with the same initial values
+ // listed in table 21.20.
+ //
+ // If we do not have a pipeline object that's been created with glBindProgramPipeline, we leave
+ // VALIDATE_STATUS at it's default false value without generating a pipeline object.
+ if (!getProgramPipeline(pipeline))
+ {
+ return;
+ }
+
+ ProgramPipeline *programPipeline =
+ mState.mProgramPipelineManager->checkProgramPipelineAllocation(mImplementation.get(),
+ pipeline);
+ ASSERT(programPipeline);
+
+ programPipeline->validate(this);
+}
+
+void Context::getProgramBinary(ShaderProgramID program,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject != nullptr);
+
+ ANGLE_CONTEXT_TRY(programObject->saveBinary(this, binaryFormat, binary, bufSize, length));
+}
+
+void Context::programBinary(ShaderProgramID program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject != nullptr);
+
+ ANGLE_CONTEXT_TRY(programObject->loadBinary(this, binaryFormat, binary, length));
+ ANGLE_CONTEXT_TRY(onProgramLink(programObject));
+}
+
+void Context::uniform1ui(UniformLocation location, GLuint v0)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniform1uiv(location, 1, &v0);
+}
+
+void Context::uniform2ui(UniformLocation location, GLuint v0, GLuint v1)
+{
+ Program *program = getActiveLinkedProgram();
+ const GLuint xy[] = {v0, v1};
+ program->setUniform2uiv(location, 1, xy);
+}
+
+void Context::uniform3ui(UniformLocation location, GLuint v0, GLuint v1, GLuint v2)
+{
+ Program *program = getActiveLinkedProgram();
+ const GLuint xyz[] = {v0, v1, v2};
+ program->setUniform3uiv(location, 1, xyz);
+}
+
+void Context::uniform4ui(UniformLocation location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ Program *program = getActiveLinkedProgram();
+ const GLuint xyzw[] = {v0, v1, v2, v3};
+ program->setUniform4uiv(location, 1, xyzw);
+}
+
+void Context::uniform1uiv(UniformLocation location, GLsizei count, const GLuint *value)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniform1uiv(location, count, value);
+}
+void Context::uniform2uiv(UniformLocation location, GLsizei count, const GLuint *value)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniform2uiv(location, count, value);
+}
+
+void Context::uniform3uiv(UniformLocation location, GLsizei count, const GLuint *value)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniform3uiv(location, count, value);
+}
+
+void Context::uniform4uiv(UniformLocation location, GLsizei count, const GLuint *value)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniform4uiv(location, count, value);
+}
+
+void Context::genQueries(GLsizei n, QueryID *ids)
+{
+ for (GLsizei i = 0; i < n; i++)
+ {
+ QueryID handle = QueryID{mQueryHandleAllocator.allocate()};
+ mQueryMap.assign(handle, nullptr);
+ ids[i] = handle;
+ }
+}
+
+void Context::deleteQueries(GLsizei n, const QueryID *ids)
+{
+ for (int i = 0; i < n; i++)
+ {
+ QueryID query = ids[i];
+
+ Query *queryObject = nullptr;
+ if (mQueryMap.erase(query, &queryObject))
+ {
+ mQueryHandleAllocator.release(query.value);
+ if (queryObject)
+ {
+ queryObject->release(this);
+ }
+ }
+ }
+}
+
+bool Context::isQueryGenerated(QueryID query) const
+{
+ return mQueryMap.contains(query);
+}
+
+GLboolean Context::isQuery(QueryID id) const
+{
+ return ConvertToGLBoolean(getQuery(id) != nullptr);
+}
+
+void Context::uniformMatrix2x3fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniformMatrix2x3fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix3x2fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniformMatrix3x2fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix2x4fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniformMatrix2x4fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix4x2fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniformMatrix4x2fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix3x4fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniformMatrix3x4fv(location, count, transpose, value);
+}
+
+void Context::uniformMatrix4x3fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *program = getActiveLinkedProgram();
+ program->setUniformMatrix4x3fv(location, count, transpose, value);
+}
+
+void Context::deleteVertexArrays(GLsizei n, const VertexArrayID *arrays)
+{
+ for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
+ {
+ VertexArrayID vertexArray = arrays[arrayIndex];
+
+ if (arrays[arrayIndex].value != 0)
+ {
+ VertexArray *vertexArrayObject = nullptr;
+ if (mVertexArrayMap.erase(vertexArray, &vertexArrayObject))
+ {
+ if (vertexArrayObject != nullptr)
+ {
+ detachVertexArray(vertexArray);
+ vertexArrayObject->onDestroy(this);
+ }
+
+ mVertexArrayHandleAllocator.release(vertexArray.value);
+ }
+ }
+ }
+}
+
+void Context::genVertexArrays(GLsizei n, VertexArrayID *arrays)
+{
+ for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
+ {
+ VertexArrayID vertexArray = {mVertexArrayHandleAllocator.allocate()};
+ mVertexArrayMap.assign(vertexArray, nullptr);
+ arrays[arrayIndex] = vertexArray;
+ }
+}
+
+GLboolean Context::isVertexArray(VertexArrayID array) const
+{
+ if (array.value == 0)
+ {
+ return GL_FALSE;
+ }
+
+ VertexArray *vao = getVertexArray(array);
+ return ConvertToGLBoolean(vao != nullptr);
+}
+
+void Context::endTransformFeedback()
+{
+ TransformFeedback *transformFeedback = mState.getCurrentTransformFeedback();
+ ANGLE_CONTEXT_TRY(transformFeedback->end(this));
+ mStateCache.onActiveTransformFeedbackChange(this);
+}
+
+void Context::transformFeedbackVaryings(ShaderProgramID program,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
+}
+
+void Context::getTransformFeedbackVarying(ShaderProgramID program,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
+}
+
+void Context::deleteTransformFeedbacks(GLsizei n, const TransformFeedbackID *ids)
+{
+ for (int i = 0; i < n; i++)
+ {
+ TransformFeedbackID transformFeedback = ids[i];
+ if (transformFeedback.value == 0)
+ {
+ continue;
+ }
+
+ TransformFeedback *transformFeedbackObject = nullptr;
+ if (mTransformFeedbackMap.erase(transformFeedback, &transformFeedbackObject))
+ {
+ if (transformFeedbackObject != nullptr)
+ {
+ detachTransformFeedback(transformFeedback);
+ transformFeedbackObject->release(this);
+ }
+
+ mTransformFeedbackHandleAllocator.release(transformFeedback.value);
+ }
+ }
+}
+
+void Context::genTransformFeedbacks(GLsizei n, TransformFeedbackID *ids)
+{
+ for (int i = 0; i < n; i++)
+ {
+ TransformFeedbackID transformFeedback = {mTransformFeedbackHandleAllocator.allocate()};
+ mTransformFeedbackMap.assign(transformFeedback, nullptr);
+ ids[i] = transformFeedback;
+ }
+}
+
+GLboolean Context::isTransformFeedback(TransformFeedbackID id) const
+{
+ if (id.value == 0)
+ {
+ // The 3.0.4 spec [section 6.1.11] states that if ID is zero, IsTransformFeedback
+ // returns FALSE
+ return GL_FALSE;
+ }
+
+ const TransformFeedback *transformFeedback = getTransformFeedback(id);
+ return ConvertToGLBoolean(transformFeedback != nullptr);
+}
+
+void Context::pauseTransformFeedback()
+{
+ TransformFeedback *transformFeedback = mState.getCurrentTransformFeedback();
+ ANGLE_CONTEXT_TRY(transformFeedback->pause(this));
+ mStateCache.onActiveTransformFeedbackChange(this);
+}
+
+void Context::resumeTransformFeedback()
+{
+ TransformFeedback *transformFeedback = mState.getCurrentTransformFeedback();
+ ANGLE_CONTEXT_TRY(transformFeedback->resume(this));
+ mStateCache.onActiveTransformFeedbackChange(this);
+}
+
+void Context::getUniformuiv(ShaderProgramID program, UniformLocation location, GLuint *params)
+{
+ const Program *programObject = getProgramResolveLink(program);
+ programObject->getUniformuiv(this, location, params);
+}
+
+void Context::getUniformuivRobust(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ getUniformuiv(program, location, params);
+}
+
+GLint Context::getFragDataLocation(ShaderProgramID program, const GLchar *name)
+{
+ const Program *programObject = getProgramResolveLink(program);
+ return programObject->getFragDataLocation(name);
+}
+
+void Context::getUniformIndices(ShaderProgramID program,
+ GLsizei uniformCount,
+ const GLchar *const *uniformNames,
+ GLuint *uniformIndices)
+{
+ const Program *programObject = getProgramResolveLink(program);
+ if (!programObject->isLinked())
+ {
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+ {
+ uniformIndices[uniformId] = GL_INVALID_INDEX;
+ }
+ }
+ else
+ {
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+ {
+ uniformIndices[uniformId] = programObject->getUniformIndex(uniformNames[uniformId]);
+ }
+ }
+}
+
+void Context::getActiveUniformsiv(ShaderProgramID program,
+ GLsizei uniformCount,
+ const GLuint *uniformIndices,
+ GLenum pname,
+ GLint *params)
+{
+ const Program *programObject = getProgramResolveLink(program);
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+ {
+ const GLuint index = uniformIndices[uniformId];
+ params[uniformId] = GetUniformResourceProperty(programObject, index, pname);
+ }
+}
+
+GLuint Context::getUniformBlockIndex(ShaderProgramID program, const GLchar *uniformBlockName)
+{
+ const Program *programObject = getProgramResolveLink(program);
+ return programObject->getUniformBlockIndex(uniformBlockName);
+}
+
+void Context::getActiveUniformBlockiv(ShaderProgramID program,
+ UniformBlockIndex uniformBlockIndex,
+ GLenum pname,
+ GLint *params)
+{
+ const Program *programObject = getProgramResolveLink(program);
+ QueryActiveUniformBlockiv(programObject, uniformBlockIndex, pname, params);
+}
+
+void Context::getActiveUniformBlockivRobust(ShaderProgramID program,
+ UniformBlockIndex uniformBlockIndex,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ getActiveUniformBlockiv(program, uniformBlockIndex, pname, params);
+}
+
+void Context::getActiveUniformBlockName(ShaderProgramID program,
+ UniformBlockIndex uniformBlockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformBlockName)
+{
+ const Program *programObject = getProgramResolveLink(program);
+ programObject->getActiveUniformBlockName(this, uniformBlockIndex, bufSize, length,
+ uniformBlockName);
+}
+
+void Context::uniformBlockBinding(ShaderProgramID program,
+ UniformBlockIndex uniformBlockIndex,
+ GLuint uniformBlockBinding)
+{
+ Program *programObject = getProgramResolveLink(program);
+ programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
+
+ // Note: If the Program is shared between Contexts we would be better using Observer/Subject.
+ if (programObject->isInUse())
+ {
+ mState.setObjectDirty(GL_PROGRAM);
+ mStateCache.onUniformBufferStateChange(this);
+ }
+}
+
+GLsync Context::fenceSync(GLenum condition, GLbitfield flags)
+{
+ GLuint handle = mState.mSyncManager->createSync(mImplementation.get());
+ GLsync syncHandle = reinterpret_cast<GLsync>(static_cast<uintptr_t>(handle));
+
+ Sync *syncObject = getSync(syncHandle);
+ if (syncObject->set(this, condition, flags) == angle::Result::Stop)
+ {
+ deleteSync(syncHandle);
+ return nullptr;
+ }
+
+ return syncHandle;
+}
+
+GLboolean Context::isSync(GLsync sync) const
+{
+ return (getSync(sync) != nullptr);
+}
+
+GLenum Context::clientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ Sync *syncObject = getSync(sync);
+
+ GLenum result = GL_WAIT_FAILED;
+ if (syncObject->clientWait(this, flags, timeout, &result) == angle::Result::Stop)
+ {
+ return GL_WAIT_FAILED;
+ }
+ return result;
+}
+
+void Context::waitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ Sync *syncObject = getSync(sync);
+ ANGLE_CONTEXT_TRY(syncObject->serverWait(this, flags, timeout));
+}
+
+void Context::getInteger64v(GLenum pname, GLint64 *params)
+{
+ GLenum nativeType = GL_NONE;
+ unsigned int numParams = 0;
+ getQueryParameterInfo(pname, &nativeType, &numParams);
+
+ if (nativeType == GL_INT_64_ANGLEX)
+ {
+ getInteger64vImpl(pname, params);
+ }
+ else
+ {
+ CastStateValues(this, nativeType, pname, numParams, params);
+ }
+}
+
+void Context::getInteger64vRobust(GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *data)
+{
+ getInteger64v(pname, data);
+}
+
+void Context::getBufferParameteri64v(BufferBinding target, GLenum pname, GLint64 *params)
+{
+ Buffer *buffer = mState.getTargetBuffer(target);
+ QueryBufferParameteri64v(buffer, pname, params);
+}
+
+void Context::getBufferParameteri64vRobust(BufferBinding target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params)
+{
+ getBufferParameteri64v(target, pname, params);
+}
+
+void Context::genSamplers(GLsizei count, SamplerID *samplers)
+{
+ for (int i = 0; i < count; i++)
+ {
+ samplers[i] = mState.mSamplerManager->createSampler();
+ }
+}
+
+void Context::deleteSamplers(GLsizei count, const SamplerID *samplers)
+{
+ for (int i = 0; i < count; i++)
+ {
+ SamplerID sampler = samplers[i];
+
+ if (mState.mSamplerManager->getSampler(sampler))
+ {
+ detachSampler(sampler);
+ }
+
+ mState.mSamplerManager->deleteObject(this, sampler);
+ }
+}
+
+void Context::minSampleShading(GLfloat value)
+{
+ mState.setMinSampleShading(value);
+}
+
+void Context::getInternalformativ(GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLint *params)
+{
+ const TextureCaps &formatCaps = mState.mTextureCaps.get(internalformat);
+ QueryInternalFormativ(formatCaps, pname, bufSize, params);
+}
+
+void Context::getInternalformativRobust(GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ getInternalformativ(target, internalformat, pname, bufSize, params);
+}
+
+void Context::programUniform1i(ShaderProgramID program, UniformLocation location, GLint v0)
+{
+ programUniform1iv(program, location, 1, &v0);
+}
+
+void Context::programUniform2i(ShaderProgramID program,
+ UniformLocation location,
+ GLint v0,
+ GLint v1)
+{
+ GLint xy[2] = {v0, v1};
+ programUniform2iv(program, location, 1, xy);
+}
+
+void Context::programUniform3i(ShaderProgramID program,
+ UniformLocation location,
+ GLint v0,
+ GLint v1,
+ GLint v2)
+{
+ GLint xyz[3] = {v0, v1, v2};
+ programUniform3iv(program, location, 1, xyz);
+}
+
+void Context::programUniform4i(ShaderProgramID program,
+ UniformLocation location,
+ GLint v0,
+ GLint v1,
+ GLint v2,
+ GLint v3)
+{
+ GLint xyzw[4] = {v0, v1, v2, v3};
+ programUniform4iv(program, location, 1, xyzw);
+}
+
+void Context::programUniform1ui(ShaderProgramID program, UniformLocation location, GLuint v0)
+{
+ programUniform1uiv(program, location, 1, &v0);
+}
+
+void Context::programUniform2ui(ShaderProgramID program,
+ UniformLocation location,
+ GLuint v0,
+ GLuint v1)
+{
+ GLuint xy[2] = {v0, v1};
+ programUniform2uiv(program, location, 1, xy);
+}
+
+void Context::programUniform3ui(ShaderProgramID program,
+ UniformLocation location,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLuint xyz[3] = {v0, v1, v2};
+ programUniform3uiv(program, location, 1, xyz);
+}
+
+void Context::programUniform4ui(ShaderProgramID program,
+ UniformLocation location,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLuint xyzw[4] = {v0, v1, v2, v3};
+ programUniform4uiv(program, location, 1, xyzw);
+}
+
+void Context::programUniform1f(ShaderProgramID program, UniformLocation location, GLfloat v0)
+{
+ programUniform1fv(program, location, 1, &v0);
+}
+
+void Context::programUniform2f(ShaderProgramID program,
+ UniformLocation location,
+ GLfloat v0,
+ GLfloat v1)
+{
+ GLfloat xy[2] = {v0, v1};
+ programUniform2fv(program, location, 1, xy);
+}
+
+void Context::programUniform3f(ShaderProgramID program,
+ UniformLocation location,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2)
+{
+ GLfloat xyz[3] = {v0, v1, v2};
+ programUniform3fv(program, location, 1, xyz);
+}
+
+void Context::programUniform4f(ShaderProgramID program,
+ UniformLocation location,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2,
+ GLfloat v3)
+{
+ GLfloat xyzw[4] = {v0, v1, v2, v3};
+ programUniform4fv(program, location, 1, xyzw);
+}
+
+void Context::programUniform1iv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLint *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ setUniform1iImpl(programObject, location, count, value);
+}
+
+void Context::programUniform2iv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLint *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniform2iv(location, count, value);
+}
+
+void Context::programUniform3iv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLint *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniform3iv(location, count, value);
+}
+
+void Context::programUniform4iv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLint *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniform4iv(location, count, value);
+}
+
+void Context::programUniform1uiv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLuint *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniform1uiv(location, count, value);
+}
+
+void Context::programUniform2uiv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLuint *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniform2uiv(location, count, value);
+}
+
+void Context::programUniform3uiv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLuint *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniform3uiv(location, count, value);
+}
+
+void Context::programUniform4uiv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLuint *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniform4uiv(location, count, value);
+}
+
+void Context::programUniform1fv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniform1fv(location, count, value);
+}
+
+void Context::programUniform2fv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniform2fv(location, count, value);
+}
+
+void Context::programUniform3fv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniform3fv(location, count, value);
+}
+
+void Context::programUniform4fv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniform4fv(location, count, value);
+}
+
+void Context::programUniformMatrix2fv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix2fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix3fv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix3fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix4fv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix4fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix2x3fv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix2x3fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix3x2fv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix3x2fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix2x4fv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix2x4fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix4x2fv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix4x2fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix3x4fv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix3x4fv(location, count, transpose, value);
+}
+
+void Context::programUniformMatrix4x3fv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+ programObject->setUniformMatrix4x3fv(location, count, transpose, value);
+}
+
+bool Context::isCurrentTransformFeedback(const TransformFeedback *tf) const
+{
+ return mState.isCurrentTransformFeedback(tf);
+}
+
+void Context::genProgramPipelines(GLsizei count, ProgramPipelineID *pipelines)
+{
+ for (int i = 0; i < count; i++)
+ {
+ pipelines[i] = createProgramPipeline();
+ }
+}
+
+void Context::deleteProgramPipelines(GLsizei count, const ProgramPipelineID *pipelines)
+{
+ for (int i = 0; i < count; i++)
+ {
+ if (pipelines[i].value != 0)
+ {
+ deleteProgramPipeline(pipelines[i]);
+ }
+ }
+}
+
+GLboolean Context::isProgramPipeline(ProgramPipelineID pipeline) const
+{
+ if (pipeline.value == 0)
+ {
+ return GL_FALSE;
+ }
+
+ if (getProgramPipeline(pipeline))
+ {
+ return GL_TRUE;
+ }
+
+ return GL_FALSE;
+}
+
+void Context::finishFenceNV(FenceNVID fence)
+{
+ FenceNV *fenceObject = getFenceNV(fence);
+
+ ASSERT(fenceObject && fenceObject->isSet());
+ ANGLE_CONTEXT_TRY(fenceObject->finish(this));
+}
+
+void Context::getFenceivNV(FenceNVID fence, GLenum pname, GLint *params)
+{
+ FenceNV *fenceObject = getFenceNV(fence);
+
+ ASSERT(fenceObject && fenceObject->isSet());
+
+ switch (pname)
+ {
+ case GL_FENCE_STATUS_NV:
+ {
+ // GL_NV_fence spec:
+ // Once the status of a fence has been finished (via FinishFenceNV) or tested and
+ // the returned status is TRUE (via either TestFenceNV or GetFenceivNV querying the
+ // FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
+ GLboolean status = GL_TRUE;
+ if (fenceObject->getStatus() != GL_TRUE)
+ {
+ ANGLE_CONTEXT_TRY(fenceObject->test(this, &status));
+ }
+ *params = status;
+ break;
+ }
+
+ case GL_FENCE_CONDITION_NV:
+ {
+ *params = static_cast<GLint>(fenceObject->getCondition());
+ break;
+ }
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+void Context::getTranslatedShaderSource(ShaderProgramID shader,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *source)
+{
+ Shader *shaderObject = getShader(shader);
+ ASSERT(shaderObject);
+ shaderObject->getTranslatedSourceWithDebugInfo(this, bufsize, length, source);
+}
+
+void Context::getnUniformfv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ GLfloat *params)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+
+ programObject->getUniformfv(this, location, params);
+}
+
+void Context::getnUniformfvRobust(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnUniformiv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ GLint *params)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+
+ programObject->getUniformiv(this, location, params);
+}
+
+void Context::getnUniformuiv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ GLuint *params)
+{
+ Program *programObject = getProgramResolveLink(program);
+ ASSERT(programObject);
+
+ programObject->getUniformuiv(this, location, params);
+}
+
+void Context::getnUniformivRobust(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnUniformuivRobust(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params)
+{
+ UNIMPLEMENTED();
+}
+
+GLboolean Context::isFenceNV(FenceNVID fence) const
+{
+ FenceNV *fenceObject = getFenceNV(fence);
+
+ if (fenceObject == nullptr)
+ {
+ return GL_FALSE;
+ }
+
+ // GL_NV_fence spec:
+ // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an
+ // existing fence.
+ return fenceObject->isSet();
+}
+
+void Context::readnPixels(GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *data)
+{
+ return readPixels(x, y, width, height, format, type, data);
+}
+
+void Context::setFenceNV(FenceNVID fence, GLenum condition)
+{
+ ASSERT(condition == GL_ALL_COMPLETED_NV);
+
+ FenceNV *fenceObject = getFenceNV(fence);
+ ASSERT(fenceObject != nullptr);
+ ANGLE_CONTEXT_TRY(fenceObject->set(this, condition));
+}
+
+GLboolean Context::testFenceNV(FenceNVID fence)
+{
+ FenceNV *fenceObject = getFenceNV(fence);
+
+ ASSERT(fenceObject != nullptr);
+ ASSERT(fenceObject->isSet() == GL_TRUE);
+
+ GLboolean result = GL_TRUE;
+ if (fenceObject->test(this, &result) == angle::Result::Stop)
+ {
+ return GL_TRUE;
+ }
+
+ return result;
+}
+
+void Context::deleteMemoryObjects(GLsizei n, const MemoryObjectID *memoryObjects)
+{
+ for (int i = 0; i < n; i++)
+ {
+ deleteMemoryObject(memoryObjects[i]);
+ }
+}
+
+GLboolean Context::isMemoryObject(MemoryObjectID memoryObject) const
+{
+ if (memoryObject.value == 0)
+ {
+ return GL_FALSE;
+ }
+
+ return ConvertToGLBoolean(getMemoryObject(memoryObject));
+}
+
+void Context::createMemoryObjects(GLsizei n, MemoryObjectID *memoryObjects)
+{
+ for (int i = 0; i < n; i++)
+ {
+ memoryObjects[i] = createMemoryObject();
+ }
+}
+
+void Context::memoryObjectParameteriv(MemoryObjectID memory, GLenum pname, const GLint *params)
+{
+ MemoryObject *memoryObject = getMemoryObject(memory);
+ ASSERT(memoryObject);
+ ANGLE_CONTEXT_TRY(SetMemoryObjectParameteriv(this, memoryObject, pname, params));
+}
+
+void Context::getMemoryObjectParameteriv(MemoryObjectID memory, GLenum pname, GLint *params)
+{
+ const MemoryObject *memoryObject = getMemoryObject(memory);
+ ASSERT(memoryObject);
+ QueryMemoryObjectParameteriv(memoryObject, pname, params);
+}
+
+void Context::texStorageMem2D(TextureType target,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ MemoryObjectID memory,
+ GLuint64 offset)
+{
+ texStorageMemFlags2D(target, levels, internalFormat, width, height, memory, offset, 0,
+ std::numeric_limits<uint32_t>::max(), nullptr);
+}
+
+void Context::texStorageMem2DMultisample(TextureType target,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memory,
+ GLuint64 offset)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texStorageMem3D(TextureType target,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ MemoryObjectID memory,
+ GLuint64 offset)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texStorageMem3DMultisample(TextureType target,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memory,
+ GLuint64 offset)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::bufferStorageMem(TextureType target,
+ GLsizeiptr size,
+ MemoryObjectID memory,
+ GLuint64 offset)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::importMemoryFd(MemoryObjectID memory, GLuint64 size, HandleType handleType, GLint fd)
+{
+ MemoryObject *memoryObject = getMemoryObject(memory);
+ ASSERT(memoryObject != nullptr);
+ ANGLE_CONTEXT_TRY(memoryObject->importFd(this, size, handleType, fd));
+}
+
+void Context::texStorageMemFlags2D(TextureType target,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ MemoryObjectID memory,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext)
+{
+ MemoryObject *memoryObject = getMemoryObject(memory);
+ ASSERT(memoryObject);
+ Extents size(width, height, 1);
+ Texture *texture = getTextureByType(target);
+ ANGLE_CONTEXT_TRY(texture->setStorageExternalMemory(this, target, levels, internalFormat, size,
+ memoryObject, offset, createFlags,
+ usageFlags, imageCreateInfoPNext));
+}
+
+void Context::texStorageMemFlags2DMultisample(TextureType target,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memory,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texStorageMemFlags3D(TextureType target,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ MemoryObjectID memory,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texStorageMemFlags3DMultisample(TextureType target,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memory,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::importMemoryZirconHandle(MemoryObjectID memory,
+ GLuint64 size,
+ HandleType handleType,
+ GLuint handle)
+{
+ MemoryObject *memoryObject = getMemoryObject(memory);
+ ASSERT(memoryObject != nullptr);
+ ANGLE_CONTEXT_TRY(memoryObject->importZirconHandle(this, size, handleType, handle));
+}
+
+void Context::genSemaphores(GLsizei n, SemaphoreID *semaphores)
+{
+ for (int i = 0; i < n; i++)
+ {
+ semaphores[i] = createSemaphore();
+ }
+}
+
+void Context::deleteSemaphores(GLsizei n, const SemaphoreID *semaphores)
+{
+ for (int i = 0; i < n; i++)
+ {
+ deleteSemaphore(semaphores[i]);
+ }
+}
+
+GLboolean Context::isSemaphore(SemaphoreID semaphore) const
+{
+ if (semaphore.value == 0)
+ {
+ return GL_FALSE;
+ }
+
+ return ConvertToGLBoolean(getSemaphore(semaphore));
+}
+
+void Context::semaphoreParameterui64v(SemaphoreID semaphore, GLenum pname, const GLuint64 *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getSemaphoreParameterui64v(SemaphoreID semaphore, GLenum pname, GLuint64 *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::acquireTextures(GLuint numTextures,
+ const TextureID *textureIds,
+ const GLenum *layouts)
+{
+ TextureBarrierVector textureBarriers(numTextures);
+ for (size_t i = 0; i < numTextures; i++)
+ {
+ textureBarriers[i].texture = getTexture(textureIds[i]);
+ textureBarriers[i].layout = layouts[i];
+ }
+ ANGLE_CONTEXT_TRY(mImplementation->acquireTextures(this, textureBarriers));
+}
+
+void Context::releaseTextures(GLuint numTextures, const TextureID *textureIds, GLenum *layouts)
+{
+ TextureBarrierVector textureBarriers(numTextures);
+ for (size_t i = 0; i < numTextures; i++)
+ {
+ textureBarriers[i].texture = getTexture(textureIds[i]);
+ }
+ ANGLE_CONTEXT_TRY(mImplementation->releaseTextures(this, &textureBarriers));
+ for (size_t i = 0; i < numTextures; i++)
+ {
+ layouts[i] = textureBarriers[i].layout;
+ }
+}
+
+void Context::waitSemaphore(SemaphoreID semaphoreHandle,
+ GLuint numBufferBarriers,
+ const BufferID *buffers,
+ GLuint numTextureBarriers,
+ const TextureID *textures,
+ const GLenum *srcLayouts)
+{
+ Semaphore *semaphore = getSemaphore(semaphoreHandle);
+ ASSERT(semaphore);
+
+ BufferBarrierVector bufferBarriers(numBufferBarriers);
+ for (GLuint bufferBarrierIdx = 0; bufferBarrierIdx < numBufferBarriers; bufferBarrierIdx++)
+ {
+ bufferBarriers[bufferBarrierIdx] = getBuffer(buffers[bufferBarrierIdx]);
+ }
+
+ TextureBarrierVector textureBarriers(numTextureBarriers);
+ for (GLuint textureBarrierIdx = 0; textureBarrierIdx < numTextureBarriers; textureBarrierIdx++)
+ {
+ textureBarriers[textureBarrierIdx].texture = getTexture(textures[textureBarrierIdx]);
+ textureBarriers[textureBarrierIdx].layout = srcLayouts[textureBarrierIdx];
+ }
+
+ ANGLE_CONTEXT_TRY(semaphore->wait(this, bufferBarriers, textureBarriers));
+}
+
+void Context::signalSemaphore(SemaphoreID semaphoreHandle,
+ GLuint numBufferBarriers,
+ const BufferID *buffers,
+ GLuint numTextureBarriers,
+ const TextureID *textures,
+ const GLenum *dstLayouts)
+{
+ Semaphore *semaphore = getSemaphore(semaphoreHandle);
+ ASSERT(semaphore);
+
+ BufferBarrierVector bufferBarriers(numBufferBarriers);
+ for (GLuint bufferBarrierIdx = 0; bufferBarrierIdx < numBufferBarriers; bufferBarrierIdx++)
+ {
+ bufferBarriers[bufferBarrierIdx] = getBuffer(buffers[bufferBarrierIdx]);
+ }
+
+ TextureBarrierVector textureBarriers(numTextureBarriers);
+ for (GLuint textureBarrierIdx = 0; textureBarrierIdx < numTextureBarriers; textureBarrierIdx++)
+ {
+ textureBarriers[textureBarrierIdx].texture = getTexture(textures[textureBarrierIdx]);
+ textureBarriers[textureBarrierIdx].layout = dstLayouts[textureBarrierIdx];
+ }
+
+ ANGLE_CONTEXT_TRY(semaphore->signal(this, bufferBarriers, textureBarriers));
+}
+
+void Context::importSemaphoreFd(SemaphoreID semaphore, HandleType handleType, GLint fd)
+{
+ Semaphore *semaphoreObject = getSemaphore(semaphore);
+ ASSERT(semaphoreObject != nullptr);
+ ANGLE_CONTEXT_TRY(semaphoreObject->importFd(this, handleType, fd));
+}
+
+void Context::importSemaphoreZirconHandle(SemaphoreID semaphore,
+ HandleType handleType,
+ GLuint handle)
+{
+ Semaphore *semaphoreObject = getSemaphore(semaphore);
+ ASSERT(semaphoreObject != nullptr);
+ ANGLE_CONTEXT_TRY(semaphoreObject->importZirconHandle(this, handleType, handle));
+}
+
+void Context::framebufferMemorylessPixelLocalStorage(GLint plane, GLenum internalformat)
+{
+ Framebuffer *framebuffer = mState.getDrawFramebuffer();
+ ASSERT(framebuffer);
+ PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this);
+
+ if (internalformat == GL_NONE)
+ {
+ pls.deinitialize(this, plane);
+ }
+ else
+ {
+ pls.setMemoryless(this, plane, internalformat);
+ }
+}
+
+void Context::framebufferTexturePixelLocalStorage(GLint plane,
+ TextureID backingtexture,
+ GLint level,
+ GLint layer)
+{
+ Framebuffer *framebuffer = mState.getDrawFramebuffer();
+ ASSERT(framebuffer);
+ PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this);
+
+ if (backingtexture.value == 0)
+ {
+ pls.deinitialize(this, plane);
+ }
+ else
+ {
+ Texture *tex = getTexture(backingtexture);
+ ASSERT(tex); // Validation guarantees this.
+ pls.setTextureBacked(this, plane, tex, level, layer);
+ }
+}
+
+void Context::beginPixelLocalStorage(GLsizei planes, const GLenum loadops[], const void *cleardata)
+{
+ Framebuffer *framebuffer = mState.getDrawFramebuffer();
+ ASSERT(framebuffer);
+ PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this);
+
+ pls.begin(this, planes, loadops, cleardata);
+ mState.setPixelLocalStorageActive(true);
+}
+
+void Context::endPixelLocalStorage()
+{
+ Framebuffer *framebuffer = mState.getDrawFramebuffer();
+ ASSERT(framebuffer);
+ PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this);
+
+ pls.end(this);
+ mState.setPixelLocalStorageActive(false);
+}
+
+void Context::pixelLocalStorageBarrier()
+{
+ if (getExtensions().shaderPixelLocalStorageCoherentANGLE)
+ {
+ return;
+ }
+
+ Framebuffer *framebuffer = mState.getDrawFramebuffer();
+ ASSERT(framebuffer);
+ PixelLocalStorage &pls = framebuffer->getPixelLocalStorage(this);
+
+ pls.barrier(this);
+}
+
+void Context::eGLImageTargetTexStorage(GLenum target, GLeglImageOES image, const GLint *attrib_list)
+{
+ Texture *texture = getTextureByType(FromGLenum<TextureType>(target));
+ egl::Image *imageObject = static_cast<egl::Image *>(image);
+ ANGLE_CONTEXT_TRY(texture->setStorageEGLImageTarget(this, FromGLenum<TextureType>(target),
+ imageObject, attrib_list));
+}
+
+void Context::eGLImageTargetTextureStorage(GLuint texture,
+ GLeglImageOES image,
+ const GLint *attrib_list)
+{
+ return;
+}
+
+void Context::eGLImageTargetTexture2D(TextureType target, GLeglImageOES image)
+{
+ Texture *texture = getTextureByType(target);
+ egl::Image *imageObject = static_cast<egl::Image *>(image);
+ ANGLE_CONTEXT_TRY(texture->setEGLImageTarget(this, target, imageObject));
+}
+
+void Context::eGLImageTargetRenderbufferStorage(GLenum target, GLeglImageOES image)
+{
+ Renderbuffer *renderbuffer = mState.getCurrentRenderbuffer();
+ egl::Image *imageObject = static_cast<egl::Image *>(image);
+ ANGLE_CONTEXT_TRY(renderbuffer->setStorageEGLImageTarget(this, imageObject));
+}
+
+void Context::framebufferFetchBarrier()
+{
+ mImplementation->framebufferFetchBarrier();
+}
+
+void Context::texStorage1D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width)
+{
+ UNIMPLEMENTED();
+}
+
+bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams) const
+{
+ return GetQueryParameterInfo(mState, pname, type, numParams);
+}
+
+bool Context::getIndexedQueryParameterInfo(GLenum target,
+ GLenum *type,
+ unsigned int *numParams) const
+{
+ if (getClientVersion() < Version(3, 0))
+ {
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ case GL_UNIFORM_BUFFER_BINDING:
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ case GL_UNIFORM_BUFFER_START:
+ case GL_UNIFORM_BUFFER_SIZE:
+ {
+ *type = GL_INT_64_ANGLEX;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (mSupportedExtensions.drawBuffersIndexedAny())
+ {
+ switch (target)
+ {
+ case GL_BLEND_SRC_RGB:
+ case GL_BLEND_SRC_ALPHA:
+ case GL_BLEND_DST_RGB:
+ case GL_BLEND_DST_ALPHA:
+ case GL_BLEND_EQUATION_RGB:
+ case GL_BLEND_EQUATION_ALPHA:
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_COLOR_WRITEMASK:
+ {
+ *type = GL_BOOL;
+ *numParams = 4;
+ return true;
+ }
+ }
+ }
+
+ if (mSupportedExtensions.shaderPixelLocalStorageANGLE)
+ {
+ switch (target)
+ {
+ case GL_PIXEL_LOCAL_FORMAT_ANGLE:
+ case GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE:
+ case GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE:
+ case GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE:
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (getClientVersion() < Version(3, 1))
+ {
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_IMAGE_BINDING_LAYERED:
+ {
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
+ case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ case GL_SHADER_STORAGE_BUFFER_BINDING:
+ case GL_VERTEX_BINDING_BUFFER:
+ case GL_VERTEX_BINDING_DIVISOR:
+ case GL_VERTEX_BINDING_OFFSET:
+ case GL_VERTEX_BINDING_STRIDE:
+ case GL_SAMPLE_MASK_VALUE:
+ case GL_IMAGE_BINDING_NAME:
+ case GL_IMAGE_BINDING_LEVEL:
+ case GL_IMAGE_BINDING_LAYER:
+ case GL_IMAGE_BINDING_ACCESS:
+ case GL_IMAGE_BINDING_FORMAT:
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_ATOMIC_COUNTER_BUFFER_START:
+ case GL_ATOMIC_COUNTER_BUFFER_SIZE:
+ case GL_SHADER_STORAGE_BUFFER_START:
+ case GL_SHADER_STORAGE_BUFFER_SIZE:
+ {
+ *type = GL_INT_64_ANGLEX;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+Program *Context::getProgramNoResolveLink(ShaderProgramID handle) const
+{
+ return mState.mShaderProgramManager->getProgram(handle);
+}
+
+Shader *Context::getShader(ShaderProgramID handle) const
+{
+ return mState.mShaderProgramManager->getShader(handle);
+}
+
+const angle::FrontendFeatures &Context::getFrontendFeatures() const
+{
+ return mDisplay->getFrontendFeatures();
+}
+
+bool Context::isRenderbufferGenerated(RenderbufferID renderbuffer) const
+{
+ return mState.mRenderbufferManager->isHandleGenerated(renderbuffer);
+}
+
+bool Context::isFramebufferGenerated(FramebufferID framebuffer) const
+{
+ return mState.mFramebufferManager->isHandleGenerated(framebuffer);
+}
+
+bool Context::isProgramPipelineGenerated(ProgramPipelineID pipeline) const
+{
+ return mState.mProgramPipelineManager->isHandleGenerated(pipeline);
+}
+
+bool Context::usingDisplayTextureShareGroup() const
+{
+ return mDisplayTextureShareGroup;
+}
+
+bool Context::usingDisplaySemaphoreShareGroup() const
+{
+ return mDisplaySemaphoreShareGroup;
+}
+
+GLenum Context::getConvertedRenderbufferFormat(GLenum internalformat) const
+{
+ if (isWebGL() && mState.mClientVersion.major == 2 && internalformat == GL_DEPTH_STENCIL)
+ {
+ return GL_DEPTH24_STENCIL8;
+ }
+ if (getClientType() == EGL_OPENGL_API && internalformat == GL_DEPTH_COMPONENT)
+ {
+ return GL_DEPTH_COMPONENT24;
+ }
+ return internalformat;
+}
+
+void Context::maxShaderCompilerThreads(GLuint count)
+{
+ GLuint oldCount = mState.getMaxShaderCompilerThreads();
+ mState.setMaxShaderCompilerThreads(count);
+ // A count of zero specifies a request for no parallel compiling or linking.
+ if ((oldCount == 0 || count == 0) && (oldCount != 0 || count != 0))
+ {
+ mMultiThreadPool = angle::WorkerThreadPool::Create(count > 0);
+ }
+ mMultiThreadPool->setMaxThreads(count);
+ mImplementation->setMaxShaderCompilerThreads(count);
+}
+
+void Context::framebufferParameteriMESA(GLenum target, GLenum pname, GLint param)
+{
+ framebufferParameteri(target, pname, param);
+}
+
+void Context::getFramebufferParameterivMESA(GLenum target, GLenum pname, GLint *params)
+{
+ getFramebufferParameteriv(target, pname, params);
+}
+
+bool Context::isGLES1() const
+{
+ return mState.isGLES1();
+}
+
+void Context::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
+{
+ switch (index)
+ {
+ case kVertexArraySubjectIndex:
+ switch (message)
+ {
+ case angle::SubjectMessage::ContentsChanged:
+ mState.setObjectDirty(GL_VERTEX_ARRAY);
+ mStateCache.onVertexArrayBufferContentsChange(this);
+ break;
+ case angle::SubjectMessage::SubjectMapped:
+ case angle::SubjectMessage::SubjectUnmapped:
+ case angle::SubjectMessage::BindingChanged:
+ mStateCache.onVertexArrayBufferStateChange(this);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case kReadFramebufferSubjectIndex:
+ switch (message)
+ {
+ case angle::SubjectMessage::DirtyBitsFlagged:
+ mState.setReadFramebufferDirty();
+ break;
+ case angle::SubjectMessage::SurfaceChanged:
+ mState.setReadFramebufferBindingDirty();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ break;
+
+ case kDrawFramebufferSubjectIndex:
+ switch (message)
+ {
+ case angle::SubjectMessage::DirtyBitsFlagged:
+ mState.setDrawFramebufferDirty();
+ mStateCache.onDrawFramebufferChange(this);
+ break;
+ case angle::SubjectMessage::SurfaceChanged:
+ mState.setDrawFramebufferBindingDirty();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ break;
+
+ case kProgramPipelineSubjectIndex:
+ switch (message)
+ {
+ case angle::SubjectMessage::SubjectChanged:
+ ANGLE_CONTEXT_TRY(mState.onProgramPipelineExecutableChange(this));
+ mStateCache.onProgramExecutableChange(this);
+ break;
+ case angle::SubjectMessage::ProgramRelinked:
+ ANGLE_CONTEXT_TRY(mState.mProgramPipeline->link(this));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ break;
+
+ default:
+ if (index < kTextureMaxSubjectIndex)
+ {
+ if (message != angle::SubjectMessage::ContentsChanged &&
+ message != angle::SubjectMessage::BindingChanged)
+ {
+ mState.onActiveTextureStateChange(this, index);
+ mStateCache.onActiveTextureChange(this);
+ }
+ }
+ else if (index < kImageMaxSubjectIndex)
+ {
+ mState.onImageStateChange(this, index - kImage0SubjectIndex);
+ if (message == angle::SubjectMessage::ContentsChanged)
+ {
+ mState.mDirtyBits.set(State::DirtyBitType::DIRTY_BIT_IMAGE_BINDINGS);
+ }
+ }
+ else if (index < kUniformBufferMaxSubjectIndex)
+ {
+ mState.onUniformBufferStateChange(index - kUniformBuffer0SubjectIndex);
+ mStateCache.onUniformBufferStateChange(this);
+ }
+ else if (index < kAtomicCounterBufferMaxSubjectIndex)
+ {
+ mState.onAtomicCounterBufferStateChange(index - kAtomicCounterBuffer0SubjectIndex);
+ mStateCache.onAtomicCounterBufferStateChange(this);
+ }
+ else if (index < kShaderStorageBufferMaxSubjectIndex)
+ {
+ mState.onShaderStorageBufferStateChange(index - kShaderStorageBuffer0SubjectIndex);
+ mStateCache.onShaderStorageBufferStateChange(this);
+ }
+ else
+ {
+ ASSERT(index < kSamplerMaxSubjectIndex);
+ mState.setSamplerDirty(index - kSampler0SubjectIndex);
+ mState.onActiveTextureStateChange(this, index - kSampler0SubjectIndex);
+ }
+ break;
+ }
+}
+
+angle::Result Context::onProgramLink(Program *programObject)
+{
+ // Don't parallel link a program which is active in any GL contexts. With this assumption, we
+ // don't need to worry that:
+ // 1. Draw calls after link use the new executable code or the old one depending on the link
+ // result.
+ // 2. When a backend program, e.g., ProgramD3D is linking, other backend classes like
+ // StateManager11, Renderer11, etc., may have a chance to make unexpected calls to
+ // ProgramD3D.
+ if (programObject->isInUse())
+ {
+ programObject->resolveLink(this);
+ if (programObject->isLinked())
+ {
+ ANGLE_TRY(mState.onProgramExecutableChange(this, programObject));
+ programObject->onStateChange(angle::SubjectMessage::ProgramRelinked);
+ }
+ mStateCache.onProgramExecutableChange(this);
+ }
+
+ return angle::Result::Continue;
+}
+
+egl::Error Context::setDefaultFramebuffer(egl::Surface *drawSurface, egl::Surface *readSurface)
+{
+ ASSERT(mCurrentDrawSurface == nullptr);
+ ASSERT(mCurrentReadSurface == nullptr);
+
+ mCurrentDrawSurface = drawSurface;
+ mCurrentReadSurface = readSurface;
+
+ if (drawSurface != nullptr)
+ {
+ ANGLE_TRY(drawSurface->makeCurrent(this));
+ }
+
+ ANGLE_TRY(mDefaultFramebuffer->setSurfaces(this, drawSurface, readSurface));
+
+ if (readSurface && (drawSurface != readSurface))
+ {
+ ANGLE_TRY(readSurface->makeCurrent(this));
+ }
+
+ // Update default framebuffer, the binding of the previous default
+ // framebuffer (or lack of) will have a nullptr.
+ mState.mFramebufferManager->setDefaultFramebuffer(mDefaultFramebuffer.get());
+ if (mState.getDrawFramebuffer() == nullptr)
+ {
+ bindDrawFramebuffer(mDefaultFramebuffer->id());
+ }
+ if (mState.getReadFramebuffer() == nullptr)
+ {
+ bindReadFramebuffer(mDefaultFramebuffer->id());
+ }
+
+ return egl::NoError();
+}
+
+egl::Error Context::unsetDefaultFramebuffer()
+{
+ Framebuffer *defaultFramebuffer =
+ mState.mFramebufferManager->getFramebuffer(Framebuffer::kDefaultDrawFramebufferHandle);
+
+ if (defaultFramebuffer)
+ {
+ // Remove the default framebuffer
+ if (defaultFramebuffer == mState.getReadFramebuffer())
+ {
+ mState.setReadFramebufferBinding(nullptr);
+ mReadFramebufferObserverBinding.bind(nullptr);
+ }
+
+ if (defaultFramebuffer == mState.getDrawFramebuffer())
+ {
+ mState.setDrawFramebufferBinding(nullptr);
+ mDrawFramebufferObserverBinding.bind(nullptr);
+ }
+
+ ANGLE_TRY(defaultFramebuffer->unsetSurfaces(this));
+ mState.mFramebufferManager->setDefaultFramebuffer(nullptr);
+ }
+
+ // Always unset the current surface, even if setIsCurrent fails.
+ egl::Surface *drawSurface = mCurrentDrawSurface;
+ egl::Surface *readSurface = mCurrentReadSurface;
+ mCurrentDrawSurface = nullptr;
+ mCurrentReadSurface = nullptr;
+ if (drawSurface)
+ {
+ ANGLE_TRY(drawSurface->unMakeCurrent(this));
+ }
+ if (drawSurface != readSurface)
+ {
+ ANGLE_TRY(readSurface->unMakeCurrent(this));
+ }
+
+ return egl::NoError();
+}
+
+void Context::onPreSwap() const
+{
+ // Dump frame capture if enabled.
+ getShareGroup()->getFrameCaptureShared()->onEndFrame(this);
+}
+
+void Context::getTexImage(TextureTarget target,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ void *pixels)
+{
+ Texture *texture = getTextureByTarget(target);
+ Buffer *packBuffer = mState.getTargetBuffer(BufferBinding::PixelPack);
+ ANGLE_CONTEXT_TRY(texture->getTexImage(this, mState.getPackState(), packBuffer, target, level,
+ format, type, pixels));
+}
+
+void Context::getCompressedTexImage(TextureTarget target, GLint level, void *pixels)
+{
+ Texture *texture = getTextureByTarget(target);
+ Buffer *packBuffer = mState.getTargetBuffer(BufferBinding::PixelPack);
+ ANGLE_CONTEXT_TRY(texture->getCompressedTexImage(this, mState.getPackState(), packBuffer,
+ target, level, pixels));
+}
+
+void Context::getRenderbufferImage(GLenum target, GLenum format, GLenum type, void *pixels)
+{
+ Renderbuffer *renderbuffer = mState.getCurrentRenderbuffer();
+ Buffer *packBuffer = mState.getTargetBuffer(BufferBinding::PixelPack);
+ ANGLE_CONTEXT_TRY(renderbuffer->getRenderbufferImage(this, mState.getPackState(), packBuffer,
+ format, type, pixels));
+}
+
+void Context::logicOpANGLE(LogicalOperation opcodePacked)
+{
+ mState.setLogicOp(opcodePacked);
+}
+
+egl::Error Context::releaseHighPowerGPU()
+{
+ return mImplementation->releaseHighPowerGPU(this);
+}
+
+egl::Error Context::reacquireHighPowerGPU()
+{
+ return mImplementation->reacquireHighPowerGPU(this);
+}
+
+void Context::onGPUSwitch()
+{
+ // Re-initialize the renderer string, which just changed, and
+ // which must be visible to applications.
+ initRendererString();
+}
+
+std::mutex &Context::getProgramCacheMutex() const
+{
+ return mDisplay->getProgramCacheMutex();
+}
+
+bool Context::supportsGeometryOrTesselation() const
+{
+ return mState.getClientVersion() == ES_3_2 || mState.getExtensions().geometryShaderAny() ||
+ mState.getExtensions().tessellationShaderEXT;
+}
+
+void Context::dirtyAllState()
+{
+ mState.setAllDirtyBits();
+ mState.setAllDirtyObjects();
+ mState.gles1().setAllDirty();
+}
+
+void Context::finishImmutable() const
+{
+ ANGLE_CONTEXT_TRY(mImplementation->finish(this));
+}
+
+void Context::beginPerfMonitor(GLuint monitor) {}
+
+void Context::deletePerfMonitors(GLsizei n, GLuint *monitors) {}
+
+void Context::endPerfMonitor(GLuint monitor) {}
+
+void Context::genPerfMonitors(GLsizei n, GLuint *monitors)
+{
+ for (GLsizei monitorIndex = 0; monitorIndex < n; ++monitorIndex)
+ {
+ monitors[n] = static_cast<GLuint>(monitorIndex);
+ }
+}
+
+void Context::getPerfMonitorCounterData(GLuint monitor,
+ GLenum pname,
+ GLsizei dataSize,
+ GLuint *data,
+ GLint *bytesWritten)
+{
+ using namespace angle;
+ const PerfMonitorCounterGroups &perfMonitorGroups = mImplementation->getPerfMonitorCounters();
+ GLint byteCount = 0;
+ switch (pname)
+ {
+ case GL_PERFMON_RESULT_AVAILABLE_AMD:
+ {
+ *data = GL_TRUE;
+ byteCount += sizeof(GLuint);
+ break;
+ }
+ case GL_PERFMON_RESULT_SIZE_AMD:
+ {
+ GLuint resultSize = 0;
+ for (const PerfMonitorCounterGroup &group : perfMonitorGroups)
+ {
+ resultSize += sizeof(PerfMonitorTriplet) * group.counters.size();
+ }
+ *data = resultSize;
+ byteCount += sizeof(GLuint);
+ break;
+ }
+ case GL_PERFMON_RESULT_AMD:
+ {
+ PerfMonitorTriplet *resultsOut = reinterpret_cast<PerfMonitorTriplet *>(data);
+ GLsizei maxResults = dataSize / (3 * sizeof(GLuint));
+ GLsizei resultCount = 0;
+ for (size_t groupIndex = 0;
+ groupIndex < perfMonitorGroups.size() && resultCount < maxResults; ++groupIndex)
+ {
+ const PerfMonitorCounterGroup &group = perfMonitorGroups[groupIndex];
+ for (size_t counterIndex = 0;
+ counterIndex < group.counters.size() && resultCount < maxResults;
+ ++counterIndex)
+ {
+ const PerfMonitorCounter &counter = group.counters[counterIndex];
+ PerfMonitorTriplet &triplet = resultsOut[resultCount++];
+ triplet.counter = static_cast<GLuint>(counterIndex);
+ triplet.group = static_cast<GLuint>(groupIndex);
+ triplet.value = counter.value;
+ }
+ }
+ byteCount += sizeof(PerfMonitorTriplet) * resultCount;
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+
+ if (bytesWritten)
+ {
+ *bytesWritten = byteCount;
+ }
+}
+
+void Context::getPerfMonitorCounterInfo(GLuint group, GLuint counter, GLenum pname, void *data)
+{
+ using namespace angle;
+ const PerfMonitorCounterGroups &perfMonitorGroups = mImplementation->getPerfMonitorCounters();
+ ASSERT(group < perfMonitorGroups.size());
+ const PerfMonitorCounters &counters = perfMonitorGroups[group].counters;
+ ASSERT(counter < counters.size());
+
+ switch (pname)
+ {
+ case GL_COUNTER_TYPE_AMD:
+ {
+ GLenum *dataOut = reinterpret_cast<GLenum *>(data);
+ *dataOut = GL_UNSIGNED_INT;
+ break;
+ }
+ case GL_COUNTER_RANGE_AMD:
+ {
+ GLuint *dataOut = reinterpret_cast<GLuint *>(data);
+ dataOut[0] = 0;
+ dataOut[1] = std::numeric_limits<GLuint>::max();
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+}
+
+void Context::getPerfMonitorCounterString(GLuint group,
+ GLuint counter,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *counterString)
+{
+ using namespace angle;
+ const PerfMonitorCounterGroups &perfMonitorGroups = mImplementation->getPerfMonitorCounters();
+ ASSERT(group < perfMonitorGroups.size());
+ const PerfMonitorCounters &counters = perfMonitorGroups[group].counters;
+ ASSERT(counter < counters.size());
+ GetPerfMonitorString(counters[counter].name, bufSize, length, counterString);
+}
+
+void Context::getPerfMonitorCounters(GLuint group,
+ GLint *numCounters,
+ GLint *maxActiveCounters,
+ GLsizei counterSize,
+ GLuint *counters)
+{
+ using namespace angle;
+ const PerfMonitorCounterGroups &perfMonitorGroups = mImplementation->getPerfMonitorCounters();
+ ASSERT(group < perfMonitorGroups.size());
+ const PerfMonitorCounters &groupCounters = perfMonitorGroups[group].counters;
+
+ if (numCounters)
+ {
+ *numCounters = static_cast<GLint>(groupCounters.size());
+ }
+
+ if (maxActiveCounters)
+ {
+ *maxActiveCounters = static_cast<GLint>(groupCounters.size());
+ }
+
+ if (counters)
+ {
+ GLsizei maxCounterIndex = std::min(counterSize, static_cast<GLsizei>(groupCounters.size()));
+ for (GLsizei counterIndex = 0; counterIndex < maxCounterIndex; ++counterIndex)
+ {
+ counters[counterIndex] = static_cast<GLuint>(counterIndex);
+ }
+ }
+}
+
+void Context::getPerfMonitorGroupString(GLuint group,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *groupString)
+{
+ using namespace angle;
+ const PerfMonitorCounterGroups &perfMonitorGroups = mImplementation->getPerfMonitorCounters();
+ ASSERT(group < perfMonitorGroups.size());
+ GetPerfMonitorString(perfMonitorGroups[group].name, bufSize, length, groupString);
+}
+
+void Context::getPerfMonitorGroups(GLint *numGroups, GLsizei groupsSize, GLuint *groups)
+{
+ using namespace angle;
+ const PerfMonitorCounterGroups &perfMonitorGroups = mImplementation->getPerfMonitorCounters();
+
+ if (numGroups)
+ {
+ *numGroups = static_cast<GLint>(perfMonitorGroups.size());
+ }
+
+ GLuint maxGroupIndex =
+ std::min<GLuint>(groupsSize, static_cast<GLuint>(perfMonitorGroups.size()));
+ for (GLuint groupIndex = 0; groupIndex < maxGroupIndex; ++groupIndex)
+ {
+ groups[groupIndex] = groupIndex;
+ }
+}
+
+void Context::selectPerfMonitorCounters(GLuint monitor,
+ GLboolean enable,
+ GLuint group,
+ GLint numCounters,
+ GLuint *counterList)
+{}
+
+const angle::PerfMonitorCounterGroups &Context::getPerfMonitorCounterGroups() const
+{
+ return mImplementation->getPerfMonitorCounters();
+}
+
+// ErrorSet implementation.
+ErrorSet::ErrorSet(Context *context) : mContext(context) {}
+
+ErrorSet::~ErrorSet() = default;
+
+void ErrorSet::handleError(GLenum errorCode,
+ const char *message,
+ const char *file,
+ const char *function,
+ unsigned int line)
+{
+ if (errorCode == GL_OUT_OF_MEMORY &&
+ mContext->getGraphicsResetStrategy() == GL_LOSE_CONTEXT_ON_RESET_EXT &&
+ mContext->getDisplay()->getFrontendFeatures().loseContextOnOutOfMemory.enabled)
+ {
+ mContext->markContextLost(GraphicsResetStatus::UnknownContextReset);
+ }
+
+ std::stringstream errorStream;
+ errorStream << "Error: " << gl::FmtHex(errorCode) << ", in " << file << ", " << function << ":"
+ << line << ". " << message;
+
+ std::string formattedMessage = errorStream.str();
+
+ // Process the error, but log it with WARN severity so it shows up in logs.
+ ASSERT(errorCode != GL_NO_ERROR);
+ mErrors.insert(errorCode);
+
+ mContext->getState().getDebug().insertMessage(
+ GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, errorCode, GL_DEBUG_SEVERITY_HIGH,
+ std::move(formattedMessage), gl::LOG_WARN, angle::EntryPoint::GLInvalid);
+}
+
+void ErrorSet::validationError(angle::EntryPoint entryPoint, GLenum errorCode, const char *message)
+{
+ ASSERT(errorCode != GL_NO_ERROR);
+ mErrors.insert(errorCode);
+
+ mContext->getState().getDebug().insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR,
+ errorCode, GL_DEBUG_SEVERITY_HIGH, message,
+ gl::LOG_INFO, entryPoint);
+}
+
+bool ErrorSet::empty() const
+{
+ return mErrors.empty();
+}
+
+GLenum ErrorSet::popError()
+{
+ ASSERT(!empty());
+ GLenum error = *mErrors.begin();
+ mErrors.erase(mErrors.begin());
+ return error;
+}
+
+// StateCache implementation.
+StateCache::StateCache()
+ : mCachedHasAnyEnabledClientAttrib(false),
+ mCachedNonInstancedVertexElementLimit(0),
+ mCachedInstancedVertexElementLimit(0),
+ mCachedBasicDrawStatesError(kInvalidPointer),
+ mCachedBasicDrawElementsError(kInvalidPointer),
+ mCachedProgramPipelineError(kInvalidPointer),
+ mCachedTransformFeedbackActiveUnpaused(false),
+ mCachedCanDraw(false)
+{
+ mCachedValidDrawModes.fill(false);
+}
+
+StateCache::~StateCache() = default;
+
+ANGLE_INLINE void StateCache::updateVertexElementLimits(Context *context)
+{
+ if (context->isBufferAccessValidationEnabled())
+ {
+ updateVertexElementLimitsImpl(context);
+ }
+}
+
+void StateCache::initialize(Context *context)
+{
+ updateValidDrawModes(context);
+ updateValidBindTextureTypes(context);
+ updateValidDrawElementsTypes(context);
+ updateBasicDrawStatesError();
+ updateBasicDrawElementsError();
+ updateVertexAttribTypesValidation(context);
+ updateCanDraw(context);
+}
+
+void StateCache::updateActiveAttribsMask(Context *context)
+{
+ bool isGLES1 = context->isGLES1();
+ const State &glState = context->getState();
+
+ if (!isGLES1 && !glState.getProgramExecutable())
+ {
+ mCachedActiveBufferedAttribsMask = AttributesMask();
+ mCachedActiveClientAttribsMask = AttributesMask();
+ mCachedActiveDefaultAttribsMask = AttributesMask();
+ return;
+ }
+
+ AttributesMask activeAttribs =
+ isGLES1 ? glState.gles1().getActiveAttributesMask()
+ : glState.getProgramExecutable()->getActiveAttribLocationsMask();
+
+ const VertexArray *vao = glState.getVertexArray();
+ ASSERT(vao);
+
+ const AttributesMask &clientAttribs = vao->getClientAttribsMask();
+ const AttributesMask &enabledAttribs = vao->getEnabledAttributesMask();
+ const AttributesMask &activeEnabled = activeAttribs & enabledAttribs;
+
+ mCachedActiveClientAttribsMask = activeEnabled & clientAttribs;
+ mCachedActiveBufferedAttribsMask = activeEnabled & ~clientAttribs;
+ mCachedActiveDefaultAttribsMask = activeAttribs & ~enabledAttribs;
+ mCachedHasAnyEnabledClientAttrib = (clientAttribs & enabledAttribs).any();
+}
+
+void StateCache::updateVertexElementLimitsImpl(Context *context)
+{
+ ASSERT(context->isBufferAccessValidationEnabled());
+
+ const VertexArray *vao = context->getState().getVertexArray();
+
+ mCachedNonInstancedVertexElementLimit = std::numeric_limits<GLint64>::max();
+ mCachedInstancedVertexElementLimit = std::numeric_limits<GLint64>::max();
+
+ // VAO can be null on Context startup. If we make this computation lazier we could ASSERT.
+ // If there are no buffered attributes then we should not limit the draw call count.
+ if (!vao || !mCachedActiveBufferedAttribsMask.any())
+ {
+ return;
+ }
+
+ const auto &vertexAttribs = vao->getVertexAttributes();
+ const auto &vertexBindings = vao->getVertexBindings();
+
+ for (size_t attributeIndex : mCachedActiveBufferedAttribsMask)
+ {
+ const VertexAttribute &attrib = vertexAttribs[attributeIndex];
+
+ const VertexBinding &binding = vertexBindings[attrib.bindingIndex];
+ ASSERT(context->isGLES1() ||
+ context->getState().getProgramExecutable()->isAttribLocationActive(attributeIndex));
+
+ GLint64 limit = attrib.getCachedElementLimit();
+ if (binding.getDivisor() > 0)
+ {
+ mCachedInstancedVertexElementLimit =
+ std::min(mCachedInstancedVertexElementLimit, limit);
+ }
+ else
+ {
+ mCachedNonInstancedVertexElementLimit =
+ std::min(mCachedNonInstancedVertexElementLimit, limit);
+ }
+ }
+}
+
+void StateCache::updateBasicDrawStatesError()
+{
+ mCachedBasicDrawStatesError = kInvalidPointer;
+}
+
+void StateCache::updateProgramPipelineError()
+{
+ mCachedProgramPipelineError = kInvalidPointer;
+}
+
+void StateCache::updateBasicDrawElementsError()
+{
+ mCachedBasicDrawElementsError = kInvalidPointer;
+}
+
+intptr_t StateCache::getBasicDrawStatesErrorImpl(const Context *context) const
+{
+ ASSERT(mCachedBasicDrawStatesError == kInvalidPointer);
+ mCachedBasicDrawStatesError = reinterpret_cast<intptr_t>(ValidateDrawStates(context));
+ return mCachedBasicDrawStatesError;
+}
+
+intptr_t StateCache::getProgramPipelineErrorImpl(const Context *context) const
+{
+ ASSERT(mCachedProgramPipelineError == kInvalidPointer);
+ mCachedProgramPipelineError = reinterpret_cast<intptr_t>(ValidateProgramPipeline(context));
+ return mCachedProgramPipelineError;
+}
+
+intptr_t StateCache::getBasicDrawElementsErrorImpl(const Context *context) const
+{
+ ASSERT(mCachedBasicDrawElementsError == kInvalidPointer);
+ mCachedBasicDrawElementsError = reinterpret_cast<intptr_t>(ValidateDrawElementsStates(context));
+ return mCachedBasicDrawElementsError;
+}
+
+void StateCache::onVertexArrayBindingChange(Context *context)
+{
+ updateActiveAttribsMask(context);
+ updateVertexElementLimits(context);
+ updateBasicDrawStatesError();
+ updateBasicDrawElementsError();
+}
+
+void StateCache::onProgramExecutableChange(Context *context)
+{
+ updateActiveAttribsMask(context);
+ updateVertexElementLimits(context);
+ updateBasicDrawStatesError();
+ updateProgramPipelineError();
+ updateValidDrawModes(context);
+ updateActiveShaderStorageBufferIndices(context);
+ updateActiveImageUnitIndices(context);
+ updateCanDraw(context);
+}
+
+void StateCache::onVertexArrayFormatChange(Context *context)
+{
+ updateVertexElementLimits(context);
+}
+
+void StateCache::onVertexArrayBufferContentsChange(Context *context)
+{
+ updateVertexElementLimits(context);
+ updateBasicDrawStatesError();
+}
+
+void StateCache::onVertexArrayStateChange(Context *context)
+{
+ updateActiveAttribsMask(context);
+ updateVertexElementLimits(context);
+ updateBasicDrawStatesError();
+ updateBasicDrawElementsError();
+}
+
+void StateCache::onVertexArrayBufferStateChange(Context *context)
+{
+ updateBasicDrawStatesError();
+ updateBasicDrawElementsError();
+}
+
+void StateCache::onGLES1ClientStateChange(Context *context)
+{
+ updateActiveAttribsMask(context);
+}
+
+void StateCache::onDrawFramebufferChange(Context *context)
+{
+ updateBasicDrawStatesError();
+}
+
+void StateCache::onContextCapChange(Context *context)
+{
+ updateBasicDrawStatesError();
+}
+
+void StateCache::onStencilStateChange(Context *context)
+{
+ updateBasicDrawStatesError();
+}
+
+void StateCache::onDefaultVertexAttributeChange(Context *context)
+{
+ updateBasicDrawStatesError();
+}
+
+void StateCache::onActiveTextureChange(Context *context)
+{
+ updateBasicDrawStatesError();
+}
+
+void StateCache::onQueryChange(Context *context)
+{
+ updateBasicDrawStatesError();
+}
+
+void StateCache::onActiveTransformFeedbackChange(Context *context)
+{
+ updateTransformFeedbackActiveUnpaused(context);
+ updateBasicDrawStatesError();
+ updateBasicDrawElementsError();
+ updateValidDrawModes(context);
+}
+
+void StateCache::onUniformBufferStateChange(Context *context)
+{
+ updateBasicDrawStatesError();
+}
+
+void StateCache::onAtomicCounterBufferStateChange(Context *context)
+{
+ updateBasicDrawStatesError();
+}
+
+void StateCache::onShaderStorageBufferStateChange(Context *context)
+{
+ updateBasicDrawStatesError();
+}
+
+void StateCache::onColorMaskChange(Context *context)
+{
+ updateBasicDrawStatesError();
+}
+
+void StateCache::onBlendFuncIndexedChange(Context *context)
+{
+ updateBasicDrawStatesError();
+}
+
+void StateCache::onBlendEquationChange(Context *context)
+{
+ updateBasicDrawStatesError();
+}
+
+void StateCache::setValidDrawModes(bool pointsOK,
+ bool linesOK,
+ bool trisOK,
+ bool lineAdjOK,
+ bool triAdjOK,
+ bool patchOK)
+{
+ mCachedValidDrawModes[PrimitiveMode::Points] = pointsOK;
+ mCachedValidDrawModes[PrimitiveMode::Lines] = linesOK;
+ mCachedValidDrawModes[PrimitiveMode::LineLoop] = linesOK;
+ mCachedValidDrawModes[PrimitiveMode::LineStrip] = linesOK;
+ mCachedValidDrawModes[PrimitiveMode::Triangles] = trisOK;
+ mCachedValidDrawModes[PrimitiveMode::TriangleStrip] = trisOK;
+ mCachedValidDrawModes[PrimitiveMode::TriangleFan] = trisOK;
+ mCachedValidDrawModes[PrimitiveMode::LinesAdjacency] = lineAdjOK;
+ mCachedValidDrawModes[PrimitiveMode::LineStripAdjacency] = lineAdjOK;
+ mCachedValidDrawModes[PrimitiveMode::TrianglesAdjacency] = triAdjOK;
+ mCachedValidDrawModes[PrimitiveMode::TriangleStripAdjacency] = triAdjOK;
+ mCachedValidDrawModes[PrimitiveMode::Patches] = patchOK;
+}
+
+void StateCache::updateValidDrawModes(Context *context)
+{
+ const State &state = context->getState();
+
+ const ProgramExecutable *programExecutable = context->getState().getProgramExecutable();
+
+ // If tessellation is active primitive mode must be GL_PATCHES.
+ if (programExecutable && programExecutable->hasLinkedTessellationShader())
+ {
+ setValidDrawModes(false, false, false, false, false, true);
+ return;
+ }
+
+ if (mCachedTransformFeedbackActiveUnpaused)
+ {
+ TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
+
+ // ES Spec 3.0 validation text:
+ // When transform feedback is active and not paused, all geometric primitives generated must
+ // match the value of primitiveMode passed to BeginTransformFeedback. The error
+ // INVALID_OPERATION is generated by DrawArrays and DrawArraysInstanced if mode is not
+ // identical to primitiveMode. The error INVALID_OPERATION is also generated by
+ // DrawElements, DrawElementsInstanced, and DrawRangeElements while transform feedback is
+ // active and not paused, regardless of mode. Any primitive type may be used while transform
+ // feedback is paused.
+ if (!context->getExtensions().geometryShaderAny() &&
+ !context->getExtensions().tessellationShaderEXT && context->getClientVersion() < ES_3_2)
+ {
+ mCachedValidDrawModes.fill(false);
+ mCachedValidDrawModes[curTransformFeedback->getPrimitiveMode()] = true;
+ return;
+ }
+ }
+
+ if (!programExecutable || !programExecutable->hasLinkedShaderStage(ShaderType::Geometry))
+ {
+ // All draw modes are valid, since drawing without a program does not generate an error and
+ // and operations requiring a GS will trigger other validation errors.
+ // `patchOK = false` due to checking above already enabling it if a TS is present.
+ setValidDrawModes(true, true, true, true, true, false);
+ return;
+ }
+
+ PrimitiveMode gsMode = programExecutable->getGeometryShaderInputPrimitiveType();
+ bool pointsOK = gsMode == PrimitiveMode::Points;
+ bool linesOK = gsMode == PrimitiveMode::Lines;
+ bool trisOK = gsMode == PrimitiveMode::Triangles;
+ bool lineAdjOK = gsMode == PrimitiveMode::LinesAdjacency;
+ bool triAdjOK = gsMode == PrimitiveMode::TrianglesAdjacency;
+
+ setValidDrawModes(pointsOK, linesOK, trisOK, lineAdjOK, triAdjOK, false);
+}
+
+void StateCache::updateValidBindTextureTypes(Context *context)
+{
+ const Extensions &exts = context->getExtensions();
+ bool isGLES3 = context->getClientMajorVersion() >= 3;
+ bool isGLES31 = context->getClientVersion() >= Version(3, 1);
+
+ mCachedValidBindTextureTypes = {{
+ {TextureType::_2D, true},
+ {TextureType::_2DArray, isGLES3},
+ {TextureType::_2DMultisample, isGLES31 || exts.textureMultisampleANGLE},
+ {TextureType::_2DMultisampleArray, exts.textureStorageMultisample2dArrayOES},
+ {TextureType::_3D, isGLES3 || exts.texture3DOES},
+ {TextureType::External, exts.EGLImageExternalOES || exts.EGLStreamConsumerExternalNV},
+ {TextureType::Rectangle, exts.textureRectangleANGLE},
+ {TextureType::CubeMap, true},
+ {TextureType::CubeMapArray, exts.textureCubeMapArrayAny()},
+ {TextureType::VideoImage, exts.videoTextureWEBGL},
+ {TextureType::Buffer, exts.textureBufferAny()},
+ }};
+}
+
+void StateCache::updateValidDrawElementsTypes(Context *context)
+{
+ bool supportsUint =
+ (context->getClientMajorVersion() >= 3 || context->getExtensions().elementIndexUintOES);
+
+ mCachedValidDrawElementsTypes = {{
+ {DrawElementsType::UnsignedByte, true},
+ {DrawElementsType::UnsignedShort, true},
+ {DrawElementsType::UnsignedInt, supportsUint},
+ }};
+}
+
+void StateCache::updateTransformFeedbackActiveUnpaused(Context *context)
+{
+ TransformFeedback *xfb = context->getState().getCurrentTransformFeedback();
+ mCachedTransformFeedbackActiveUnpaused = xfb && xfb->isActive() && !xfb->isPaused();
+}
+
+void StateCache::updateVertexAttribTypesValidation(Context *context)
+{
+ VertexAttribTypeCase halfFloatValidity = (context->getExtensions().vertexHalfFloatOES)
+ ? VertexAttribTypeCase::Valid
+ : VertexAttribTypeCase::Invalid;
+
+ VertexAttribTypeCase vertexType1010102Validity = (context->getExtensions().vertexType1010102OES)
+ ? VertexAttribTypeCase::ValidSize3or4
+ : VertexAttribTypeCase::Invalid;
+
+ if (context->getClientMajorVersion() <= 2)
+ {
+ mCachedVertexAttribTypesValidation = {{
+ {VertexAttribType::Byte, VertexAttribTypeCase::Valid},
+ {VertexAttribType::Short, VertexAttribTypeCase::Valid},
+ {VertexAttribType::UnsignedByte, VertexAttribTypeCase::Valid},
+ {VertexAttribType::UnsignedShort, VertexAttribTypeCase::Valid},
+ {VertexAttribType::Float, VertexAttribTypeCase::Valid},
+ {VertexAttribType::Fixed, VertexAttribTypeCase::Valid},
+ {VertexAttribType::HalfFloatOES, halfFloatValidity},
+ }};
+ }
+ else
+ {
+ mCachedVertexAttribTypesValidation = {{
+ {VertexAttribType::Byte, VertexAttribTypeCase::Valid},
+ {VertexAttribType::Short, VertexAttribTypeCase::Valid},
+ {VertexAttribType::Int, VertexAttribTypeCase::Valid},
+ {VertexAttribType::UnsignedByte, VertexAttribTypeCase::Valid},
+ {VertexAttribType::UnsignedShort, VertexAttribTypeCase::Valid},
+ {VertexAttribType::UnsignedInt, VertexAttribTypeCase::Valid},
+ {VertexAttribType::Float, VertexAttribTypeCase::Valid},
+ {VertexAttribType::HalfFloat, VertexAttribTypeCase::Valid},
+ {VertexAttribType::Fixed, VertexAttribTypeCase::Valid},
+ {VertexAttribType::Int2101010, VertexAttribTypeCase::ValidSize4Only},
+ {VertexAttribType::HalfFloatOES, halfFloatValidity},
+ {VertexAttribType::UnsignedInt2101010, VertexAttribTypeCase::ValidSize4Only},
+ {VertexAttribType::Int1010102, vertexType1010102Validity},
+ {VertexAttribType::UnsignedInt1010102, vertexType1010102Validity},
+ }};
+
+ mCachedIntegerVertexAttribTypesValidation = {{
+ {VertexAttribType::Byte, VertexAttribTypeCase::Valid},
+ {VertexAttribType::Short, VertexAttribTypeCase::Valid},
+ {VertexAttribType::Int, VertexAttribTypeCase::Valid},
+ {VertexAttribType::UnsignedByte, VertexAttribTypeCase::Valid},
+ {VertexAttribType::UnsignedShort, VertexAttribTypeCase::Valid},
+ {VertexAttribType::UnsignedInt, VertexAttribTypeCase::Valid},
+ }};
+ }
+}
+
+void StateCache::updateActiveShaderStorageBufferIndices(Context *context)
+{
+ mCachedActiveShaderStorageBufferIndices.reset();
+ const ProgramExecutable *executable = context->getState().getProgramExecutable();
+ if (executable)
+ {
+ for (const InterfaceBlock &block : executable->getShaderStorageBlocks())
+ {
+ mCachedActiveShaderStorageBufferIndices.set(block.binding);
+ }
+ }
+}
+
+void StateCache::updateActiveImageUnitIndices(Context *context)
+{
+ mCachedActiveImageUnitIndices.reset();
+ const ProgramExecutable *executable = context->getState().getProgramExecutable();
+ if (executable)
+ {
+ for (const ImageBinding &imageBinding : executable->getImageBindings())
+ {
+ for (GLuint binding : imageBinding.boundImageUnits)
+ {
+ mCachedActiveImageUnitIndices.set(binding);
+ }
+ }
+ }
+}
+
+void StateCache::updateCanDraw(Context *context)
+{
+ mCachedCanDraw =
+ (context->isGLES1() || (context->getState().getProgramExecutable() &&
+ context->getState().getProgramExecutable()->hasVertexShader()));
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Context.h b/gfx/angle/checkout/src/libANGLE/Context.h
new file mode 100644
index 0000000000..fec6a6653c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Context.h
@@ -0,0 +1,901 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Context.h: Defines the gl::Context class, managing all GL state and performing
+// rendering operations. It is the GLES2 specific implementation of EGLContext.
+
+#ifndef LIBANGLE_CONTEXT_H_
+#define LIBANGLE_CONTEXT_H_
+
+#include <mutex>
+#include <set>
+#include <string>
+
+#include "angle_gl.h"
+#include "common/MemoryBuffer.h"
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Context_gl_1_autogen.h"
+#include "libANGLE/Context_gl_2_autogen.h"
+#include "libANGLE/Context_gl_3_autogen.h"
+#include "libANGLE/Context_gl_4_autogen.h"
+#include "libANGLE/Context_gles_1_0_autogen.h"
+#include "libANGLE/Context_gles_2_0_autogen.h"
+#include "libANGLE/Context_gles_3_0_autogen.h"
+#include "libANGLE/Context_gles_3_1_autogen.h"
+#include "libANGLE/Context_gles_3_2_autogen.h"
+#include "libANGLE/Context_gles_ext_autogen.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/HandleAllocator.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/ResourceMap.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/WorkerThread.h"
+#include "libANGLE/angletypes.h"
+
+namespace angle
+{
+class FrameCapture;
+class FrameCaptureShared;
+struct FrontendFeatures;
+} // namespace angle
+
+namespace rx
+{
+class ContextImpl;
+class EGLImplFactory;
+} // namespace rx
+
+namespace egl
+{
+class AttributeMap;
+class Surface;
+struct Config;
+class Thread;
+} // namespace egl
+
+namespace gl
+{
+class Buffer;
+class Compiler;
+class FenceNV;
+class GLES1Renderer;
+class MemoryProgramCache;
+class MemoryShaderCache;
+class MemoryObject;
+class Program;
+class ProgramPipeline;
+class Query;
+class Renderbuffer;
+class Sampler;
+class Semaphore;
+class Shader;
+class Sync;
+class Texture;
+class TransformFeedback;
+class VertexArray;
+struct VertexAttribute;
+
+class ErrorSet : angle::NonCopyable
+{
+ public:
+ explicit ErrorSet(Context *context);
+ ~ErrorSet();
+
+ bool empty() const;
+ GLenum popError();
+
+ void handleError(GLenum errorCode,
+ const char *message,
+ const char *file,
+ const char *function,
+ unsigned int line);
+
+ void validationError(angle::EntryPoint entryPoint, GLenum errorCode, const char *message);
+
+ private:
+ Context *mContext;
+ std::set<GLenum> mErrors;
+};
+
+enum class VertexAttribTypeCase
+{
+ Invalid = 0,
+ Valid = 1,
+ ValidSize4Only = 2,
+ ValidSize3or4 = 3,
+};
+
+// Helper class for managing cache variables and state changes.
+class StateCache final : angle::NonCopyable
+{
+ public:
+ StateCache();
+ ~StateCache();
+
+ void initialize(Context *context);
+
+ // Places that can trigger updateActiveAttribsMask:
+ // 1. onVertexArrayBindingChange.
+ // 2. onProgramExecutableChange.
+ // 3. onVertexArrayStateChange.
+ // 4. onGLES1ClientStateChange.
+ AttributesMask getActiveBufferedAttribsMask() const { return mCachedActiveBufferedAttribsMask; }
+ AttributesMask getActiveClientAttribsMask() const { return mCachedActiveClientAttribsMask; }
+ AttributesMask getActiveDefaultAttribsMask() const { return mCachedActiveDefaultAttribsMask; }
+ bool hasAnyEnabledClientAttrib() const { return mCachedHasAnyEnabledClientAttrib; }
+ bool hasAnyActiveClientAttrib() const { return mCachedActiveClientAttribsMask.any(); }
+
+ // Places that can trigger updateVertexElementLimits:
+ // 1. onVertexArrayBindingChange.
+ // 2. onProgramExecutableChange.
+ // 3. onVertexArrayFormatChange.
+ // 4. onVertexArrayBufferChange.
+ // 5. onVertexArrayStateChange.
+ GLint64 getNonInstancedVertexElementLimit() const
+ {
+ return mCachedNonInstancedVertexElementLimit;
+ }
+ GLint64 getInstancedVertexElementLimit() const { return mCachedInstancedVertexElementLimit; }
+
+ // Places that can trigger updateBasicDrawStatesError:
+ // 1. onVertexArrayBindingChange.
+ // 2. onProgramExecutableChange.
+ // 3. onVertexArrayBufferContentsChange.
+ // 4. onVertexArrayStateChange.
+ // 5. onVertexArrayBufferStateChange.
+ // 6. onDrawFramebufferChange.
+ // 7. onContextCapChange.
+ // 8. onStencilStateChange.
+ // 9. onDefaultVertexAttributeChange.
+ // 10. onActiveTextureChange.
+ // 11. onQueryChange.
+ // 12. onActiveTransformFeedbackChange.
+ // 13. onUniformBufferStateChange.
+ // 14. onColorMaskChange.
+ // 15. onBufferBindingChange.
+ // 16. onBlendFuncIndexedChange.
+ bool hasBasicDrawStatesError(Context *context) const
+ {
+ if (mCachedBasicDrawStatesError == 0)
+ {
+ return false;
+ }
+ if (mCachedBasicDrawStatesError != kInvalidPointer)
+ {
+ return true;
+ }
+ return getBasicDrawStatesErrorImpl(context) != 0;
+ }
+
+ intptr_t getBasicDrawStatesError(const Context *context) const
+ {
+ if (mCachedBasicDrawStatesError != kInvalidPointer)
+ {
+ return mCachedBasicDrawStatesError;
+ }
+
+ return getBasicDrawStatesErrorImpl(context);
+ }
+
+ // Places that can trigger updateProgramPipelineError:
+ // 1. onProgramExecutableChange.
+ intptr_t getProgramPipelineError(const Context *context) const
+ {
+ if (mCachedProgramPipelineError != kInvalidPointer)
+ {
+ return mCachedProgramPipelineError;
+ }
+
+ return getProgramPipelineErrorImpl(context);
+ }
+
+ // Places that can trigger updateBasicDrawElementsError:
+ // 1. onActiveTransformFeedbackChange.
+ // 2. onVertexArrayBufferStateChange.
+ // 3. onBufferBindingChange.
+ // 4. onVertexArrayStateChange.
+ // 5. onVertexArrayBindingStateChange.
+ intptr_t getBasicDrawElementsError(const Context *context) const
+ {
+ if (mCachedBasicDrawElementsError != kInvalidPointer)
+ {
+ return mCachedBasicDrawElementsError;
+ }
+
+ return getBasicDrawElementsErrorImpl(context);
+ }
+
+ // Places that can trigger updateValidDrawModes:
+ // 1. onProgramExecutableChange.
+ // 2. onActiveTransformFeedbackChange.
+ bool isValidDrawMode(PrimitiveMode primitiveMode) const
+ {
+ return mCachedValidDrawModes[primitiveMode];
+ }
+
+ // Cannot change except on Context/Extension init.
+ bool isValidBindTextureType(TextureType type) const
+ {
+ return mCachedValidBindTextureTypes[type];
+ }
+
+ // Cannot change except on Context/Extension init.
+ bool isValidDrawElementsType(DrawElementsType type) const
+ {
+ return mCachedValidDrawElementsTypes[type];
+ }
+
+ // Places that can trigger updateTransformFeedbackActiveUnpaused:
+ // 1. onActiveTransformFeedbackChange.
+ bool isTransformFeedbackActiveUnpaused() const
+ {
+ return mCachedTransformFeedbackActiveUnpaused;
+ }
+
+ // Cannot change except on Context/Extension init.
+ VertexAttribTypeCase getVertexAttribTypeValidation(VertexAttribType type) const
+ {
+ return mCachedVertexAttribTypesValidation[type];
+ }
+
+ VertexAttribTypeCase getIntegerVertexAttribTypeValidation(VertexAttribType type) const
+ {
+ return mCachedIntegerVertexAttribTypesValidation[type];
+ }
+
+ // Places that can trigger updateActiveShaderStorageBufferIndices:
+ // 1. onProgramExecutableChange.
+ StorageBuffersMask getActiveShaderStorageBufferIndices() const
+ {
+ return mCachedActiveShaderStorageBufferIndices;
+ }
+
+ // Places that can trigger updateActiveImageUnitIndices:
+ // 1. onProgramExecutableChange.
+ const ImageUnitMask &getActiveImageUnitIndices() const { return mCachedActiveImageUnitIndices; }
+
+ // Places that can trigger updateCanDraw:
+ // 1. onProgramExecutableChange.
+ bool getCanDraw() const { return mCachedCanDraw; }
+
+ // State change notifications.
+ void onVertexArrayBindingChange(Context *context);
+ void onProgramExecutableChange(Context *context);
+ void onVertexArrayFormatChange(Context *context);
+ void onVertexArrayBufferContentsChange(Context *context);
+ void onVertexArrayStateChange(Context *context);
+ void onVertexArrayBufferStateChange(Context *context);
+ void onGLES1ClientStateChange(Context *context);
+ void onDrawFramebufferChange(Context *context);
+ void onContextCapChange(Context *context);
+ void onStencilStateChange(Context *context);
+ void onDefaultVertexAttributeChange(Context *context);
+ void onActiveTextureChange(Context *context);
+ void onQueryChange(Context *context);
+ void onActiveTransformFeedbackChange(Context *context);
+ void onUniformBufferStateChange(Context *context);
+ void onAtomicCounterBufferStateChange(Context *context);
+ void onShaderStorageBufferStateChange(Context *context);
+ void onColorMaskChange(Context *context);
+ void onBufferBindingChange(Context *context);
+ void onBlendFuncIndexedChange(Context *context);
+ void onBlendEquationChange(Context *context);
+
+ private:
+ // Cache update functions.
+ void updateActiveAttribsMask(Context *context);
+ void updateVertexElementLimits(Context *context);
+ void updateVertexElementLimitsImpl(Context *context);
+ void updateValidDrawModes(Context *context);
+ void updateValidBindTextureTypes(Context *context);
+ void updateValidDrawElementsTypes(Context *context);
+ void updateBasicDrawStatesError();
+ void updateProgramPipelineError();
+ void updateBasicDrawElementsError();
+ void updateTransformFeedbackActiveUnpaused(Context *context);
+ void updateVertexAttribTypesValidation(Context *context);
+ void updateActiveShaderStorageBufferIndices(Context *context);
+ void updateActiveImageUnitIndices(Context *context);
+ void updateCanDraw(Context *context);
+
+ void setValidDrawModes(bool pointsOK,
+ bool linesOK,
+ bool trisOK,
+ bool lineAdjOK,
+ bool triAdjOK,
+ bool patchOK);
+
+ intptr_t getBasicDrawStatesErrorImpl(const Context *context) const;
+ intptr_t getProgramPipelineErrorImpl(const Context *context) const;
+ intptr_t getBasicDrawElementsErrorImpl(const Context *context) const;
+
+ static constexpr intptr_t kInvalidPointer = 1;
+
+ AttributesMask mCachedActiveBufferedAttribsMask;
+ AttributesMask mCachedActiveClientAttribsMask;
+ AttributesMask mCachedActiveDefaultAttribsMask;
+ bool mCachedHasAnyEnabledClientAttrib;
+ GLint64 mCachedNonInstancedVertexElementLimit;
+ GLint64 mCachedInstancedVertexElementLimit;
+ mutable intptr_t mCachedBasicDrawStatesError;
+ mutable intptr_t mCachedBasicDrawElementsError;
+ // mCachedProgramPipelineError checks only the
+ // current-program-exists subset of mCachedBasicDrawStatesError.
+ // Therefore, mCachedProgramPipelineError follows
+ // mCachedBasicDrawStatesError in that if mCachedBasicDrawStatesError is
+ // no-error, so is mCachedProgramPipelineError. Otherwise, if
+ // mCachedBasicDrawStatesError is in error, the state of
+ // mCachedProgramPipelineError can be no-error or also in error, or
+ // unknown due to early exiting.
+ mutable intptr_t mCachedProgramPipelineError;
+ bool mCachedTransformFeedbackActiveUnpaused;
+ StorageBuffersMask mCachedActiveShaderStorageBufferIndices;
+ ImageUnitMask mCachedActiveImageUnitIndices;
+
+ // Reserve an extra slot at the end of these maps for invalid enum.
+ angle::PackedEnumMap<PrimitiveMode, bool, angle::EnumSize<PrimitiveMode>() + 1>
+ mCachedValidDrawModes;
+ angle::PackedEnumMap<TextureType, bool, angle::EnumSize<TextureType>() + 1>
+ mCachedValidBindTextureTypes;
+ angle::PackedEnumMap<DrawElementsType, bool, angle::EnumSize<DrawElementsType>() + 1>
+ mCachedValidDrawElementsTypes;
+ angle::PackedEnumMap<VertexAttribType,
+ VertexAttribTypeCase,
+ angle::EnumSize<VertexAttribType>() + 1>
+ mCachedVertexAttribTypesValidation;
+ angle::PackedEnumMap<VertexAttribType,
+ VertexAttribTypeCase,
+ angle::EnumSize<VertexAttribType>() + 1>
+ mCachedIntegerVertexAttribTypesValidation;
+
+ bool mCachedCanDraw;
+};
+
+using VertexArrayMap = ResourceMap<VertexArray, VertexArrayID>;
+using QueryMap = ResourceMap<Query, QueryID>;
+using TransformFeedbackMap = ResourceMap<TransformFeedback, TransformFeedbackID>;
+
+class Context final : public egl::LabeledObject, angle::NonCopyable, public angle::ObserverInterface
+{
+ public:
+ Context(egl::Display *display,
+ const egl::Config *config,
+ const Context *shareContext,
+ TextureManager *shareTextures,
+ SemaphoreManager *shareSemaphores,
+ MemoryProgramCache *memoryProgramCache,
+ MemoryShaderCache *memoryShaderCache,
+ const EGLenum clientType,
+ const egl::AttributeMap &attribs,
+ const egl::DisplayExtensions &displayExtensions,
+ const egl::ClientExtensions &clientExtensions);
+
+ // Use for debugging.
+ ContextID id() const { return mState.getContextID(); }
+
+ egl::Error initialize();
+
+ egl::Error onDestroy(const egl::Display *display);
+ ~Context() override;
+
+ void setLabel(EGLLabelKHR label) override;
+ EGLLabelKHR getLabel() const override;
+
+ egl::Error makeCurrent(egl::Display *display,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface);
+ egl::Error unMakeCurrent(const egl::Display *display);
+
+ // These create and destroy methods pass through to ResourceManager, which owns these objects.
+ BufferID createBuffer();
+ TextureID createTexture();
+ RenderbufferID createRenderbuffer();
+ ProgramPipelineID createProgramPipeline();
+ MemoryObjectID createMemoryObject();
+ SemaphoreID createSemaphore();
+
+ void deleteBuffer(BufferID buffer);
+ void deleteTexture(TextureID texture);
+ void deleteRenderbuffer(RenderbufferID renderbuffer);
+ void deleteProgramPipeline(ProgramPipelineID pipeline);
+ void deleteMemoryObject(MemoryObjectID memoryObject);
+ void deleteSemaphore(SemaphoreID semaphore);
+
+ void bindReadFramebuffer(FramebufferID framebufferHandle);
+ void bindDrawFramebuffer(FramebufferID framebufferHandle);
+
+ Buffer *getBuffer(BufferID handle) const;
+ FenceNV *getFenceNV(FenceNVID handle) const;
+ Sync *getSync(GLsync handle) const;
+ ANGLE_INLINE Texture *getTexture(TextureID handle) const
+ {
+ return mState.mTextureManager->getTexture(handle);
+ }
+
+ Framebuffer *getFramebuffer(FramebufferID handle) const;
+ Renderbuffer *getRenderbuffer(RenderbufferID handle) const;
+ VertexArray *getVertexArray(VertexArrayID handle) const;
+ Sampler *getSampler(SamplerID handle) const;
+ Query *getOrCreateQuery(QueryID handle, QueryType type);
+ Query *getQuery(QueryID handle) const;
+ TransformFeedback *getTransformFeedback(TransformFeedbackID handle) const;
+ ProgramPipeline *getProgramPipeline(ProgramPipelineID handle) const;
+ MemoryObject *getMemoryObject(MemoryObjectID handle) const;
+ Semaphore *getSemaphore(SemaphoreID handle) const;
+
+ Texture *getTextureByType(TextureType type) const;
+ Texture *getTextureByTarget(TextureTarget target) const;
+ Texture *getSamplerTexture(unsigned int sampler, TextureType type) const;
+
+ Compiler *getCompiler() const;
+
+ bool isVertexArrayGenerated(VertexArrayID vertexArray) const;
+ bool isTransformFeedbackGenerated(TransformFeedbackID transformFeedback) const;
+
+ bool isExternal() const { return mIsExternal; }
+ bool saveAndRestoreState() const { return mSaveAndRestoreState; }
+
+ void getBooleanvImpl(GLenum pname, GLboolean *params) const;
+ void getFloatvImpl(GLenum pname, GLfloat *params) const;
+ void getIntegervImpl(GLenum pname, GLint *params) const;
+ void getInteger64vImpl(GLenum pname, GLint64 *params) const;
+ void getIntegerVertexAttribImpl(GLenum pname, GLenum attribpname, GLint *params) const;
+ void getVertexAttribivImpl(GLuint index, GLenum pname, GLint *params) const;
+
+ // Framebuffers are owned by the Context, so these methods do not pass through
+ FramebufferID createFramebuffer();
+ void deleteFramebuffer(FramebufferID framebuffer);
+
+ bool hasActiveTransformFeedback(ShaderProgramID program) const;
+
+ // Desktop GL entry point interface
+ ANGLE_GL_1_CONTEXT_API
+ ANGLE_GL_2_CONTEXT_API
+ ANGLE_GL_3_CONTEXT_API
+ ANGLE_GL_4_CONTEXT_API
+
+ // GLES entry point interface
+ ANGLE_GLES_1_0_CONTEXT_API
+ ANGLE_GLES_2_0_CONTEXT_API
+ ANGLE_GLES_3_0_CONTEXT_API
+ ANGLE_GLES_3_1_CONTEXT_API
+ ANGLE_GLES_3_2_CONTEXT_API
+ ANGLE_GLES_EXT_CONTEXT_API
+
+ angle::Result handleNoopDrawEvent();
+
+ // Consumes an error.
+ void handleError(GLenum errorCode,
+ const char *message,
+ const char *file,
+ const char *function,
+ unsigned int line);
+
+ void validationError(angle::EntryPoint entryPoint, GLenum errorCode, const char *message) const;
+ ANGLE_FORMAT_PRINTF(4, 5)
+ void validationErrorF(angle::EntryPoint entryPoint,
+ GLenum errorCode,
+ const char *format,
+ ...) const;
+
+ void markContextLost(GraphicsResetStatus status);
+
+ bool isContextLost() const { return mContextLost; }
+ void setContextLost();
+
+ GLenum getGraphicsResetStrategy() const { return mResetStrategy; }
+ bool isResetNotificationEnabled() const;
+
+ bool isRobustnessEnabled() const;
+
+ const egl::Config *getConfig() const;
+ EGLenum getClientType() const;
+ EGLenum getRenderBuffer() const;
+ EGLenum getContextPriority() const;
+
+ const GLubyte *getString(GLenum name) const;
+ const GLubyte *getStringi(GLenum name, GLuint index) const;
+
+ size_t getExtensionStringCount() const;
+
+ bool isExtensionRequestable(const char *name) const;
+ bool isExtensionDisablable(const char *name) const;
+ size_t getRequestableExtensionStringCount() const;
+ void setExtensionEnabled(const char *name, bool enabled);
+ void reinitializeAfterExtensionsChanged();
+
+ rx::ContextImpl *getImplementation() const { return mImplementation.get(); }
+
+ [[nodiscard]] bool getScratchBuffer(size_t requestedSizeBytes,
+ angle::MemoryBuffer **scratchBufferOut) const;
+ [[nodiscard]] bool getZeroFilledBuffer(size_t requstedSizeBytes,
+ angle::MemoryBuffer **zeroBufferOut) const;
+ angle::ScratchBuffer *getScratchBuffer() const;
+
+ angle::Result prepareForCopyImage();
+ angle::Result prepareForDispatch();
+ angle::Result prepareForInvalidate(GLenum target);
+
+ MemoryProgramCache *getMemoryProgramCache() const { return mMemoryProgramCache; }
+ MemoryShaderCache *getMemoryShaderCache() const { return mMemoryShaderCache; }
+
+ std::mutex &getProgramCacheMutex() const;
+
+ bool hasBeenCurrent() const { return mHasBeenCurrent; }
+ egl::Display *getDisplay() const { return mDisplay; }
+ egl::Surface *getCurrentDrawSurface() const { return mCurrentDrawSurface; }
+ egl::Surface *getCurrentReadSurface() const { return mCurrentReadSurface; }
+
+ bool isRobustResourceInitEnabled() const { return mState.isRobustResourceInitEnabled(); }
+
+ bool isCurrentTransformFeedback(const TransformFeedback *tf) const;
+
+ bool isCurrentVertexArray(const VertexArray *va) const
+ {
+ return mState.isCurrentVertexArray(va);
+ }
+
+ ANGLE_INLINE bool isShared() const { return mShared; }
+ // Once a context is setShared() it cannot be undone
+ void setShared() { mShared = true; }
+
+ const State &getState() const { return mState; }
+ GLint getClientMajorVersion() const { return mState.getClientMajorVersion(); }
+ GLint getClientMinorVersion() const { return mState.getClientMinorVersion(); }
+ const Version &getClientVersion() const { return mState.getClientVersion(); }
+ const Caps &getCaps() const { return mState.getCaps(); }
+ const TextureCapsMap &getTextureCaps() const { return mState.getTextureCaps(); }
+ const Extensions &getExtensions() const { return mState.getExtensions(); }
+ const Limitations &getLimitations() const { return mState.getLimitations(); }
+ bool isGLES1() const;
+
+ bool skipValidation() const
+ {
+ // Ensure we don't skip validation when context becomes lost, since implementations
+ // generally assume a non-lost context, non-null objects, etc.
+ ASSERT(!isContextLost() || !mSkipValidation);
+ return mSkipValidation;
+ }
+
+ // Specific methods needed for validation.
+ bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams) const;
+ bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams) const;
+
+ ANGLE_INLINE Program *getProgramResolveLink(ShaderProgramID handle) const
+ {
+ Program *program = mState.mShaderProgramManager->getProgram(handle);
+ if (program)
+ {
+ program->resolveLink(this);
+ }
+ return program;
+ }
+
+ Program *getProgramNoResolveLink(ShaderProgramID handle) const;
+ Shader *getShader(ShaderProgramID handle) const;
+
+ ANGLE_INLINE bool isTextureGenerated(TextureID texture) const
+ {
+ return mState.mTextureManager->isHandleGenerated(texture);
+ }
+
+ ANGLE_INLINE bool isBufferGenerated(BufferID buffer) const
+ {
+ return mState.mBufferManager->isHandleGenerated(buffer);
+ }
+
+ bool isRenderbufferGenerated(RenderbufferID renderbuffer) const;
+ bool isFramebufferGenerated(FramebufferID framebuffer) const;
+ bool isProgramPipelineGenerated(ProgramPipelineID pipeline) const;
+ bool isQueryGenerated(QueryID query) const;
+
+ bool usingDisplayTextureShareGroup() const;
+ bool usingDisplaySemaphoreShareGroup() const;
+
+ // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
+ GLenum getConvertedRenderbufferFormat(GLenum internalformat) const;
+
+ bool isWebGL() const { return mState.isWebGL(); }
+ bool isWebGL1() const { return mState.isWebGL1(); }
+
+ bool isValidBufferBinding(BufferBinding binding) const { return mValidBufferBindings[binding]; }
+
+ // GLES1 emulation: Renderer level (for validation)
+ int vertexArrayIndex(ClientVertexArrayType type) const;
+ static int TexCoordArrayIndex(unsigned int unit);
+
+ // GL_KHR_parallel_shader_compile
+ std::shared_ptr<angle::WorkerThreadPool> getShaderCompileThreadPool() const
+ {
+ if (mState.mExtensions.parallelShaderCompileKHR)
+ {
+ return mMultiThreadPool;
+ }
+ return mSingleThreadPool;
+ }
+
+ // Generic multithread pool.
+ std::shared_ptr<angle::WorkerThreadPool> getWorkerThreadPool() const
+ {
+ return mMultiThreadPool;
+ }
+
+ const StateCache &getStateCache() const { return mStateCache; }
+ StateCache &getStateCache() { return mStateCache; }
+
+ void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
+
+ void onSamplerUniformChange(size_t textureUnitIndex);
+
+ bool isBufferAccessValidationEnabled() const { return mBufferAccessValidationEnabled; }
+
+ const angle::FrontendFeatures &getFrontendFeatures() const;
+
+ angle::FrameCapture *getFrameCapture() const { return mFrameCapture.get(); }
+
+ const VertexArrayMap &getVertexArraysForCapture() const { return mVertexArrayMap; }
+ const QueryMap &getQueriesForCapture() const { return mQueryMap; }
+ const TransformFeedbackMap &getTransformFeedbacksForCapture() const
+ {
+ return mTransformFeedbackMap;
+ }
+
+ void onPreSwap() const;
+
+ Program *getActiveLinkedProgram() const;
+
+ // EGL_ANGLE_power_preference implementation.
+ egl::Error releaseHighPowerGPU();
+ egl::Error reacquireHighPowerGPU();
+ void onGPUSwitch();
+
+ bool noopDraw(PrimitiveMode mode, GLsizei count) const;
+ bool noopDrawInstanced(PrimitiveMode mode, GLsizei count, GLsizei instanceCount) const;
+
+ bool isClearBufferMaskedOut(GLenum buffer, GLint drawbuffer) const;
+ bool noopClearBuffer(GLenum buffer, GLint drawbuffer) const;
+
+ void addRef() const { mRefCount++; }
+ void release() const { mRefCount--; }
+ size_t getRefCount() const { return mRefCount; }
+
+ egl::ShareGroup *getShareGroup() const { return mState.getShareGroup(); }
+
+ bool supportsGeometryOrTesselation() const;
+ void dirtyAllState();
+
+ bool isDestroyed() const { return mIsDestroyed; }
+ void setIsDestroyed() { mIsDestroyed = true; }
+
+ void setLogicOpEnabled(bool enabled) { mState.setLogicOpEnabled(enabled); }
+ void setLogicOp(LogicalOperation opcode) { mState.setLogicOp(opcode); }
+
+ // Needed by capture serialization logic that works with a "const" Context pointer.
+ void finishImmutable() const;
+
+ const angle::PerfMonitorCounterGroups &getPerfMonitorCounterGroups() const;
+
+ private:
+ void initializeDefaultResources();
+
+ angle::Result prepareForDraw(PrimitiveMode mode);
+ angle::Result prepareForClear(GLbitfield mask);
+ angle::Result prepareForClearBuffer(GLenum buffer, GLint drawbuffer);
+ angle::Result syncState(const State::DirtyBits &bitMask,
+ const State::DirtyObjects &objectMask,
+ Command command);
+ angle::Result syncDirtyBits(Command command);
+ angle::Result syncDirtyBits(const State::DirtyBits &bitMask, Command command);
+ angle::Result syncDirtyObjects(const State::DirtyObjects &objectMask, Command command);
+ angle::Result syncStateForReadPixels();
+ angle::Result syncStateForTexImage();
+ angle::Result syncStateForBlit(GLbitfield mask);
+ angle::Result syncStateForClear();
+ angle::Result syncTextureForCopy(Texture *texture);
+
+ VertexArray *checkVertexArrayAllocation(VertexArrayID vertexArrayHandle);
+ TransformFeedback *checkTransformFeedbackAllocation(TransformFeedbackID transformFeedback);
+
+ angle::Result onProgramLink(Program *programObject);
+
+ void detachBuffer(Buffer *buffer);
+ void detachTexture(TextureID texture);
+ void detachFramebuffer(FramebufferID framebuffer);
+ void detachRenderbuffer(RenderbufferID renderbuffer);
+ void detachVertexArray(VertexArrayID vertexArray);
+ void detachTransformFeedback(TransformFeedbackID transformFeedback);
+ void detachSampler(SamplerID sampler);
+ void detachProgramPipeline(ProgramPipelineID pipeline);
+
+ egl::Error setDefaultFramebuffer(egl::Surface *drawSurface, egl::Surface *readSurface);
+ egl::Error unsetDefaultFramebuffer();
+
+ void initRendererString();
+ void initVersionStrings();
+ void initExtensionStrings();
+
+ Extensions generateSupportedExtensions() const;
+ void initCaps();
+ void updateCaps();
+
+ gl::LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const;
+ gl::LabeledObject *getLabeledObjectFromPtr(const void *ptr) const;
+
+ void setUniform1iImpl(Program *program,
+ UniformLocation location,
+ GLsizei count,
+ const GLint *v);
+ void renderbufferStorageMultisampleImpl(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ MultisamplingMode mode);
+
+ State mState;
+ bool mShared;
+ bool mSkipValidation;
+ bool mDisplayTextureShareGroup;
+ bool mDisplaySemaphoreShareGroup;
+
+ // Recorded errors
+ ErrorSet mErrors;
+
+ // Stores for each buffer binding type whether is it allowed to be used in this context.
+ angle::PackedEnumBitSet<BufferBinding> mValidBufferBindings;
+
+ std::unique_ptr<rx::ContextImpl> mImplementation;
+
+ EGLLabelKHR mLabel;
+
+ // Extensions supported by the implementation plus extensions that are implemented entirely
+ // within the frontend.
+ Extensions mSupportedExtensions;
+
+ // Shader compiler. Lazily initialized hence the mutable value.
+ mutable BindingPointer<Compiler> mCompiler;
+
+ const egl::Config *mConfig;
+
+ TextureMap mZeroTextures;
+
+ ResourceMap<FenceNV, FenceNVID> mFenceNVMap;
+ HandleAllocator mFenceNVHandleAllocator;
+
+ QueryMap mQueryMap;
+ HandleAllocator mQueryHandleAllocator;
+
+ VertexArrayMap mVertexArrayMap;
+ HandleAllocator mVertexArrayHandleAllocator;
+
+ TransformFeedbackMap mTransformFeedbackMap;
+ HandleAllocator mTransformFeedbackHandleAllocator;
+
+ const char *mVersionString;
+ const char *mShadingLanguageString;
+ const char *mRendererString;
+ const char *mExtensionString;
+ std::vector<const char *> mExtensionStrings;
+ const char *mRequestableExtensionString;
+ std::vector<const char *> mRequestableExtensionStrings;
+
+ // GLES1 renderer state
+ std::unique_ptr<GLES1Renderer> mGLES1Renderer;
+
+ // Current/lost context flags
+ bool mHasBeenCurrent;
+ bool mContextLost; // Set with setContextLost so that we also set mSkipValidation=false.
+ GraphicsResetStatus mResetStatus;
+ bool mContextLostForced;
+ GLenum mResetStrategy;
+ const bool mSurfacelessSupported;
+ egl::Surface *mCurrentDrawSurface;
+ egl::Surface *mCurrentReadSurface;
+ egl::Display *mDisplay;
+ const bool mWebGLContext;
+ bool mBufferAccessValidationEnabled;
+ const bool mExtensionsEnabled;
+ MemoryProgramCache *mMemoryProgramCache;
+ MemoryShaderCache *mMemoryShaderCache;
+
+ State::DirtyObjects mDrawDirtyObjects;
+
+ StateCache mStateCache;
+
+ State::DirtyBits mAllDirtyBits;
+ State::DirtyBits mTexImageDirtyBits;
+ State::DirtyObjects mTexImageDirtyObjects;
+ State::DirtyBits mReadPixelsDirtyBits;
+ State::DirtyObjects mReadPixelsDirtyObjects;
+ State::DirtyBits mClearDirtyBits;
+ State::DirtyObjects mClearDirtyObjects;
+ State::DirtyBits mBlitDirtyBits;
+ State::DirtyObjects mBlitDirtyObjects;
+ State::DirtyBits mComputeDirtyBits;
+ State::DirtyObjects mComputeDirtyObjects;
+ State::DirtyBits mCopyImageDirtyBits;
+ State::DirtyObjects mCopyImageDirtyObjects;
+ State::DirtyBits mReadInvalidateDirtyBits;
+ State::DirtyBits mDrawInvalidateDirtyBits;
+
+ // Binding to container objects that use dependent state updates.
+ angle::ObserverBinding mVertexArrayObserverBinding;
+ angle::ObserverBinding mDrawFramebufferObserverBinding;
+ angle::ObserverBinding mReadFramebufferObserverBinding;
+ angle::ObserverBinding mProgramPipelineObserverBinding;
+ std::vector<angle::ObserverBinding> mUniformBufferObserverBindings;
+ std::vector<angle::ObserverBinding> mAtomicCounterBufferObserverBindings;
+ std::vector<angle::ObserverBinding> mShaderStorageBufferObserverBindings;
+ std::vector<angle::ObserverBinding> mSamplerObserverBindings;
+ std::vector<angle::ObserverBinding> mImageObserverBindings;
+
+ // Not really a property of context state. The size and contexts change per-api-call.
+ mutable Optional<angle::ScratchBuffer> mScratchBuffer;
+ mutable Optional<angle::ScratchBuffer> mZeroFilledBuffer;
+
+ // Single-threaded pool may not always be initialized. It currently depends on the extension
+ // GL_KHR_parallel_shader_compile being disabled.
+ std::shared_ptr<angle::WorkerThreadPool> mSingleThreadPool;
+ // Multithreaded pool will always be initialized so it can be used for more generic work.
+ std::shared_ptr<angle::WorkerThreadPool> mMultiThreadPool;
+
+ // Note: we use a raw pointer here so we can exclude frame capture sources from the build.
+ std::unique_ptr<angle::FrameCapture> mFrameCapture;
+
+ // Cache representation of the serialized context string.
+ mutable std::string mCachedSerializedStateString;
+
+ mutable size_t mRefCount;
+
+ OverlayType mOverlay;
+
+ const bool mIsExternal;
+ const bool mSaveAndRestoreState;
+
+ bool mIsDestroyed;
+
+ std::unique_ptr<Framebuffer> mDefaultFramebuffer;
+};
+
+class [[nodiscard]] ScopedContextRef
+{
+ public:
+ ScopedContextRef(Context *context) : mContext(context)
+ {
+ if (mContext)
+ {
+ mContext->addRef();
+ }
+ }
+ ~ScopedContextRef()
+ {
+ if (mContext)
+ {
+ mContext->release();
+ }
+ }
+
+ private:
+ Context *const mContext;
+};
+
+// Thread-local current valid context bound to the thread.
+#if defined(ANGLE_PLATFORM_APPLE)
+extern Context *GetCurrentValidContextTLS();
+extern void SetCurrentValidContextTLS(Context *context);
+#else
+extern thread_local Context *gCurrentValidContext;
+#endif
+
+} // namespace gl
+
+#endif // LIBANGLE_CONTEXT_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Context.inl.h b/gfx/angle/checkout/src/libANGLE/Context.inl.h
new file mode 100644
index 0000000000..3a0573d307
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Context.inl.h
@@ -0,0 +1,176 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Context.inl.h: Defines inline functions of gl::Context class
+// Has to be included after libANGLE/Context.h when using one
+// of the defined functions
+
+#ifndef LIBANGLE_CONTEXT_INL_H_
+#define LIBANGLE_CONTEXT_INL_H_
+
+#include "libANGLE/Context.h"
+#include "libANGLE/GLES1Renderer.h"
+#include "libANGLE/renderer/ContextImpl.h"
+
+#define ANGLE_HANDLE_ERR(X) \
+ (void)(X); \
+ return;
+#define ANGLE_CONTEXT_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_HANDLE_ERR)
+
+namespace gl
+{
+constexpr angle::PackedEnumMap<PrimitiveMode, GLsizei> kMinimumPrimitiveCounts = {{
+ {PrimitiveMode::Points, 1},
+ {PrimitiveMode::Lines, 2},
+ {PrimitiveMode::LineLoop, 2},
+ {PrimitiveMode::LineStrip, 2},
+ {PrimitiveMode::Triangles, 3},
+ {PrimitiveMode::TriangleStrip, 3},
+ {PrimitiveMode::TriangleFan, 3},
+ {PrimitiveMode::LinesAdjacency, 2},
+ {PrimitiveMode::LineStripAdjacency, 2},
+ {PrimitiveMode::TrianglesAdjacency, 3},
+ {PrimitiveMode::TriangleStripAdjacency, 3},
+}};
+
+ANGLE_INLINE void MarkTransformFeedbackBufferUsage(const Context *context,
+ GLsizei count,
+ GLsizei instanceCount)
+{
+ if (context->getStateCache().isTransformFeedbackActiveUnpaused())
+ {
+ TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
+ transformFeedback->onVerticesDrawn(context, count, instanceCount);
+ }
+}
+
+ANGLE_INLINE void MarkShaderStorageUsage(const Context *context)
+{
+ for (size_t index : context->getStateCache().getActiveShaderStorageBufferIndices())
+ {
+ Buffer *buffer = context->getState().getIndexedShaderStorageBuffer(index).get();
+ if (buffer)
+ {
+ buffer->onDataChanged();
+ }
+ }
+
+ for (size_t index : context->getStateCache().getActiveImageUnitIndices())
+ {
+ const ImageUnit &imageUnit = context->getState().getImageUnit(index);
+ const Texture *texture = imageUnit.texture.get();
+ if (texture)
+ {
+ texture->onStateChange(angle::SubjectMessage::ContentsChanged);
+ }
+ }
+}
+
+// Return true if the draw is a no-op, else return false.
+// If there is no active program for the vertex or fragment shader stages, the results of vertex
+// and fragment shader execution will respectively be undefined. However, this is not
+// an error. ANGLE will treat this as a no-op.
+// A no-op draw occurs if the count of vertices is less than the minimum required to
+// have a valid primitive for this mode (0 for points, 0-1 for lines, 0-2 for tris).
+ANGLE_INLINE bool Context::noopDraw(PrimitiveMode mode, GLsizei count) const
+{
+ if (!mStateCache.getCanDraw())
+ {
+ return true;
+ }
+
+ return count < kMinimumPrimitiveCounts[mode];
+}
+
+ANGLE_INLINE angle::Result Context::syncDirtyBits(Command command)
+{
+ const State::DirtyBits &dirtyBits = mState.getDirtyBits();
+ ANGLE_TRY(mImplementation->syncState(this, dirtyBits, mAllDirtyBits, command));
+ mState.clearDirtyBits();
+ return angle::Result::Continue;
+}
+
+ANGLE_INLINE angle::Result Context::syncDirtyBits(const State::DirtyBits &bitMask, Command command)
+{
+ const State::DirtyBits &dirtyBits = (mState.getDirtyBits() & bitMask);
+ ANGLE_TRY(mImplementation->syncState(this, dirtyBits, bitMask, command));
+ mState.clearDirtyBits(dirtyBits);
+ return angle::Result::Continue;
+}
+
+ANGLE_INLINE angle::Result Context::syncDirtyObjects(const State::DirtyObjects &objectMask,
+ Command command)
+{
+ return mState.syncDirtyObjects(this, objectMask, command);
+}
+
+ANGLE_INLINE angle::Result Context::prepareForDraw(PrimitiveMode mode)
+{
+ if (mGLES1Renderer)
+ {
+ ANGLE_TRY(mGLES1Renderer->prepareForDraw(mode, this, &mState));
+ }
+
+ ANGLE_TRY(syncDirtyObjects(mDrawDirtyObjects, Command::Draw));
+ ASSERT(!isRobustResourceInitEnabled() ||
+ !mState.getDrawFramebuffer()->hasResourceThatNeedsInit());
+ return syncDirtyBits(Command::Draw);
+}
+
+ANGLE_INLINE void Context::drawArrays(PrimitiveMode mode, GLint first, GLsizei count)
+{
+ // No-op if count draws no primitives for given mode
+ if (noopDraw(mode, count))
+ {
+ ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(mImplementation->drawArrays(this, mode, first, count));
+ MarkTransformFeedbackBufferUsage(this, count, 1);
+}
+
+ANGLE_INLINE void Context::drawElements(PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices)
+{
+ // No-op if count draws no primitives for given mode
+ if (noopDraw(mode, count))
+ {
+ ANGLE_CONTEXT_TRY(mImplementation->handleNoopDrawEvent());
+ return;
+ }
+
+ ANGLE_CONTEXT_TRY(prepareForDraw(mode));
+ ANGLE_CONTEXT_TRY(mImplementation->drawElements(this, mode, count, type, indices));
+}
+
+ANGLE_INLINE void StateCache::onBufferBindingChange(Context *context)
+{
+ updateBasicDrawStatesError();
+ updateBasicDrawElementsError();
+}
+
+ANGLE_INLINE void Context::bindBuffer(BufferBinding target, BufferID buffer)
+{
+ Buffer *bufferObject =
+ mState.mBufferManager->checkBufferAllocation(mImplementation.get(), buffer);
+
+ // Early return if rebinding the same buffer
+ if (bufferObject == mState.getTargetBuffer(target))
+ {
+ return;
+ }
+
+ mState.setBufferBinding(this, target, bufferObject);
+ mStateCache.onBufferBindingChange(this);
+}
+
+} // namespace gl
+
+#endif // LIBANGLE_CONTEXT_INL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Context_gl.cpp b/gfx/angle/checkout/src/libANGLE/Context_gl.cpp
new file mode 100644
index 0000000000..28f3685a20
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Context_gl.cpp
@@ -0,0 +1,3706 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context_gl.cpp: Implements the GL specific parts of Context.
+
+#include "Context.h"
+#include "common/debug.h"
+
+namespace gl
+{
+
+void Context::compressedTexImage1D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLint border,
+ GLsizei imageSize,
+ const void *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::compressedTexSubImage1D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::loadTransposeMatrixd(const GLdouble *m)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::loadTransposeMatrixf(const GLfloat *m)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multTransposeMatrixd(const GLdouble *m)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multTransposeMatrixf(const GLfloat *m)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord1d(GLenum target, GLdouble s)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord1dv(GLenum target, const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord1f(GLenum target, GLfloat s)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord1fv(GLenum target, const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord1i(GLenum target, GLint s)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord1iv(GLenum target, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord1s(GLenum target, GLshort s)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord1sv(GLenum target, const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord2d(GLenum target, GLdouble s, GLdouble t)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord2dv(GLenum target, const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord2f(GLenum target, GLfloat s, GLfloat t)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord2fv(GLenum target, const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord2i(GLenum target, GLint s, GLint t)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord2iv(GLenum target, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord2s(GLenum target, GLshort s, GLshort t)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord2sv(GLenum target, const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord3d(GLenum target, GLdouble s, GLdouble t, GLdouble r)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord3dv(GLenum target, const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord3f(GLenum target, GLfloat s, GLfloat t, GLfloat r)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord3fv(GLenum target, const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord3i(GLenum target, GLint s, GLint t, GLint r)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord3iv(GLenum target, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord3s(GLenum target, GLshort s, GLshort t, GLshort r)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord3sv(GLenum target, const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord4d(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord4dv(GLenum target, const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord4fv(GLenum target, const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord4i(GLenum target, GLint s, GLint t, GLint r, GLint q)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord4iv(GLenum target, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord4s(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoord4sv(GLenum target, const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getVertexAttribdv(GLuint index, GLenum pname, GLdouble *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib1d(GLuint index, GLdouble x)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib1dv(GLuint index, const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib1s(GLuint index, GLshort x)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib1sv(GLuint index, const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib2d(GLuint index, GLdouble x, GLdouble y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib2dv(GLuint index, const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib2s(GLuint index, GLshort x, GLshort y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib2sv(GLuint index, const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib3d(GLuint index, GLdouble x, GLdouble y, GLdouble z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib3dv(GLuint index, const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib3s(GLuint index, GLshort x, GLshort y, GLshort z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib3sv(GLuint index, const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4Nbv(GLuint index, const GLbyte *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4Niv(GLuint index, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4Nsv(GLuint index, const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4Nub(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4Nubv(GLuint index, const GLubyte *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4Nuiv(GLuint index, const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4Nusv(GLuint index, const GLushort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4bv(GLuint index, const GLbyte *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4dv(GLuint index, const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4iv(GLuint index, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4s(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4sv(GLuint index, const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4ubv(GLuint index, const GLubyte *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4uiv(GLuint index, const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttrib4usv(GLuint index, const GLushort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::beginConditionalRender(GLuint id, GLenum mode)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::clampColor(GLenum target, GLenum clamp)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::endConditionalRender()
+{
+ UNIMPLEMENTED();
+}
+
+void Context::framebufferTexture1D(GLenum target,
+ GLenum attachment,
+ TextureTarget textarget,
+ TextureID texture,
+ GLint level)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI1i(GLuint index, GLint x)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI1iv(GLuint index, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI1ui(GLuint index, GLuint x)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI1uiv(GLuint index, const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI2i(GLuint index, GLint x, GLint y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI2iv(GLuint index, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI2ui(GLuint index, GLuint x, GLuint y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI2uiv(GLuint index, const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI3i(GLuint index, GLint x, GLint y, GLint z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI3iv(GLuint index, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI3ui(GLuint index, GLuint x, GLuint y, GLuint z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI3uiv(GLuint index, const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI4bv(GLuint index, const GLbyte *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI4sv(GLuint index, const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI4ubv(GLuint index, const GLubyte *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribI4usv(GLuint index, const GLushort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getActiveUniformName(ShaderProgramID program,
+ GLuint uniformIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformName)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::primitiveRestartIndex(GLuint index)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::fogCoordPointer(GLenum type, GLsizei stride, const void *pointer)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::fogCoordd(GLdouble coord)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::fogCoorddv(const GLdouble *coord)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::fogCoordf(GLfloat coord)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::fogCoordfv(const GLfloat *coord)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::pointParameteri(GLenum pname, GLint param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::pointParameteriv(GLenum pname, const GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3b(GLbyte red, GLbyte green, GLbyte blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3bv(const GLbyte *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3d(GLdouble red, GLdouble green, GLdouble blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3f(GLfloat red, GLfloat green, GLfloat blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3i(GLint red, GLint green, GLint blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3s(GLshort red, GLshort green, GLshort blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3ub(GLubyte red, GLubyte green, GLubyte blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3ubv(const GLubyte *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3ui(GLuint red, GLuint green, GLuint blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3uiv(const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3us(GLushort red, GLushort green, GLushort blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColor3usv(const GLushort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos2d(GLdouble x, GLdouble y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos2dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos2f(GLfloat x, GLfloat y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos2fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos2i(GLint x, GLint y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos2iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos2s(GLshort x, GLshort y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos2sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos3d(GLdouble x, GLdouble y, GLdouble z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos3dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos3fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos3i(GLint x, GLint y, GLint z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos3iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos3s(GLshort x, GLshort y, GLshort z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::windowPos3sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, void *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::accum(GLenum op, GLfloat value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::begin(GLenum mode)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::bitmap(GLsizei width,
+ GLsizei height,
+ GLfloat xorig,
+ GLfloat yorig,
+ GLfloat xmove,
+ GLfloat ymove,
+ const GLubyte *bitmap)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::callList(GLuint list)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::callLists(GLsizei n, GLenum type, const void *lists)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::clearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::clearDepth(GLdouble depth)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::clearIndex(GLfloat c)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::clipPlane(GLenum plane, const GLdouble *equation)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3b(GLbyte red, GLbyte green, GLbyte blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3bv(const GLbyte *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3d(GLdouble red, GLdouble green, GLdouble blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3f(GLfloat red, GLfloat green, GLfloat blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3i(GLint red, GLint green, GLint blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3s(GLshort red, GLshort green, GLshort blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3ub(GLubyte red, GLubyte green, GLubyte blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3ubv(const GLubyte *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3ui(GLuint red, GLuint green, GLuint blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3uiv(const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3us(GLushort red, GLushort green, GLushort blue)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color3usv(const GLushort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color4b(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color4bv(const GLbyte *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color4d(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color4dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color4fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color4i(GLint red, GLint green, GLint blue, GLint alpha)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color4iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color4s(GLshort red, GLshort green, GLshort blue, GLshort alpha)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color4sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color4ubv(const GLubyte *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color4ui(GLuint red, GLuint green, GLuint blue, GLuint alpha)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color4uiv(const GLuint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color4us(GLushort red, GLushort green, GLushort blue, GLushort alpha)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::color4usv(const GLushort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::colorMaterial(GLenum face, GLenum mode)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::copyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::deleteLists(GLuint list, GLsizei range)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::depthRange(GLdouble n, GLdouble f)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::drawBuffer(GLenum buf)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::drawPixels(GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::edgeFlag(GLboolean flag)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::edgeFlagv(const GLboolean *flag)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::end()
+{
+ UNIMPLEMENTED();
+}
+
+void Context::endList()
+{
+ UNIMPLEMENTED();
+}
+
+void Context::evalCoord1d(GLdouble u)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::evalCoord1dv(const GLdouble *u)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::evalCoord1f(GLfloat u)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::evalCoord1fv(const GLfloat *u)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::evalCoord2d(GLdouble u, GLdouble v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::evalCoord2dv(const GLdouble *u)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::evalCoord2f(GLfloat u, GLfloat v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::evalCoord2fv(const GLfloat *u)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::evalMesh1(GLenum mode, GLint i1, GLint i2)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::evalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::evalPoint1(GLint i)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::evalPoint2(GLint i, GLint j)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::feedbackBuffer(GLsizei size, GLenum type, GLfloat *buffer)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::fogi(GLenum pname, GLint param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::fogiv(GLenum pname, const GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::frustum(GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble zNear,
+ GLdouble zFar)
+{
+ UNIMPLEMENTED();
+}
+
+GLuint Context::genLists(GLsizei range)
+{
+ UNIMPLEMENTED();
+ return 0;
+}
+
+void Context::getClipPlane(GLenum plane, GLdouble *equation)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getDoublev(GLenum pname, GLdouble *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getLightiv(GLenum light, GLenum pname, GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getMapdv(GLenum target, GLenum query, GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getMapfv(GLenum target, GLenum query, GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getMapiv(GLenum target, GLenum query, GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getMaterialiv(GLenum face, GLenum pname, GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getPixelMapfv(GLenum map, GLfloat *values)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getPixelMapuiv(GLenum map, GLuint *values)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getPixelMapusv(GLenum map, GLushort *values)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getPolygonStipple(GLubyte *mask)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTexGendv(GLenum coord, GLenum pname, GLdouble *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::indexMask(GLuint mask)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::indexd(GLdouble c)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::indexdv(const GLdouble *c)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::indexf(GLfloat c)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::indexfv(const GLfloat *c)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::indexi(GLint c)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::indexiv(const GLint *c)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::indexs(GLshort c)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::indexsv(const GLshort *c)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::initNames()
+{
+ UNIMPLEMENTED();
+}
+
+GLboolean Context::isList(GLuint list) const
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+void Context::lightModeli(GLenum pname, GLint param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::lightModeliv(GLenum pname, const GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::lighti(GLenum light, GLenum pname, GLint param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::lightiv(GLenum light, GLenum pname, const GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::lineStipple(GLint factor, GLushort pattern)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::listBase(GLuint base)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::loadMatrixd(const GLdouble *m)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::loadName(GLuint name)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::map1d(GLenum target,
+ GLdouble u1,
+ GLdouble u2,
+ GLint stride,
+ GLint order,
+ const GLdouble *points)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::map1f(GLenum target,
+ GLfloat u1,
+ GLfloat u2,
+ GLint stride,
+ GLint order,
+ const GLfloat *points)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::map2d(GLenum target,
+ GLdouble u1,
+ GLdouble u2,
+ GLint ustride,
+ GLint uorder,
+ GLdouble v1,
+ GLdouble v2,
+ GLint vstride,
+ GLint vorder,
+ const GLdouble *points)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::map2f(GLenum target,
+ GLfloat u1,
+ GLfloat u2,
+ GLint ustride,
+ GLint uorder,
+ GLfloat v1,
+ GLfloat v2,
+ GLint vstride,
+ GLint vorder,
+ const GLfloat *points)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::mapGrid1d(GLint un, GLdouble u1, GLdouble u2)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::mapGrid1f(GLint un, GLfloat u1, GLfloat u2)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::mapGrid2d(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::mapGrid2f(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::materiali(GLenum face, GLenum pname, GLint param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::materialiv(GLenum face, GLenum pname, const GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multMatrixd(const GLdouble *m)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::newList(GLuint list, GLenum mode)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::normal3b(GLbyte nx, GLbyte ny, GLbyte nz)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::normal3bv(const GLbyte *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::normal3d(GLdouble nx, GLdouble ny, GLdouble nz)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::normal3dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::normal3fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::normal3i(GLint nx, GLint ny, GLint nz)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::normal3iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::normal3s(GLshort nx, GLshort ny, GLshort nz)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::normal3sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::ortho(GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble zNear,
+ GLdouble zFar)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::passThrough(GLfloat token)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::pixelMapfv(GLenum map, GLsizei mapsize, const GLfloat *values)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::pixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::pixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::pixelStoref(GLenum pname, GLfloat param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::pixelTransferf(GLenum pname, GLfloat param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::pixelTransferi(GLenum pname, GLint param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::pixelZoom(GLfloat xfactor, GLfloat yfactor)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::polygonMode(GLenum face, GLenum mode)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::polygonStipple(const GLubyte *mask)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::popAttrib()
+{
+ UNIMPLEMENTED();
+}
+
+void Context::popName()
+{
+ UNIMPLEMENTED();
+}
+
+void Context::pushAttrib(GLbitfield mask)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::pushName(GLuint name)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos2d(GLdouble x, GLdouble y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos2dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos2f(GLfloat x, GLfloat y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos2fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos2i(GLint x, GLint y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos2iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos2s(GLshort x, GLshort y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos2sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos3d(GLdouble x, GLdouble y, GLdouble z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos3dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos3fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos3i(GLint x, GLint y, GLint z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos3iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos3s(GLshort x, GLshort y, GLshort z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos3sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos4dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos4fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos4i(GLint x, GLint y, GLint z, GLint w)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos4iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rasterPos4sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rectdv(const GLdouble *v1, const GLdouble *v2)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rectfv(const GLfloat *v1, const GLfloat *v2)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::recti(GLint x1, GLint y1, GLint x2, GLint y2)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rectiv(const GLint *v1, const GLint *v2)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::rectsv(const GLshort *v1, const GLshort *v2)
+{
+ UNIMPLEMENTED();
+}
+
+GLint Context::renderMode(GLenum mode)
+{
+ UNIMPLEMENTED();
+ return 0;
+}
+
+void Context::rotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::scaled(GLdouble x, GLdouble y, GLdouble z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::selectBuffer(GLsizei size, GLuint *buffer)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord1d(GLdouble s)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord1dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord1f(GLfloat s)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord1fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord1i(GLint s)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord1iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord1s(GLshort s)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord1sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord2d(GLdouble s, GLdouble t)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord2dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord2f(GLfloat s, GLfloat t)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord2fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord2i(GLint s, GLint t)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord2iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord2s(GLshort s, GLshort t)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord2sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord3d(GLdouble s, GLdouble t, GLdouble r)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord3dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord3f(GLfloat s, GLfloat t, GLfloat r)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord3fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord3i(GLint s, GLint t, GLint r)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord3iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord3s(GLshort s, GLshort t, GLshort r)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord3sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord4d(GLdouble s, GLdouble t, GLdouble r, GLdouble q)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord4dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord4fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord4i(GLint s, GLint t, GLint r, GLint q)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord4iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord4s(GLshort s, GLshort t, GLshort r, GLshort q)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoord4sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texGend(GLenum coord, GLenum pname, GLdouble param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texGendv(GLenum coord, GLenum pname, const GLdouble *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texImage1D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::translated(GLdouble x, GLdouble y, GLdouble z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex2d(GLdouble x, GLdouble y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex2dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex2f(GLfloat x, GLfloat y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex2fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex2i(GLint x, GLint y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex2iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex2s(GLshort x, GLshort y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex2sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex3d(GLdouble x, GLdouble y, GLdouble z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex3dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex3fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex3i(GLint x, GLint y, GLint z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex3iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex3s(GLshort x, GLshort y, GLshort z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex3sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex4dv(const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex4fv(const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex4i(GLint x, GLint y, GLint z, GLint w)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex4iv(const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex4s(GLshort x, GLshort y, GLshort z, GLshort w)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertex4sv(const GLshort *v)
+{
+ UNIMPLEMENTED();
+}
+
+GLboolean Context::areTexturesResident(GLsizei n, const GLuint *textures, GLboolean *residences)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+void Context::arrayElement(GLint i)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::copyTexImage1D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLint border)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::copyTexSubImage1D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint x,
+ GLint y,
+ GLsizei width)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::edgeFlagPointer(GLsizei stride, const void *pointer)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::indexPointer(GLenum type, GLsizei stride, const void *pointer)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::indexub(GLubyte c)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::indexubv(const GLubyte *c)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::interleavedArrays(GLenum format, GLsizei stride, const void *pointer)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::popClientAttrib()
+{
+ UNIMPLEMENTED();
+}
+
+void Context::prioritizeTextures(GLsizei n, const GLuint *textures, const GLfloat *priorities)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::pushClientAttrib(GLbitfield mask)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texSubImage1D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiDrawElementsBaseVertex(PrimitiveMode mode,
+ const GLsizei *count,
+ DrawElementsType type,
+ const void *const *indices,
+ GLsizei drawcount,
+ const GLint *basevertex)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texImage2DMultisample(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texImage3DMultisample(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedsamplelocations)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::colorP3ui(GLenum type, GLuint color)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::colorP3uiv(GLenum type, const GLuint *color)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::colorP4ui(GLenum type, GLuint color)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::colorP4uiv(GLenum type, const GLuint *color)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoordP1ui(GLenum texture, GLenum type, GLuint coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoordP1uiv(GLenum texture, GLenum type, const GLuint *coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoordP2ui(GLenum texture, GLenum type, GLuint coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoordP2uiv(GLenum texture, GLenum type, const GLuint *coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoordP3ui(GLenum texture, GLenum type, GLuint coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoordP3uiv(GLenum texture, GLenum type, const GLuint *coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoordP4ui(GLenum texture, GLenum type, GLuint coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiTexCoordP4uiv(GLenum texture, GLenum type, const GLuint *coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::normalP3ui(GLenum type, GLuint coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::normalP3uiv(GLenum type, const GLuint *coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColorP3ui(GLenum type, GLuint color)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::secondaryColorP3uiv(GLenum type, const GLuint *color)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoordP1ui(GLenum type, GLuint coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoordP1uiv(GLenum type, const GLuint *coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoordP2ui(GLenum type, GLuint coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoordP2uiv(GLenum type, const GLuint *coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoordP3ui(GLenum type, GLuint coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoordP3uiv(GLenum type, const GLuint *coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoordP4ui(GLenum type, GLuint coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texCoordP4uiv(GLenum type, const GLuint *coords)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribP1ui(GLuint index, GLenum type, GLboolean normalized, GLuint value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribP1uiv(GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribP2ui(GLuint index, GLenum type, GLboolean normalized, GLuint value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribP2uiv(GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribP3ui(GLuint index, GLenum type, GLboolean normalized, GLuint value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribP3uiv(GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribP4ui(GLuint index, GLenum type, GLboolean normalized, GLuint value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribP4uiv(GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexP2ui(GLenum type, GLuint value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexP2uiv(GLenum type, const GLuint *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexP3ui(GLenum type, GLuint value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexP3uiv(GLenum type, const GLuint *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexP4ui(GLenum type, GLuint value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexP4uiv(GLenum type, const GLuint *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::beginQueryIndexed(GLenum target, GLuint index, QueryID id)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::drawTransformFeedback(GLenum mode, TransformFeedbackID id)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::drawTransformFeedbackStream(GLenum mode, TransformFeedbackID id, GLuint stream)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::endQueryIndexed(GLenum target, GLuint index)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getActiveSubroutineName(ShaderProgramID program,
+ GLenum shadertype,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *name)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getActiveSubroutineUniformName(ShaderProgramID program,
+ GLenum shadertype,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLchar *name)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getActiveSubroutineUniformiv(ShaderProgramID program,
+ GLenum shadertype,
+ GLuint index,
+ GLenum pname,
+ GLint *values)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getProgramStageiv(ShaderProgramID program,
+ GLenum shadertype,
+ GLenum pname,
+ GLint *values)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getQueryIndexediv(GLenum target, GLuint index, GLenum pname, GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+GLuint Context::getSubroutineIndex(ShaderProgramID program, GLenum shadertype, const GLchar *name)
+{
+ UNIMPLEMENTED();
+ return 0;
+}
+
+GLint Context::getSubroutineUniformLocation(ShaderProgramID program,
+ GLenum shadertype,
+ const GLchar *name)
+{
+ UNIMPLEMENTED();
+ return 0;
+}
+
+void Context::getUniformSubroutineuiv(GLenum shadertype, GLint location, GLuint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getUniformdv(ShaderProgramID program, UniformLocation location, GLdouble *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::patchParameterfv(GLenum pname, const GLfloat *values)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniform1d(UniformLocation location, GLdouble x)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniform1dv(UniformLocation location, GLsizei count, const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniform2d(UniformLocation location, GLdouble x, GLdouble y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniform2dv(UniformLocation location, GLsizei count, const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniform3d(UniformLocation location, GLdouble x, GLdouble y, GLdouble z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniform3dv(UniformLocation location, GLsizei count, const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniform4d(UniformLocation location, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniform4dv(UniformLocation location, GLsizei count, const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniformMatrix2dv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniformMatrix2x3dv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniformMatrix2x4dv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniformMatrix3dv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniformMatrix3x2dv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniformMatrix3x4dv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniformMatrix4dv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniformMatrix4x2dv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniformMatrix4x3dv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::uniformSubroutinesuiv(GLenum shadertype, GLsizei count, const GLuint *indices)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::depthRangeArrayv(GLuint first, GLsizei count, const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::depthRangeIndexed(GLuint index, GLdouble n, GLdouble f)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getDoublei_v(GLenum target, GLuint index, GLdouble *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getFloati_v(GLenum target, GLuint index, GLfloat *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getVertexAttribLdv(GLuint index, GLenum pname, GLdouble *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniform1d(ShaderProgramID program, UniformLocation location, GLdouble v0)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniform1dv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniform2d(ShaderProgramID program,
+ UniformLocation location,
+ GLdouble v0,
+ GLdouble v1)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniform2dv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniform3d(ShaderProgramID program,
+ UniformLocation location,
+ GLdouble v0,
+ GLdouble v1,
+ GLdouble v2)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniform3dv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniform4d(ShaderProgramID program,
+ UniformLocation location,
+ GLdouble v0,
+ GLdouble v1,
+ GLdouble v2,
+ GLdouble v3)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniform4dv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniformMatrix2dv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniformMatrix2x3dv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniformMatrix2x4dv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniformMatrix3dv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniformMatrix3x2dv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniformMatrix3x4dv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniformMatrix4dv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniformMatrix4x2dv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::programUniformMatrix4x3dv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::scissorArrayv(GLuint first, GLsizei count, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::scissorIndexed(GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::scissorIndexedv(GLuint index, const GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribL1d(GLuint index, GLdouble x)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribL1dv(GLuint index, const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribL2d(GLuint index, GLdouble x, GLdouble y)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribL2dv(GLuint index, const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribL3d(GLuint index, GLdouble x, GLdouble y, GLdouble z)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribL3dv(GLuint index, const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribL4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribL4dv(GLuint index, const GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribLPointer(GLuint index,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::viewportArrayv(GLuint first, GLsizei count, const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::viewportIndexedf(GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::viewportIndexedfv(GLuint index, const GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::drawTransformFeedbackInstanced(GLenum mode,
+ TransformFeedbackID id,
+ GLsizei instancecount)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::drawTransformFeedbackStreamInstanced(GLenum mode,
+ TransformFeedbackID id,
+ GLuint stream,
+ GLsizei instancecount)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getActiveAtomicCounterBufferiv(ShaderProgramID program,
+ GLuint bufferIndex,
+ GLenum pname,
+ GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::clearBufferData(GLenum target,
+ GLenum internalformat,
+ GLenum format,
+ GLenum type,
+ const void *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::clearBufferSubData(GLenum target,
+ GLenum internalformat,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLenum format,
+ GLenum type,
+ const void *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getInternalformati64v(GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLint64 *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::invalidateBufferData(BufferID buffer)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::invalidateBufferSubData(BufferID buffer, GLintptr offset, GLsizeiptr length)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::invalidateTexImage(TextureID texture, GLint level)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::invalidateTexSubImage(TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::shaderStorageBlockBinding(ShaderProgramID program,
+ GLuint storageBlockIndex,
+ GLuint storageBlockBinding)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureView(TextureID texture,
+ GLenum target,
+ GLuint origtexture,
+ GLenum internalformat,
+ GLuint minlevel,
+ GLuint numlevels,
+ GLuint minlayer,
+ GLuint numlayers)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexAttribLFormat(GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::bindBuffersBase(GLenum target, GLuint first, GLsizei count, const BufferID *buffers)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::bindBuffersRange(GLenum target,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffers,
+ const GLintptr *offsets,
+ const GLsizeiptr *sizes)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::bindImageTextures(GLuint first, GLsizei count, const GLuint *textures)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::bindSamplers(GLuint first, GLsizei count, const GLuint *samplers)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::bindTextures(GLuint first, GLsizei count, const GLuint *textures)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::bindVertexBuffers(GLuint first,
+ GLsizei count,
+ const BufferID *buffers,
+ const GLintptr *offsets,
+ const GLsizei *strides)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::clearTexImage(TextureID texture,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ const void *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::clearTexSubImage(TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::bindTextureUnit(GLuint unit, TextureID texture)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::blitNamedFramebuffer(GLuint readFramebuffer,
+ GLuint drawFramebuffer,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter)
+{
+ UNIMPLEMENTED();
+}
+
+GLenum Context::checkNamedFramebufferStatus(FramebufferID framebuffer, GLenum target)
+{
+ UNIMPLEMENTED();
+ return 0;
+}
+
+void Context::clearNamedBufferData(BufferID buffer,
+ GLenum internalformat,
+ GLenum format,
+ GLenum type,
+ const void *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::clearNamedBufferSubData(BufferID buffer,
+ GLenum internalformat,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLenum format,
+ GLenum type,
+ const void *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::clearNamedFramebufferfi(FramebufferID framebuffer,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::clearNamedFramebufferfv(FramebufferID framebuffer,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::clearNamedFramebufferiv(FramebufferID framebuffer,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::clearNamedFramebufferuiv(FramebufferID framebuffer,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *value)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::compressedTextureSubImage1D(TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::compressedTextureSubImage2D(TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::compressedTextureSubImage3D(TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::copyNamedBufferSubData(GLuint readBuffer,
+ GLuint writeBuffer,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::copyTextureSubImage1D(TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint x,
+ GLint y,
+ GLsizei width)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::copyTextureSubImage2D(TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::copyTextureSubImage3D(TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::createBuffers(GLsizei n, BufferID *buffers)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::createFramebuffers(GLsizei n, GLuint *framebuffers)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::createProgramPipelines(GLsizei n, GLuint *pipelines)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::createQueries(GLenum target, GLsizei n, GLuint *ids)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::createRenderbuffers(GLsizei n, RenderbufferID *renderbuffers)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::createSamplers(GLsizei n, GLuint *samplers)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::createTextures(GLenum target, GLsizei n, GLuint *textures)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::createTransformFeedbacks(GLsizei n, GLuint *ids)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::createVertexArrays(GLsizei n, VertexArrayID *arrays)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::disableVertexArrayAttrib(VertexArrayID vaobj, GLuint index)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::enableVertexArrayAttrib(VertexArrayID vaobj, GLuint index)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::flushMappedNamedBufferRange(BufferID buffer, GLintptr offset, GLsizeiptr length)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::generateTextureMipmap(TextureID texture)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getCompressedTextureImage(TextureID texture,
+ GLint level,
+ GLsizei bufSize,
+ void *pixels)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getCompressedTextureSubImage(TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei bufSize,
+ void *pixels)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getNamedBufferParameteri64v(BufferID buffer, GLenum pname, GLint64 *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getNamedBufferParameteriv(BufferID buffer, GLenum pname, GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getNamedBufferPointerv(BufferID buffer, GLenum pname, void **params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getNamedBufferSubData(BufferID buffer, GLintptr offset, GLsizeiptr size, void *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getNamedFramebufferAttachmentParameteriv(FramebufferID framebuffer,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getNamedFramebufferParameteriv(FramebufferID framebuffer, GLenum pname, GLint *param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getNamedRenderbufferParameteriv(RenderbufferID renderbuffer,
+ GLenum pname,
+ GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getQueryBufferObjecti64v(GLuint id, BufferID buffer, GLenum pname, GLintptr offset)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getQueryBufferObjectiv(GLuint id, BufferID buffer, GLenum pname, GLintptr offset)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getQueryBufferObjectui64v(GLuint id, BufferID buffer, GLenum pname, GLintptr offset)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getQueryBufferObjectuiv(GLuint id, BufferID buffer, GLenum pname, GLintptr offset)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTextureImage(TextureID texture,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *pixels)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTextureLevelParameterfv(TextureID texture,
+ GLint level,
+ GLenum pname,
+ GLfloat *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTextureLevelParameteriv(TextureID texture,
+ GLint level,
+ GLenum pname,
+ GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTextureParameterIiv(TextureID texture, GLenum pname, GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTextureParameterIuiv(TextureID texture, GLenum pname, GLuint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTextureParameterfv(TextureID texture, GLenum pname, GLfloat *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTextureParameteriv(TextureID texture, GLenum pname, GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTextureSubImage(TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *pixels)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTransformFeedbacki64_v(GLuint xfb, GLenum pname, GLuint index, GLint64 *param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTransformFeedbacki_v(GLuint xfb, GLenum pname, GLuint index, GLint *param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTransformFeedbackiv(GLuint xfb, GLenum pname, GLint *param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getVertexArrayIndexed64iv(VertexArrayID vaobj,
+ GLuint index,
+ GLenum pname,
+ GLint64 *param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getVertexArrayIndexediv(VertexArrayID vaobj, GLuint index, GLenum pname, GLint *param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getVertexArrayiv(VertexArrayID vaobj, GLenum pname, GLint *param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnColorTable(GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *table)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnCompressedTexImage(GLenum target, GLint lod, GLsizei bufSize, void *pixels)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnConvolutionFilter(GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *image)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnHistogram(GLenum target,
+ GLboolean reset,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *values)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnMapdv(GLenum target, GLenum query, GLsizei bufSize, GLdouble *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnMapfv(GLenum target, GLenum query, GLsizei bufSize, GLfloat *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnMapiv(GLenum target, GLenum query, GLsizei bufSize, GLint *v)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnMinmax(GLenum target,
+ GLboolean reset,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *values)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnPixelMapfv(GLenum map, GLsizei bufSize, GLfloat *values)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnPixelMapuiv(GLenum map, GLsizei bufSize, GLuint *values)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnPixelMapusv(GLenum map, GLsizei bufSize, GLushort *values)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnPolygonStipple(GLsizei bufSize, GLubyte *pattern)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnSeparableFilter(GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei rowBufSize,
+ void *row,
+ GLsizei columnBufSize,
+ void *column,
+ void *span)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnTexImage(GLenum target,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *pixels)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getnUniformdv(ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ GLdouble *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::invalidateNamedFramebufferData(FramebufferID framebuffer,
+ GLsizei numAttachments,
+ const GLenum *attachments)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::invalidateNamedFramebufferSubData(FramebufferID framebuffer,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ UNIMPLEMENTED();
+}
+
+void *Context::mapNamedBuffer(BufferID buffer, GLenum access)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+void *Context::mapNamedBufferRange(BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+void Context::namedBufferData(BufferID buffer, GLsizeiptr size, const void *data, GLenum usage)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::namedBufferStorage(BufferID buffer,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::namedBufferSubData(BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::namedFramebufferDrawBuffer(FramebufferID framebuffer, GLenum buf)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::namedFramebufferDrawBuffers(FramebufferID framebuffer, GLsizei n, const GLenum *bufs)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::namedFramebufferParameteri(FramebufferID framebuffer, GLenum pname, GLint param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::namedFramebufferReadBuffer(FramebufferID framebuffer, GLenum src)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::namedFramebufferRenderbuffer(FramebufferID framebuffer,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ RenderbufferID renderbuffer)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::namedFramebufferTexture(FramebufferID framebuffer,
+ GLenum attachment,
+ TextureID texture,
+ GLint level)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::namedFramebufferTextureLayer(FramebufferID framebuffer,
+ GLenum attachment,
+ TextureID texture,
+ GLint level,
+ GLint layer)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::namedRenderbufferStorage(RenderbufferID renderbuffer,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::namedRenderbufferStorageMultisample(RenderbufferID renderbuffer,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureBarrier()
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureBuffer(TextureID texture, GLenum internalformat, BufferID buffer)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureBufferRange(TextureID texture,
+ GLenum internalformat,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureParameterIiv(TextureID texture, GLenum pname, const GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureParameterIuiv(TextureID texture, GLenum pname, const GLuint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureParameterf(TextureID texture, GLenum pname, GLfloat param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureParameterfv(TextureID texture, GLenum pname, const GLfloat *param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureParameteri(TextureID texture, GLenum pname, GLint param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureParameteriv(TextureID texture, GLenum pname, const GLint *param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureStorage1D(TextureID texture,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureStorage2D(TextureID texture,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureStorage2DMultisample(TextureID texture,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureStorage3D(TextureID texture,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureStorage3DMultisample(TextureID texture,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedsamplelocations)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureSubImage1D(TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureSubImage2D(TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::textureSubImage3D(TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::transformFeedbackBufferBase(GLuint xfb, GLuint index, BufferID buffer)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::transformFeedbackBufferRange(GLuint xfb,
+ GLuint index,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ UNIMPLEMENTED();
+}
+
+GLboolean Context::unmapNamedBuffer(BufferID buffer)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+void Context::vertexArrayAttribBinding(VertexArrayID vaobj, GLuint attribindex, GLuint bindingindex)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexArrayAttribFormat(VertexArrayID vaobj,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLuint relativeoffset)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexArrayAttribIFormat(VertexArrayID vaobj,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexArrayAttribLFormat(VertexArrayID vaobj,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexArrayBindingDivisor(VertexArrayID vaobj, GLuint bindingindex, GLuint divisor)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexArrayElementBuffer(VertexArrayID vaobj, BufferID buffer)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexArrayVertexBuffer(VertexArrayID vaobj,
+ GLuint bindingindex,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizei stride)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::vertexArrayVertexBuffers(VertexArrayID vaobj,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffers,
+ const GLintptr *offsets,
+ const GLsizei *strides)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiDrawArraysIndirectCount(GLenum mode,
+ const void *indirect,
+ GLintptr drawcount,
+ GLsizei maxdrawcount,
+ GLsizei stride)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::multiDrawElementsIndirectCount(GLenum mode,
+ GLenum type,
+ const void *indirect,
+ GLintptr drawcount,
+ GLsizei maxdrawcount,
+ GLsizei stride)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::polygonOffsetClamp(GLfloat factor, GLfloat units, GLfloat clamp)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::specializeShader(GLuint shader,
+ const GLchar *pEntryPoint,
+ GLuint numSpecializationConstants,
+ const GLuint *pConstantIndex,
+ const GLuint *pConstantValue)
+{
+ UNIMPLEMENTED();
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Context_gl_1_autogen.h b/gfx/angle/checkout/src/libANGLE/Context_gl_1_autogen.h
new file mode 100644
index 0000000000..7bddff4c34
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Context_gl_1_autogen.h
@@ -0,0 +1,349 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context_gl_1_autogen.h: Creates a macro for interfaces in Context.
+
+#ifndef ANGLE_CONTEXT_GL_1_AUTOGEN_H_
+#define ANGLE_CONTEXT_GL_1_AUTOGEN_H_
+
+#define ANGLE_GL_1_CONTEXT_API \
+ void accum(GLenum op, GLfloat value); \
+ void begin(GLenum mode); \
+ void bitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, \
+ GLfloat ymove, const GLubyte *bitmap); \
+ void callList(GLuint list); \
+ void callLists(GLsizei n, GLenum type, const void *lists); \
+ void clearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); \
+ void clearDepth(GLdouble depth); \
+ void clearIndex(GLfloat c); \
+ void clipPlane(GLenum plane, const GLdouble *equation); \
+ void color3b(GLbyte red, GLbyte green, GLbyte blue); \
+ void color3bv(const GLbyte *v); \
+ void color3d(GLdouble red, GLdouble green, GLdouble blue); \
+ void color3dv(const GLdouble *v); \
+ void color3f(GLfloat red, GLfloat green, GLfloat blue); \
+ void color3fv(const GLfloat *v); \
+ void color3i(GLint red, GLint green, GLint blue); \
+ void color3iv(const GLint *v); \
+ void color3s(GLshort red, GLshort green, GLshort blue); \
+ void color3sv(const GLshort *v); \
+ void color3ub(GLubyte red, GLubyte green, GLubyte blue); \
+ void color3ubv(const GLubyte *v); \
+ void color3ui(GLuint red, GLuint green, GLuint blue); \
+ void color3uiv(const GLuint *v); \
+ void color3us(GLushort red, GLushort green, GLushort blue); \
+ void color3usv(const GLushort *v); \
+ void color4b(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); \
+ void color4bv(const GLbyte *v); \
+ void color4d(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); \
+ void color4dv(const GLdouble *v); \
+ void color4fv(const GLfloat *v); \
+ void color4i(GLint red, GLint green, GLint blue, GLint alpha); \
+ void color4iv(const GLint *v); \
+ void color4s(GLshort red, GLshort green, GLshort blue, GLshort alpha); \
+ void color4sv(const GLshort *v); \
+ void color4ubv(const GLubyte *v); \
+ void color4ui(GLuint red, GLuint green, GLuint blue, GLuint alpha); \
+ void color4uiv(const GLuint *v); \
+ void color4us(GLushort red, GLushort green, GLushort blue, GLushort alpha); \
+ void color4usv(const GLushort *v); \
+ void colorMaterial(GLenum face, GLenum mode); \
+ void copyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); \
+ void deleteLists(GLuint list, GLsizei range); \
+ void depthRange(GLdouble n, GLdouble f); \
+ void drawBuffer(GLenum buf); \
+ void drawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, \
+ const void *pixels); \
+ void edgeFlag(GLboolean flag); \
+ void edgeFlagv(const GLboolean *flag); \
+ void end(); \
+ void endList(); \
+ void evalCoord1d(GLdouble u); \
+ void evalCoord1dv(const GLdouble *u); \
+ void evalCoord1f(GLfloat u); \
+ void evalCoord1fv(const GLfloat *u); \
+ void evalCoord2d(GLdouble u, GLdouble v); \
+ void evalCoord2dv(const GLdouble *u); \
+ void evalCoord2f(GLfloat u, GLfloat v); \
+ void evalCoord2fv(const GLfloat *u); \
+ void evalMesh1(GLenum mode, GLint i1, GLint i2); \
+ void evalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); \
+ void evalPoint1(GLint i); \
+ void evalPoint2(GLint i, GLint j); \
+ void feedbackBuffer(GLsizei size, GLenum type, GLfloat *buffer); \
+ void fogi(GLenum pname, GLint param); \
+ void fogiv(GLenum pname, const GLint *params); \
+ void frustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, \
+ GLdouble zFar); \
+ GLuint genLists(GLsizei range); \
+ void getClipPlane(GLenum plane, GLdouble *equation); \
+ void getDoublev(GLenum pname, GLdouble *data); \
+ void getLightiv(GLenum light, GLenum pname, GLint *params); \
+ void getMapdv(GLenum target, GLenum query, GLdouble *v); \
+ void getMapfv(GLenum target, GLenum query, GLfloat *v); \
+ void getMapiv(GLenum target, GLenum query, GLint *v); \
+ void getMaterialiv(GLenum face, GLenum pname, GLint *params); \
+ void getPixelMapfv(GLenum map, GLfloat *values); \
+ void getPixelMapuiv(GLenum map, GLuint *values); \
+ void getPixelMapusv(GLenum map, GLushort *values); \
+ void getPolygonStipple(GLubyte *mask); \
+ void getTexGendv(GLenum coord, GLenum pname, GLdouble *params); \
+ void indexMask(GLuint mask); \
+ void indexd(GLdouble c); \
+ void indexdv(const GLdouble *c); \
+ void indexf(GLfloat c); \
+ void indexfv(const GLfloat *c); \
+ void indexi(GLint c); \
+ void indexiv(const GLint *c); \
+ void indexs(GLshort c); \
+ void indexsv(const GLshort *c); \
+ void initNames(); \
+ GLboolean isList(GLuint list) const; \
+ void lightModeli(GLenum pname, GLint param); \
+ void lightModeliv(GLenum pname, const GLint *params); \
+ void lighti(GLenum light, GLenum pname, GLint param); \
+ void lightiv(GLenum light, GLenum pname, const GLint *params); \
+ void lineStipple(GLint factor, GLushort pattern); \
+ void listBase(GLuint base); \
+ void loadMatrixd(const GLdouble *m); \
+ void loadName(GLuint name); \
+ void map1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, \
+ const GLdouble *points); \
+ void map1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, \
+ const GLfloat *points); \
+ void map2d(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, \
+ GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points); \
+ void map2f(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, \
+ GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points); \
+ void mapGrid1d(GLint un, GLdouble u1, GLdouble u2); \
+ void mapGrid1f(GLint un, GLfloat u1, GLfloat u2); \
+ void mapGrid2d(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); \
+ void mapGrid2f(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); \
+ void materiali(GLenum face, GLenum pname, GLint param); \
+ void materialiv(GLenum face, GLenum pname, const GLint *params); \
+ void multMatrixd(const GLdouble *m); \
+ void newList(GLuint list, GLenum mode); \
+ void normal3b(GLbyte nx, GLbyte ny, GLbyte nz); \
+ void normal3bv(const GLbyte *v); \
+ void normal3d(GLdouble nx, GLdouble ny, GLdouble nz); \
+ void normal3dv(const GLdouble *v); \
+ void normal3fv(const GLfloat *v); \
+ void normal3i(GLint nx, GLint ny, GLint nz); \
+ void normal3iv(const GLint *v); \
+ void normal3s(GLshort nx, GLshort ny, GLshort nz); \
+ void normal3sv(const GLshort *v); \
+ void ortho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, \
+ GLdouble zFar); \
+ void passThrough(GLfloat token); \
+ void pixelMapfv(GLenum map, GLsizei mapsize, const GLfloat *values); \
+ void pixelMapuiv(GLenum map, GLsizei mapsize, const GLuint *values); \
+ void pixelMapusv(GLenum map, GLsizei mapsize, const GLushort *values); \
+ void pixelStoref(GLenum pname, GLfloat param); \
+ void pixelTransferf(GLenum pname, GLfloat param); \
+ void pixelTransferi(GLenum pname, GLint param); \
+ void pixelZoom(GLfloat xfactor, GLfloat yfactor); \
+ void polygonMode(GLenum face, GLenum mode); \
+ void polygonStipple(const GLubyte *mask); \
+ void popAttrib(); \
+ void popName(); \
+ void pushAttrib(GLbitfield mask); \
+ void pushName(GLuint name); \
+ void rasterPos2d(GLdouble x, GLdouble y); \
+ void rasterPos2dv(const GLdouble *v); \
+ void rasterPos2f(GLfloat x, GLfloat y); \
+ void rasterPos2fv(const GLfloat *v); \
+ void rasterPos2i(GLint x, GLint y); \
+ void rasterPos2iv(const GLint *v); \
+ void rasterPos2s(GLshort x, GLshort y); \
+ void rasterPos2sv(const GLshort *v); \
+ void rasterPos3d(GLdouble x, GLdouble y, GLdouble z); \
+ void rasterPos3dv(const GLdouble *v); \
+ void rasterPos3f(GLfloat x, GLfloat y, GLfloat z); \
+ void rasterPos3fv(const GLfloat *v); \
+ void rasterPos3i(GLint x, GLint y, GLint z); \
+ void rasterPos3iv(const GLint *v); \
+ void rasterPos3s(GLshort x, GLshort y, GLshort z); \
+ void rasterPos3sv(const GLshort *v); \
+ void rasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w); \
+ void rasterPos4dv(const GLdouble *v); \
+ void rasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w); \
+ void rasterPos4fv(const GLfloat *v); \
+ void rasterPos4i(GLint x, GLint y, GLint z, GLint w); \
+ void rasterPos4iv(const GLint *v); \
+ void rasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w); \
+ void rasterPos4sv(const GLshort *v); \
+ void rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); \
+ void rectdv(const GLdouble *v1, const GLdouble *v2); \
+ void rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); \
+ void rectfv(const GLfloat *v1, const GLfloat *v2); \
+ void recti(GLint x1, GLint y1, GLint x2, GLint y2); \
+ void rectiv(const GLint *v1, const GLint *v2); \
+ void rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2); \
+ void rectsv(const GLshort *v1, const GLshort *v2); \
+ GLint renderMode(GLenum mode); \
+ void rotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); \
+ void scaled(GLdouble x, GLdouble y, GLdouble z); \
+ void selectBuffer(GLsizei size, GLuint *buffer); \
+ void texCoord1d(GLdouble s); \
+ void texCoord1dv(const GLdouble *v); \
+ void texCoord1f(GLfloat s); \
+ void texCoord1fv(const GLfloat *v); \
+ void texCoord1i(GLint s); \
+ void texCoord1iv(const GLint *v); \
+ void texCoord1s(GLshort s); \
+ void texCoord1sv(const GLshort *v); \
+ void texCoord2d(GLdouble s, GLdouble t); \
+ void texCoord2dv(const GLdouble *v); \
+ void texCoord2f(GLfloat s, GLfloat t); \
+ void texCoord2fv(const GLfloat *v); \
+ void texCoord2i(GLint s, GLint t); \
+ void texCoord2iv(const GLint *v); \
+ void texCoord2s(GLshort s, GLshort t); \
+ void texCoord2sv(const GLshort *v); \
+ void texCoord3d(GLdouble s, GLdouble t, GLdouble r); \
+ void texCoord3dv(const GLdouble *v); \
+ void texCoord3f(GLfloat s, GLfloat t, GLfloat r); \
+ void texCoord3fv(const GLfloat *v); \
+ void texCoord3i(GLint s, GLint t, GLint r); \
+ void texCoord3iv(const GLint *v); \
+ void texCoord3s(GLshort s, GLshort t, GLshort r); \
+ void texCoord3sv(const GLshort *v); \
+ void texCoord4d(GLdouble s, GLdouble t, GLdouble r, GLdouble q); \
+ void texCoord4dv(const GLdouble *v); \
+ void texCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q); \
+ void texCoord4fv(const GLfloat *v); \
+ void texCoord4i(GLint s, GLint t, GLint r, GLint q); \
+ void texCoord4iv(const GLint *v); \
+ void texCoord4s(GLshort s, GLshort t, GLshort r, GLshort q); \
+ void texCoord4sv(const GLshort *v); \
+ void texGend(GLenum coord, GLenum pname, GLdouble param); \
+ void texGendv(GLenum coord, GLenum pname, const GLdouble *params); \
+ void texImage1D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, \
+ GLenum format, GLenum type, const void *pixels); \
+ void translated(GLdouble x, GLdouble y, GLdouble z); \
+ void vertex2d(GLdouble x, GLdouble y); \
+ void vertex2dv(const GLdouble *v); \
+ void vertex2f(GLfloat x, GLfloat y); \
+ void vertex2fv(const GLfloat *v); \
+ void vertex2i(GLint x, GLint y); \
+ void vertex2iv(const GLint *v); \
+ void vertex2s(GLshort x, GLshort y); \
+ void vertex2sv(const GLshort *v); \
+ void vertex3d(GLdouble x, GLdouble y, GLdouble z); \
+ void vertex3dv(const GLdouble *v); \
+ void vertex3f(GLfloat x, GLfloat y, GLfloat z); \
+ void vertex3fv(const GLfloat *v); \
+ void vertex3i(GLint x, GLint y, GLint z); \
+ void vertex3iv(const GLint *v); \
+ void vertex3s(GLshort x, GLshort y, GLshort z); \
+ void vertex3sv(const GLshort *v); \
+ void vertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w); \
+ void vertex4dv(const GLdouble *v); \
+ void vertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w); \
+ void vertex4fv(const GLfloat *v); \
+ void vertex4i(GLint x, GLint y, GLint z, GLint w); \
+ void vertex4iv(const GLint *v); \
+ void vertex4s(GLshort x, GLshort y, GLshort z, GLshort w); \
+ void vertex4sv(const GLshort *v); \
+ GLboolean areTexturesResident(GLsizei n, const GLuint *textures, GLboolean *residences); \
+ void arrayElement(GLint i); \
+ void copyTexImage1D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, \
+ GLsizei width, GLint border); \
+ void copyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, \
+ GLsizei width); \
+ void edgeFlagPointer(GLsizei stride, const void *pointer); \
+ void indexPointer(GLenum type, GLsizei stride, const void *pointer); \
+ void indexub(GLubyte c); \
+ void indexubv(const GLubyte *c); \
+ void interleavedArrays(GLenum format, GLsizei stride, const void *pointer); \
+ void popClientAttrib(); \
+ void prioritizeTextures(GLsizei n, const GLuint *textures, const GLfloat *priorities); \
+ void pushClientAttrib(GLbitfield mask); \
+ void texSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, \
+ GLenum type, const void *pixels); \
+ void compressedTexImage1D(GLenum target, GLint level, GLenum internalformat, GLsizei width, \
+ GLint border, GLsizei imageSize, const void *data); \
+ void compressedTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, \
+ GLenum format, GLsizei imageSize, const void *data); \
+ void loadTransposeMatrixd(const GLdouble *m); \
+ void loadTransposeMatrixf(const GLfloat *m); \
+ void multTransposeMatrixd(const GLdouble *m); \
+ void multTransposeMatrixf(const GLfloat *m); \
+ void multiTexCoord1d(GLenum target, GLdouble s); \
+ void multiTexCoord1dv(GLenum target, const GLdouble *v); \
+ void multiTexCoord1f(GLenum target, GLfloat s); \
+ void multiTexCoord1fv(GLenum target, const GLfloat *v); \
+ void multiTexCoord1i(GLenum target, GLint s); \
+ void multiTexCoord1iv(GLenum target, const GLint *v); \
+ void multiTexCoord1s(GLenum target, GLshort s); \
+ void multiTexCoord1sv(GLenum target, const GLshort *v); \
+ void multiTexCoord2d(GLenum target, GLdouble s, GLdouble t); \
+ void multiTexCoord2dv(GLenum target, const GLdouble *v); \
+ void multiTexCoord2f(GLenum target, GLfloat s, GLfloat t); \
+ void multiTexCoord2fv(GLenum target, const GLfloat *v); \
+ void multiTexCoord2i(GLenum target, GLint s, GLint t); \
+ void multiTexCoord2iv(GLenum target, const GLint *v); \
+ void multiTexCoord2s(GLenum target, GLshort s, GLshort t); \
+ void multiTexCoord2sv(GLenum target, const GLshort *v); \
+ void multiTexCoord3d(GLenum target, GLdouble s, GLdouble t, GLdouble r); \
+ void multiTexCoord3dv(GLenum target, const GLdouble *v); \
+ void multiTexCoord3f(GLenum target, GLfloat s, GLfloat t, GLfloat r); \
+ void multiTexCoord3fv(GLenum target, const GLfloat *v); \
+ void multiTexCoord3i(GLenum target, GLint s, GLint t, GLint r); \
+ void multiTexCoord3iv(GLenum target, const GLint *v); \
+ void multiTexCoord3s(GLenum target, GLshort s, GLshort t, GLshort r); \
+ void multiTexCoord3sv(GLenum target, const GLshort *v); \
+ void multiTexCoord4d(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); \
+ void multiTexCoord4dv(GLenum target, const GLdouble *v); \
+ void multiTexCoord4fv(GLenum target, const GLfloat *v); \
+ void multiTexCoord4i(GLenum target, GLint s, GLint t, GLint r, GLint q); \
+ void multiTexCoord4iv(GLenum target, const GLint *v); \
+ void multiTexCoord4s(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); \
+ void multiTexCoord4sv(GLenum target, const GLshort *v); \
+ void fogCoordPointer(GLenum type, GLsizei stride, const void *pointer); \
+ void fogCoordd(GLdouble coord); \
+ void fogCoorddv(const GLdouble *coord); \
+ void fogCoordf(GLfloat coord); \
+ void fogCoordfv(const GLfloat *coord); \
+ void pointParameteri(GLenum pname, GLint param); \
+ void pointParameteriv(GLenum pname, const GLint *params); \
+ void secondaryColor3b(GLbyte red, GLbyte green, GLbyte blue); \
+ void secondaryColor3bv(const GLbyte *v); \
+ void secondaryColor3d(GLdouble red, GLdouble green, GLdouble blue); \
+ void secondaryColor3dv(const GLdouble *v); \
+ void secondaryColor3f(GLfloat red, GLfloat green, GLfloat blue); \
+ void secondaryColor3fv(const GLfloat *v); \
+ void secondaryColor3i(GLint red, GLint green, GLint blue); \
+ void secondaryColor3iv(const GLint *v); \
+ void secondaryColor3s(GLshort red, GLshort green, GLshort blue); \
+ void secondaryColor3sv(const GLshort *v); \
+ void secondaryColor3ub(GLubyte red, GLubyte green, GLubyte blue); \
+ void secondaryColor3ubv(const GLubyte *v); \
+ void secondaryColor3ui(GLuint red, GLuint green, GLuint blue); \
+ void secondaryColor3uiv(const GLuint *v); \
+ void secondaryColor3us(GLushort red, GLushort green, GLushort blue); \
+ void secondaryColor3usv(const GLushort *v); \
+ void secondaryColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); \
+ void windowPos2d(GLdouble x, GLdouble y); \
+ void windowPos2dv(const GLdouble *v); \
+ void windowPos2f(GLfloat x, GLfloat y); \
+ void windowPos2fv(const GLfloat *v); \
+ void windowPos2i(GLint x, GLint y); \
+ void windowPos2iv(const GLint *v); \
+ void windowPos2s(GLshort x, GLshort y); \
+ void windowPos2sv(const GLshort *v); \
+ void windowPos3d(GLdouble x, GLdouble y, GLdouble z); \
+ void windowPos3dv(const GLdouble *v); \
+ void windowPos3f(GLfloat x, GLfloat y, GLfloat z); \
+ void windowPos3fv(const GLfloat *v); \
+ void windowPos3i(GLint x, GLint y, GLint z); \
+ void windowPos3iv(const GLint *v); \
+ void windowPos3s(GLshort x, GLshort y, GLshort z); \
+ void windowPos3sv(const GLshort *v); \
+ void getBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, void *data);
+
+#endif // ANGLE_CONTEXT_API_1_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Context_gl_2_autogen.h b/gfx/angle/checkout/src/libANGLE/Context_gl_2_autogen.h
new file mode 100644
index 0000000000..92e17d1d6e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Context_gl_2_autogen.h
@@ -0,0 +1,44 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context_gl_2_autogen.h: Creates a macro for interfaces in Context.
+
+#ifndef ANGLE_CONTEXT_GL_2_AUTOGEN_H_
+#define ANGLE_CONTEXT_GL_2_AUTOGEN_H_
+
+#define ANGLE_GL_2_CONTEXT_API \
+ void getVertexAttribdv(GLuint index, GLenum pname, GLdouble *params); \
+ void vertexAttrib1d(GLuint index, GLdouble x); \
+ void vertexAttrib1dv(GLuint index, const GLdouble *v); \
+ void vertexAttrib1s(GLuint index, GLshort x); \
+ void vertexAttrib1sv(GLuint index, const GLshort *v); \
+ void vertexAttrib2d(GLuint index, GLdouble x, GLdouble y); \
+ void vertexAttrib2dv(GLuint index, const GLdouble *v); \
+ void vertexAttrib2s(GLuint index, GLshort x, GLshort y); \
+ void vertexAttrib2sv(GLuint index, const GLshort *v); \
+ void vertexAttrib3d(GLuint index, GLdouble x, GLdouble y, GLdouble z); \
+ void vertexAttrib3dv(GLuint index, const GLdouble *v); \
+ void vertexAttrib3s(GLuint index, GLshort x, GLshort y, GLshort z); \
+ void vertexAttrib3sv(GLuint index, const GLshort *v); \
+ void vertexAttrib4Nbv(GLuint index, const GLbyte *v); \
+ void vertexAttrib4Niv(GLuint index, const GLint *v); \
+ void vertexAttrib4Nsv(GLuint index, const GLshort *v); \
+ void vertexAttrib4Nub(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); \
+ void vertexAttrib4Nubv(GLuint index, const GLubyte *v); \
+ void vertexAttrib4Nuiv(GLuint index, const GLuint *v); \
+ void vertexAttrib4Nusv(GLuint index, const GLushort *v); \
+ void vertexAttrib4bv(GLuint index, const GLbyte *v); \
+ void vertexAttrib4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); \
+ void vertexAttrib4dv(GLuint index, const GLdouble *v); \
+ void vertexAttrib4iv(GLuint index, const GLint *v); \
+ void vertexAttrib4s(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); \
+ void vertexAttrib4sv(GLuint index, const GLshort *v); \
+ void vertexAttrib4ubv(GLuint index, const GLubyte *v); \
+ void vertexAttrib4uiv(GLuint index, const GLuint *v); \
+ void vertexAttrib4usv(GLuint index, const GLushort *v);
+
+#endif // ANGLE_CONTEXT_API_2_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Context_gl_3_autogen.h b/gfx/angle/checkout/src/libANGLE/Context_gl_3_autogen.h
new file mode 100644
index 0000000000..598a9055ef
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Context_gl_3_autogen.h
@@ -0,0 +1,82 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context_gl_3_autogen.h: Creates a macro for interfaces in Context.
+
+#ifndef ANGLE_CONTEXT_GL_3_AUTOGEN_H_
+#define ANGLE_CONTEXT_GL_3_AUTOGEN_H_
+
+#define ANGLE_GL_3_CONTEXT_API \
+ void beginConditionalRender(GLuint id, GLenum mode); \
+ void clampColor(GLenum target, GLenum clamp); \
+ void endConditionalRender(); \
+ void framebufferTexture1D(GLenum target, GLenum attachment, TextureTarget textargetPacked, \
+ TextureID texturePacked, GLint level); \
+ void vertexAttribI1i(GLuint index, GLint x); \
+ void vertexAttribI1iv(GLuint index, const GLint *v); \
+ void vertexAttribI1ui(GLuint index, GLuint x); \
+ void vertexAttribI1uiv(GLuint index, const GLuint *v); \
+ void vertexAttribI2i(GLuint index, GLint x, GLint y); \
+ void vertexAttribI2iv(GLuint index, const GLint *v); \
+ void vertexAttribI2ui(GLuint index, GLuint x, GLuint y); \
+ void vertexAttribI2uiv(GLuint index, const GLuint *v); \
+ void vertexAttribI3i(GLuint index, GLint x, GLint y, GLint z); \
+ void vertexAttribI3iv(GLuint index, const GLint *v); \
+ void vertexAttribI3ui(GLuint index, GLuint x, GLuint y, GLuint z); \
+ void vertexAttribI3uiv(GLuint index, const GLuint *v); \
+ void vertexAttribI4bv(GLuint index, const GLbyte *v); \
+ void vertexAttribI4sv(GLuint index, const GLshort *v); \
+ void vertexAttribI4ubv(GLuint index, const GLubyte *v); \
+ void vertexAttribI4usv(GLuint index, const GLushort *v); \
+ void getActiveUniformName(ShaderProgramID programPacked, GLuint uniformIndex, GLsizei bufSize, \
+ GLsizei *length, GLchar *uniformName); \
+ void primitiveRestartIndex(GLuint index); \
+ void texImage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, \
+ GLsizei width, GLsizei height, GLboolean fixedsamplelocations); \
+ void texImage3DMultisample(GLenum target, GLsizei samples, GLenum internalformat, \
+ GLsizei width, GLsizei height, GLsizei depth, \
+ GLboolean fixedsamplelocations); \
+ void colorP3ui(GLenum type, GLuint color); \
+ void colorP3uiv(GLenum type, const GLuint *color); \
+ void colorP4ui(GLenum type, GLuint color); \
+ void colorP4uiv(GLenum type, const GLuint *color); \
+ void multiTexCoordP1ui(GLenum texture, GLenum type, GLuint coords); \
+ void multiTexCoordP1uiv(GLenum texture, GLenum type, const GLuint *coords); \
+ void multiTexCoordP2ui(GLenum texture, GLenum type, GLuint coords); \
+ void multiTexCoordP2uiv(GLenum texture, GLenum type, const GLuint *coords); \
+ void multiTexCoordP3ui(GLenum texture, GLenum type, GLuint coords); \
+ void multiTexCoordP3uiv(GLenum texture, GLenum type, const GLuint *coords); \
+ void multiTexCoordP4ui(GLenum texture, GLenum type, GLuint coords); \
+ void multiTexCoordP4uiv(GLenum texture, GLenum type, const GLuint *coords); \
+ void normalP3ui(GLenum type, GLuint coords); \
+ void normalP3uiv(GLenum type, const GLuint *coords); \
+ void secondaryColorP3ui(GLenum type, GLuint color); \
+ void secondaryColorP3uiv(GLenum type, const GLuint *color); \
+ void texCoordP1ui(GLenum type, GLuint coords); \
+ void texCoordP1uiv(GLenum type, const GLuint *coords); \
+ void texCoordP2ui(GLenum type, GLuint coords); \
+ void texCoordP2uiv(GLenum type, const GLuint *coords); \
+ void texCoordP3ui(GLenum type, GLuint coords); \
+ void texCoordP3uiv(GLenum type, const GLuint *coords); \
+ void texCoordP4ui(GLenum type, GLuint coords); \
+ void texCoordP4uiv(GLenum type, const GLuint *coords); \
+ void vertexAttribP1ui(GLuint index, GLenum type, GLboolean normalized, GLuint value); \
+ void vertexAttribP1uiv(GLuint index, GLenum type, GLboolean normalized, const GLuint *value); \
+ void vertexAttribP2ui(GLuint index, GLenum type, GLboolean normalized, GLuint value); \
+ void vertexAttribP2uiv(GLuint index, GLenum type, GLboolean normalized, const GLuint *value); \
+ void vertexAttribP3ui(GLuint index, GLenum type, GLboolean normalized, GLuint value); \
+ void vertexAttribP3uiv(GLuint index, GLenum type, GLboolean normalized, const GLuint *value); \
+ void vertexAttribP4ui(GLuint index, GLenum type, GLboolean normalized, GLuint value); \
+ void vertexAttribP4uiv(GLuint index, GLenum type, GLboolean normalized, const GLuint *value); \
+ void vertexP2ui(GLenum type, GLuint value); \
+ void vertexP2uiv(GLenum type, const GLuint *value); \
+ void vertexP3ui(GLenum type, GLuint value); \
+ void vertexP3uiv(GLenum type, const GLuint *value); \
+ void vertexP4ui(GLenum type, GLuint value); \
+ void vertexP4uiv(GLenum type, const GLuint *value);
+
+#endif // ANGLE_CONTEXT_API_3_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Context_gl_4_autogen.h b/gfx/angle/checkout/src/libANGLE/Context_gl_4_autogen.h
new file mode 100644
index 0000000000..2c5570149e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Context_gl_4_autogen.h
@@ -0,0 +1,358 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context_gl_4_autogen.h: Creates a macro for interfaces in Context.
+
+#ifndef ANGLE_CONTEXT_GL_4_AUTOGEN_H_
+#define ANGLE_CONTEXT_GL_4_AUTOGEN_H_
+
+#define ANGLE_GL_4_CONTEXT_API \
+ void beginQueryIndexed(GLenum target, GLuint index, QueryID idPacked); \
+ void drawTransformFeedback(GLenum mode, TransformFeedbackID idPacked); \
+ void drawTransformFeedbackStream(GLenum mode, TransformFeedbackID idPacked, GLuint stream); \
+ void endQueryIndexed(GLenum target, GLuint index); \
+ void getActiveSubroutineName(ShaderProgramID programPacked, GLenum shadertype, GLuint index, \
+ GLsizei bufSize, GLsizei *length, GLchar *name); \
+ void getActiveSubroutineUniformName(ShaderProgramID programPacked, GLenum shadertype, \
+ GLuint index, GLsizei bufSize, GLsizei *length, \
+ GLchar *name); \
+ void getActiveSubroutineUniformiv(ShaderProgramID programPacked, GLenum shadertype, \
+ GLuint index, GLenum pname, GLint *values); \
+ void getProgramStageiv(ShaderProgramID programPacked, GLenum shadertype, GLenum pname, \
+ GLint *values); \
+ void getQueryIndexediv(GLenum target, GLuint index, GLenum pname, GLint *params); \
+ GLuint getSubroutineIndex(ShaderProgramID programPacked, GLenum shadertype, \
+ const GLchar *name); \
+ GLint getSubroutineUniformLocation(ShaderProgramID programPacked, GLenum shadertype, \
+ const GLchar *name); \
+ void getUniformSubroutineuiv(GLenum shadertype, GLint location, GLuint *params); \
+ void getUniformdv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLdouble *params); \
+ void patchParameterfv(GLenum pname, const GLfloat *values); \
+ void uniform1d(UniformLocation locationPacked, GLdouble x); \
+ void uniform1dv(UniformLocation locationPacked, GLsizei count, const GLdouble *value); \
+ void uniform2d(UniformLocation locationPacked, GLdouble x, GLdouble y); \
+ void uniform2dv(UniformLocation locationPacked, GLsizei count, const GLdouble *value); \
+ void uniform3d(UniformLocation locationPacked, GLdouble x, GLdouble y, GLdouble z); \
+ void uniform3dv(UniformLocation locationPacked, GLsizei count, const GLdouble *value); \
+ void uniform4d(UniformLocation locationPacked, GLdouble x, GLdouble y, GLdouble z, \
+ GLdouble w); \
+ void uniform4dv(UniformLocation locationPacked, GLsizei count, const GLdouble *value); \
+ void uniformMatrix2dv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLdouble *value); \
+ void uniformMatrix2x3dv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLdouble *value); \
+ void uniformMatrix2x4dv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLdouble *value); \
+ void uniformMatrix3dv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLdouble *value); \
+ void uniformMatrix3x2dv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLdouble *value); \
+ void uniformMatrix3x4dv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLdouble *value); \
+ void uniformMatrix4dv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLdouble *value); \
+ void uniformMatrix4x2dv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLdouble *value); \
+ void uniformMatrix4x3dv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLdouble *value); \
+ void uniformSubroutinesuiv(GLenum shadertype, GLsizei count, const GLuint *indices); \
+ void depthRangeArrayv(GLuint first, GLsizei count, const GLdouble *v); \
+ void depthRangeIndexed(GLuint index, GLdouble n, GLdouble f); \
+ void getDoublei_v(GLenum target, GLuint index, GLdouble *data); \
+ void getFloati_v(GLenum target, GLuint index, GLfloat *data); \
+ void getVertexAttribLdv(GLuint index, GLenum pname, GLdouble *params); \
+ void programUniform1d(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLdouble v0); \
+ void programUniform1dv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLdouble *value); \
+ void programUniform2d(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLdouble v0, GLdouble v1); \
+ void programUniform2dv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLdouble *value); \
+ void programUniform3d(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLdouble v0, GLdouble v1, GLdouble v2); \
+ void programUniform3dv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLdouble *value); \
+ void programUniform4d(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3); \
+ void programUniform4dv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLdouble *value); \
+ void programUniformMatrix2dv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLdouble *value); \
+ void programUniformMatrix2x3dv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLdouble *value); \
+ void programUniformMatrix2x4dv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLdouble *value); \
+ void programUniformMatrix3dv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLdouble *value); \
+ void programUniformMatrix3x2dv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLdouble *value); \
+ void programUniformMatrix3x4dv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLdouble *value); \
+ void programUniformMatrix4dv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLdouble *value); \
+ void programUniformMatrix4x2dv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLdouble *value); \
+ void programUniformMatrix4x3dv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLdouble *value); \
+ void scissorArrayv(GLuint first, GLsizei count, const GLint *v); \
+ void scissorIndexed(GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); \
+ void scissorIndexedv(GLuint index, const GLint *v); \
+ void vertexAttribL1d(GLuint index, GLdouble x); \
+ void vertexAttribL1dv(GLuint index, const GLdouble *v); \
+ void vertexAttribL2d(GLuint index, GLdouble x, GLdouble y); \
+ void vertexAttribL2dv(GLuint index, const GLdouble *v); \
+ void vertexAttribL3d(GLuint index, GLdouble x, GLdouble y, GLdouble z); \
+ void vertexAttribL3dv(GLuint index, const GLdouble *v); \
+ void vertexAttribL4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); \
+ void vertexAttribL4dv(GLuint index, const GLdouble *v); \
+ void vertexAttribLPointer(GLuint index, GLint size, GLenum type, GLsizei stride, \
+ const void *pointer); \
+ void viewportArrayv(GLuint first, GLsizei count, const GLfloat *v); \
+ void viewportIndexedf(GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); \
+ void viewportIndexedfv(GLuint index, const GLfloat *v); \
+ void drawTransformFeedbackInstanced(GLenum mode, TransformFeedbackID idPacked, \
+ GLsizei instancecount); \
+ void drawTransformFeedbackStreamInstanced(GLenum mode, TransformFeedbackID idPacked, \
+ GLuint stream, GLsizei instancecount); \
+ void getActiveAtomicCounterBufferiv(ShaderProgramID programPacked, GLuint bufferIndex, \
+ GLenum pname, GLint *params); \
+ void clearBufferData(GLenum target, GLenum internalformat, GLenum format, GLenum type, \
+ const void *data); \
+ void clearBufferSubData(GLenum target, GLenum internalformat, GLintptr offset, \
+ GLsizeiptr size, GLenum format, GLenum type, const void *data); \
+ void getInternalformati64v(GLenum target, GLenum internalformat, GLenum pname, GLsizei count, \
+ GLint64 *params); \
+ void invalidateBufferData(BufferID bufferPacked); \
+ void invalidateBufferSubData(BufferID bufferPacked, GLintptr offset, GLsizeiptr length); \
+ void invalidateTexImage(TextureID texturePacked, GLint level); \
+ void invalidateTexSubImage(TextureID texturePacked, GLint level, GLint xoffset, GLint yoffset, \
+ GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); \
+ void shaderStorageBlockBinding(ShaderProgramID programPacked, GLuint storageBlockIndex, \
+ GLuint storageBlockBinding); \
+ void textureView(TextureID texturePacked, GLenum target, GLuint origtexture, \
+ GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, \
+ GLuint numlayers); \
+ void vertexAttribLFormat(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); \
+ void bindBuffersBase(GLenum target, GLuint first, GLsizei count, \
+ const BufferID *buffersPacked); \
+ void bindBuffersRange(GLenum target, GLuint first, GLsizei count, \
+ const BufferID *buffersPacked, const GLintptr *offsets, \
+ const GLsizeiptr *sizes); \
+ void bindImageTextures(GLuint first, GLsizei count, const GLuint *textures); \
+ void bindSamplers(GLuint first, GLsizei count, const GLuint *samplers); \
+ void bindTextures(GLuint first, GLsizei count, const GLuint *textures); \
+ void bindVertexBuffers(GLuint first, GLsizei count, const BufferID *buffersPacked, \
+ const GLintptr *offsets, const GLsizei *strides); \
+ void clearTexImage(TextureID texturePacked, GLint level, GLenum format, GLenum type, \
+ const void *data); \
+ void clearTexSubImage(TextureID texturePacked, GLint level, GLint xoffset, GLint yoffset, \
+ GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, \
+ GLenum format, GLenum type, const void *data); \
+ void bindTextureUnit(GLuint unit, TextureID texturePacked); \
+ void blitNamedFramebuffer(GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, \
+ GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, \
+ GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); \
+ GLenum checkNamedFramebufferStatus(FramebufferID framebufferPacked, GLenum target); \
+ void clearNamedBufferData(BufferID bufferPacked, GLenum internalformat, GLenum format, \
+ GLenum type, const void *data); \
+ void clearNamedBufferSubData(BufferID bufferPacked, GLenum internalformat, GLintptr offset, \
+ GLsizeiptr size, GLenum format, GLenum type, const void *data); \
+ void clearNamedFramebufferfi(FramebufferID framebufferPacked, GLenum buffer, GLint drawbuffer, \
+ GLfloat depth, GLint stencil); \
+ void clearNamedFramebufferfv(FramebufferID framebufferPacked, GLenum buffer, GLint drawbuffer, \
+ const GLfloat *value); \
+ void clearNamedFramebufferiv(FramebufferID framebufferPacked, GLenum buffer, GLint drawbuffer, \
+ const GLint *value); \
+ void clearNamedFramebufferuiv(FramebufferID framebufferPacked, GLenum buffer, \
+ GLint drawbuffer, const GLuint *value); \
+ void compressedTextureSubImage1D(TextureID texturePacked, GLint level, GLint xoffset, \
+ GLsizei width, GLenum format, GLsizei imageSize, \
+ const void *data); \
+ void compressedTextureSubImage2D(TextureID texturePacked, GLint level, GLint xoffset, \
+ GLint yoffset, GLsizei width, GLsizei height, GLenum format, \
+ GLsizei imageSize, const void *data); \
+ void compressedTextureSubImage3D(TextureID texturePacked, GLint level, GLint xoffset, \
+ GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, \
+ GLsizei depth, GLenum format, GLsizei imageSize, \
+ const void *data); \
+ void copyNamedBufferSubData(GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, \
+ GLintptr writeOffset, GLsizeiptr size); \
+ void copyTextureSubImage1D(TextureID texturePacked, GLint level, GLint xoffset, GLint x, \
+ GLint y, GLsizei width); \
+ void copyTextureSubImage2D(TextureID texturePacked, GLint level, GLint xoffset, GLint yoffset, \
+ GLint x, GLint y, GLsizei width, GLsizei height); \
+ void copyTextureSubImage3D(TextureID texturePacked, GLint level, GLint xoffset, GLint yoffset, \
+ GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); \
+ void createBuffers(GLsizei n, BufferID *buffersPacked); \
+ void createFramebuffers(GLsizei n, GLuint *framebuffers); \
+ void createProgramPipelines(GLsizei n, GLuint *pipelines); \
+ void createQueries(GLenum target, GLsizei n, GLuint *ids); \
+ void createRenderbuffers(GLsizei n, RenderbufferID *renderbuffersPacked); \
+ void createSamplers(GLsizei n, GLuint *samplers); \
+ void createTextures(GLenum target, GLsizei n, GLuint *textures); \
+ void createTransformFeedbacks(GLsizei n, GLuint *ids); \
+ void createVertexArrays(GLsizei n, VertexArrayID *arraysPacked); \
+ void disableVertexArrayAttrib(VertexArrayID vaobjPacked, GLuint index); \
+ void enableVertexArrayAttrib(VertexArrayID vaobjPacked, GLuint index); \
+ void flushMappedNamedBufferRange(BufferID bufferPacked, GLintptr offset, GLsizeiptr length); \
+ void generateTextureMipmap(TextureID texturePacked); \
+ void getCompressedTextureImage(TextureID texturePacked, GLint level, GLsizei bufSize, \
+ void *pixels); \
+ void getCompressedTextureSubImage(TextureID texturePacked, GLint level, GLint xoffset, \
+ GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, \
+ GLsizei depth, GLsizei bufSize, void *pixels); \
+ void getNamedBufferParameteri64v(BufferID bufferPacked, GLenum pname, GLint64 *params); \
+ void getNamedBufferParameteriv(BufferID bufferPacked, GLenum pname, GLint *params); \
+ void getNamedBufferPointerv(BufferID bufferPacked, GLenum pname, void **params); \
+ void getNamedBufferSubData(BufferID bufferPacked, GLintptr offset, GLsizeiptr size, \
+ void *data); \
+ void getNamedFramebufferAttachmentParameteriv(FramebufferID framebufferPacked, \
+ GLenum attachment, GLenum pname, GLint *params); \
+ void getNamedFramebufferParameteriv(FramebufferID framebufferPacked, GLenum pname, \
+ GLint *param); \
+ void getNamedRenderbufferParameteriv(RenderbufferID renderbufferPacked, GLenum pname, \
+ GLint *params); \
+ void getQueryBufferObjecti64v(GLuint id, BufferID bufferPacked, GLenum pname, \
+ GLintptr offset); \
+ void getQueryBufferObjectiv(GLuint id, BufferID bufferPacked, GLenum pname, GLintptr offset); \
+ void getQueryBufferObjectui64v(GLuint id, BufferID bufferPacked, GLenum pname, \
+ GLintptr offset); \
+ void getQueryBufferObjectuiv(GLuint id, BufferID bufferPacked, GLenum pname, GLintptr offset); \
+ void getTextureImage(TextureID texturePacked, GLint level, GLenum format, GLenum type, \
+ GLsizei bufSize, void *pixels); \
+ void getTextureLevelParameterfv(TextureID texturePacked, GLint level, GLenum pname, \
+ GLfloat *params); \
+ void getTextureLevelParameteriv(TextureID texturePacked, GLint level, GLenum pname, \
+ GLint *params); \
+ void getTextureParameterIiv(TextureID texturePacked, GLenum pname, GLint *params); \
+ void getTextureParameterIuiv(TextureID texturePacked, GLenum pname, GLuint *params); \
+ void getTextureParameterfv(TextureID texturePacked, GLenum pname, GLfloat *params); \
+ void getTextureParameteriv(TextureID texturePacked, GLenum pname, GLint *params); \
+ void getTextureSubImage(TextureID texturePacked, GLint level, GLint xoffset, GLint yoffset, \
+ GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, \
+ GLenum format, GLenum type, GLsizei bufSize, void *pixels); \
+ void getTransformFeedbacki64_v(GLuint xfb, GLenum pname, GLuint index, GLint64 *param); \
+ void getTransformFeedbacki_v(GLuint xfb, GLenum pname, GLuint index, GLint *param); \
+ void getTransformFeedbackiv(GLuint xfb, GLenum pname, GLint *param); \
+ void getVertexArrayIndexed64iv(VertexArrayID vaobjPacked, GLuint index, GLenum pname, \
+ GLint64 *param); \
+ void getVertexArrayIndexediv(VertexArrayID vaobjPacked, GLuint index, GLenum pname, \
+ GLint *param); \
+ void getVertexArrayiv(VertexArrayID vaobjPacked, GLenum pname, GLint *param); \
+ void getnColorTable(GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table); \
+ void getnCompressedTexImage(GLenum target, GLint lod, GLsizei bufSize, void *pixels); \
+ void getnConvolutionFilter(GLenum target, GLenum format, GLenum type, GLsizei bufSize, \
+ void *image); \
+ void getnHistogram(GLenum target, GLboolean reset, GLenum format, GLenum type, \
+ GLsizei bufSize, void *values); \
+ void getnMapdv(GLenum target, GLenum query, GLsizei bufSize, GLdouble *v); \
+ void getnMapfv(GLenum target, GLenum query, GLsizei bufSize, GLfloat *v); \
+ void getnMapiv(GLenum target, GLenum query, GLsizei bufSize, GLint *v); \
+ void getnMinmax(GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, \
+ void *values); \
+ void getnPixelMapfv(GLenum map, GLsizei bufSize, GLfloat *values); \
+ void getnPixelMapuiv(GLenum map, GLsizei bufSize, GLuint *values); \
+ void getnPixelMapusv(GLenum map, GLsizei bufSize, GLushort *values); \
+ void getnPolygonStipple(GLsizei bufSize, GLubyte *pattern); \
+ void getnSeparableFilter(GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, \
+ void *row, GLsizei columnBufSize, void *column, void *span); \
+ void getnTexImage(GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, \
+ void *pixels); \
+ void getnUniformdv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei bufSize, GLdouble *params); \
+ void invalidateNamedFramebufferData(FramebufferID framebufferPacked, GLsizei numAttachments, \
+ const GLenum *attachments); \
+ void invalidateNamedFramebufferSubData(FramebufferID framebufferPacked, \
+ GLsizei numAttachments, const GLenum *attachments, \
+ GLint x, GLint y, GLsizei width, GLsizei height); \
+ void *mapNamedBuffer(BufferID bufferPacked, GLenum access); \
+ void *mapNamedBufferRange(BufferID bufferPacked, GLintptr offset, GLsizeiptr length, \
+ GLbitfield access); \
+ void namedBufferData(BufferID bufferPacked, GLsizeiptr size, const void *data, GLenum usage); \
+ void namedBufferStorage(BufferID bufferPacked, GLsizeiptr size, const void *data, \
+ GLbitfield flags); \
+ void namedBufferSubData(BufferID bufferPacked, GLintptr offset, GLsizeiptr size, \
+ const void *data); \
+ void namedFramebufferDrawBuffer(FramebufferID framebufferPacked, GLenum buf); \
+ void namedFramebufferDrawBuffers(FramebufferID framebufferPacked, GLsizei n, \
+ const GLenum *bufs); \
+ void namedFramebufferParameteri(FramebufferID framebufferPacked, GLenum pname, GLint param); \
+ void namedFramebufferReadBuffer(FramebufferID framebufferPacked, GLenum src); \
+ void namedFramebufferRenderbuffer(FramebufferID framebufferPacked, GLenum attachment, \
+ GLenum renderbuffertarget, \
+ RenderbufferID renderbufferPacked); \
+ void namedFramebufferTexture(FramebufferID framebufferPacked, GLenum attachment, \
+ TextureID texturePacked, GLint level); \
+ void namedFramebufferTextureLayer(FramebufferID framebufferPacked, GLenum attachment, \
+ TextureID texturePacked, GLint level, GLint layer); \
+ void namedRenderbufferStorage(RenderbufferID renderbufferPacked, GLenum internalformat, \
+ GLsizei width, GLsizei height); \
+ void namedRenderbufferStorageMultisample(RenderbufferID renderbufferPacked, GLsizei samples, \
+ GLenum internalformat, GLsizei width, \
+ GLsizei height); \
+ void textureBarrier(); \
+ void textureBuffer(TextureID texturePacked, GLenum internalformat, BufferID bufferPacked); \
+ void textureBufferRange(TextureID texturePacked, GLenum internalformat, BufferID bufferPacked, \
+ GLintptr offset, GLsizeiptr size); \
+ void textureParameterIiv(TextureID texturePacked, GLenum pname, const GLint *params); \
+ void textureParameterIuiv(TextureID texturePacked, GLenum pname, const GLuint *params); \
+ void textureParameterf(TextureID texturePacked, GLenum pname, GLfloat param); \
+ void textureParameterfv(TextureID texturePacked, GLenum pname, const GLfloat *param); \
+ void textureParameteri(TextureID texturePacked, GLenum pname, GLint param); \
+ void textureParameteriv(TextureID texturePacked, GLenum pname, const GLint *param); \
+ void textureStorage1D(TextureID texturePacked, GLsizei levels, GLenum internalformat, \
+ GLsizei width); \
+ void textureStorage2D(TextureID texturePacked, GLsizei levels, GLenum internalformat, \
+ GLsizei width, GLsizei height); \
+ void textureStorage2DMultisample(TextureID texturePacked, GLsizei samples, \
+ GLenum internalformat, GLsizei width, GLsizei height, \
+ GLboolean fixedsamplelocations); \
+ void textureStorage3D(TextureID texturePacked, GLsizei levels, GLenum internalformat, \
+ GLsizei width, GLsizei height, GLsizei depth); \
+ void textureStorage3DMultisample(TextureID texturePacked, GLsizei samples, \
+ GLenum internalformat, GLsizei width, GLsizei height, \
+ GLsizei depth, GLboolean fixedsamplelocations); \
+ void textureSubImage1D(TextureID texturePacked, GLint level, GLint xoffset, GLsizei width, \
+ GLenum format, GLenum type, const void *pixels); \
+ void textureSubImage2D(TextureID texturePacked, GLint level, GLint xoffset, GLint yoffset, \
+ GLsizei width, GLsizei height, GLenum format, GLenum type, \
+ const void *pixels); \
+ void textureSubImage3D(TextureID texturePacked, GLint level, GLint xoffset, GLint yoffset, \
+ GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, \
+ GLenum format, GLenum type, const void *pixels); \
+ void transformFeedbackBufferBase(GLuint xfb, GLuint index, BufferID bufferPacked); \
+ void transformFeedbackBufferRange(GLuint xfb, GLuint index, BufferID bufferPacked, \
+ GLintptr offset, GLsizeiptr size); \
+ GLboolean unmapNamedBuffer(BufferID bufferPacked); \
+ void vertexArrayAttribBinding(VertexArrayID vaobjPacked, GLuint attribindex, \
+ GLuint bindingindex); \
+ void vertexArrayAttribFormat(VertexArrayID vaobjPacked, GLuint attribindex, GLint size, \
+ GLenum type, GLboolean normalized, GLuint relativeoffset); \
+ void vertexArrayAttribIFormat(VertexArrayID vaobjPacked, GLuint attribindex, GLint size, \
+ GLenum type, GLuint relativeoffset); \
+ void vertexArrayAttribLFormat(VertexArrayID vaobjPacked, GLuint attribindex, GLint size, \
+ GLenum type, GLuint relativeoffset); \
+ void vertexArrayBindingDivisor(VertexArrayID vaobjPacked, GLuint bindingindex, \
+ GLuint divisor); \
+ void vertexArrayElementBuffer(VertexArrayID vaobjPacked, BufferID bufferPacked); \
+ void vertexArrayVertexBuffer(VertexArrayID vaobjPacked, GLuint bindingindex, \
+ BufferID bufferPacked, GLintptr offset, GLsizei stride); \
+ void vertexArrayVertexBuffers(VertexArrayID vaobjPacked, GLuint first, GLsizei count, \
+ const BufferID *buffersPacked, const GLintptr *offsets, \
+ const GLsizei *strides); \
+ void multiDrawArraysIndirectCount(GLenum mode, const void *indirect, GLintptr drawcount, \
+ GLsizei maxdrawcount, GLsizei stride); \
+ void multiDrawElementsIndirectCount(GLenum mode, GLenum type, const void *indirect, \
+ GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); \
+ void polygonOffsetClamp(GLfloat factor, GLfloat units, GLfloat clamp); \
+ void specializeShader(GLuint shader, const GLchar *pEntryPoint, \
+ GLuint numSpecializationConstants, const GLuint *pConstantIndex, \
+ const GLuint *pConstantValue);
+
+#endif // ANGLE_CONTEXT_API_4_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Context_gles_1_0.cpp b/gfx/angle/checkout/src/libANGLE/Context_gles_1_0.cpp
new file mode 100644
index 0000000000..611085cfae
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Context_gles_1_0.cpp
@@ -0,0 +1,746 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Context_gles_1_0.cpp: Implements the GLES1-specific parts of Context.
+
+#include "libANGLE/Context.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+
+#include "libANGLE/GLES1Renderer.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/queryutils.h"
+
+namespace
+{
+
+angle::Mat4 FixedMatrixToMat4(const GLfixed *m)
+{
+ angle::Mat4 matrixAsFloat;
+ GLfloat *floatData = matrixAsFloat.data();
+
+ for (int i = 0; i < 16; i++)
+ {
+ floatData[i] = gl::ConvertFixedToFloat(m[i]);
+ }
+
+ return matrixAsFloat;
+}
+
+} // namespace
+
+namespace gl
+{
+
+void Context::alphaFunc(AlphaTestFunc func, GLfloat ref)
+{
+ mState.gles1().setAlphaFunc(func, ref);
+}
+
+void Context::alphaFuncx(AlphaTestFunc func, GLfixed ref)
+{
+ mState.gles1().setAlphaFunc(func, ConvertFixedToFloat(ref));
+}
+
+void Context::clearColorx(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+{
+ mState.setColorClearValue(ConvertFixedToFloat(red), ConvertFixedToFloat(green),
+ ConvertFixedToFloat(blue), ConvertFixedToFloat(alpha));
+}
+
+void Context::clearDepthx(GLfixed depth)
+{
+ mState.setDepthClearValue(clamp01(ConvertFixedToFloat(depth)));
+}
+
+void Context::clientActiveTexture(GLenum texture)
+{
+ mState.gles1().setClientTextureUnit(texture - GL_TEXTURE0);
+ mStateCache.onGLES1ClientStateChange(this);
+}
+
+void Context::clipPlanef(GLenum p, const GLfloat *eqn)
+{
+ mState.gles1().setClipPlane(p - GL_CLIP_PLANE0, eqn);
+}
+
+void Context::clipPlanex(GLenum plane, const GLfixed *equation)
+{
+ const GLfloat equationf[4] = {
+ ConvertFixedToFloat(equation[0]),
+ ConvertFixedToFloat(equation[1]),
+ ConvertFixedToFloat(equation[2]),
+ ConvertFixedToFloat(equation[3]),
+ };
+
+ mState.gles1().setClipPlane(plane - GL_CLIP_PLANE0, equationf);
+}
+
+void Context::color4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
+{
+ mState.gles1().setCurrentColor({red, green, blue, alpha});
+}
+
+void Context::color4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha)
+{
+ mState.gles1().setCurrentColor(
+ {normalizedToFloat<uint8_t>(red), normalizedToFloat<uint8_t>(green),
+ normalizedToFloat<uint8_t>(blue), normalizedToFloat<uint8_t>(alpha)});
+}
+
+void Context::color4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha)
+{
+ mState.gles1().setCurrentColor({ConvertFixedToFloat(red), ConvertFixedToFloat(green),
+ ConvertFixedToFloat(blue), ConvertFixedToFloat(alpha)});
+}
+
+void Context::colorPointer(GLint size, VertexAttribType type, GLsizei stride, const void *ptr)
+{
+ // Note that we normalize data for UnsignedByte types. This is to match the behavior
+ // of current native GLES drivers.
+ vertexAttribPointer(vertexArrayIndex(ClientVertexArrayType::Color), size, type,
+ type == VertexAttribType::UnsignedByte, stride, ptr);
+}
+
+void Context::depthRangex(GLfixed n, GLfixed f)
+{
+ mState.setDepthRange(clamp01(ConvertFixedToFloat(n)), clamp01(ConvertFixedToFloat(f)));
+}
+
+void Context::disableClientState(ClientVertexArrayType clientState)
+{
+ mState.gles1().setClientStateEnabled(clientState, false);
+ disableVertexAttribArray(vertexArrayIndex(clientState));
+ mStateCache.onGLES1ClientStateChange(this);
+}
+
+void Context::enableClientState(ClientVertexArrayType clientState)
+{
+ mState.gles1().setClientStateEnabled(clientState, true);
+ enableVertexAttribArray(vertexArrayIndex(clientState));
+ mStateCache.onGLES1ClientStateChange(this);
+}
+
+void Context::fogf(GLenum pname, GLfloat param)
+{
+ SetFogParameters(&mState.gles1(), pname, &param);
+}
+
+void Context::fogfv(GLenum pname, const GLfloat *params)
+{
+ SetFogParameters(&mState.gles1(), pname, params);
+}
+
+void Context::fogx(GLenum pname, GLfixed param)
+{
+ if (GetFogParameterCount(pname) == 1)
+ {
+ GLfloat paramf = pname == GL_FOG_MODE ? ConvertToGLenum(param) : ConvertFixedToFloat(param);
+ fogf(pname, paramf);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+}
+
+void Context::fogxv(GLenum pname, const GLfixed *params)
+{
+ int paramCount = GetFogParameterCount(pname);
+
+ if (paramCount > 0)
+ {
+ GLfloat paramsf[4];
+ for (int i = 0; i < paramCount; i++)
+ {
+ paramsf[i] =
+ pname == GL_FOG_MODE ? ConvertToGLenum(params[i]) : ConvertFixedToFloat(params[i]);
+ }
+ fogfv(pname, paramsf);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+}
+
+void Context::frustumf(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f)
+{
+ mState.gles1().multMatrix(angle::Mat4::Frustum(l, r, b, t, n, f));
+}
+
+void Context::frustumx(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f)
+{
+ mState.gles1().multMatrix(angle::Mat4::Frustum(ConvertFixedToFloat(l), ConvertFixedToFloat(r),
+ ConvertFixedToFloat(b), ConvertFixedToFloat(t),
+ ConvertFixedToFloat(n), ConvertFixedToFloat(f)));
+}
+
+void Context::getClipPlanef(GLenum plane, GLfloat *equation)
+{
+ mState.gles1().getClipPlane(plane - GL_CLIP_PLANE0, equation);
+}
+
+void Context::getClipPlanex(GLenum plane, GLfixed *equation)
+{
+ GLfloat equationf[4] = {};
+
+ mState.gles1().getClipPlane(plane - GL_CLIP_PLANE0, equationf);
+
+ for (int i = 0; i < 4; i++)
+ {
+ equation[i] = ConvertFloatToFixed(equationf[i]);
+ }
+}
+
+void Context::getFixedv(GLenum pname, GLfixed *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+
+ getQueryParameterInfo(pname, &nativeType, &numParams);
+
+ std::vector<GLfloat> paramsf(numParams, 0);
+ CastStateValues(this, nativeType, pname, numParams, paramsf.data());
+
+ for (unsigned int i = 0; i < numParams; i++)
+ {
+ params[i] = ConvertFloatToFixed(paramsf[i]);
+ }
+}
+
+void Context::getLightfv(GLenum light, LightParameter pname, GLfloat *params)
+{
+ GetLightParameters(&mState.gles1(), light, pname, params);
+}
+
+void Context::getLightxv(GLenum light, LightParameter pname, GLfixed *params)
+{
+ GLfloat paramsf[4];
+ getLightfv(light, pname, paramsf);
+
+ for (unsigned int i = 0; i < GetLightParameterCount(pname); i++)
+ {
+ params[i] = ConvertFloatToFixed(paramsf[i]);
+ }
+}
+
+void Context::getMaterialfv(GLenum face, MaterialParameter pname, GLfloat *params)
+{
+ GetMaterialParameters(&mState.gles1(), face, pname, params);
+}
+
+void Context::getMaterialxv(GLenum face, MaterialParameter pname, GLfixed *params)
+{
+ GLfloat paramsf[4];
+ getMaterialfv(face, pname, paramsf);
+
+ for (unsigned int i = 0; i < GetMaterialParameterCount(pname); i++)
+ {
+ params[i] = ConvertFloatToFixed(paramsf[i]);
+ }
+}
+
+void Context::getTexEnvfv(TextureEnvTarget target, TextureEnvParameter pname, GLfloat *params)
+{
+ GetTextureEnv(mState.getActiveSampler(), &mState.gles1(), target, pname, params);
+}
+
+void Context::getTexEnviv(TextureEnvTarget target, TextureEnvParameter pname, GLint *params)
+{
+ GLfloat paramsf[4];
+ GetTextureEnv(mState.getActiveSampler(), &mState.gles1(), target, pname, paramsf);
+ ConvertTextureEnvToInt(pname, paramsf, params);
+}
+
+void Context::getTexEnvxv(TextureEnvTarget target, TextureEnvParameter pname, GLfixed *params)
+{
+ GLfloat paramsf[4];
+ GetTextureEnv(mState.getActiveSampler(), &mState.gles1(), target, pname, paramsf);
+ ConvertTextureEnvToFixed(pname, paramsf, params);
+}
+
+void Context::getTexParameterxv(TextureType target, GLenum pname, GLfixed *params)
+{
+ const Texture *const texture = getTextureByType(target);
+ QueryTexParameterxv(this, texture, pname, params);
+}
+
+void Context::lightModelf(GLenum pname, GLfloat param)
+{
+ SetLightModelParameters(&mState.gles1(), pname, &param);
+}
+
+void Context::lightModelfv(GLenum pname, const GLfloat *params)
+{
+ SetLightModelParameters(&mState.gles1(), pname, params);
+}
+
+void Context::lightModelx(GLenum pname, GLfixed param)
+{
+ lightModelf(pname, ConvertFixedToFloat(param));
+}
+
+void Context::lightModelxv(GLenum pname, const GLfixed *param)
+{
+ GLfloat paramsf[4];
+
+ for (unsigned int i = 0; i < GetLightModelParameterCount(pname); i++)
+ {
+ paramsf[i] = ConvertFixedToFloat(param[i]);
+ }
+
+ lightModelfv(pname, paramsf);
+}
+
+void Context::lightf(GLenum light, LightParameter pname, GLfloat param)
+{
+ SetLightParameters(&mState.gles1(), light, pname, &param);
+}
+
+void Context::lightfv(GLenum light, LightParameter pname, const GLfloat *params)
+{
+ SetLightParameters(&mState.gles1(), light, pname, params);
+}
+
+void Context::lightx(GLenum light, LightParameter pname, GLfixed param)
+{
+ lightf(light, pname, ConvertFixedToFloat(param));
+}
+
+void Context::lightxv(GLenum light, LightParameter pname, const GLfixed *params)
+{
+ GLfloat paramsf[4];
+
+ for (unsigned int i = 0; i < GetLightParameterCount(pname); i++)
+ {
+ paramsf[i] = ConvertFixedToFloat(params[i]);
+ }
+
+ lightfv(light, pname, paramsf);
+}
+
+void Context::lineWidthx(GLfixed width)
+{
+ mState.setLineWidth(ConvertFixedToFloat(width));
+}
+
+void Context::loadIdentity()
+{
+ mState.gles1().loadMatrix(angle::Mat4());
+}
+
+void Context::loadMatrixf(const GLfloat *m)
+{
+ mState.gles1().loadMatrix(angle::Mat4(m));
+}
+
+void Context::loadMatrixx(const GLfixed *m)
+{
+ mState.gles1().loadMatrix(FixedMatrixToMat4(m));
+}
+
+void Context::logicOp(LogicalOperation opcodePacked)
+{
+ mState.gles1().setLogicOp(opcodePacked);
+}
+
+void Context::materialf(GLenum face, MaterialParameter pname, GLfloat param)
+{
+ SetMaterialParameters(&mState.gles1(), face, pname, &param);
+}
+
+void Context::materialfv(GLenum face, MaterialParameter pname, const GLfloat *params)
+{
+ SetMaterialParameters(&mState.gles1(), face, pname, params);
+}
+
+void Context::materialx(GLenum face, MaterialParameter pname, GLfixed param)
+{
+ materialf(face, pname, ConvertFixedToFloat(param));
+}
+
+void Context::materialxv(GLenum face, MaterialParameter pname, const GLfixed *param)
+{
+ GLfloat paramsf[4];
+
+ for (unsigned int i = 0; i < GetMaterialParameterCount(pname); i++)
+ {
+ paramsf[i] = ConvertFixedToFloat(param[i]);
+ }
+
+ materialfv(face, pname, paramsf);
+}
+
+void Context::matrixMode(MatrixType mode)
+{
+ mState.gles1().setMatrixMode(mode);
+}
+
+void Context::multMatrixf(const GLfloat *m)
+{
+ mState.gles1().multMatrix(angle::Mat4(m));
+}
+
+void Context::multMatrixx(const GLfixed *m)
+{
+ mState.gles1().multMatrix(FixedMatrixToMat4(m));
+}
+
+void Context::multiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+{
+ unsigned int unit = target - GL_TEXTURE0;
+ ASSERT(target >= GL_TEXTURE0 && unit < getCaps().maxMultitextureUnits);
+ mState.gles1().setCurrentTextureCoords(unit, {s, t, r, q});
+}
+
+void Context::multiTexCoord4x(GLenum target, GLfixed s, GLfixed t, GLfixed r, GLfixed q)
+{
+ unsigned int unit = target - GL_TEXTURE0;
+ ASSERT(target >= GL_TEXTURE0 && unit < getCaps().maxMultitextureUnits);
+ mState.gles1().setCurrentTextureCoords(unit, {ConvertFixedToFloat(s), ConvertFixedToFloat(t),
+ ConvertFixedToFloat(r), ConvertFixedToFloat(q)});
+}
+
+void Context::normal3f(GLfloat nx, GLfloat ny, GLfloat nz)
+{
+ mState.gles1().setCurrentNormal({nx, ny, nz});
+}
+
+void Context::normal3x(GLfixed nx, GLfixed ny, GLfixed nz)
+{
+ mState.gles1().setCurrentNormal(
+ {ConvertFixedToFloat(nx), ConvertFixedToFloat(ny), ConvertFixedToFloat(nz)});
+}
+
+void Context::normalPointer(VertexAttribType type, GLsizei stride, const void *ptr)
+{
+ vertexAttribPointer(vertexArrayIndex(ClientVertexArrayType::Normal), 3, type, GL_FALSE, stride,
+ ptr);
+}
+
+void Context::orthof(GLfloat left,
+ GLfloat right,
+ GLfloat bottom,
+ GLfloat top,
+ GLfloat zNear,
+ GLfloat zFar)
+{
+ mState.gles1().multMatrix(angle::Mat4::Ortho(left, right, bottom, top, zNear, zFar));
+}
+
+void Context::orthox(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f)
+{
+ mState.gles1().multMatrix(angle::Mat4::Ortho(ConvertFixedToFloat(l), ConvertFixedToFloat(r),
+ ConvertFixedToFloat(b), ConvertFixedToFloat(t),
+ ConvertFixedToFloat(n), ConvertFixedToFloat(f)));
+}
+
+void Context::pointParameterf(PointParameter pname, GLfloat param)
+{
+ SetPointParameter(&mState.gles1(), pname, &param);
+}
+
+void Context::pointParameterfv(PointParameter pname, const GLfloat *params)
+{
+ SetPointParameter(&mState.gles1(), pname, params);
+}
+
+void Context::pointParameterx(PointParameter pname, GLfixed param)
+{
+ GLfloat paramf = ConvertFixedToFloat(param);
+ SetPointParameter(&mState.gles1(), pname, &paramf);
+}
+
+void Context::pointParameterxv(PointParameter pname, const GLfixed *params)
+{
+ GLfloat paramsf[4] = {};
+ for (unsigned int i = 0; i < GetPointParameterCount(pname); i++)
+ {
+ paramsf[i] = ConvertFixedToFloat(params[i]);
+ }
+ SetPointParameter(&mState.gles1(), pname, paramsf);
+}
+
+void Context::pointSize(GLfloat size)
+{
+ SetPointSize(&mState.gles1(), size);
+}
+
+void Context::pointSizex(GLfixed size)
+{
+ SetPointSize(&mState.gles1(), ConvertFixedToFloat(size));
+}
+
+void Context::polygonOffsetx(GLfixed factor, GLfixed units)
+{
+ mState.setPolygonOffsetParams(ConvertFixedToFloat(factor), ConvertFixedToFloat(units));
+}
+
+void Context::popMatrix()
+{
+ mState.gles1().popMatrix();
+}
+
+void Context::pushMatrix()
+{
+ mState.gles1().pushMatrix();
+}
+
+void Context::rotatef(float angle, float x, float y, float z)
+{
+ mState.gles1().multMatrix(angle::Mat4::Rotate(angle, angle::Vector3(x, y, z)));
+}
+
+void Context::rotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z)
+{
+ mState.gles1().multMatrix(angle::Mat4::Rotate(
+ ConvertFixedToFloat(angle),
+ angle::Vector3(ConvertFixedToFloat(x), ConvertFixedToFloat(y), ConvertFixedToFloat(z))));
+}
+
+void Context::sampleCoveragex(GLclampx value, GLboolean invert)
+{
+ GLclampf valuef = ConvertFixedToFloat(value);
+ mState.setSampleCoverageParams(clamp01(valuef), ConvertToBool(invert));
+}
+
+void Context::scalef(float x, float y, float z)
+{
+ mState.gles1().multMatrix(angle::Mat4::Scale(angle::Vector3(x, y, z)));
+}
+
+void Context::scalex(GLfixed x, GLfixed y, GLfixed z)
+{
+ mState.gles1().multMatrix(angle::Mat4::Scale(
+ angle::Vector3(ConvertFixedToFloat(x), ConvertFixedToFloat(y), ConvertFixedToFloat(z))));
+}
+
+void Context::shadeModel(ShadingModel model)
+{
+ mState.gles1().setShadeModel(model);
+}
+
+void Context::texCoordPointer(GLint size, VertexAttribType type, GLsizei stride, const void *ptr)
+{
+ vertexAttribPointer(vertexArrayIndex(ClientVertexArrayType::TextureCoord), size, type, GL_FALSE,
+ stride, ptr);
+}
+
+void Context::texEnvf(TextureEnvTarget target, TextureEnvParameter pname, GLfloat param)
+{
+ SetTextureEnv(mState.getActiveSampler(), &mState.gles1(), target, pname, &param);
+}
+
+void Context::texEnvfv(TextureEnvTarget target, TextureEnvParameter pname, const GLfloat *params)
+{
+ SetTextureEnv(mState.getActiveSampler(), &mState.gles1(), target, pname, params);
+}
+
+void Context::texEnvi(TextureEnvTarget target, TextureEnvParameter pname, GLint param)
+{
+ GLfloat paramsf[4] = {};
+ ConvertTextureEnvFromInt(pname, &param, paramsf);
+ SetTextureEnv(mState.getActiveSampler(), &mState.gles1(), target, pname, paramsf);
+}
+
+void Context::texEnviv(TextureEnvTarget target, TextureEnvParameter pname, const GLint *params)
+{
+ GLfloat paramsf[4] = {};
+ ConvertTextureEnvFromInt(pname, params, paramsf);
+ SetTextureEnv(mState.getActiveSampler(), &mState.gles1(), target, pname, paramsf);
+}
+
+void Context::texEnvx(TextureEnvTarget target, TextureEnvParameter pname, GLfixed param)
+{
+ GLfloat paramsf[4] = {};
+ ConvertTextureEnvFromFixed(pname, &param, paramsf);
+ SetTextureEnv(mState.getActiveSampler(), &mState.gles1(), target, pname, paramsf);
+}
+
+void Context::texEnvxv(TextureEnvTarget target, TextureEnvParameter pname, const GLfixed *params)
+{
+ GLfloat paramsf[4] = {};
+ ConvertTextureEnvFromFixed(pname, params, paramsf);
+ SetTextureEnv(mState.getActiveSampler(), &mState.gles1(), target, pname, paramsf);
+}
+
+void Context::texParameterx(TextureType target, GLenum pname, GLfixed param)
+{
+ Texture *const texture = getTextureByType(target);
+ SetTexParameterx(this, texture, pname, param);
+}
+
+void Context::texParameterxv(TextureType target, GLenum pname, const GLfixed *params)
+{
+ Texture *const texture = getTextureByType(target);
+ SetTexParameterxv(this, texture, pname, params);
+}
+
+void Context::translatef(float x, float y, float z)
+{
+ mState.gles1().multMatrix(angle::Mat4::Translate(angle::Vector3(x, y, z)));
+}
+
+void Context::translatex(GLfixed x, GLfixed y, GLfixed z)
+{
+ mState.gles1().multMatrix(angle::Mat4::Translate(
+ angle::Vector3(ConvertFixedToFloat(x), ConvertFixedToFloat(y), ConvertFixedToFloat(z))));
+}
+
+void Context::vertexPointer(GLint size, VertexAttribType type, GLsizei stride, const void *ptr)
+{
+ vertexAttribPointer(vertexArrayIndex(ClientVertexArrayType::Vertex), size, type, GL_FALSE,
+ stride, ptr);
+}
+
+// GL_OES_draw_texture
+void Context::drawTexf(float x, float y, float z, float width, float height)
+{
+ mGLES1Renderer->drawTexture(this, &mState, x, y, z, width, height);
+}
+
+void Context::drawTexfv(const GLfloat *coords)
+{
+ mGLES1Renderer->drawTexture(this, &mState, coords[0], coords[1], coords[2], coords[3],
+ coords[4]);
+}
+
+void Context::drawTexi(GLint x, GLint y, GLint z, GLint width, GLint height)
+{
+ mGLES1Renderer->drawTexture(this, &mState, static_cast<GLfloat>(x), static_cast<GLfloat>(y),
+ static_cast<GLfloat>(z), static_cast<GLfloat>(width),
+ static_cast<GLfloat>(height));
+}
+
+void Context::drawTexiv(const GLint *coords)
+{
+ mGLES1Renderer->drawTexture(this, &mState, static_cast<GLfloat>(coords[0]),
+ static_cast<GLfloat>(coords[1]), static_cast<GLfloat>(coords[2]),
+ static_cast<GLfloat>(coords[3]), static_cast<GLfloat>(coords[4]));
+}
+
+void Context::drawTexs(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height)
+{
+ mGLES1Renderer->drawTexture(this, &mState, static_cast<GLfloat>(x), static_cast<GLfloat>(y),
+ static_cast<GLfloat>(z), static_cast<GLfloat>(width),
+ static_cast<GLfloat>(height));
+}
+
+void Context::drawTexsv(const GLshort *coords)
+{
+ mGLES1Renderer->drawTexture(this, &mState, static_cast<GLfloat>(coords[0]),
+ static_cast<GLfloat>(coords[1]), static_cast<GLfloat>(coords[2]),
+ static_cast<GLfloat>(coords[3]), static_cast<GLfloat>(coords[4]));
+}
+
+void Context::drawTexx(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height)
+{
+ mGLES1Renderer->drawTexture(this, &mState, ConvertFixedToFloat(x), ConvertFixedToFloat(y),
+ ConvertFixedToFloat(z), ConvertFixedToFloat(width),
+ ConvertFixedToFloat(height));
+}
+
+void Context::drawTexxv(const GLfixed *coords)
+{
+ mGLES1Renderer->drawTexture(this, &mState, ConvertFixedToFloat(coords[0]),
+ ConvertFixedToFloat(coords[1]), ConvertFixedToFloat(coords[2]),
+ ConvertFixedToFloat(coords[3]), ConvertFixedToFloat(coords[4]));
+}
+
+// GL_OES_matrix_palette
+void Context::currentPaletteMatrix(GLuint matrixpaletteindex)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::loadPaletteFromModelViewMatrix()
+{
+ UNIMPLEMENTED();
+}
+
+void Context::matrixIndexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::weightPointer(GLint size, GLenum type, GLsizei stride, const void *pointer)
+{
+ UNIMPLEMENTED();
+}
+
+// GL_OES_point_size_array
+void Context::pointSizePointer(VertexAttribType type, GLsizei stride, const void *ptr)
+{
+ vertexAttribPointer(vertexArrayIndex(ClientVertexArrayType::PointSize), 1, type, GL_FALSE,
+ stride, ptr);
+}
+
+// GL_OES_query_matrix
+GLbitfield Context::queryMatrixx(GLfixed *mantissa, GLint *exponent)
+{
+ UNIMPLEMENTED();
+ return 0;
+}
+
+// GL_OES_texture_cube_map
+void Context::getTexGenfv(GLenum coord, GLenum pname, GLfloat *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTexGeniv(GLenum coord, GLenum pname, GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::getTexGenxv(GLenum coord, GLenum pname, GLfixed *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texGenf(GLenum coord, GLenum pname, GLfloat param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texGenfv(GLenum coord, GLenum pname, const GLfloat *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texGeni(GLenum coord, GLenum pname, GLint param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texGeniv(GLenum coord, GLenum pname, const GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texGenx(GLenum coord, GLenum pname, GLfixed param)
+{
+ UNIMPLEMENTED();
+}
+
+void Context::texGenxv(GLenum coord, GLenum pname, const GLint *params)
+{
+ UNIMPLEMENTED();
+}
+
+int Context::vertexArrayIndex(ClientVertexArrayType type) const
+{
+ return GLES1Renderer::VertexArrayIndex(type, mState.gles1());
+}
+
+// static
+int Context::TexCoordArrayIndex(unsigned int unit)
+{
+ return GLES1Renderer::TexCoordArrayIndex(unit);
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Context_gles_1_0_autogen.h b/gfx/angle/checkout/src/libANGLE/Context_gles_1_0_autogen.h
new file mode 100644
index 0000000000..77f1a9afce
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Context_gles_1_0_autogen.h
@@ -0,0 +1,109 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context_gles_1_0_autogen.h: Creates a macro for interfaces in Context.
+
+#ifndef ANGLE_CONTEXT_GLES_1_0_AUTOGEN_H_
+#define ANGLE_CONTEXT_GLES_1_0_AUTOGEN_H_
+
+#define ANGLE_GLES_1_0_CONTEXT_API \
+ void alphaFunc(AlphaTestFunc funcPacked, GLfloat ref); \
+ void alphaFuncx(AlphaTestFunc funcPacked, GLfixed ref); \
+ void clearColorx(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); \
+ void clearDepthx(GLfixed depth); \
+ void clientActiveTexture(GLenum texture); \
+ void clipPlanef(GLenum p, const GLfloat *eqn); \
+ void clipPlanex(GLenum plane, const GLfixed *equation); \
+ void color4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); \
+ void color4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); \
+ void color4x(GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); \
+ void colorPointer(GLint size, VertexAttribType typePacked, GLsizei stride, \
+ const void *pointer); \
+ void depthRangex(GLfixed n, GLfixed f); \
+ void disableClientState(ClientVertexArrayType arrayPacked); \
+ void enableClientState(ClientVertexArrayType arrayPacked); \
+ void fogf(GLenum pname, GLfloat param); \
+ void fogfv(GLenum pname, const GLfloat *params); \
+ void fogx(GLenum pname, GLfixed param); \
+ void fogxv(GLenum pname, const GLfixed *param); \
+ void frustumf(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); \
+ void frustumx(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f); \
+ void getClipPlanef(GLenum plane, GLfloat *equation); \
+ void getClipPlanex(GLenum plane, GLfixed *equation); \
+ void getFixedv(GLenum pname, GLfixed *params); \
+ void getLightfv(GLenum light, LightParameter pnamePacked, GLfloat *params); \
+ void getLightxv(GLenum light, LightParameter pnamePacked, GLfixed *params); \
+ void getMaterialfv(GLenum face, MaterialParameter pnamePacked, GLfloat *params); \
+ void getMaterialxv(GLenum face, MaterialParameter pnamePacked, GLfixed *params); \
+ void getTexEnvfv(TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, \
+ GLfloat *params); \
+ void getTexEnviv(TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, \
+ GLint *params); \
+ void getTexEnvxv(TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, \
+ GLfixed *params); \
+ void getTexParameterxv(TextureType targetPacked, GLenum pname, GLfixed *params); \
+ void lightModelf(GLenum pname, GLfloat param); \
+ void lightModelfv(GLenum pname, const GLfloat *params); \
+ void lightModelx(GLenum pname, GLfixed param); \
+ void lightModelxv(GLenum pname, const GLfixed *param); \
+ void lightf(GLenum light, LightParameter pnamePacked, GLfloat param); \
+ void lightfv(GLenum light, LightParameter pnamePacked, const GLfloat *params); \
+ void lightx(GLenum light, LightParameter pnamePacked, GLfixed param); \
+ void lightxv(GLenum light, LightParameter pnamePacked, const GLfixed *params); \
+ void lineWidthx(GLfixed width); \
+ void loadIdentity(); \
+ void loadMatrixf(const GLfloat *m); \
+ void loadMatrixx(const GLfixed *m); \
+ void logicOp(LogicalOperation opcodePacked); \
+ void materialf(GLenum face, MaterialParameter pnamePacked, GLfloat param); \
+ void materialfv(GLenum face, MaterialParameter pnamePacked, const GLfloat *params); \
+ void materialx(GLenum face, MaterialParameter pnamePacked, GLfixed param); \
+ void materialxv(GLenum face, MaterialParameter pnamePacked, const GLfixed *param); \
+ void matrixMode(MatrixType modePacked); \
+ void multMatrixf(const GLfloat *m); \
+ void multMatrixx(const GLfixed *m); \
+ void multiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); \
+ void multiTexCoord4x(GLenum texture, GLfixed s, GLfixed t, GLfixed r, GLfixed q); \
+ void normal3f(GLfloat nx, GLfloat ny, GLfloat nz); \
+ void normal3x(GLfixed nx, GLfixed ny, GLfixed nz); \
+ void normalPointer(VertexAttribType typePacked, GLsizei stride, const void *pointer); \
+ void orthof(GLfloat l, GLfloat r, GLfloat b, GLfloat t, GLfloat n, GLfloat f); \
+ void orthox(GLfixed l, GLfixed r, GLfixed b, GLfixed t, GLfixed n, GLfixed f); \
+ void pointParameterf(PointParameter pnamePacked, GLfloat param); \
+ void pointParameterfv(PointParameter pnamePacked, const GLfloat *params); \
+ void pointParameterx(PointParameter pnamePacked, GLfixed param); \
+ void pointParameterxv(PointParameter pnamePacked, const GLfixed *params); \
+ void pointSize(GLfloat size); \
+ void pointSizex(GLfixed size); \
+ void polygonOffsetx(GLfixed factor, GLfixed units); \
+ void popMatrix(); \
+ void pushMatrix(); \
+ void rotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); \
+ void rotatex(GLfixed angle, GLfixed x, GLfixed y, GLfixed z); \
+ void sampleCoveragex(GLclampx value, GLboolean invert); \
+ void scalef(GLfloat x, GLfloat y, GLfloat z); \
+ void scalex(GLfixed x, GLfixed y, GLfixed z); \
+ void shadeModel(ShadingModel modePacked); \
+ void texCoordPointer(GLint size, VertexAttribType typePacked, GLsizei stride, \
+ const void *pointer); \
+ void texEnvf(TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, GLfloat param); \
+ void texEnvfv(TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, \
+ const GLfloat *params); \
+ void texEnvi(TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, GLint param); \
+ void texEnviv(TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, \
+ const GLint *params); \
+ void texEnvx(TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, GLfixed param); \
+ void texEnvxv(TextureEnvTarget targetPacked, TextureEnvParameter pnamePacked, \
+ const GLfixed *params); \
+ void texParameterx(TextureType targetPacked, GLenum pname, GLfixed param); \
+ void texParameterxv(TextureType targetPacked, GLenum pname, const GLfixed *params); \
+ void translatef(GLfloat x, GLfloat y, GLfloat z); \
+ void translatex(GLfixed x, GLfixed y, GLfixed z); \
+ void vertexPointer(GLint size, VertexAttribType typePacked, GLsizei stride, \
+ const void *pointer);
+
+#endif // ANGLE_CONTEXT_API_1_0_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Context_gles_2_0_autogen.h b/gfx/angle/checkout/src/libANGLE/Context_gles_2_0_autogen.h
new file mode 100644
index 0000000000..1c0501eaf3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Context_gles_2_0_autogen.h
@@ -0,0 +1,190 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context_gles_2_0_autogen.h: Creates a macro for interfaces in Context.
+
+#ifndef ANGLE_CONTEXT_GLES_2_0_AUTOGEN_H_
+#define ANGLE_CONTEXT_GLES_2_0_AUTOGEN_H_
+
+#define ANGLE_GLES_2_0_CONTEXT_API \
+ void activeTexture(GLenum texture); \
+ void attachShader(ShaderProgramID programPacked, ShaderProgramID shaderPacked); \
+ void bindAttribLocation(ShaderProgramID programPacked, GLuint index, const GLchar *name); \
+ void bindBuffer(BufferBinding targetPacked, BufferID bufferPacked); \
+ void bindFramebuffer(GLenum target, FramebufferID framebufferPacked); \
+ void bindRenderbuffer(GLenum target, RenderbufferID renderbufferPacked); \
+ void bindTexture(TextureType targetPacked, TextureID texturePacked); \
+ void blendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); \
+ void blendEquation(GLenum mode); \
+ void blendEquationSeparate(GLenum modeRGB, GLenum modeAlpha); \
+ void blendFunc(GLenum sfactor, GLenum dfactor); \
+ void blendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, \
+ GLenum dfactorAlpha); \
+ void bufferData(BufferBinding targetPacked, GLsizeiptr size, const void *data, \
+ BufferUsage usagePacked); \
+ void bufferSubData(BufferBinding targetPacked, GLintptr offset, GLsizeiptr size, \
+ const void *data); \
+ GLenum checkFramebufferStatus(GLenum target); \
+ void clear(GLbitfield mask); \
+ void clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); \
+ void clearDepthf(GLfloat d); \
+ void clearStencil(GLint s); \
+ void colorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); \
+ void compileShader(ShaderProgramID shaderPacked); \
+ void compressedTexImage2D(TextureTarget targetPacked, GLint level, GLenum internalformat, \
+ GLsizei width, GLsizei height, GLint border, GLsizei imageSize, \
+ const void *data); \
+ void compressedTexSubImage2D(TextureTarget targetPacked, GLint level, GLint xoffset, \
+ GLint yoffset, GLsizei width, GLsizei height, GLenum format, \
+ GLsizei imageSize, const void *data); \
+ void copyTexImage2D(TextureTarget targetPacked, GLint level, GLenum internalformat, GLint x, \
+ GLint y, GLsizei width, GLsizei height, GLint border); \
+ void copyTexSubImage2D(TextureTarget targetPacked, GLint level, GLint xoffset, GLint yoffset, \
+ GLint x, GLint y, GLsizei width, GLsizei height); \
+ GLuint createProgram(); \
+ GLuint createShader(ShaderType typePacked); \
+ void cullFace(CullFaceMode modePacked); \
+ void deleteBuffers(GLsizei n, const BufferID *buffersPacked); \
+ void deleteFramebuffers(GLsizei n, const FramebufferID *framebuffersPacked); \
+ void deleteProgram(ShaderProgramID programPacked); \
+ void deleteRenderbuffers(GLsizei n, const RenderbufferID *renderbuffersPacked); \
+ void deleteShader(ShaderProgramID shaderPacked); \
+ void deleteTextures(GLsizei n, const TextureID *texturesPacked); \
+ void depthFunc(GLenum func); \
+ void depthMask(GLboolean flag); \
+ void depthRangef(GLfloat n, GLfloat f); \
+ void detachShader(ShaderProgramID programPacked, ShaderProgramID shaderPacked); \
+ void disable(GLenum cap); \
+ void disableVertexAttribArray(GLuint index); \
+ void drawArrays(PrimitiveMode modePacked, GLint first, GLsizei count); \
+ void drawElements(PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, \
+ const void *indices); \
+ void enable(GLenum cap); \
+ void enableVertexAttribArray(GLuint index); \
+ void finish(); \
+ void flush(); \
+ void framebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, \
+ RenderbufferID renderbufferPacked); \
+ void framebufferTexture2D(GLenum target, GLenum attachment, TextureTarget textargetPacked, \
+ TextureID texturePacked, GLint level); \
+ void frontFace(GLenum mode); \
+ void genBuffers(GLsizei n, BufferID *buffersPacked); \
+ void genFramebuffers(GLsizei n, FramebufferID *framebuffersPacked); \
+ void genRenderbuffers(GLsizei n, RenderbufferID *renderbuffersPacked); \
+ void genTextures(GLsizei n, TextureID *texturesPacked); \
+ void generateMipmap(TextureType targetPacked); \
+ void getActiveAttrib(ShaderProgramID programPacked, GLuint index, GLsizei bufSize, \
+ GLsizei *length, GLint *size, GLenum *type, GLchar *name); \
+ void getActiveUniform(ShaderProgramID programPacked, GLuint index, GLsizei bufSize, \
+ GLsizei *length, GLint *size, GLenum *type, GLchar *name); \
+ void getAttachedShaders(ShaderProgramID programPacked, GLsizei maxCount, GLsizei *count, \
+ ShaderProgramID *shadersPacked); \
+ GLint getAttribLocation(ShaderProgramID programPacked, const GLchar *name); \
+ void getBooleanv(GLenum pname, GLboolean *data); \
+ void getBufferParameteriv(BufferBinding targetPacked, GLenum pname, GLint *params); \
+ GLenum getError(); \
+ void getFloatv(GLenum pname, GLfloat *data); \
+ void getFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, \
+ GLint *params); \
+ void getIntegerv(GLenum pname, GLint *data); \
+ void getProgramInfoLog(ShaderProgramID programPacked, GLsizei bufSize, GLsizei *length, \
+ GLchar *infoLog); \
+ void getProgramiv(ShaderProgramID programPacked, GLenum pname, GLint *params); \
+ void getRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params); \
+ void getShaderInfoLog(ShaderProgramID shaderPacked, GLsizei bufSize, GLsizei *length, \
+ GLchar *infoLog); \
+ void getShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint *range, \
+ GLint *precision); \
+ void getShaderSource(ShaderProgramID shaderPacked, GLsizei bufSize, GLsizei *length, \
+ GLchar *source); \
+ void getShaderiv(ShaderProgramID shaderPacked, GLenum pname, GLint *params); \
+ const GLubyte *getString(GLenum name); \
+ void getTexParameterfv(TextureType targetPacked, GLenum pname, GLfloat *params); \
+ void getTexParameteriv(TextureType targetPacked, GLenum pname, GLint *params); \
+ GLint getUniformLocation(ShaderProgramID programPacked, const GLchar *name); \
+ void getUniformfv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLfloat *params); \
+ void getUniformiv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLint *params); \
+ void getVertexAttribPointerv(GLuint index, GLenum pname, void **pointer); \
+ void getVertexAttribfv(GLuint index, GLenum pname, GLfloat *params); \
+ void getVertexAttribiv(GLuint index, GLenum pname, GLint *params); \
+ void hint(GLenum target, GLenum mode); \
+ GLboolean isBuffer(BufferID bufferPacked) const; \
+ GLboolean isEnabled(GLenum cap) const; \
+ GLboolean isFramebuffer(FramebufferID framebufferPacked) const; \
+ GLboolean isProgram(ShaderProgramID programPacked) const; \
+ GLboolean isRenderbuffer(RenderbufferID renderbufferPacked) const; \
+ GLboolean isShader(ShaderProgramID shaderPacked) const; \
+ GLboolean isTexture(TextureID texturePacked) const; \
+ void lineWidth(GLfloat width); \
+ void linkProgram(ShaderProgramID programPacked); \
+ void pixelStorei(GLenum pname, GLint param); \
+ void polygonOffset(GLfloat factor, GLfloat units); \
+ void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, \
+ void *pixels); \
+ void releaseShaderCompiler(); \
+ void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); \
+ void sampleCoverage(GLfloat value, GLboolean invert); \
+ void scissor(GLint x, GLint y, GLsizei width, GLsizei height); \
+ void shaderBinary(GLsizei count, const ShaderProgramID *shadersPacked, GLenum binaryFormat, \
+ const void *binary, GLsizei length); \
+ void shaderSource(ShaderProgramID shaderPacked, GLsizei count, const GLchar *const *string, \
+ const GLint *length); \
+ void stencilFunc(GLenum func, GLint ref, GLuint mask); \
+ void stencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask); \
+ void stencilMask(GLuint mask); \
+ void stencilMaskSeparate(GLenum face, GLuint mask); \
+ void stencilOp(GLenum fail, GLenum zfail, GLenum zpass); \
+ void stencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); \
+ void texImage2D(TextureTarget targetPacked, GLint level, GLint internalformat, GLsizei width, \
+ GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); \
+ void texParameterf(TextureType targetPacked, GLenum pname, GLfloat param); \
+ void texParameterfv(TextureType targetPacked, GLenum pname, const GLfloat *params); \
+ void texParameteri(TextureType targetPacked, GLenum pname, GLint param); \
+ void texParameteriv(TextureType targetPacked, GLenum pname, const GLint *params); \
+ void texSubImage2D(TextureTarget targetPacked, GLint level, GLint xoffset, GLint yoffset, \
+ GLsizei width, GLsizei height, GLenum format, GLenum type, \
+ const void *pixels); \
+ void uniform1f(UniformLocation locationPacked, GLfloat v0); \
+ void uniform1fv(UniformLocation locationPacked, GLsizei count, const GLfloat *value); \
+ void uniform1i(UniformLocation locationPacked, GLint v0); \
+ void uniform1iv(UniformLocation locationPacked, GLsizei count, const GLint *value); \
+ void uniform2f(UniformLocation locationPacked, GLfloat v0, GLfloat v1); \
+ void uniform2fv(UniformLocation locationPacked, GLsizei count, const GLfloat *value); \
+ void uniform2i(UniformLocation locationPacked, GLint v0, GLint v1); \
+ void uniform2iv(UniformLocation locationPacked, GLsizei count, const GLint *value); \
+ void uniform3f(UniformLocation locationPacked, GLfloat v0, GLfloat v1, GLfloat v2); \
+ void uniform3fv(UniformLocation locationPacked, GLsizei count, const GLfloat *value); \
+ void uniform3i(UniformLocation locationPacked, GLint v0, GLint v1, GLint v2); \
+ void uniform3iv(UniformLocation locationPacked, GLsizei count, const GLint *value); \
+ void uniform4f(UniformLocation locationPacked, GLfloat v0, GLfloat v1, GLfloat v2, \
+ GLfloat v3); \
+ void uniform4fv(UniformLocation locationPacked, GLsizei count, const GLfloat *value); \
+ void uniform4i(UniformLocation locationPacked, GLint v0, GLint v1, GLint v2, GLint v3); \
+ void uniform4iv(UniformLocation locationPacked, GLsizei count, const GLint *value); \
+ void uniformMatrix2fv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLfloat *value); \
+ void uniformMatrix3fv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLfloat *value); \
+ void uniformMatrix4fv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLfloat *value); \
+ void useProgram(ShaderProgramID programPacked); \
+ void validateProgram(ShaderProgramID programPacked); \
+ void vertexAttrib1f(GLuint index, GLfloat x); \
+ void vertexAttrib1fv(GLuint index, const GLfloat *v); \
+ void vertexAttrib2f(GLuint index, GLfloat x, GLfloat y); \
+ void vertexAttrib2fv(GLuint index, const GLfloat *v); \
+ void vertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z); \
+ void vertexAttrib3fv(GLuint index, const GLfloat *v); \
+ void vertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); \
+ void vertexAttrib4fv(GLuint index, const GLfloat *v); \
+ void vertexAttribPointer(GLuint index, GLint size, VertexAttribType typePacked, \
+ GLboolean normalized, GLsizei stride, const void *pointer); \
+ void viewport(GLint x, GLint y, GLsizei width, GLsizei height);
+
+#endif // ANGLE_CONTEXT_API_2_0_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Context_gles_3_0_autogen.h b/gfx/angle/checkout/src/libANGLE/Context_gles_3_0_autogen.h
new file mode 100644
index 0000000000..f87f49f43d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Context_gles_3_0_autogen.h
@@ -0,0 +1,164 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context_gles_3_0_autogen.h: Creates a macro for interfaces in Context.
+
+#ifndef ANGLE_CONTEXT_GLES_3_0_AUTOGEN_H_
+#define ANGLE_CONTEXT_GLES_3_0_AUTOGEN_H_
+
+#define ANGLE_GLES_3_0_CONTEXT_API \
+ void beginQuery(QueryType targetPacked, QueryID idPacked); \
+ void beginTransformFeedback(PrimitiveMode primitiveModePacked); \
+ void bindBufferBase(BufferBinding targetPacked, GLuint index, BufferID bufferPacked); \
+ void bindBufferRange(BufferBinding targetPacked, GLuint index, BufferID bufferPacked, \
+ GLintptr offset, GLsizeiptr size); \
+ void bindSampler(GLuint unit, SamplerID samplerPacked); \
+ void bindTransformFeedback(GLenum target, TransformFeedbackID idPacked); \
+ void bindVertexArray(VertexArrayID arrayPacked); \
+ void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, \
+ GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); \
+ void clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); \
+ void clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value); \
+ void clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value); \
+ void clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value); \
+ GLenum clientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout); \
+ void compressedTexImage3D(TextureTarget targetPacked, GLint level, GLenum internalformat, \
+ GLsizei width, GLsizei height, GLsizei depth, GLint border, \
+ GLsizei imageSize, const void *data); \
+ void compressedTexSubImage3D(TextureTarget targetPacked, GLint level, GLint xoffset, \
+ GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, \
+ GLsizei depth, GLenum format, GLsizei imageSize, \
+ const void *data); \
+ void copyBufferSubData(BufferBinding readTargetPacked, BufferBinding writeTargetPacked, \
+ GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); \
+ void copyTexSubImage3D(TextureTarget targetPacked, GLint level, GLint xoffset, GLint yoffset, \
+ GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); \
+ void deleteQueries(GLsizei n, const QueryID *idsPacked); \
+ void deleteSamplers(GLsizei count, const SamplerID *samplersPacked); \
+ void deleteSync(GLsync sync); \
+ void deleteTransformFeedbacks(GLsizei n, const TransformFeedbackID *idsPacked); \
+ void deleteVertexArrays(GLsizei n, const VertexArrayID *arraysPacked); \
+ void drawArraysInstanced(PrimitiveMode modePacked, GLint first, GLsizei count, \
+ GLsizei instancecount); \
+ void drawBuffers(GLsizei n, const GLenum *bufs); \
+ void drawElementsInstanced(PrimitiveMode modePacked, GLsizei count, \
+ DrawElementsType typePacked, const void *indices, \
+ GLsizei instancecount); \
+ void drawRangeElements(PrimitiveMode modePacked, GLuint start, GLuint end, GLsizei count, \
+ DrawElementsType typePacked, const void *indices); \
+ void endQuery(QueryType targetPacked); \
+ void endTransformFeedback(); \
+ GLsync fenceSync(GLenum condition, GLbitfield flags); \
+ void flushMappedBufferRange(BufferBinding targetPacked, GLintptr offset, GLsizeiptr length); \
+ void framebufferTextureLayer(GLenum target, GLenum attachment, TextureID texturePacked, \
+ GLint level, GLint layer); \
+ void genQueries(GLsizei n, QueryID *idsPacked); \
+ void genSamplers(GLsizei count, SamplerID *samplersPacked); \
+ void genTransformFeedbacks(GLsizei n, TransformFeedbackID *idsPacked); \
+ void genVertexArrays(GLsizei n, VertexArrayID *arraysPacked); \
+ void getActiveUniformBlockName(ShaderProgramID programPacked, \
+ UniformBlockIndex uniformBlockIndexPacked, GLsizei bufSize, \
+ GLsizei *length, GLchar *uniformBlockName); \
+ void getActiveUniformBlockiv(ShaderProgramID programPacked, \
+ UniformBlockIndex uniformBlockIndexPacked, GLenum pname, \
+ GLint *params); \
+ void getActiveUniformsiv(ShaderProgramID programPacked, GLsizei uniformCount, \
+ const GLuint *uniformIndices, GLenum pname, GLint *params); \
+ void getBufferParameteri64v(BufferBinding targetPacked, GLenum pname, GLint64 *params); \
+ void getBufferPointerv(BufferBinding targetPacked, GLenum pname, void **params); \
+ GLint getFragDataLocation(ShaderProgramID programPacked, const GLchar *name); \
+ void getInteger64i_v(GLenum target, GLuint index, GLint64 *data); \
+ void getInteger64v(GLenum pname, GLint64 *data); \
+ void getIntegeri_v(GLenum target, GLuint index, GLint *data); \
+ void getInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei count, \
+ GLint *params); \
+ void getProgramBinary(ShaderProgramID programPacked, GLsizei bufSize, GLsizei *length, \
+ GLenum *binaryFormat, void *binary); \
+ void getQueryObjectuiv(QueryID idPacked, GLenum pname, GLuint *params); \
+ void getQueryiv(QueryType targetPacked, GLenum pname, GLint *params); \
+ void getSamplerParameterfv(SamplerID samplerPacked, GLenum pname, GLfloat *params); \
+ void getSamplerParameteriv(SamplerID samplerPacked, GLenum pname, GLint *params); \
+ const GLubyte *getStringi(GLenum name, GLuint index); \
+ void getSynciv(GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *values); \
+ void getTransformFeedbackVarying(ShaderProgramID programPacked, GLuint index, GLsizei bufSize, \
+ GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); \
+ GLuint getUniformBlockIndex(ShaderProgramID programPacked, const GLchar *uniformBlockName); \
+ void getUniformIndices(ShaderProgramID programPacked, GLsizei uniformCount, \
+ const GLchar *const *uniformNames, GLuint *uniformIndices); \
+ void getUniformuiv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLuint *params); \
+ void getVertexAttribIiv(GLuint index, GLenum pname, GLint *params); \
+ void getVertexAttribIuiv(GLuint index, GLenum pname, GLuint *params); \
+ void invalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments); \
+ void invalidateSubFramebuffer(GLenum target, GLsizei numAttachments, \
+ const GLenum *attachments, GLint x, GLint y, GLsizei width, \
+ GLsizei height); \
+ GLboolean isQuery(QueryID idPacked) const; \
+ GLboolean isSampler(SamplerID samplerPacked) const; \
+ GLboolean isSync(GLsync sync) const; \
+ GLboolean isTransformFeedback(TransformFeedbackID idPacked) const; \
+ GLboolean isVertexArray(VertexArrayID arrayPacked) const; \
+ void *mapBufferRange(BufferBinding targetPacked, GLintptr offset, GLsizeiptr length, \
+ GLbitfield access); \
+ void pauseTransformFeedback(); \
+ void programBinary(ShaderProgramID programPacked, GLenum binaryFormat, const void *binary, \
+ GLsizei length); \
+ void programParameteri(ShaderProgramID programPacked, GLenum pname, GLint value); \
+ void readBuffer(GLenum src); \
+ void renderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, \
+ GLsizei width, GLsizei height); \
+ void resumeTransformFeedback(); \
+ void samplerParameterf(SamplerID samplerPacked, GLenum pname, GLfloat param); \
+ void samplerParameterfv(SamplerID samplerPacked, GLenum pname, const GLfloat *param); \
+ void samplerParameteri(SamplerID samplerPacked, GLenum pname, GLint param); \
+ void samplerParameteriv(SamplerID samplerPacked, GLenum pname, const GLint *param); \
+ void texImage3D(TextureTarget targetPacked, GLint level, GLint internalformat, GLsizei width, \
+ GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, \
+ const void *pixels); \
+ void texStorage2D(TextureType targetPacked, GLsizei levels, GLenum internalformat, \
+ GLsizei width, GLsizei height); \
+ void texStorage3D(TextureType targetPacked, GLsizei levels, GLenum internalformat, \
+ GLsizei width, GLsizei height, GLsizei depth); \
+ void texSubImage3D(TextureTarget targetPacked, GLint level, GLint xoffset, GLint yoffset, \
+ GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, \
+ GLenum type, const void *pixels); \
+ void transformFeedbackVaryings(ShaderProgramID programPacked, GLsizei count, \
+ const GLchar *const *varyings, GLenum bufferMode); \
+ void uniform1ui(UniformLocation locationPacked, GLuint v0); \
+ void uniform1uiv(UniformLocation locationPacked, GLsizei count, const GLuint *value); \
+ void uniform2ui(UniformLocation locationPacked, GLuint v0, GLuint v1); \
+ void uniform2uiv(UniformLocation locationPacked, GLsizei count, const GLuint *value); \
+ void uniform3ui(UniformLocation locationPacked, GLuint v0, GLuint v1, GLuint v2); \
+ void uniform3uiv(UniformLocation locationPacked, GLsizei count, const GLuint *value); \
+ void uniform4ui(UniformLocation locationPacked, GLuint v0, GLuint v1, GLuint v2, GLuint v3); \
+ void uniform4uiv(UniformLocation locationPacked, GLsizei count, const GLuint *value); \
+ void uniformBlockBinding(ShaderProgramID programPacked, \
+ UniformBlockIndex uniformBlockIndexPacked, \
+ GLuint uniformBlockBinding); \
+ void uniformMatrix2x3fv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLfloat *value); \
+ void uniformMatrix2x4fv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLfloat *value); \
+ void uniformMatrix3x2fv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLfloat *value); \
+ void uniformMatrix3x4fv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLfloat *value); \
+ void uniformMatrix4x2fv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLfloat *value); \
+ void uniformMatrix4x3fv(UniformLocation locationPacked, GLsizei count, GLboolean transpose, \
+ const GLfloat *value); \
+ GLboolean unmapBuffer(BufferBinding targetPacked); \
+ void vertexAttribDivisor(GLuint index, GLuint divisor); \
+ void vertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w); \
+ void vertexAttribI4iv(GLuint index, const GLint *v); \
+ void vertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); \
+ void vertexAttribI4uiv(GLuint index, const GLuint *v); \
+ void vertexAttribIPointer(GLuint index, GLint size, VertexAttribType typePacked, \
+ GLsizei stride, const void *pointer); \
+ void waitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
+
+#endif // ANGLE_CONTEXT_API_3_0_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Context_gles_3_1_autogen.h b/gfx/angle/checkout/src/libANGLE/Context_gles_3_1_autogen.h
new file mode 100644
index 0000000000..0d8c5dcabd
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Context_gles_3_1_autogen.h
@@ -0,0 +1,133 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context_gles_3_1_autogen.h: Creates a macro for interfaces in Context.
+
+#ifndef ANGLE_CONTEXT_GLES_3_1_AUTOGEN_H_
+#define ANGLE_CONTEXT_GLES_3_1_AUTOGEN_H_
+
+#define ANGLE_GLES_3_1_CONTEXT_API \
+ void activeShaderProgram(ProgramPipelineID pipelinePacked, ShaderProgramID programPacked); \
+ void bindImageTexture(GLuint unit, TextureID texturePacked, GLint level, GLboolean layered, \
+ GLint layer, GLenum access, GLenum format); \
+ void bindProgramPipeline(ProgramPipelineID pipelinePacked); \
+ void bindVertexBuffer(GLuint bindingindex, BufferID bufferPacked, GLintptr offset, \
+ GLsizei stride); \
+ GLuint createShaderProgramv(ShaderType typePacked, GLsizei count, \
+ const GLchar *const *strings); \
+ void deleteProgramPipelines(GLsizei n, const ProgramPipelineID *pipelinesPacked); \
+ void dispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); \
+ void dispatchComputeIndirect(GLintptr indirect); \
+ void drawArraysIndirect(PrimitiveMode modePacked, const void *indirect); \
+ void drawElementsIndirect(PrimitiveMode modePacked, DrawElementsType typePacked, \
+ const void *indirect); \
+ void framebufferParameteri(GLenum target, GLenum pname, GLint param); \
+ void genProgramPipelines(GLsizei n, ProgramPipelineID *pipelinesPacked); \
+ void getBooleani_v(GLenum target, GLuint index, GLboolean *data); \
+ void getFramebufferParameteriv(GLenum target, GLenum pname, GLint *params); \
+ void getMultisamplefv(GLenum pname, GLuint index, GLfloat *val); \
+ void getProgramInterfaceiv(ShaderProgramID programPacked, GLenum programInterface, \
+ GLenum pname, GLint *params); \
+ void getProgramPipelineInfoLog(ProgramPipelineID pipelinePacked, GLsizei bufSize, \
+ GLsizei *length, GLchar *infoLog); \
+ void getProgramPipelineiv(ProgramPipelineID pipelinePacked, GLenum pname, GLint *params); \
+ GLuint getProgramResourceIndex(ShaderProgramID programPacked, GLenum programInterface, \
+ const GLchar *name); \
+ GLint getProgramResourceLocation(ShaderProgramID programPacked, GLenum programInterface, \
+ const GLchar *name); \
+ void getProgramResourceName(ShaderProgramID programPacked, GLenum programInterface, \
+ GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); \
+ void getProgramResourceiv(ShaderProgramID programPacked, GLenum programInterface, \
+ GLuint index, GLsizei propCount, const GLenum *props, GLsizei count, \
+ GLsizei *length, GLint *params); \
+ void getTexLevelParameterfv(TextureTarget targetPacked, GLint level, GLenum pname, \
+ GLfloat *params); \
+ void getTexLevelParameteriv(TextureTarget targetPacked, GLint level, GLenum pname, \
+ GLint *params); \
+ GLboolean isProgramPipeline(ProgramPipelineID pipelinePacked) const; \
+ void memoryBarrier(GLbitfield barriers); \
+ void memoryBarrierByRegion(GLbitfield barriers); \
+ void programUniform1f(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLfloat v0); \
+ void programUniform1fv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLfloat *value); \
+ void programUniform1i(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLint v0); \
+ void programUniform1iv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLint *value); \
+ void programUniform1ui(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLuint v0); \
+ void programUniform1uiv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLuint *value); \
+ void programUniform2f(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLfloat v0, GLfloat v1); \
+ void programUniform2fv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLfloat *value); \
+ void programUniform2i(ShaderProgramID programPacked, UniformLocation locationPacked, GLint v0, \
+ GLint v1); \
+ void programUniform2iv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLint *value); \
+ void programUniform2ui(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLuint v0, GLuint v1); \
+ void programUniform2uiv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLuint *value); \
+ void programUniform3f(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLfloat v0, GLfloat v1, GLfloat v2); \
+ void programUniform3fv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLfloat *value); \
+ void programUniform3i(ShaderProgramID programPacked, UniformLocation locationPacked, GLint v0, \
+ GLint v1, GLint v2); \
+ void programUniform3iv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLint *value); \
+ void programUniform3ui(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLuint v0, GLuint v1, GLuint v2); \
+ void programUniform3uiv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLuint *value); \
+ void programUniform4f(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); \
+ void programUniform4fv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLfloat *value); \
+ void programUniform4i(ShaderProgramID programPacked, UniformLocation locationPacked, GLint v0, \
+ GLint v1, GLint v2, GLint v3); \
+ void programUniform4iv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLint *value); \
+ void programUniform4ui(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLuint v0, GLuint v1, GLuint v2, GLuint v3); \
+ void programUniform4uiv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, const GLuint *value); \
+ void programUniformMatrix2fv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLfloat *value); \
+ void programUniformMatrix2x3fv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLfloat *value); \
+ void programUniformMatrix2x4fv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLfloat *value); \
+ void programUniformMatrix3fv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLfloat *value); \
+ void programUniformMatrix3x2fv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLfloat *value); \
+ void programUniformMatrix3x4fv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLfloat *value); \
+ void programUniformMatrix4fv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLfloat *value); \
+ void programUniformMatrix4x2fv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLfloat *value); \
+ void programUniformMatrix4x3fv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei count, GLboolean transpose, const GLfloat *value); \
+ void sampleMaski(GLuint maskNumber, GLbitfield mask); \
+ void texStorage2DMultisample(TextureType targetPacked, GLsizei samples, GLenum internalformat, \
+ GLsizei width, GLsizei height, GLboolean fixedsamplelocations); \
+ void useProgramStages(ProgramPipelineID pipelinePacked, GLbitfield stages, \
+ ShaderProgramID programPacked); \
+ void validateProgramPipeline(ProgramPipelineID pipelinePacked); \
+ void vertexAttribBinding(GLuint attribindex, GLuint bindingindex); \
+ void vertexAttribFormat(GLuint attribindex, GLint size, VertexAttribType typePacked, \
+ GLboolean normalized, GLuint relativeoffset); \
+ void vertexAttribIFormat(GLuint attribindex, GLint size, VertexAttribType typePacked, \
+ GLuint relativeoffset); \
+ void vertexBindingDivisor(GLuint bindingindex, GLuint divisor);
+
+#endif // ANGLE_CONTEXT_API_3_1_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Context_gles_3_2_autogen.h b/gfx/angle/checkout/src/libANGLE/Context_gles_3_2_autogen.h
new file mode 100644
index 0000000000..520b86c130
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Context_gles_3_2_autogen.h
@@ -0,0 +1,83 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context_gles_3_2_autogen.h: Creates a macro for interfaces in Context.
+
+#ifndef ANGLE_CONTEXT_GLES_3_2_AUTOGEN_H_
+#define ANGLE_CONTEXT_GLES_3_2_AUTOGEN_H_
+
+#define ANGLE_GLES_3_2_CONTEXT_API \
+ void blendBarrier(); \
+ void blendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeAlpha); \
+ void blendEquationi(GLuint buf, GLenum mode); \
+ void blendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, \
+ GLenum dstAlpha); \
+ void blendFunci(GLuint buf, GLenum src, GLenum dst); \
+ void colorMaski(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); \
+ void copyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, \
+ GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, \
+ GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, \
+ GLsizei srcHeight, GLsizei srcDepth); \
+ void debugMessageCallback(GLDEBUGPROC callback, const void *userParam); \
+ void debugMessageControl(GLenum source, GLenum type, GLenum severity, GLsizei count, \
+ const GLuint *ids, GLboolean enabled); \
+ void debugMessageInsert(GLenum source, GLenum type, GLuint id, GLenum severity, \
+ GLsizei length, const GLchar *buf); \
+ void disablei(GLenum target, GLuint index); \
+ void drawElementsBaseVertex(PrimitiveMode modePacked, GLsizei count, \
+ DrawElementsType typePacked, const void *indices, \
+ GLint basevertex); \
+ void drawElementsInstancedBaseVertex(PrimitiveMode modePacked, GLsizei count, \
+ DrawElementsType typePacked, const void *indices, \
+ GLsizei instancecount, GLint basevertex); \
+ void drawRangeElementsBaseVertex(PrimitiveMode modePacked, GLuint start, GLuint end, \
+ GLsizei count, DrawElementsType typePacked, \
+ const void *indices, GLint basevertex); \
+ void enablei(GLenum target, GLuint index); \
+ void framebufferTexture(GLenum target, GLenum attachment, TextureID texturePacked, \
+ GLint level); \
+ GLuint getDebugMessageLog(GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, \
+ GLuint *ids, GLenum *severities, GLsizei *lengths, \
+ GLchar *messageLog); \
+ GLenum getGraphicsResetStatus(); \
+ void getObjectLabel(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, \
+ GLchar *label); \
+ void getObjectPtrLabel(const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); \
+ void getPointerv(GLenum pname, void **params); \
+ void getSamplerParameterIiv(SamplerID samplerPacked, GLenum pname, GLint *params); \
+ void getSamplerParameterIuiv(SamplerID samplerPacked, GLenum pname, GLuint *params); \
+ void getTexParameterIiv(TextureType targetPacked, GLenum pname, GLint *params); \
+ void getTexParameterIuiv(TextureType targetPacked, GLenum pname, GLuint *params); \
+ void getnUniformfv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei bufSize, GLfloat *params); \
+ void getnUniformiv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei bufSize, GLint *params); \
+ void getnUniformuiv(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei bufSize, GLuint *params); \
+ GLboolean isEnabledi(GLenum target, GLuint index) const; \
+ void minSampleShading(GLfloat value); \
+ void objectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar *label); \
+ void objectPtrLabel(const void *ptr, GLsizei length, const GLchar *label); \
+ void patchParameteri(GLenum pname, GLint value); \
+ void popDebugGroup(); \
+ void primitiveBoundingBox(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, \
+ GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); \
+ void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar *message); \
+ void readnPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, \
+ GLsizei bufSize, void *data); \
+ void samplerParameterIiv(SamplerID samplerPacked, GLenum pname, const GLint *param); \
+ void samplerParameterIuiv(SamplerID samplerPacked, GLenum pname, const GLuint *param); \
+ void texBuffer(TextureType targetPacked, GLenum internalformat, BufferID bufferPacked); \
+ void texBufferRange(TextureType targetPacked, GLenum internalformat, BufferID bufferPacked, \
+ GLintptr offset, GLsizeiptr size); \
+ void texParameterIiv(TextureType targetPacked, GLenum pname, const GLint *params); \
+ void texParameterIuiv(TextureType targetPacked, GLenum pname, const GLuint *params); \
+ void texStorage3DMultisample(TextureType targetPacked, GLsizei samples, GLenum internalformat, \
+ GLsizei width, GLsizei height, GLsizei depth, \
+ GLboolean fixedsamplelocations);
+
+#endif // ANGLE_CONTEXT_API_3_2_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Context_gles_ext_autogen.h b/gfx/angle/checkout/src/libANGLE/Context_gles_ext_autogen.h
new file mode 100644
index 0000000000..286a5061e2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Context_gles_ext_autogen.h
@@ -0,0 +1,616 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context_gles_ext_autogen.h: Creates a macro for interfaces in Context.
+
+#ifndef ANGLE_CONTEXT_GLES_EXT_AUTOGEN_H_
+#define ANGLE_CONTEXT_GLES_EXT_AUTOGEN_H_
+
+#define ANGLE_GLES_EXT_CONTEXT_API \
+ \
+ /* GLES1 Extensions */ \
+ \
+ /* GL_OES_draw_texture */ \
+ void drawTexf(GLfloat x, GLfloat y, GLfloat z, GLfloat width, GLfloat height); \
+ void drawTexfv(const GLfloat *coords); \
+ void drawTexi(GLint x, GLint y, GLint z, GLint width, GLint height); \
+ void drawTexiv(const GLint *coords); \
+ void drawTexs(GLshort x, GLshort y, GLshort z, GLshort width, GLshort height); \
+ void drawTexsv(const GLshort *coords); \
+ void drawTexx(GLfixed x, GLfixed y, GLfixed z, GLfixed width, GLfixed height); \
+ void drawTexxv(const GLfixed *coords); \
+ /* GL_OES_framebuffer_object */ \
+ /* GL_OES_matrix_palette */ \
+ void currentPaletteMatrix(GLuint matrixpaletteindex); \
+ void loadPaletteFromModelViewMatrix(); \
+ void matrixIndexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); \
+ void weightPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); \
+ /* GL_OES_point_size_array */ \
+ void pointSizePointer(VertexAttribType typePacked, GLsizei stride, const void *pointer); \
+ /* GL_OES_point_sprite */ \
+ /* GL_OES_query_matrix */ \
+ GLbitfield queryMatrixx(GLfixed *mantissa, GLint *exponent); \
+ /* GL_OES_texture_cube_map */ \
+ void getTexGenfv(GLenum coord, GLenum pname, GLfloat *params); \
+ void getTexGeniv(GLenum coord, GLenum pname, GLint *params); \
+ void getTexGenxv(GLenum coord, GLenum pname, GLfixed *params); \
+ void texGenf(GLenum coord, GLenum pname, GLfloat param); \
+ void texGenfv(GLenum coord, GLenum pname, const GLfloat *params); \
+ void texGeni(GLenum coord, GLenum pname, GLint param); \
+ void texGeniv(GLenum coord, GLenum pname, const GLint *params); \
+ void texGenx(GLenum coord, GLenum pname, GLfixed param); \
+ void texGenxv(GLenum coord, GLenum pname, const GLfixed *params); \
+ \
+ /* GLES2+ Extensions */ \
+ \
+ /* GL_AMD_performance_monitor */ \
+ void beginPerfMonitor(GLuint monitor); \
+ void deletePerfMonitors(GLsizei n, GLuint *monitors); \
+ void endPerfMonitor(GLuint monitor); \
+ void genPerfMonitors(GLsizei n, GLuint *monitors); \
+ void getPerfMonitorCounterData(GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, \
+ GLint *bytesWritten); \
+ void getPerfMonitorCounterInfo(GLuint group, GLuint counter, GLenum pname, void *data); \
+ void getPerfMonitorCounterString(GLuint group, GLuint counter, GLsizei bufSize, \
+ GLsizei *length, GLchar *counterString); \
+ void getPerfMonitorCounters(GLuint group, GLint *numCounters, GLint *maxActiveCounters, \
+ GLsizei counterSize, GLuint *counters); \
+ void getPerfMonitorGroupString(GLuint group, GLsizei bufSize, GLsizei *length, \
+ GLchar *groupString); \
+ void getPerfMonitorGroups(GLint *numGroups, GLsizei groupsSize, GLuint *groups); \
+ void selectPerfMonitorCounters(GLuint monitor, GLboolean enable, GLuint group, \
+ GLint numCounters, GLuint *counterList); \
+ /* GL_ANDROID_extension_pack_es31a */ \
+ /* GL_ANGLE_depth_texture */ \
+ /* GL_ANGLE_framebuffer_blit */ \
+ /* GL_ANGLE_instanced_arrays */ \
+ /* GL_ANGLE_pack_reverse_row_order */ \
+ /* GL_ANGLE_texture_usage */ \
+ /* GL_ANGLE_translated_shader_source */ \
+ void getTranslatedShaderSource(ShaderProgramID shaderPacked, GLsizei bufSize, GLsizei *length, \
+ GLchar *source); \
+ /* GL_APPLE_clip_distance */ \
+ /* GL_ARB_sync */ \
+ /* GL_EXT_EGL_image_array */ \
+ /* GL_EXT_EGL_image_external_wrap_modes */ \
+ /* GL_EXT_EGL_image_storage */ \
+ void eGLImageTargetTexStorage(GLenum target, GLeglImageOES image, const GLint *attrib_list); \
+ void eGLImageTargetTextureStorage(GLuint texture, GLeglImageOES image, \
+ const GLint *attrib_list); \
+ /* GL_EXT_YUV_target */ \
+ /* GL_EXT_base_instance */ \
+ void drawArraysInstancedBaseInstance(PrimitiveMode modePacked, GLint first, GLsizei count, \
+ GLsizei instancecount, GLuint baseinstance); \
+ void drawElementsInstancedBaseInstance(PrimitiveMode modePacked, GLsizei count, \
+ DrawElementsType typePacked, const void *indices, \
+ GLsizei instancecount, GLuint baseinstance); \
+ void drawElementsInstancedBaseVertexBaseInstance( \
+ PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, const void *indices, \
+ GLsizei instancecount, GLint basevertex, GLuint baseinstance); \
+ /* GL_EXT_blend_func_extended */ \
+ void bindFragDataLocation(ShaderProgramID programPacked, GLuint color, const GLchar *name); \
+ void bindFragDataLocationIndexed(ShaderProgramID programPacked, GLuint colorNumber, \
+ GLuint index, const GLchar *name); \
+ GLint getFragDataIndex(ShaderProgramID programPacked, const GLchar *name); \
+ GLint getProgramResourceLocationIndex(ShaderProgramID programPacked, GLenum programInterface, \
+ const GLchar *name); \
+ /* GL_EXT_blend_minmax */ \
+ /* GL_EXT_buffer_storage */ \
+ void bufferStorage(BufferBinding targetPacked, GLsizeiptr size, const void *data, \
+ GLbitfield flags); \
+ /* GL_EXT_clip_control */ \
+ void clipControl(GLenum origin, GLenum depth); \
+ /* GL_EXT_clip_cull_distance */ \
+ /* GL_EXT_color_buffer_float */ \
+ /* GL_EXT_color_buffer_half_float */ \
+ /* GL_EXT_compressed_ETC1_RGB8_sub_texture */ \
+ /* GL_EXT_copy_image */ \
+ /* GL_EXT_debug_label */ \
+ void labelObject(GLenum type, GLuint object, GLsizei length, const GLchar *label); \
+ /* GL_EXT_debug_marker */ \
+ void insertEventMarker(GLsizei length, const GLchar *marker); \
+ void popGroupMarker(); \
+ void pushGroupMarker(GLsizei length, const GLchar *marker); \
+ /* GL_EXT_discard_framebuffer */ \
+ void discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments); \
+ /* GL_EXT_disjoint_timer_query */ \
+ void getQueryObjecti64v(QueryID idPacked, GLenum pname, GLint64 *params); \
+ void getQueryObjectiv(QueryID idPacked, GLenum pname, GLint *params); \
+ void getQueryObjectui64v(QueryID idPacked, GLenum pname, GLuint64 *params); \
+ void queryCounter(QueryID idPacked, QueryType targetPacked); \
+ /* GL_EXT_draw_buffers */ \
+ /* GL_EXT_draw_buffers_indexed */ \
+ /* GL_EXT_draw_elements_base_vertex */ \
+ void multiDrawElementsBaseVertex(PrimitiveMode modePacked, const GLsizei *count, \
+ DrawElementsType typePacked, const void *const *indices, \
+ GLsizei drawcount, const GLint *basevertex); \
+ /* GL_EXT_external_buffer */ \
+ void bufferStorageExternal(BufferBinding targetPacked, GLintptr offset, GLsizeiptr size, \
+ GLeglClientBufferEXT clientBuffer, GLbitfield flags); \
+ void namedBufferStorageExternal(GLuint buffer, GLintptr offset, GLsizeiptr size, \
+ GLeglClientBufferEXT clientBuffer, GLbitfield flags); \
+ /* GL_EXT_float_blend */ \
+ /* GL_EXT_frag_depth */ \
+ /* GL_EXT_geometry_shader */ \
+ /* GL_EXT_gpu_shader5 */ \
+ /* GL_EXT_instanced_arrays */ \
+ /* GL_EXT_map_buffer_range */ \
+ /* GL_EXT_memory_object */ \
+ void bufferStorageMem(TextureType targetPacked, GLsizeiptr size, MemoryObjectID memoryPacked, \
+ GLuint64 offset); \
+ void createMemoryObjects(GLsizei n, MemoryObjectID *memoryObjectsPacked); \
+ void deleteMemoryObjects(GLsizei n, const MemoryObjectID *memoryObjectsPacked); \
+ void getMemoryObjectParameteriv(MemoryObjectID memoryObjectPacked, GLenum pname, \
+ GLint *params); \
+ void getUnsignedBytev(GLenum pname, GLubyte *data); \
+ void getUnsignedBytei_v(GLenum target, GLuint index, GLubyte *data); \
+ GLboolean isMemoryObject(MemoryObjectID memoryObjectPacked) const; \
+ void memoryObjectParameteriv(MemoryObjectID memoryObjectPacked, GLenum pname, \
+ const GLint *params); \
+ void texStorageMem2D(TextureType targetPacked, GLsizei levels, GLenum internalFormat, \
+ GLsizei width, GLsizei height, MemoryObjectID memoryPacked, \
+ GLuint64 offset); \
+ void texStorageMem2DMultisample(TextureType targetPacked, GLsizei samples, \
+ GLenum internalFormat, GLsizei width, GLsizei height, \
+ GLboolean fixedSampleLocations, MemoryObjectID memoryPacked, \
+ GLuint64 offset); \
+ void texStorageMem3D(TextureType targetPacked, GLsizei levels, GLenum internalFormat, \
+ GLsizei width, GLsizei height, GLsizei depth, \
+ MemoryObjectID memoryPacked, GLuint64 offset); \
+ void texStorageMem3DMultisample(TextureType targetPacked, GLsizei samples, \
+ GLenum internalFormat, GLsizei width, GLsizei height, \
+ GLsizei depth, GLboolean fixedSampleLocations, \
+ MemoryObjectID memoryPacked, GLuint64 offset); \
+ /* GL_EXT_memory_object_fd */ \
+ void importMemoryFd(MemoryObjectID memoryPacked, GLuint64 size, HandleType handleTypePacked, \
+ GLint fd); \
+ /* GL_EXT_multi_draw_indirect */ \
+ void multiDrawArraysIndirect(PrimitiveMode modePacked, const void *indirect, \
+ GLsizei drawcount, GLsizei stride); \
+ void multiDrawElementsIndirect(PrimitiveMode modePacked, DrawElementsType typePacked, \
+ const void *indirect, GLsizei drawcount, GLsizei stride); \
+ /* GL_EXT_multisample_compatibility */ \
+ /* GL_EXT_multisampled_render_to_texture */ \
+ void framebufferTexture2DMultisample(GLenum target, GLenum attachment, \
+ TextureTarget textargetPacked, TextureID texturePacked, \
+ GLint level, GLsizei samples); \
+ void renderbufferStorageMultisampleEXT(GLenum target, GLsizei samples, GLenum internalformat, \
+ GLsizei width, GLsizei height); \
+ /* GL_EXT_multisampled_render_to_texture2 */ \
+ /* GL_EXT_occlusion_query_boolean */ \
+ /* GL_EXT_primitive_bounding_box */ \
+ /* GL_EXT_protected_textures */ \
+ /* GL_EXT_pvrtc_sRGB */ \
+ /* GL_EXT_read_format_bgra */ \
+ /* GL_EXT_robustness */ \
+ /* GL_EXT_sRGB */ \
+ /* GL_EXT_sRGB_write_control */ \
+ /* GL_EXT_semaphore */ \
+ void deleteSemaphores(GLsizei n, const SemaphoreID *semaphoresPacked); \
+ void genSemaphores(GLsizei n, SemaphoreID *semaphoresPacked); \
+ void getSemaphoreParameterui64v(SemaphoreID semaphorePacked, GLenum pname, GLuint64 *params); \
+ GLboolean isSemaphore(SemaphoreID semaphorePacked) const; \
+ void semaphoreParameterui64v(SemaphoreID semaphorePacked, GLenum pname, \
+ const GLuint64 *params); \
+ void signalSemaphore(SemaphoreID semaphorePacked, GLuint numBufferBarriers, \
+ const BufferID *buffersPacked, GLuint numTextureBarriers, \
+ const TextureID *texturesPacked, const GLenum *dstLayouts); \
+ void waitSemaphore(SemaphoreID semaphorePacked, GLuint numBufferBarriers, \
+ const BufferID *buffersPacked, GLuint numTextureBarriers, \
+ const TextureID *texturesPacked, const GLenum *srcLayouts); \
+ /* GL_EXT_semaphore_fd */ \
+ void importSemaphoreFd(SemaphoreID semaphorePacked, HandleType handleTypePacked, GLint fd); \
+ /* GL_EXT_separate_shader_objects */ \
+ /* GL_EXT_shader_framebuffer_fetch */ \
+ /* GL_EXT_shader_framebuffer_fetch_non_coherent */ \
+ void framebufferFetchBarrier(); \
+ /* GL_EXT_shader_io_blocks */ \
+ /* GL_EXT_shader_non_constant_global_initializers */ \
+ /* GL_EXT_shader_texture_lod */ \
+ /* GL_EXT_shadow_samplers */ \
+ /* GL_EXT_tessellation_shader */ \
+ /* GL_EXT_texture_border_clamp */ \
+ /* GL_EXT_texture_buffer */ \
+ /* GL_EXT_texture_compression_bptc */ \
+ /* GL_EXT_texture_compression_dxt1 */ \
+ /* GL_EXT_texture_compression_rgtc */ \
+ /* GL_EXT_texture_compression_s3tc */ \
+ /* GL_EXT_texture_compression_s3tc_srgb */ \
+ /* GL_EXT_texture_cube_map_array */ \
+ /* GL_EXT_texture_filter_anisotropic */ \
+ /* GL_EXT_texture_format_BGRA8888 */ \
+ /* GL_EXT_texture_format_sRGB_override */ \
+ /* GL_EXT_texture_norm16 */ \
+ /* GL_EXT_texture_rg */ \
+ /* GL_EXT_texture_sRGB_R8 */ \
+ /* GL_EXT_texture_sRGB_RG8 */ \
+ /* GL_EXT_texture_sRGB_decode */ \
+ /* GL_EXT_texture_storage */ \
+ void texStorage1D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); \
+ /* GL_EXT_texture_type_2_10_10_10_REV */ \
+ /* GL_EXT_unpack_subimage */ \
+ /* GL_IMG_texture_compression_pvrtc */ \
+ /* GL_IMG_texture_compression_pvrtc2 */ \
+ /* GL_KHR_blend_equation_advanced */ \
+ /* GL_KHR_debug */ \
+ /* GL_KHR_no_error */ \
+ /* GL_KHR_parallel_shader_compile */ \
+ void maxShaderCompilerThreads(GLuint count); \
+ /* GL_KHR_robust_buffer_access_behavior */ \
+ /* GL_KHR_texture_compression_astc_hdr */ \
+ /* GL_KHR_texture_compression_astc_ldr */ \
+ /* GL_KHR_texture_compression_astc_sliced_3d */ \
+ /* GL_MESA_framebuffer_flip_y */ \
+ void framebufferParameteriMESA(GLenum target, GLenum pname, GLint param); \
+ void getFramebufferParameterivMESA(GLenum target, GLenum pname, GLint *params); \
+ /* GL_NV_EGL_stream_consumer_external */ \
+ /* GL_NV_depth_buffer_float2 */ \
+ /* GL_NV_fence */ \
+ void deleteFencesNV(GLsizei n, const FenceNVID *fencesPacked); \
+ void finishFenceNV(FenceNVID fencePacked); \
+ void genFencesNV(GLsizei n, FenceNVID *fencesPacked); \
+ void getFenceivNV(FenceNVID fencePacked, GLenum pname, GLint *params); \
+ GLboolean isFenceNV(FenceNVID fencePacked) const; \
+ void setFenceNV(FenceNVID fencePacked, GLenum condition); \
+ GLboolean testFenceNV(FenceNVID fencePacked); \
+ /* GL_NV_framebuffer_blit */ \
+ void blitFramebufferNV(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, \
+ GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); \
+ /* GL_NV_pack_subimage */ \
+ /* GL_NV_pixel_buffer_object */ \
+ /* GL_NV_read_depth */ \
+ /* GL_NV_read_depth_stencil */ \
+ /* GL_NV_read_stencil */ \
+ /* GL_NV_robustness_video_memory_purge */ \
+ /* GL_NV_shader_noperspective_interpolation */ \
+ /* GL_OES_EGL_image */ \
+ void eGLImageTargetRenderbufferStorage(GLenum target, GLeglImageOES image); \
+ void eGLImageTargetTexture2D(TextureType targetPacked, GLeglImageOES image); \
+ /* GL_OES_EGL_image_external */ \
+ /* GL_OES_EGL_image_external_essl3 */ \
+ /* GL_OES_EGL_sync */ \
+ /* GL_OES_compressed_EAC_R11_signed_texture */ \
+ /* GL_OES_compressed_EAC_R11_unsigned_texture */ \
+ /* GL_OES_compressed_EAC_RG11_signed_texture */ \
+ /* GL_OES_compressed_EAC_RG11_unsigned_texture */ \
+ /* GL_OES_compressed_ETC1_RGB8_texture */ \
+ /* GL_OES_compressed_ETC2_RGB8_texture */ \
+ /* GL_OES_compressed_ETC2_RGBA8_texture */ \
+ /* GL_OES_compressed_ETC2_punchthroughA_RGBA8_texture */ \
+ /* GL_OES_compressed_ETC2_punchthroughA_sRGB8_alpha_texture */ \
+ /* GL_OES_compressed_ETC2_sRGB8_alpha8_texture */ \
+ /* GL_OES_compressed_ETC2_sRGB8_texture */ \
+ /* GL_OES_compressed_paletted_texture */ \
+ /* GL_OES_copy_image */ \
+ /* GL_OES_depth24 */ \
+ /* GL_OES_depth32 */ \
+ /* GL_OES_depth_texture */ \
+ /* GL_OES_depth_texture_cube_map */ \
+ /* GL_OES_draw_buffers_indexed */ \
+ /* GL_OES_draw_elements_base_vertex */ \
+ /* GL_OES_element_index_uint */ \
+ /* GL_OES_fbo_render_mipmap */ \
+ /* GL_OES_geometry_shader */ \
+ /* GL_OES_get_program_binary */ \
+ /* GL_OES_mapbuffer */ \
+ void *mapBuffer(BufferBinding targetPacked, GLenum access); \
+ /* GL_OES_packed_depth_stencil */ \
+ /* GL_OES_primitive_bounding_box */ \
+ /* GL_OES_rgb8_rgba8 */ \
+ /* GL_OES_sample_shading */ \
+ /* GL_OES_sample_variables */ \
+ /* GL_OES_shader_image_atomic */ \
+ /* GL_OES_shader_io_blocks */ \
+ /* GL_OES_shader_multisample_interpolation */ \
+ /* GL_OES_standard_derivatives */ \
+ /* GL_OES_surfaceless_context */ \
+ /* GL_OES_texture_3D */ \
+ void framebufferTexture3D(GLenum target, GLenum attachment, TextureTarget textargetPacked, \
+ TextureID texturePacked, GLint level, GLint zoffset); \
+ /* GL_OES_texture_border_clamp */ \
+ /* GL_OES_texture_buffer */ \
+ /* GL_OES_texture_compression_astc */ \
+ /* GL_OES_texture_cube_map_array */ \
+ /* GL_OES_texture_float */ \
+ /* GL_OES_texture_float_linear */ \
+ /* GL_OES_texture_half_float */ \
+ /* GL_OES_texture_half_float_linear */ \
+ /* GL_OES_texture_npot */ \
+ /* GL_OES_texture_stencil8 */ \
+ /* GL_OES_texture_storage_multisample_2d_array */ \
+ /* GL_OES_vertex_array_object */ \
+ /* GL_OES_vertex_half_float */ \
+ /* GL_OES_vertex_type_10_10_10_2 */ \
+ /* GL_OVR_multiview */ \
+ void framebufferTextureMultiview(GLenum target, GLenum attachment, TextureID texturePacked, \
+ GLint level, GLint baseViewIndex, GLsizei numViews); \
+ /* GL_OVR_multiview2 */ \
+ /* GL_QCOM_shading_rate */ \
+ void shadingRateQCOM(GLenum rate); \
+ /* GL_WEBGL_video_texture */ \
+ \
+ /* ANGLE Extensions */ \
+ \
+ /* GL_ANGLE_base_vertex_base_instance */ \
+ void drawArraysInstancedBaseInstanceANGLE(PrimitiveMode modePacked, GLint first, \
+ GLsizei count, GLsizei instanceCount, \
+ GLuint baseInstance); \
+ void drawElementsInstancedBaseVertexBaseInstanceANGLE( \
+ PrimitiveMode modePacked, GLsizei count, DrawElementsType typePacked, \
+ const GLvoid *indices, GLsizei instanceCount, GLint baseVertex, GLuint baseInstance); \
+ void multiDrawArraysInstancedBaseInstance( \
+ PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, \
+ const GLsizei *instanceCounts, const GLuint *baseInstances, GLsizei drawcount); \
+ void multiDrawElementsInstancedBaseVertexBaseInstance( \
+ PrimitiveMode modePacked, const GLsizei *counts, DrawElementsType typePacked, \
+ const GLvoid *const *indices, const GLsizei *instanceCounts, const GLint *baseVertices, \
+ const GLuint *baseInstances, GLsizei drawcount); \
+ /* GL_ANGLE_base_vertex_base_instance_shader_builtin */ \
+ /* GL_ANGLE_client_arrays */ \
+ /* GL_ANGLE_compressed_texture_etc */ \
+ /* GL_ANGLE_copy_texture_3d */ \
+ void copyTexture3D(TextureID sourceIdPacked, GLint sourceLevel, \
+ TextureTarget destTargetPacked, TextureID destIdPacked, GLint destLevel, \
+ GLint internalFormat, GLenum destType, GLboolean unpackFlipY, \
+ GLboolean unpackPremultiplyAlpha, GLboolean unpackUnmultiplyAlpha); \
+ void copySubTexture3D(TextureID sourceIdPacked, GLint sourceLevel, \
+ TextureTarget destTargetPacked, TextureID destIdPacked, GLint destLevel, \
+ GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLint z, \
+ GLint width, GLint height, GLint depth, GLboolean unpackFlipY, \
+ GLboolean unpackPremultiplyAlpha, GLboolean unpackUnmultiplyAlpha); \
+ /* GL_ANGLE_framebuffer_multisample */ \
+ /* GL_ANGLE_get_image */ \
+ void getTexImage(TextureTarget targetPacked, GLint level, GLenum format, GLenum type, \
+ void *pixels); \
+ void getCompressedTexImage(TextureTarget targetPacked, GLint level, void *pixels); \
+ void getRenderbufferImage(GLenum target, GLenum format, GLenum type, void *pixels); \
+ /* GL_ANGLE_get_serialized_context_string */ \
+ /* GL_ANGLE_get_tex_level_parameter */ \
+ /* GL_ANGLE_logic_op */ \
+ void logicOpANGLE(LogicalOperation opcodePacked); \
+ /* GL_ANGLE_lossy_etc_decode */ \
+ /* GL_ANGLE_memory_object_flags */ \
+ void texStorageMemFlags2D(TextureType targetPacked, GLsizei levels, GLenum internalFormat, \
+ GLsizei width, GLsizei height, MemoryObjectID memoryPacked, \
+ GLuint64 offset, GLbitfield createFlags, GLbitfield usageFlags, \
+ const void *imageCreateInfoPNext); \
+ void texStorageMemFlags2DMultisample( \
+ TextureType targetPacked, GLsizei samples, GLenum internalFormat, GLsizei width, \
+ GLsizei height, GLboolean fixedSampleLocations, MemoryObjectID memoryPacked, \
+ GLuint64 offset, GLbitfield createFlags, GLbitfield usageFlags, \
+ const void *imageCreateInfoPNext); \
+ void texStorageMemFlags3D( \
+ TextureType targetPacked, GLsizei levels, GLenum internalFormat, GLsizei width, \
+ GLsizei height, GLsizei depth, MemoryObjectID memoryPacked, GLuint64 offset, \
+ GLbitfield createFlags, GLbitfield usageFlags, const void *imageCreateInfoPNext); \
+ void texStorageMemFlags3DMultisample( \
+ TextureType targetPacked, GLsizei samples, GLenum internalFormat, GLsizei width, \
+ GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, \
+ MemoryObjectID memoryPacked, GLuint64 offset, GLbitfield createFlags, \
+ GLbitfield usageFlags, const void *imageCreateInfoPNext); \
+ /* GL_ANGLE_memory_object_fuchsia */ \
+ void importMemoryZirconHandle(MemoryObjectID memoryPacked, GLuint64 size, \
+ HandleType handleTypePacked, GLuint handle); \
+ /* GL_ANGLE_memory_size */ \
+ /* GL_ANGLE_multi_draw */ \
+ void multiDrawArrays(PrimitiveMode modePacked, const GLint *firsts, const GLsizei *counts, \
+ GLsizei drawcount); \
+ void multiDrawArraysInstanced(PrimitiveMode modePacked, const GLint *firsts, \
+ const GLsizei *counts, const GLsizei *instanceCounts, \
+ GLsizei drawcount); \
+ void multiDrawElements(PrimitiveMode modePacked, const GLsizei *counts, \
+ DrawElementsType typePacked, const GLvoid *const *indices, \
+ GLsizei drawcount); \
+ void multiDrawElementsInstanced(PrimitiveMode modePacked, const GLsizei *counts, \
+ DrawElementsType typePacked, const GLvoid *const *indices, \
+ const GLsizei *instanceCounts, GLsizei drawcount); \
+ /* GL_ANGLE_multiview_multisample */ \
+ /* GL_ANGLE_program_binary */ \
+ /* GL_ANGLE_program_cache_control */ \
+ /* GL_ANGLE_provoking_vertex */ \
+ void provokingVertex(ProvokingVertexConvention modePacked); \
+ /* GL_ANGLE_read_only_depth_stencil_feedback_loops */ \
+ /* GL_ANGLE_relaxed_vertex_attribute_type */ \
+ /* GL_ANGLE_request_extension */ \
+ void requestExtension(const GLchar *name); \
+ void disableExtension(const GLchar *name); \
+ /* GL_ANGLE_rgbx_internal_format */ \
+ /* GL_ANGLE_robust_client_memory */ \
+ void getBooleanvRobust(GLenum pname, GLsizei bufSize, GLsizei *length, GLboolean *params); \
+ void getBufferParameterivRobust(BufferBinding targetPacked, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLint *params); \
+ void getFloatvRobust(GLenum pname, GLsizei bufSize, GLsizei *length, GLfloat *params); \
+ void getFramebufferAttachmentParameterivRobust(GLenum target, GLenum attachment, GLenum pname, \
+ GLsizei bufSize, GLsizei *length, \
+ GLint *params); \
+ void getIntegervRobust(GLenum pname, GLsizei bufSize, GLsizei *length, GLint *data); \
+ void getProgramivRobust(ShaderProgramID programPacked, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLint *params); \
+ void getRenderbufferParameterivRobust(GLenum target, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLint *params); \
+ void getShaderivRobust(ShaderProgramID shaderPacked, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLint *params); \
+ void getTexParameterfvRobust(TextureType targetPacked, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLfloat *params); \
+ void getTexParameterivRobust(TextureType targetPacked, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLint *params); \
+ void getUniformfvRobust(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei bufSize, GLsizei *length, GLfloat *params); \
+ void getUniformivRobust(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei bufSize, GLsizei *length, GLint *params); \
+ void getVertexAttribfvRobust(GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, \
+ GLfloat *params); \
+ void getVertexAttribivRobust(GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, \
+ GLint *params); \
+ void getVertexAttribPointervRobust(GLuint index, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, void **pointer); \
+ void readPixelsRobust(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, \
+ GLenum type, GLsizei bufSize, GLsizei *length, GLsizei *columns, \
+ GLsizei *rows, void *pixels); \
+ void texImage2DRobust(TextureTarget targetPacked, GLint level, GLint internalformat, \
+ GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, \
+ GLsizei bufSize, const void *pixels); \
+ void texParameterfvRobust(TextureType targetPacked, GLenum pname, GLsizei bufSize, \
+ const GLfloat *params); \
+ void texParameterivRobust(TextureType targetPacked, GLenum pname, GLsizei bufSize, \
+ const GLint *params); \
+ void texSubImage2DRobust(TextureTarget targetPacked, GLint level, GLint xoffset, \
+ GLint yoffset, GLsizei width, GLsizei height, GLenum format, \
+ GLenum type, GLsizei bufSize, const void *pixels); \
+ void texImage3DRobust(TextureTarget targetPacked, GLint level, GLint internalformat, \
+ GLsizei width, GLsizei height, GLsizei depth, GLint border, \
+ GLenum format, GLenum type, GLsizei bufSize, const void *pixels); \
+ void texSubImage3DRobust(TextureTarget targetPacked, GLint level, GLint xoffset, \
+ GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, \
+ GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, \
+ const void *pixels); \
+ void compressedTexImage2DRobust( \
+ TextureTarget targetPacked, GLint level, GLenum internalformat, GLsizei width, \
+ GLsizei height, GLint border, GLsizei imageSize, GLsizei dataSize, const GLvoid *data); \
+ void compressedTexSubImage2DRobust( \
+ TextureTarget targetPacked, GLint level, GLsizei xoffset, GLsizei yoffset, GLsizei width, \
+ GLsizei height, GLenum format, GLsizei imageSize, GLsizei dataSize, const GLvoid *data); \
+ void compressedTexImage3DRobust(TextureTarget targetPacked, GLint level, \
+ GLenum internalformat, GLsizei width, GLsizei height, \
+ GLsizei depth, GLint border, GLsizei imageSize, \
+ GLsizei dataSize, const GLvoid *data); \
+ void compressedTexSubImage3DRobust(TextureTarget targetPacked, GLint level, GLint xoffset, \
+ GLint yoffset, GLint zoffset, GLsizei width, \
+ GLsizei height, GLsizei depth, GLenum format, \
+ GLsizei imageSize, GLsizei dataSize, const GLvoid *data); \
+ void getQueryivRobust(QueryType targetPacked, GLenum pname, GLsizei bufSize, GLsizei *length, \
+ GLint *params); \
+ void getQueryObjectuivRobust(QueryID idPacked, GLenum pname, GLsizei bufSize, GLsizei *length, \
+ GLuint *params); \
+ void getBufferPointervRobust(BufferBinding targetPacked, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, void **params); \
+ void getIntegeri_vRobust(GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, \
+ GLint *data); \
+ void getInternalformativRobust(GLenum target, GLenum internalformat, GLenum pname, \
+ GLsizei bufSize, GLsizei *length, GLint *params); \
+ void getVertexAttribIivRobust(GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, \
+ GLint *params); \
+ void getVertexAttribIuivRobust(GLuint index, GLenum pname, GLsizei bufSize, GLsizei *length, \
+ GLuint *params); \
+ void getUniformuivRobust(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei bufSize, GLsizei *length, GLuint *params); \
+ void getActiveUniformBlockivRobust(ShaderProgramID programPacked, \
+ UniformBlockIndex uniformBlockIndexPacked, GLenum pname, \
+ GLsizei bufSize, GLsizei *length, GLint *params); \
+ void getInteger64vRobust(GLenum pname, GLsizei bufSize, GLsizei *length, GLint64 *data); \
+ void getInteger64i_vRobust(GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, \
+ GLint64 *data); \
+ void getBufferParameteri64vRobust(BufferBinding targetPacked, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLint64 *params); \
+ void samplerParameterivRobust(SamplerID samplerPacked, GLuint pname, GLsizei bufSize, \
+ const GLint *param); \
+ void samplerParameterfvRobust(SamplerID samplerPacked, GLenum pname, GLsizei bufSize, \
+ const GLfloat *param); \
+ void getSamplerParameterivRobust(SamplerID samplerPacked, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLint *params); \
+ void getSamplerParameterfvRobust(SamplerID samplerPacked, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLfloat *params); \
+ void getFramebufferParameterivRobust(GLenum target, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLint *params); \
+ void getProgramInterfaceivRobust(ShaderProgramID programPacked, GLenum programInterface, \
+ GLenum pname, GLsizei bufSize, GLsizei *length, \
+ GLint *params); \
+ void getBooleani_vRobust(GLenum target, GLuint index, GLsizei bufSize, GLsizei *length, \
+ GLboolean *data); \
+ void getMultisamplefvRobust(GLenum pname, GLuint index, GLsizei bufSize, GLsizei *length, \
+ GLfloat *val); \
+ void getTexLevelParameterivRobust(TextureTarget targetPacked, GLint level, GLenum pname, \
+ GLsizei bufSize, GLsizei *length, GLint *params); \
+ void getTexLevelParameterfvRobust(TextureTarget targetPacked, GLint level, GLenum pname, \
+ GLsizei bufSize, GLsizei *length, GLfloat *params); \
+ void getPointervRobustANGLERobust(GLenum pname, GLsizei bufSize, GLsizei *length, \
+ void **params); \
+ void readnPixelsRobust(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, \
+ GLenum type, GLsizei bufSize, GLsizei *length, GLsizei *columns, \
+ GLsizei *rows, void *data); \
+ void getnUniformfvRobust(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei bufSize, GLsizei *length, GLfloat *params); \
+ void getnUniformivRobust(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei bufSize, GLsizei *length, GLint *params); \
+ void getnUniformuivRobust(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ GLsizei bufSize, GLsizei *length, GLuint *params); \
+ void texParameterIivRobust(TextureType targetPacked, GLenum pname, GLsizei bufSize, \
+ const GLint *params); \
+ void texParameterIuivRobust(TextureType targetPacked, GLenum pname, GLsizei bufSize, \
+ const GLuint *params); \
+ void getTexParameterIivRobust(TextureType targetPacked, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLint *params); \
+ void getTexParameterIuivRobust(TextureType targetPacked, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLuint *params); \
+ void samplerParameterIivRobust(SamplerID samplerPacked, GLenum pname, GLsizei bufSize, \
+ const GLint *param); \
+ void samplerParameterIuivRobust(SamplerID samplerPacked, GLenum pname, GLsizei bufSize, \
+ const GLuint *param); \
+ void getSamplerParameterIivRobust(SamplerID samplerPacked, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLint *params); \
+ void getSamplerParameterIuivRobust(SamplerID samplerPacked, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLuint *params); \
+ void getQueryObjectivRobust(QueryID idPacked, GLenum pname, GLsizei bufSize, GLsizei *length, \
+ GLint *params); \
+ void getQueryObjecti64vRobust(QueryID idPacked, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLint64 *params); \
+ void getQueryObjectui64vRobust(QueryID idPacked, GLenum pname, GLsizei bufSize, \
+ GLsizei *length, GLuint64 *params); \
+ /* GL_ANGLE_robust_fragment_shader_output */ \
+ /* GL_ANGLE_robust_resource_initialization */ \
+ /* GL_ANGLE_semaphore_fuchsia */ \
+ void importSemaphoreZirconHandle(SemaphoreID semaphorePacked, HandleType handleTypePacked, \
+ GLuint handle); \
+ /* GL_ANGLE_shader_pixel_local_storage */ \
+ void framebufferMemorylessPixelLocalStorage(GLint plane, GLenum internalformat); \
+ void framebufferTexturePixelLocalStorage(GLint plane, TextureID backingtexturePacked, \
+ GLint level, GLint layer); \
+ void beginPixelLocalStorage(GLsizei planes, const GLenum *loadops, const void *cleardata); \
+ void endPixelLocalStorage(); \
+ void pixelLocalStorageBarrier(); \
+ /* GL_ANGLE_shader_pixel_local_storage_coherent */ \
+ /* GL_ANGLE_texture_compression_dxt3 */ \
+ /* GL_ANGLE_texture_compression_dxt5 */ \
+ /* GL_ANGLE_texture_external_update */ \
+ void texImage2DExternal(TextureTarget targetPacked, GLint level, GLint internalformat, \
+ GLsizei width, GLsizei height, GLint border, GLenum format, \
+ GLenum type); \
+ void invalidateTexture(TextureType targetPacked); \
+ /* GL_ANGLE_texture_multisample */ \
+ /* GL_ANGLE_texture_rectangle */ \
+ /* GL_ANGLE_vulkan_image */ \
+ void acquireTextures(GLuint numTextures, const TextureID *texturesPacked, \
+ const GLenum *layouts); \
+ void releaseTextures(GLuint numTextures, const TextureID *texturesPacked, GLenum *layouts); \
+ /* GL_ANGLE_webgl_compatibility */ \
+ /* GL_ANGLE_yuv_internal_format */ \
+ /* GL_CHROMIUM_bind_generates_resource */ \
+ /* GL_CHROMIUM_bind_uniform_location */ \
+ void bindUniformLocation(ShaderProgramID programPacked, UniformLocation locationPacked, \
+ const GLchar *name); \
+ /* GL_CHROMIUM_color_buffer_float_rgb */ \
+ /* GL_CHROMIUM_color_buffer_float_rgba */ \
+ /* GL_CHROMIUM_copy_compressed_texture */ \
+ void compressedCopyTexture(TextureID sourceIdPacked, TextureID destIdPacked); \
+ /* GL_CHROMIUM_copy_texture */ \
+ void copyTexture(TextureID sourceIdPacked, GLint sourceLevel, TextureTarget destTargetPacked, \
+ TextureID destIdPacked, GLint destLevel, GLint internalFormat, \
+ GLenum destType, GLboolean unpackFlipY, GLboolean unpackPremultiplyAlpha, \
+ GLboolean unpackUnmultiplyAlpha); \
+ void copySubTexture(TextureID sourceIdPacked, GLint sourceLevel, \
+ TextureTarget destTargetPacked, TextureID destIdPacked, GLint destLevel, \
+ GLint xoffset, GLint yoffset, GLint x, GLint y, GLint width, GLint height, \
+ GLboolean unpackFlipY, GLboolean unpackPremultiplyAlpha, \
+ GLboolean unpackUnmultiplyAlpha); \
+ /* GL_CHROMIUM_framebuffer_mixed_samples */ \
+ void coverageModulation(GLenum components); \
+ /* GL_CHROMIUM_lose_context */ \
+ void loseContext(GraphicsResetStatus currentPacked, GraphicsResetStatus otherPacked); \
+ /* GL_CHROMIUM_sync_query */ \
+ /* GL_CHROMIUM_texture_filtering_hint */
+
+#endif // ANGLE_CONTEXT_API_EXT_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Debug.cpp b/gfx/angle/checkout/src/libANGLE/Debug.cpp
new file mode 100644
index 0000000000..da97ae9d9e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Debug.cpp
@@ -0,0 +1,507 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Debug.cpp: Defines debug state used for GL_KHR_debug
+
+#include "libANGLE/Debug.h"
+
+#include "common/debug.h"
+
+#include <algorithm>
+#include <tuple>
+
+namespace
+{
+const char *GLSeverityToString(GLenum severity)
+{
+ switch (severity)
+ {
+ case GL_DEBUG_SEVERITY_HIGH:
+ return "HIGH";
+ case GL_DEBUG_SEVERITY_MEDIUM:
+ return "MEDIUM";
+ case GL_DEBUG_SEVERITY_LOW:
+ return "LOW";
+ case GL_DEBUG_SEVERITY_NOTIFICATION:
+ default:
+ return "NOTIFICATION";
+ }
+}
+
+const char *EGLMessageTypeToString(egl::MessageType messageType)
+{
+ switch (messageType)
+ {
+ case egl::MessageType::Critical:
+ return "CRITICAL";
+ case egl::MessageType::Error:
+ return "ERROR";
+ case egl::MessageType::Warn:
+ return "WARNING";
+ case egl::MessageType::Info:
+ default:
+ return "INFO";
+ }
+}
+
+const char *GLMessageTypeToString(GLenum type)
+{
+ switch (type)
+ {
+ case GL_DEBUG_TYPE_ERROR:
+ return "error";
+ case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
+ return "deprecated behavior";
+ case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
+ return "undefined behavior";
+ case GL_DEBUG_TYPE_PORTABILITY:
+ return "portability";
+ case GL_DEBUG_TYPE_PERFORMANCE:
+ return "performance";
+ case GL_DEBUG_TYPE_MARKER:
+ return "marker";
+ case GL_DEBUG_TYPE_PUSH_GROUP:
+ return "start of group";
+ case GL_DEBUG_TYPE_POP_GROUP:
+ return "end of group";
+ case GL_DEBUG_TYPE_OTHER:
+ default:
+ return "other message";
+ }
+}
+} // namespace
+
+namespace gl
+{
+
+Debug::Control::Control() {}
+
+Debug::Control::~Control() {}
+
+Debug::Control::Control(const Control &other) = default;
+
+Debug::Group::Group() {}
+
+Debug::Group::~Group() {}
+
+Debug::Group::Group(const Group &other) = default;
+
+Debug::Debug(bool initialDebugState)
+ : mOutputEnabled(initialDebugState),
+ mCallbackFunction(nullptr),
+ mCallbackUserParam(nullptr),
+ mMessages(),
+ mMaxLoggedMessages(0),
+ mOutputSynchronous(false),
+ mGroups()
+{
+ pushDefaultGroup();
+}
+
+Debug::~Debug() {}
+
+void Debug::setMaxLoggedMessages(GLuint maxLoggedMessages)
+{
+ mMaxLoggedMessages = maxLoggedMessages;
+}
+
+void Debug::setOutputEnabled(bool enabled)
+{
+ mOutputEnabled = enabled;
+}
+
+bool Debug::isOutputEnabled() const
+{
+ return mOutputEnabled;
+}
+
+void Debug::setOutputSynchronous(bool synchronous)
+{
+ mOutputSynchronous = synchronous;
+}
+
+bool Debug::isOutputSynchronous() const
+{
+ return mOutputSynchronous;
+}
+
+void Debug::setCallback(GLDEBUGPROCKHR callback, const void *userParam)
+{
+ mCallbackFunction = callback;
+ mCallbackUserParam = userParam;
+}
+
+GLDEBUGPROCKHR Debug::getCallback() const
+{
+ return mCallbackFunction;
+}
+
+const void *Debug::getUserParam() const
+{
+ return mCallbackUserParam;
+}
+
+void Debug::insertMessage(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ const std::string &message,
+ gl::LogSeverity logSeverity,
+ angle::EntryPoint entryPoint) const
+{
+ std::string messageCopy(message);
+ insertMessage(source, type, id, severity, std::move(messageCopy), logSeverity, entryPoint);
+}
+
+void Debug::insertMessage(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ std::string &&message,
+ gl::LogSeverity logSeverity,
+ angle::EntryPoint entryPoint) const
+{
+ {
+ // output all messages to the debug log
+ const char *messageTypeString = GLMessageTypeToString(type);
+ const char *severityString = GLSeverityToString(severity);
+ std::ostringstream messageStream;
+ if (entryPoint != angle::EntryPoint::GLInvalid)
+ {
+ messageStream << GetEntryPointName(entryPoint) << ": ";
+ }
+ messageStream << "GL " << messageTypeString << ": " << severityString << ": " << message;
+ switch (logSeverity)
+ {
+ case gl::LOG_FATAL:
+ FATAL() << messageStream.str();
+ break;
+ case gl::LOG_ERR:
+ ERR() << messageStream.str();
+ break;
+ case gl::LOG_WARN:
+ WARN() << messageStream.str();
+ break;
+ case gl::LOG_INFO:
+ INFO() << messageStream.str();
+ break;
+ case gl::LOG_EVENT:
+ ANGLE_LOG(EVENT) << messageStream.str();
+ break;
+ }
+ }
+
+ if (!isMessageEnabled(source, type, id, severity))
+ {
+ return;
+ }
+
+ if (mCallbackFunction != nullptr)
+ {
+ // TODO(geofflang) Check the synchronous flag and potentially flush messages from another
+ // thread.
+ mCallbackFunction(source, type, id, severity, static_cast<GLsizei>(message.length()),
+ message.c_str(), mCallbackUserParam);
+ }
+ else
+ {
+ if (mMessages.size() >= mMaxLoggedMessages)
+ {
+ // Drop messages over the limit
+ return;
+ }
+
+ Message m;
+ m.source = source;
+ m.type = type;
+ m.id = id;
+ m.severity = severity;
+ m.message = std::move(message);
+
+ mMessages.push_back(std::move(m));
+ }
+}
+
+size_t Debug::getMessages(GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog)
+{
+ size_t messageCount = 0;
+ size_t messageStringIndex = 0;
+ while (messageCount <= count && !mMessages.empty())
+ {
+ const Message &m = mMessages.front();
+
+ if (messageLog != nullptr)
+ {
+ // Check that this message can fit in the message buffer
+ if (messageStringIndex + m.message.length() + 1 > static_cast<size_t>(bufSize))
+ {
+ break;
+ }
+
+ std::copy(m.message.begin(), m.message.end(), messageLog + messageStringIndex);
+ messageStringIndex += m.message.length();
+
+ messageLog[messageStringIndex] = '\0';
+ messageStringIndex += 1;
+ }
+
+ if (sources != nullptr)
+ {
+ sources[messageCount] = m.source;
+ }
+
+ if (types != nullptr)
+ {
+ types[messageCount] = m.type;
+ }
+
+ if (ids != nullptr)
+ {
+ ids[messageCount] = m.id;
+ }
+
+ if (severities != nullptr)
+ {
+ severities[messageCount] = m.severity;
+ }
+
+ if (lengths != nullptr)
+ {
+ lengths[messageCount] = static_cast<GLsizei>(m.message.length()) + 1;
+ }
+
+ mMessages.pop_front();
+
+ messageCount++;
+ }
+
+ return messageCount;
+}
+
+size_t Debug::getNextMessageLength() const
+{
+ return mMessages.empty() ? 0 : mMessages.front().message.length() + 1;
+}
+
+size_t Debug::getMessageCount() const
+{
+ return mMessages.size();
+}
+
+void Debug::setMessageControl(GLenum source,
+ GLenum type,
+ GLenum severity,
+ std::vector<GLuint> &&ids,
+ bool enabled)
+{
+ Control c;
+ c.source = source;
+ c.type = type;
+ c.severity = severity;
+ c.ids = std::move(ids);
+ c.enabled = enabled;
+
+ auto &controls = mGroups.back().controls;
+ controls.push_back(std::move(c));
+}
+
+void Debug::pushGroup(GLenum source, GLuint id, std::string &&message)
+{
+ insertMessage(source, GL_DEBUG_TYPE_PUSH_GROUP, id, GL_DEBUG_SEVERITY_NOTIFICATION,
+ std::string(message), gl::LOG_INFO, angle::EntryPoint::GLPushDebugGroup);
+
+ Group g;
+ g.source = source;
+ g.id = id;
+ g.message = std::move(message);
+ mGroups.push_back(std::move(g));
+}
+
+void Debug::popGroup()
+{
+ // Make sure the default group is not about to be popped
+ ASSERT(mGroups.size() > 1);
+
+ Group g = mGroups.back();
+ mGroups.pop_back();
+
+ insertMessage(g.source, GL_DEBUG_TYPE_POP_GROUP, g.id, GL_DEBUG_SEVERITY_NOTIFICATION,
+ g.message, gl::LOG_INFO, angle::EntryPoint::GLPopDebugGroup);
+}
+
+size_t Debug::getGroupStackDepth() const
+{
+ return mGroups.size();
+}
+
+void Debug::insertPerfWarning(GLenum severity, const char *message, uint32_t *repeatCount) const
+{
+ bool repeatLast;
+
+ {
+ constexpr uint32_t kMaxRepeat = 4;
+ std::lock_guard<std::mutex> lock(GetDebugMutex());
+
+ if (*repeatCount >= kMaxRepeat)
+ {
+ return;
+ }
+
+ ++*repeatCount;
+ repeatLast = (*repeatCount == kMaxRepeat);
+ }
+
+ std::string msg = message;
+ if (repeatLast)
+ {
+ msg += " (this message will no longer repeat)";
+ }
+
+ // Release the lock before we call insertMessage. It will re-acquire the lock.
+ insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_PERFORMANCE, 0, severity, std::move(msg),
+ gl::LOG_INFO, angle::EntryPoint::GLInvalid);
+}
+
+bool Debug::isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const
+{
+ if (!mOutputEnabled)
+ {
+ return false;
+ }
+
+ for (auto groupIter = mGroups.rbegin(); groupIter != mGroups.rend(); groupIter++)
+ {
+ const auto &controls = groupIter->controls;
+ for (auto controlIter = controls.rbegin(); controlIter != controls.rend(); controlIter++)
+ {
+ const auto &control = *controlIter;
+
+ if (control.source != GL_DONT_CARE && control.source != source)
+ {
+ continue;
+ }
+
+ if (control.type != GL_DONT_CARE && control.type != type)
+ {
+ continue;
+ }
+
+ if (control.severity != GL_DONT_CARE && control.severity != severity)
+ {
+ continue;
+ }
+
+ if (!control.ids.empty() &&
+ std::find(control.ids.begin(), control.ids.end(), id) == control.ids.end())
+ {
+ continue;
+ }
+
+ return control.enabled;
+ }
+ }
+
+ return true;
+}
+
+void Debug::pushDefaultGroup()
+{
+ Group g;
+ g.source = GL_NONE;
+ g.id = 0;
+ g.message = "";
+
+ Control c0;
+ c0.source = GL_DONT_CARE;
+ c0.type = GL_DONT_CARE;
+ c0.severity = GL_DONT_CARE;
+ c0.enabled = true;
+ g.controls.push_back(std::move(c0));
+
+ Control c1;
+ c1.source = GL_DONT_CARE;
+ c1.type = GL_DONT_CARE;
+ c1.severity = GL_DEBUG_SEVERITY_LOW;
+ c1.enabled = false;
+ g.controls.push_back(std::move(c1));
+
+ mGroups.push_back(std::move(g));
+}
+} // namespace gl
+
+namespace egl
+{
+
+namespace
+{
+angle::PackedEnumBitSet<MessageType> GetDefaultMessageTypeBits()
+{
+ angle::PackedEnumBitSet<MessageType> result;
+ result.set(MessageType::Critical);
+ result.set(MessageType::Error);
+ return result;
+}
+} // anonymous namespace
+
+Debug::Debug() : mCallback(nullptr), mEnabledMessageTypes(GetDefaultMessageTypeBits()) {}
+
+void Debug::setCallback(EGLDEBUGPROCKHR callback, const AttributeMap &attribs)
+{
+ mCallback = callback;
+
+ const angle::PackedEnumBitSet<MessageType> defaultMessageTypes = GetDefaultMessageTypeBits();
+ if (mCallback != nullptr)
+ {
+ for (MessageType messageType : angle::AllEnums<MessageType>())
+ {
+ mEnabledMessageTypes[messageType] =
+ (attribs.getAsInt(egl::ToEGLenum(messageType), defaultMessageTypes[messageType]) ==
+ EGL_TRUE);
+ }
+ }
+}
+
+EGLDEBUGPROCKHR Debug::getCallback() const
+{
+ return mCallback;
+}
+
+bool Debug::isMessageTypeEnabled(MessageType type) const
+{
+ return mEnabledMessageTypes[type];
+}
+
+void Debug::insertMessage(EGLenum error,
+ const char *command,
+ MessageType messageType,
+ EGLLabelKHR threadLabel,
+ EGLLabelKHR objectLabel,
+ const std::string &message) const
+{
+ {
+ // output all messages to the debug log
+ const char *messageTypeString = EGLMessageTypeToString(messageType);
+ std::ostringstream messageStream;
+ messageStream << "EGL " << messageTypeString << ": " << command << ": " << message;
+ INFO() << messageStream.str();
+ }
+
+ // TODO(geofflang): Lock before checking the callback. http://anglebug.com/2464
+ if (mCallback && isMessageTypeEnabled(messageType))
+ {
+ mCallback(error, command, egl::ToEGLenum(messageType), threadLabel, objectLabel,
+ message.c_str());
+ }
+}
+
+} // namespace egl
diff --git a/gfx/angle/checkout/src/libANGLE/Debug.h b/gfx/angle/checkout/src/libANGLE/Debug.h
new file mode 100644
index 0000000000..873a60df6f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Debug.h
@@ -0,0 +1,180 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Debug.h: Defines debug state used for GL_KHR_debug
+
+#ifndef LIBANGLE_DEBUG_H_
+#define LIBANGLE_DEBUG_H_
+
+#include "angle_gl.h"
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Error.h"
+
+#include <deque>
+#include <string>
+#include <vector>
+
+namespace gl
+{
+class Context;
+
+class LabeledObject
+{
+ public:
+ virtual ~LabeledObject() {}
+ virtual angle::Result setLabel(const Context *context, const std::string &label) = 0;
+ virtual const std::string &getLabel() const = 0;
+};
+
+class Debug : angle::NonCopyable
+{
+ public:
+ Debug(bool initialDebugState);
+ ~Debug();
+
+ void setMaxLoggedMessages(GLuint maxLoggedMessages);
+
+ void setOutputEnabled(bool enabled);
+ bool isOutputEnabled() const;
+
+ void setOutputSynchronous(bool synchronous);
+ bool isOutputSynchronous() const;
+
+ void setCallback(GLDEBUGPROCKHR callback, const void *userParam);
+ GLDEBUGPROCKHR getCallback() const;
+ const void *getUserParam() const;
+
+ void insertMessage(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ const std::string &message,
+ gl::LogSeverity logSeverity,
+ angle::EntryPoint entryPoint) const;
+ void insertMessage(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ std::string &&message,
+ gl::LogSeverity logSeverity,
+ angle::EntryPoint entryPoint) const;
+
+ void setMessageControl(GLenum source,
+ GLenum type,
+ GLenum severity,
+ std::vector<GLuint> &&ids,
+ bool enabled);
+ size_t getMessages(GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog);
+ size_t getNextMessageLength() const;
+ size_t getMessageCount() const;
+
+ void pushGroup(GLenum source, GLuint id, std::string &&message);
+ void popGroup();
+ size_t getGroupStackDepth() const;
+
+ // Helper for ANGLE_PERF_WARNING
+ void insertPerfWarning(GLenum severity, const char *message, uint32_t *repeatCount) const;
+
+ private:
+ bool isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const;
+
+ void pushDefaultGroup();
+
+ struct Message
+ {
+ GLenum source;
+ GLenum type;
+ GLuint id;
+ GLenum severity;
+ std::string message;
+ };
+
+ struct Control
+ {
+ Control();
+ ~Control();
+ Control(const Control &other);
+
+ GLenum source;
+ GLenum type;
+ GLenum severity;
+ std::vector<GLuint> ids;
+ bool enabled;
+ };
+
+ struct Group
+ {
+ Group();
+ ~Group();
+ Group(const Group &other);
+
+ GLenum source;
+ GLuint id;
+ std::string message;
+
+ std::vector<Control> controls;
+ };
+
+ bool mOutputEnabled;
+ GLDEBUGPROCKHR mCallbackFunction;
+ const void *mCallbackUserParam;
+ mutable std::deque<Message> mMessages;
+ GLuint mMaxLoggedMessages;
+ bool mOutputSynchronous;
+ std::vector<Group> mGroups;
+};
+} // namespace gl
+
+namespace egl
+{
+class LabeledObject
+{
+ public:
+ virtual ~LabeledObject() {}
+ virtual void setLabel(EGLLabelKHR label) = 0;
+ virtual EGLLabelKHR getLabel() const = 0;
+};
+
+class Debug : angle::NonCopyable
+{
+ public:
+ Debug();
+
+ void setCallback(EGLDEBUGPROCKHR callback, const AttributeMap &attribs);
+ EGLDEBUGPROCKHR getCallback() const;
+ bool isMessageTypeEnabled(MessageType type) const;
+
+ void insertMessage(EGLenum error,
+ const char *command,
+ MessageType messageType,
+ EGLLabelKHR threadLabel,
+ EGLLabelKHR objectLabel,
+ const std::string &message) const;
+
+ private:
+ EGLDEBUGPROCKHR mCallback;
+ angle::PackedEnumBitSet<MessageType> mEnabledMessageTypes;
+};
+} // namespace egl
+
+// Generate a perf warning. Only outputs the same message a few times to avoid spamming the logs.
+#define ANGLE_PERF_WARNING(debug, severity, message) \
+ do \
+ { \
+ static uint32_t sRepeatCount = 0; \
+ (debug).insertPerfWarning(severity, message, &sRepeatCount); \
+ } while (0)
+
+#endif // LIBANGLE_DEBUG_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Device.cpp b/gfx/angle/checkout/src/libANGLE/Device.cpp
new file mode 100644
index 0000000000..550708fd13
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Device.cpp
@@ -0,0 +1,133 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Device.cpp: Implements the egl::Device class, representing the abstract
+// device. Implements EGLDevice.
+
+#include "libANGLE/Device.h"
+
+#include <iterator>
+
+#include <EGL/eglext.h>
+#include <platform/PlatformMethods.h>
+
+#include "anglebase/no_destructor.h"
+#include "common/debug.h"
+#include "common/platform.h"
+#include "libANGLE/renderer/DeviceImpl.h"
+
+#if defined(ANGLE_ENABLE_D3D11)
+# include "libANGLE/renderer/d3d/DeviceD3D.h"
+#endif
+
+namespace egl
+{
+
+template <typename T>
+static std::string GenerateExtensionsString(const T &extensions)
+{
+ std::vector<std::string> extensionsVector = extensions.getStrings();
+
+ std::ostringstream stream;
+ std::copy(extensionsVector.begin(), extensionsVector.end(),
+ std::ostream_iterator<std::string>(stream, " "));
+ return stream.str();
+}
+
+typedef std::set<egl::Device *> DeviceSet;
+static DeviceSet *GetDeviceSet()
+{
+ static angle::base::NoDestructor<DeviceSet> devices;
+ return devices.get();
+}
+
+// Static factory methods
+egl::Error Device::CreateDevice(EGLint deviceType, void *nativeDevice, Device **outDevice)
+{
+ *outDevice = nullptr;
+
+ std::unique_ptr<rx::DeviceImpl> newDeviceImpl;
+
+#if defined(ANGLE_ENABLE_D3D11)
+ if (deviceType == EGL_D3D11_DEVICE_ANGLE)
+ {
+ newDeviceImpl.reset(new rx::DeviceD3D(deviceType, nativeDevice));
+ }
+#endif
+
+ // Note that creating an EGL device from inputted D3D9 parameters isn't currently supported
+
+ if (newDeviceImpl == nullptr)
+ {
+ return EglBadAttribute();
+ }
+
+ ANGLE_TRY(newDeviceImpl->initialize());
+ *outDevice = new Device(nullptr, newDeviceImpl.release());
+
+ return NoError();
+}
+
+bool Device::IsValidDevice(const Device *device)
+{
+ const DeviceSet *deviceSet = GetDeviceSet();
+ return deviceSet->find(const_cast<Device *>(device)) != deviceSet->end();
+}
+
+Device::Device(Display *owningDisplay, rx::DeviceImpl *impl)
+ : mLabel(nullptr), mOwningDisplay(owningDisplay), mImplementation(impl)
+{
+ ASSERT(GetDeviceSet()->find(this) == GetDeviceSet()->end());
+ GetDeviceSet()->insert(this);
+ initDeviceExtensions();
+}
+
+Device::~Device()
+{
+ ASSERT(GetDeviceSet()->find(this) != GetDeviceSet()->end());
+ GetDeviceSet()->erase(this);
+}
+
+void Device::setLabel(EGLLabelKHR label)
+{
+ mLabel = label;
+}
+
+EGLLabelKHR Device::getLabel() const
+{
+ return mLabel;
+}
+
+Error Device::getAttribute(EGLint attribute, EGLAttrib *value)
+{
+ void *nativeAttribute = nullptr;
+ egl::Error error =
+ getImplementation()->getAttribute(getOwningDisplay(), attribute, &nativeAttribute);
+ *value = reinterpret_cast<EGLAttrib>(nativeAttribute);
+ return error;
+}
+
+EGLint Device::getType() const
+{
+ return mImplementation.get()->getType();
+}
+
+void Device::initDeviceExtensions()
+{
+ mImplementation->generateExtensions(&mDeviceExtensions);
+ mDeviceExtensionString = GenerateExtensionsString(mDeviceExtensions);
+}
+
+const DeviceExtensions &Device::getExtensions() const
+{
+ return mDeviceExtensions;
+}
+
+const std::string &Device::getExtensionString() const
+{
+ return mDeviceExtensionString;
+}
+} // namespace egl
diff --git a/gfx/angle/checkout/src/libANGLE/Device.h b/gfx/angle/checkout/src/libANGLE/Device.h
new file mode 100644
index 0000000000..8fbdf72e68
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Device.h
@@ -0,0 +1,60 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Device.h: Implements the egl::Device class, representing the abstract
+// device. Implements EGLDevice.
+
+#ifndef LIBANGLE_DEVICE_H_
+#define LIBANGLE_DEVICE_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Error.h"
+
+#include <memory>
+
+namespace rx
+{
+class DeviceImpl;
+} // namespace rx
+
+namespace egl
+{
+class Device final : public LabeledObject, angle::NonCopyable
+{
+ public:
+ Device(Display *owningDisplay, rx::DeviceImpl *impl);
+ ~Device() override;
+
+ void setLabel(EGLLabelKHR label) override;
+ EGLLabelKHR getLabel() const override;
+
+ Error getAttribute(EGLint attribute, EGLAttrib *value);
+ Display *getOwningDisplay() const { return mOwningDisplay; }
+ EGLint getType() const;
+
+ const DeviceExtensions &getExtensions() const;
+ const std::string &getExtensionString() const;
+
+ rx::DeviceImpl *getImplementation() { return mImplementation.get(); }
+
+ static egl::Error CreateDevice(EGLint deviceType, void *nativeDevice, Device **outDevice);
+ static bool IsValidDevice(const Device *device);
+
+ private:
+ void initDeviceExtensions();
+
+ EGLLabelKHR mLabel;
+
+ Display *mOwningDisplay;
+ std::unique_ptr<rx::DeviceImpl> mImplementation;
+
+ DeviceExtensions mDeviceExtensions;
+ std::string mDeviceExtensionString;
+};
+} // namespace egl
+
+#endif // LIBANGLE_DEVICE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Display.cpp b/gfx/angle/checkout/src/libANGLE/Display.cpp
new file mode 100644
index 0000000000..4b7ced36fb
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Display.cpp
@@ -0,0 +1,2506 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Display.cpp: Implements the egl::Display class, representing the abstract
+// display on which graphics are drawn. Implements EGLDisplay.
+// [EGL 1.4] section 2.1.2 page 3.
+
+#include "libANGLE/Display.h"
+
+#include <algorithm>
+#include <iterator>
+#include <sstream>
+#include <vector>
+
+#include <EGL/eglext.h>
+#include <platform/PlatformMethods.h>
+
+#include "anglebase/no_destructor.h"
+#include "common/android_util.h"
+#include "common/debug.h"
+#include "common/mathutil.h"
+#include "common/platform.h"
+#include "common/string_utils.h"
+#include "common/system_utils.h"
+#include "common/tls.h"
+#include "common/utilities.h"
+#include "gpu_info_util/SystemInfo.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Device.h"
+#include "libANGLE/EGLSync.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Thread.h"
+#include "libANGLE/capture/FrameCapture.h"
+#include "libANGLE/histogram_macros.h"
+#include "libANGLE/renderer/DeviceImpl.h"
+#include "libANGLE/renderer/DisplayImpl.h"
+#include "libANGLE/renderer/ImageImpl.h"
+#include "libANGLE/trace.h"
+
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+# include <versionhelpers.h>
+
+# include "libANGLE/renderer/d3d/DisplayD3D.h"
+#endif
+
+#if defined(ANGLE_ENABLE_OPENGL)
+# if defined(ANGLE_PLATFORM_WINDOWS)
+# include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
+# elif defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_IOS)
+# include "libANGLE/renderer/gl/apple/DisplayApple_api.h"
+# elif defined(ANGLE_PLATFORM_LINUX)
+# include "libANGLE/renderer/gl/egl/DisplayEGL.h"
+# if defined(ANGLE_USE_GBM)
+# include "libANGLE/renderer/gl/egl/gbm/DisplayGbm.h"
+# endif
+# if defined(ANGLE_USE_X11)
+# include "libANGLE/renderer/gl/glx/DisplayGLX.h"
+# endif
+# elif defined(ANGLE_PLATFORM_ANDROID)
+# include "libANGLE/renderer/gl/egl/android/DisplayAndroid.h"
+# else
+# error Unsupported OpenGL platform.
+# endif
+#endif
+
+#if defined(ANGLE_ENABLE_NULL)
+# include "libANGLE/renderer/null/DisplayNULL.h"
+#endif // defined(ANGLE_ENABLE_NULL)
+
+#if defined(ANGLE_ENABLE_VULKAN)
+# include "libANGLE/renderer/vulkan/DisplayVk_api.h"
+#endif // defined(ANGLE_ENABLE_VULKAN)
+
+#if defined(ANGLE_ENABLE_METAL)
+# include "libANGLE/renderer/metal/DisplayMtl_api.h"
+#endif // defined(ANGLE_ENABLE_METAL)
+
+namespace egl
+{
+
+namespace
+{
+
+constexpr angle::SubjectIndex kGPUSwitchedSubjectIndex = 0;
+
+static constexpr size_t kWindowSurfaceMapSize = 32;
+typedef angle::FlatUnorderedMap<EGLNativeWindowType, Surface *, kWindowSurfaceMapSize>
+ WindowSurfaceMap;
+// Get a map of all EGL window surfaces to validate that no window has more than one EGL surface
+// associated with it.
+static WindowSurfaceMap *GetWindowSurfaces()
+{
+ static angle::base::NoDestructor<WindowSurfaceMap> windowSurfaces;
+ return windowSurfaces.get();
+}
+
+struct ANGLEPlatformDisplay
+{
+ ANGLEPlatformDisplay() = default;
+
+ ANGLEPlatformDisplay(EGLNativeDisplayType nativeDisplayType)
+ : nativeDisplayType(nativeDisplayType)
+ {}
+
+ ANGLEPlatformDisplay(EGLNativeDisplayType nativeDisplayType,
+ EGLAttrib powerPreference,
+ EGLAttrib platformANGLEType,
+ EGLAttrib deviceIdHigh,
+ EGLAttrib deviceIdLow)
+ : nativeDisplayType(nativeDisplayType),
+ powerPreference(powerPreference),
+ platformANGLEType(platformANGLEType),
+ deviceIdHigh(deviceIdHigh),
+ deviceIdLow(deviceIdLow)
+ {}
+
+ auto tie() const
+ {
+ return std::tie(nativeDisplayType, powerPreference, platformANGLEType, deviceIdHigh,
+ deviceIdLow);
+ }
+
+ EGLNativeDisplayType nativeDisplayType{EGL_DEFAULT_DISPLAY};
+ EGLAttrib powerPreference{EGL_LOW_POWER_ANGLE};
+ EGLAttrib platformANGLEType{EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE};
+ EGLAttrib deviceIdHigh{0};
+ EGLAttrib deviceIdLow{0};
+};
+
+inline bool operator==(const ANGLEPlatformDisplay &a, const ANGLEPlatformDisplay &b)
+{
+ return a.tie() == b.tie();
+}
+
+static constexpr size_t kANGLEPlatformDisplayMapSize = 9;
+typedef angle::FlatUnorderedMap<ANGLEPlatformDisplay, Display *, kANGLEPlatformDisplayMapSize>
+ ANGLEPlatformDisplayMap;
+static ANGLEPlatformDisplayMap *GetANGLEPlatformDisplayMap()
+{
+ static angle::base::NoDestructor<ANGLEPlatformDisplayMap> displays;
+ return displays.get();
+}
+
+static constexpr size_t kDevicePlatformDisplayMapSize = 8;
+typedef angle::FlatUnorderedMap<Device *, Display *, kDevicePlatformDisplayMapSize>
+ DevicePlatformDisplayMap;
+static DevicePlatformDisplayMap *GetDevicePlatformDisplayMap()
+{
+ static angle::base::NoDestructor<DevicePlatformDisplayMap> displays;
+ return displays.get();
+}
+
+rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice, const DisplayState &state)
+{
+ rx::DisplayImpl *impl = nullptr;
+
+ switch (eglDevice->getType())
+ {
+#if defined(ANGLE_ENABLE_D3D11)
+ case EGL_D3D11_DEVICE_ANGLE:
+ impl = new rx::DisplayD3D(state);
+ break;
+#endif
+#if defined(ANGLE_ENABLE_D3D9)
+ case EGL_D3D9_DEVICE_ANGLE:
+ // Currently the only way to get EGLDeviceEXT representing a D3D9 device
+ // is to retrieve one from an already-existing EGLDisplay.
+ // When eglGetPlatformDisplayEXT is called with a D3D9 EGLDeviceEXT,
+ // the already-existing display should be returned.
+ // Therefore this codepath to create a new display from the device
+ // should never be hit.
+ UNREACHABLE();
+ break;
+#endif
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ ASSERT(impl != nullptr);
+ return impl;
+}
+
+// On platforms with support for multiple back-ends, allow an environment variable to control
+// the default. This is useful to run angle with benchmarks without having to modify the
+// benchmark source. Possible values for this environment variable (ANGLE_DEFAULT_PLATFORM)
+// are: vulkan, gl, d3d11, null.
+EGLAttrib GetDisplayTypeFromEnvironment()
+{
+ std::string angleDefaultEnv = angle::GetEnvironmentVar("ANGLE_DEFAULT_PLATFORM");
+ angle::ToLower(&angleDefaultEnv);
+
+#if defined(ANGLE_ENABLE_VULKAN)
+ if ((angleDefaultEnv == "vulkan") || (angleDefaultEnv == "vulkan-null") ||
+ (angleDefaultEnv == "swiftshader"))
+ {
+ return EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
+ }
+#endif
+
+#if defined(ANGLE_ENABLE_OPENGL)
+ if (angleDefaultEnv == "gl")
+ {
+ return EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
+ }
+#endif
+
+#if defined(ANGLE_ENABLE_D3D11)
+ if (angleDefaultEnv == "d3d11")
+ {
+ return EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
+ }
+#endif
+
+#if defined(ANGLE_ENABLE_METAL)
+ if (angleDefaultEnv == "metal")
+ {
+ return EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE;
+ }
+#endif
+
+#if defined(ANGLE_ENABLE_NULL)
+ if (angleDefaultEnv == "null")
+ {
+ return EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE;
+ }
+#endif
+#if defined(ANGLE_ENABLE_METAL)
+ if (angleDefaultEnv == "metal")
+ {
+ return EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE;
+ }
+
+#endif
+#if defined(ANGLE_ENABLE_D3D11)
+ return EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
+#elif defined(ANGLE_ENABLE_D3D9)
+ return EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
+#elif defined(ANGLE_ENABLE_VULKAN) && defined(ANGLE_PLATFORM_ANDROID)
+ return EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
+#elif defined(ANGLE_ENABLE_OPENGL)
+# if defined(ANGLE_PLATFORM_ANDROID) || defined(ANGLE_USE_GBM)
+ return EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
+# else
+ return EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE;
+# endif
+#elif defined(ANGLE_ENABLE_METAL)
+ return EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE;
+#elif defined(ANGLE_ENABLE_VULKAN)
+ return EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
+#elif defined(ANGLE_ENABLE_NULL)
+ return EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE;
+#else
+# error No default ANGLE platform type
+#endif
+}
+
+EGLAttrib GetDeviceTypeFromEnvironment()
+{
+ std::string angleDefaultEnv = angle::GetEnvironmentVar("ANGLE_DEFAULT_PLATFORM");
+ angle::ToLower(&angleDefaultEnv);
+
+#if defined(ANGLE_ENABLE_VULKAN)
+ if (angleDefaultEnv == "vulkan-null")
+ {
+ return EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE;
+ }
+ else if (angleDefaultEnv == "swiftshader")
+ {
+ return EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE;
+ }
+#endif
+ return EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE;
+}
+
+EGLAttrib GetPlatformTypeFromEnvironment()
+{
+#if defined(ANGLE_USE_OZONE)
+ return 0;
+#elif defined(ANGLE_USE_X11)
+ return EGL_PLATFORM_X11_EXT;
+#elif defined(ANGLE_USE_WAYLAND)
+ return EGL_PLATFORM_WAYLAND_EXT;
+#elif defined(ANGLE_USE_VULKAN_DISPLAY) && defined(ANGLE_VULKAN_DISPLAY_MODE_SIMPLE)
+ return EGL_PLATFORM_VULKAN_DISPLAY_MODE_SIMPLE_ANGLE;
+#elif defined(ANGLE_USE_VULKAN_DISPLAY) && defined(ANGLE_VULKAN_DISPLAY_MODE_HEADLESS)
+ return EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE;
+#else
+ return 0;
+#endif // defined(ANGLE_USE_OZONE)
+}
+
+rx::DisplayImpl *CreateDisplayFromAttribs(EGLAttrib displayType,
+ EGLAttrib deviceType,
+ EGLAttrib platformType,
+ const DisplayState &state)
+{
+ ASSERT(displayType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+ rx::DisplayImpl *impl = nullptr;
+
+ switch (displayType)
+ {
+ case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+ UNREACHABLE();
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
+ case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+ impl = new rx::DisplayD3D(state);
+ break;
+#else
+ // A D3D display was requested on a platform that doesn't support it
+ UNREACHABLE();
+ break;
+#endif
+
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
+#if defined(ANGLE_ENABLE_OPENGL)
+# if defined(ANGLE_PLATFORM_WINDOWS)
+ impl = new rx::DisplayWGL(state);
+ break;
+
+# elif defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_IOS)
+ impl = rx::CreateDisplayCGLOrEAGL(state);
+ break;
+
+# elif defined(ANGLE_PLATFORM_LINUX)
+# if defined(ANGLE_USE_GBM)
+ if (platformType == 0)
+ {
+ // If platformType is unknown, use DisplayGbm now. In the future, it should use
+ // DisplayEGL letting native EGL decide what display to use.
+ impl = new rx::DisplayGbm(state);
+ break;
+ }
+# endif
+ if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE)
+ {
+ impl = new rx::DisplayEGL(state);
+ break;
+ }
+# if defined(ANGLE_USE_X11)
+ if (platformType == EGL_PLATFORM_X11_EXT)
+ {
+ impl = new rx::DisplayGLX(state);
+ break;
+ }
+# endif
+ break;
+
+# elif defined(ANGLE_PLATFORM_ANDROID)
+ // No GL support on this platform, fail display creation.
+ impl = nullptr;
+ break;
+
+# else
+# error Unsupported OpenGL platform.
+# endif
+#else
+ // No display available
+ UNREACHABLE();
+ break;
+
+#endif // defined(ANGLE_ENABLE_OPENGL)
+
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+#if defined(ANGLE_ENABLE_OPENGL)
+# if defined(ANGLE_PLATFORM_WINDOWS)
+ impl = new rx::DisplayWGL(state);
+# elif defined(ANGLE_PLATFORM_LINUX)
+# if defined(ANGLE_USE_GBM)
+ if (platformType == 0 ||
+ platformType == EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE)
+ {
+ // If platformType is unknown, use DisplayGbm now. In the future, it should use
+ // DisplayEGL letting native EGL decide what display to use.
+ // platformType == EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE is a hack,
+ // to allow ChromeOS GLES backend to continue functioning when Vulkan is enabled.
+ impl = new rx::DisplayGbm(state);
+ break;
+ }
+# endif
+ if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE)
+ {
+ impl = new rx::DisplayEGL(state);
+ break;
+ }
+ else
+ {
+# if defined(ANGLE_USE_X11)
+ if (platformType == EGL_PLATFORM_X11_EXT)
+ {
+ impl = new rx::DisplayGLX(state);
+ break;
+ }
+# endif
+ }
+# elif defined(ANGLE_PLATFORM_ANDROID)
+ impl = new rx::DisplayAndroid(state);
+# else
+ // No GLES support on this platform, fail display creation.
+ impl = nullptr;
+# endif
+#endif // defined(ANGLE_ENABLE_OPENGL)
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
+#if defined(ANGLE_ENABLE_VULKAN)
+# if defined(ANGLE_USE_VULKAN_NULL_DISPLAY)
+ if (rx::IsVulkanNullDisplayAvailable())
+ {
+ impl = rx::CreateVulkanNullDisplay(state);
+ }
+ break;
+# elif defined(ANGLE_PLATFORM_WINDOWS)
+ if (rx::IsVulkanWin32DisplayAvailable())
+ {
+ impl = rx::CreateVulkanWin32Display(state);
+ }
+ break;
+# elif defined(ANGLE_PLATFORM_LINUX)
+# if defined(ANGLE_USE_GBM)
+ if (platformType == EGL_PLATFORM_GBM_KHR && rx::IsVulkanGbmDisplayAvailable())
+ {
+ impl = rx::CreateVulkanGbmDisplay(state);
+ break;
+ }
+# endif
+# if defined(ANGLE_USE_X11)
+ if (platformType == EGL_PLATFORM_X11_EXT && rx::IsVulkanXcbDisplayAvailable())
+ {
+ impl = rx::CreateVulkanXcbDisplay(state);
+ break;
+ }
+# endif
+# if defined(ANGLE_USE_WAYLAND)
+ if (platformType == EGL_PLATFORM_WAYLAND_EXT && rx::IsVulkanWaylandDisplayAvailable())
+ {
+ impl = rx::CreateVulkanWaylandDisplay(state);
+ break;
+ }
+# endif
+# if defined(ANGLE_USE_VULKAN_DISPLAY)
+ if (platformType == EGL_PLATFORM_VULKAN_DISPLAY_MODE_SIMPLE_ANGLE &&
+ rx::IsVulkanSimpleDisplayAvailable())
+ {
+ impl = rx::CreateVulkanSimpleDisplay(state);
+ }
+ else if (platformType == EGL_PLATFORM_VULKAN_DISPLAY_MODE_HEADLESS_ANGLE &&
+ rx::IsVulkanHeadlessDisplayAvailable())
+ {
+ impl = rx::CreateVulkanHeadlessDisplay(state);
+ }
+ else
+ {
+ // Not supported creation type on vulkan display, fail display creation.
+ impl = nullptr;
+ }
+# endif
+ break;
+# elif defined(ANGLE_PLATFORM_ANDROID)
+ if (rx::IsVulkanAndroidDisplayAvailable())
+ {
+ impl = rx::CreateVulkanAndroidDisplay(state);
+ }
+ break;
+# elif defined(ANGLE_PLATFORM_FUCHSIA)
+ if (rx::IsVulkanFuchsiaDisplayAvailable())
+ {
+ impl = rx::CreateVulkanFuchsiaDisplay(state);
+ }
+ break;
+# elif defined(ANGLE_PLATFORM_GGP)
+ if (rx::IsVulkanGGPDisplayAvailable())
+ {
+ impl = rx::CreateVulkanGGPDisplay(state);
+ }
+ break;
+# elif defined(ANGLE_PLATFORM_APPLE)
+ if (rx::IsVulkanMacDisplayAvailable())
+ {
+ impl = rx::CreateVulkanMacDisplay(state);
+ }
+ break;
+# else
+# error Unsupported Vulkan platform.
+# endif
+#else
+ // No display available
+ UNREACHABLE();
+ break;
+#endif // defined(ANGLE_ENABLE_VULKAN)
+
+ case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE:
+#if defined(ANGLE_ENABLE_METAL)
+ if (rx::IsMetalDisplayAvailable())
+ {
+ impl = rx::CreateMetalDisplay(state);
+ break;
+ }
+#endif
+ // No display available
+ UNREACHABLE();
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
+#if defined(ANGLE_ENABLE_NULL)
+ impl = new rx::DisplayNULL(state);
+ break;
+#else
+ // No display available
+ UNREACHABLE();
+ break;
+#endif // defined(ANGLE_ENABLE_NULL)
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return impl;
+}
+
+void Display_logError(angle::PlatformMethods *platform, const char *errorMessage)
+{
+ gl::Trace(gl::LOG_ERR, errorMessage);
+}
+
+void Display_logWarning(angle::PlatformMethods *platform, const char *warningMessage)
+{
+ gl::Trace(gl::LOG_WARN, warningMessage);
+}
+
+void Display_logInfo(angle::PlatformMethods *platform, const char *infoMessage)
+{
+ // Uncomment to get info spam
+#if defined(ANGLE_ENABLE_DEBUG_TRACE)
+ gl::Trace(gl::LOG_INFO, infoMessage);
+#endif
+}
+
+const std::vector<std::string> EGLStringArrayToStringVector(const char **ary)
+{
+ std::vector<std::string> vec;
+ if (ary != nullptr)
+ {
+ for (; *ary != nullptr; ary++)
+ {
+ vec.push_back(std::string(*ary));
+ }
+ }
+ return vec;
+}
+
+void ANGLESetDefaultDisplayPlatform(angle::EGLDisplayType display)
+{
+ angle::PlatformMethods *platformMethods = ANGLEPlatformCurrent();
+
+ ANGLEResetDisplayPlatform(display);
+ platformMethods->logError = Display_logError;
+ platformMethods->logWarning = Display_logWarning;
+ platformMethods->logInfo = Display_logInfo;
+}
+
+void UpdateAttribsFromEnvironment(AttributeMap &attribMap)
+{
+ EGLAttrib displayType =
+ attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+ if (displayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
+ {
+ displayType = GetDisplayTypeFromEnvironment();
+ attribMap.insert(EGL_PLATFORM_ANGLE_TYPE_ANGLE, displayType);
+ }
+ EGLAttrib deviceType = attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, 0);
+ if (deviceType == 0)
+ {
+ deviceType = GetDeviceTypeFromEnvironment();
+ attribMap.insert(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, deviceType);
+ }
+ EGLAttrib platformType = attribMap.get(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE, 0);
+ if (platformType == 0)
+ {
+ platformType = GetPlatformTypeFromEnvironment();
+ attribMap.insert(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE, platformType);
+ }
+}
+
+static constexpr uint32_t kScratchBufferLifetime = 64u;
+
+} // anonymous namespace
+
+// ShareGroup
+ShareGroup::ShareGroup(rx::EGLImplFactory *factory)
+ : mRefCount(1),
+ mImplementation(factory->createShareGroup()),
+ mFrameCaptureShared(new angle::FrameCaptureShared)
+{}
+
+void ShareGroup::finishAllContexts()
+{
+ for (gl::Context *shareContext : mContexts)
+ {
+ if (shareContext->hasBeenCurrent() && !shareContext->isDestroyed())
+ {
+ shareContext->finish();
+ }
+ }
+}
+
+void ShareGroup::addSharedContext(gl::Context *context)
+{
+ mContexts.insert(context);
+
+ if (context->isRobustnessEnabled())
+ {
+ mImplementation->onRobustContextAdd();
+ }
+}
+
+void ShareGroup::removeSharedContext(gl::Context *context)
+{
+ mContexts.erase(context);
+}
+
+ShareGroup::~ShareGroup()
+{
+ SafeDelete(mImplementation);
+}
+
+void ShareGroup::addRef()
+{
+ // This is protected by global lock, so no atomic is required
+ mRefCount++;
+}
+
+void ShareGroup::release(const Display *display)
+{
+ if (--mRefCount == 0)
+ {
+ if (mImplementation)
+ {
+ mImplementation->onDestroy(display);
+ }
+ delete this;
+ }
+}
+
+// DisplayState
+DisplayState::DisplayState(EGLNativeDisplayType nativeDisplayId)
+ : label(nullptr), featuresAllDisabled(false), displayId(nativeDisplayId)
+{}
+
+DisplayState::~DisplayState() {}
+
+// Note that ANGLE support on Ozone platform is limited. Our preferred support Matrix for
+// EGL_ANGLE_platform_angle on Linux and Ozone/Linux/Fuchsia platforms should be the following:
+//
+// |--------------------------------------------------------|
+// | ANGLE type | DEVICE type | PLATFORM type | Display |
+// |--------------------------------------------------------|
+// | OPENGL | EGL | ANY | EGL |
+// | OPENGL | HARDWARE | X11_EXT | GLX |
+// | OPENGLES | HARDWARE | X11_EXT | GLX |
+// | OPENGLES | EGL | ANY | EGL |
+// | VULKAN | HARDWARE | X11_EXT | VkXcb |
+// | VULKAN | SWIFTSHADER | X11_EXT | VkXcb |
+// | OPENGLES | HARDWARE | SURFACELESS_MESA | EGL* |
+// | OPENGLES | HARDWARE | DEVICE_EXT | EGL |
+// | VULKAN | HARDWARE | SURFACELESS_MESA | VkBase** |
+// | VULKAN | SWIFTSHADER | SURFACELESS_MESA | VkBase** |
+// |--------------------------------------------------------|
+//
+// * No surfaceless support yet.
+// ** Not implemented yet.
+//
+// |-----------------------------------------------|
+// | OS | BUILD type | Default PLATFORM type |
+// |-----------------------------------------------|
+// | Linux | X11 | X11_EXT |
+// | Linux | Ozone | SURFACELESS_MESA |
+// | Fuchsia | Ozone | FUCHSIA*** |
+// |-----------------------------------------------|
+//
+// *** Chosen implicitly. No EGLAttrib available.
+//
+// For more details, please refer to
+// https://docs.google.com/document/d/1XjHiDZQISq1AMrg_l1TX1_kIKvDpU76hidn9i4cAjl8/edit?disco=AAAAJl9V_YY
+//
+// static
+Display *Display::GetDisplayFromNativeDisplay(EGLenum platform,
+ EGLNativeDisplayType nativeDisplay,
+ const AttributeMap &attribMap)
+{
+ Display *display = nullptr;
+
+ AttributeMap updatedAttribMap(attribMap);
+ UpdateAttribsFromEnvironment(updatedAttribMap);
+
+ EGLAttrib powerPreference =
+ updatedAttribMap.get(EGL_POWER_PREFERENCE_ANGLE, EGL_LOW_POWER_ANGLE);
+ EGLAttrib platformANGLEType =
+ updatedAttribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+ EGLAttrib deviceIdHigh = updatedAttribMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0);
+ EGLAttrib deviceIdLow = updatedAttribMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0);
+ ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
+ ANGLEPlatformDisplay displayKey(nativeDisplay, powerPreference, platformANGLEType, deviceIdHigh,
+ deviceIdLow);
+ const auto &iter = displays->find(displayKey);
+ if (iter != displays->end())
+ {
+ display = iter->second;
+ }
+
+ if (display == nullptr)
+ {
+ // Validate the native display
+ if (!Display::isValidNativeDisplay(nativeDisplay))
+ {
+ return nullptr;
+ }
+
+ display = new Display(platform, nativeDisplay, nullptr);
+ displays->insert(std::make_pair(displayKey, display));
+ }
+ // Apply new attributes if the display is not initialized yet.
+ if (!display->isInitialized())
+ {
+ display->setAttributes(updatedAttribMap);
+
+ EGLAttrib displayType = display->mAttributeMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
+ EGLAttrib deviceType = display->mAttributeMap.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE);
+ EGLAttrib platformType = platform;
+ if (platform == EGL_PLATFORM_ANGLE_ANGLE)
+ {
+ platformType =
+ display->mAttributeMap.get(EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE);
+ }
+ rx::DisplayImpl *impl =
+ CreateDisplayFromAttribs(displayType, deviceType, platformType, display->getState());
+ if (impl == nullptr)
+ {
+ // No valid display implementation for these attributes
+ return nullptr;
+ }
+
+#if defined(ANGLE_USE_ANDROID_TLS_SLOT)
+ angle::gUseAndroidOpenGLTlsSlot = displayType == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
+#endif // defined(ANGLE_PLATFORM_ANDROID)
+
+ display->setupDisplayPlatform(impl);
+ }
+
+ return display;
+}
+
+// static
+Display *Display::GetExistingDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay)
+{
+ ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
+ const auto &iter = displays->find(nativeDisplay);
+
+ // Check that there is a matching display
+ if (iter == displays->end())
+ {
+ return nullptr;
+ }
+
+ return iter->second;
+}
+
+// static
+Display *Display::GetDisplayFromDevice(Device *device, const AttributeMap &attribMap)
+{
+ Display *display = nullptr;
+
+ ASSERT(Device::IsValidDevice(device));
+
+ ANGLEPlatformDisplayMap *anglePlatformDisplays = GetANGLEPlatformDisplayMap();
+ DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap();
+
+ // First see if this eglDevice is in use by a Display created using ANGLE platform
+ for (auto &displayMapEntry : *anglePlatformDisplays)
+ {
+ egl::Display *iterDisplay = displayMapEntry.second;
+ if (iterDisplay->getDevice() == device)
+ {
+ display = iterDisplay;
+ }
+ }
+
+ if (display == nullptr)
+ {
+ // See if the eglDevice is in use by a Display created using the DEVICE platform
+ const auto &iter = devicePlatformDisplays->find(device);
+ if (iter != devicePlatformDisplays->end())
+ {
+ display = iter->second;
+ }
+ }
+
+ if (display == nullptr)
+ {
+ // Otherwise create a new Display
+ display = new Display(EGL_PLATFORM_DEVICE_EXT, 0, device);
+ devicePlatformDisplays->insert(std::make_pair(device, display));
+ }
+
+ // Apply new attributes if the display is not initialized yet.
+ if (!display->isInitialized())
+ {
+ display->setAttributes(attribMap);
+ rx::DisplayImpl *impl = CreateDisplayFromDevice(device, display->getState());
+ display->setupDisplayPlatform(impl);
+ }
+
+ return display;
+}
+
+// static
+Display::EglDisplaySet Display::GetEglDisplaySet()
+{
+ Display::EglDisplaySet displays;
+
+ ANGLEPlatformDisplayMap *anglePlatformDisplays = GetANGLEPlatformDisplayMap();
+ DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap();
+
+ for (auto anglePlatformDisplayMapEntry : *anglePlatformDisplays)
+ {
+ displays.insert(anglePlatformDisplayMapEntry.second);
+ }
+
+ for (auto devicePlatformDisplayMapEntry : *devicePlatformDisplays)
+ {
+ displays.insert(devicePlatformDisplayMapEntry.second);
+ }
+
+ return displays;
+}
+
+Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
+ : mState(displayId),
+ mImplementation(nullptr),
+ mGPUSwitchedBinding(this, kGPUSwitchedSubjectIndex),
+ mAttributeMap(),
+ mConfigSet(),
+ mStreamSet(),
+ mInvalidContextSet(),
+ mInvalidImageSet(),
+ mInvalidStreamSet(),
+ mInvalidSurfaceSet(),
+ mInvalidSyncSet(),
+ mInitialized(false),
+ mDeviceLost(false),
+ mCaps(),
+ mDisplayExtensions(),
+ mDisplayExtensionString(),
+ mVendorString(),
+ mVersionString(),
+ mDevice(eglDevice),
+ mSurface(nullptr),
+ mPlatform(platform),
+ mTextureManager(nullptr),
+ mSemaphoreManager(nullptr),
+ mBlobCache(gl::kDefaultMaxProgramCacheMemoryBytes),
+ mMemoryProgramCache(mBlobCache),
+ mMemoryShaderCache(mBlobCache),
+ mGlobalTextureShareGroupUsers(0),
+ mGlobalSemaphoreShareGroupUsers(0),
+ mTerminatedByApi(false),
+ mActiveThreads()
+{}
+
+Display::~Display()
+{
+ switch (mPlatform)
+ {
+ case EGL_PLATFORM_ANGLE_ANGLE:
+ case EGL_PLATFORM_GBM_KHR:
+ case EGL_PLATFORM_WAYLAND_EXT:
+ {
+ ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
+ ANGLEPlatformDisplayMap::iterator iter = displays->find(ANGLEPlatformDisplay(
+ mState.displayId,
+ mAttributeMap.get(EGL_POWER_PREFERENCE_ANGLE, EGL_LOW_POWER_ANGLE),
+ mAttributeMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE,
+ EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE),
+ mAttributeMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0),
+ mAttributeMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0)));
+ if (iter != displays->end())
+ {
+ displays->erase(iter);
+ }
+ break;
+ }
+ case EGL_PLATFORM_DEVICE_EXT:
+ {
+ DevicePlatformDisplayMap *displays = GetDevicePlatformDisplayMap();
+ DevicePlatformDisplayMap::iterator iter = displays->find(mDevice);
+ if (iter != displays->end())
+ {
+ displays->erase(iter);
+ }
+ break;
+ }
+ default:
+ {
+ UNREACHABLE();
+ }
+ }
+
+ SafeDelete(mDevice);
+ SafeDelete(mImplementation);
+}
+
+void Display::setLabel(EGLLabelKHR label)
+{
+ mState.label = label;
+}
+
+EGLLabelKHR Display::getLabel() const
+{
+ return mState.label;
+}
+
+void Display::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
+{
+ ASSERT(index == kGPUSwitchedSubjectIndex);
+ ASSERT(message == angle::SubjectMessage::SubjectChanged);
+ for (gl::Context *context : mState.contextSet)
+ {
+ context->onGPUSwitch();
+ }
+}
+
+void Display::setupDisplayPlatform(rx::DisplayImpl *impl)
+{
+ ASSERT(!mInitialized);
+
+ ASSERT(impl != nullptr);
+ SafeDelete(mImplementation);
+ mImplementation = impl;
+
+ // TODO(anglebug.com/7365): Remove PlatformMethods.
+ const angle::PlatformMethods *platformMethods =
+ reinterpret_cast<const angle::PlatformMethods *>(
+ mAttributeMap.get(EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX, 0));
+ if (platformMethods != nullptr)
+ {
+ *ANGLEPlatformCurrent() = *platformMethods;
+ }
+ else
+ {
+ ANGLESetDefaultDisplayPlatform(this);
+ }
+
+ const char **featuresForceEnabled =
+ reinterpret_cast<const char **>(mAttributeMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0));
+ const char **featuresForceDisabled =
+ reinterpret_cast<const char **>(mAttributeMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0));
+ mState.featureOverridesEnabled = EGLStringArrayToStringVector(featuresForceEnabled);
+ mState.featureOverridesDisabled = EGLStringArrayToStringVector(featuresForceDisabled);
+ mState.featuresAllDisabled =
+ static_cast<bool>(mAttributeMap.get(EGL_FEATURE_ALL_DISABLED_ANGLE, 0));
+ mImplementation->addObserver(&mGPUSwitchedBinding);
+}
+
+Error Display::initialize()
+{
+ mTerminatedByApi = false;
+
+ ASSERT(mImplementation != nullptr);
+ mImplementation->setBlobCache(&mBlobCache);
+
+ // Enable shader caching if debug layers are turned on. This allows us to test that shaders are
+ // properly saved & restored on all platforms. The cache won't allocate space until it's used
+ // and will be ignored entirely if the application / system sets it's own cache functions.
+ if (rx::ShouldUseDebugLayers(mAttributeMap))
+ {
+ mBlobCache.resize(1024 * 1024);
+ }
+
+ setGlobalDebugAnnotator();
+
+ gl::InitializeDebugMutexIfNeeded();
+
+ ANGLE_TRACE_EVENT0("gpu.angle", "egl::Display::initialize");
+
+ if (isInitialized())
+ {
+ return NoError();
+ }
+
+ Error error = mImplementation->initialize(this);
+ if (error.isError())
+ {
+ // Log extended error message here
+ ERR() << "ANGLE Display::initialize error " << error.getID() << ": " << error.getMessage();
+ return error;
+ }
+
+ mCaps = mImplementation->getCaps();
+
+ mConfigSet = mImplementation->generateConfigs();
+ if (mConfigSet.size() == 0)
+ {
+ mImplementation->terminate();
+ return EglNotInitialized() << "No configs were generated.";
+ }
+
+ // OpenGL ES1 is implemented in the frontend, explicitly add ES1 support to all configs
+ for (auto &config : mConfigSet)
+ {
+ // TODO(geofflang): Enable the conformant bit once we pass enough tests
+ // config.second.conformant |= EGL_OPENGL_ES_BIT;
+
+ config.second.renderableType |= EGL_OPENGL_ES_BIT;
+
+ // If we aren't using desktop GL entry points, remove desktop GL support from all configs
+#if !defined(ANGLE_ENABLE_GL_DESKTOP_FRONTEND)
+ config.second.renderableType &= ~EGL_OPENGL_BIT;
+#endif
+ }
+
+ if (!mState.featuresAllDisabled)
+ {
+ initializeFrontendFeatures();
+ }
+
+ mFeatures.clear();
+ mFrontendFeatures.populateFeatureList(&mFeatures);
+ mImplementation->populateFeatureList(&mFeatures);
+
+ initDisplayExtensions();
+ initVendorString();
+ initVersionString();
+ initClientAPIString();
+
+ // Populate the Display's EGLDeviceEXT if the Display wasn't created using one
+ if (mPlatform == EGL_PLATFORM_DEVICE_EXT)
+ {
+ // For EGL_PLATFORM_DEVICE_EXT, mDevice should always be populated using
+ // an external device
+ ASSERT(mDevice != nullptr);
+ }
+ else if (GetClientExtensions().deviceQueryEXT)
+ {
+ std::unique_ptr<rx::DeviceImpl> impl(mImplementation->createDevice());
+ ASSERT(impl);
+ error = impl->initialize();
+ if (error.isError())
+ {
+ ERR() << "Failed to initialize display because device creation failed: "
+ << error.getMessage();
+ mImplementation->terminate();
+ return error;
+ }
+ // Don't leak Device memory.
+ ASSERT(mDevice == nullptr);
+ mDevice = new Device(this, impl.release());
+ }
+ else
+ {
+ mDevice = nullptr;
+ }
+
+ mInitialized = true;
+
+ return NoError();
+}
+
+Error Display::destroyInvalidEglObjects()
+{
+ // Destroy invalid EGL objects
+ while (!mInvalidContextSet.empty())
+ {
+ gl::Context *context = *mInvalidContextSet.begin();
+ context->setIsDestroyed();
+ ANGLE_TRY(releaseContextImpl(context, &mInvalidContextSet));
+ }
+
+ while (!mInvalidImageSet.empty())
+ {
+ destroyImageImpl(*mInvalidImageSet.begin(), &mInvalidImageSet);
+ }
+
+ while (!mInvalidStreamSet.empty())
+ {
+ destroyStreamImpl(*mInvalidStreamSet.begin(), &mInvalidStreamSet);
+ }
+
+ while (!mInvalidSurfaceSet.empty())
+ {
+ ANGLE_TRY(destroySurfaceImpl(*mInvalidSurfaceSet.begin(), &mInvalidSurfaceSet));
+ }
+
+ while (!mInvalidSyncSet.empty())
+ {
+ destroySyncImpl(*mInvalidSyncSet.begin(), &mInvalidSyncSet);
+ }
+
+ return NoError();
+}
+
+Error Display::terminate(Thread *thread, TerminateReason terminateReason)
+{
+ if (terminateReason == TerminateReason::Api)
+ {
+ mTerminatedByApi = true;
+ }
+
+ // All subsequent calls assume the display to be valid and terminated by app.
+ // If it is not terminated or if it isn't even initialized, early return.
+ if (!mTerminatedByApi || !mInitialized)
+ {
+ return NoError();
+ }
+
+ // EGL 1.5 Specification
+ // 3.2 Initialization
+ // Termination marks all EGL-specific resources, such as contexts and surfaces, associated
+ // with the specified display for deletion. Handles to all such resources are invalid as soon
+ // as eglTerminate returns. Cache EGL objects that are no longer valid.
+ //
+ // It is fairly common for apps to call eglTerminate while some contexts and/or surfaces are
+ // still current on some thread. Since objects are refCounted, trying to destroy them right away
+ // would only result in a decRef. We instead cache such invalid objects and use other EGL
+ // entrypoints like eglReleaseThread or thread exit events (on the Android platform) to
+ // perform the necessary cleanup.
+ mInvalidImageSet.insert(mImageSet.begin(), mImageSet.end());
+ mImageSet.clear();
+
+ mInvalidStreamSet.insert(mStreamSet.begin(), mStreamSet.end());
+ mStreamSet.clear();
+
+ mInvalidSurfaceSet.insert(mState.surfaceSet.begin(), mState.surfaceSet.end());
+ mState.surfaceSet.clear();
+
+ mInvalidSyncSet.insert(mSyncSet.begin(), mSyncSet.end());
+ mSyncSet.clear();
+
+ // Cache total number of contexts before invalidation. This is used as a check to verify that
+ // no context is "lost" while being moved between the various sets.
+ size_t contextSetSizeBeforeInvalidation = mState.contextSet.size() + mInvalidContextSet.size();
+
+ // If app called eglTerminate and no active threads remain,
+ // force realease any context that is still current.
+ ContextSet contextsStillCurrent = {};
+ for (gl::Context *context : mState.contextSet)
+ {
+ if (context->getRefCount() > 0)
+ {
+ if (terminateReason == TerminateReason::NoActiveThreads)
+ {
+ ASSERT(mTerminatedByApi);
+ context->release();
+ (void)context->unMakeCurrent(this);
+ }
+ else
+ {
+ contextsStillCurrent.emplace(context);
+ continue;
+ }
+ }
+
+ // Add context that is not current to mInvalidContextSet for cleanup.
+ mInvalidContextSet.emplace(context);
+ }
+
+ // There are many methods that require contexts that are still current to be present in
+ // display's contextSet like during context release or to notify of state changes in a subject.
+ // So as to not interrupt this flow, do not remove contexts that are still current on some
+ // thread from display's contextSet even though eglTerminate marks such contexts as invalid.
+ //
+ // "mState.contextSet" will now contain only those contexts that are still current on some
+ // thread.
+ mState.contextSet = std::move(contextsStillCurrent);
+
+ // Assert that the total number of contexts is the same before and after context invalidation.
+ ASSERT(contextSetSizeBeforeInvalidation ==
+ mState.contextSet.size() + mInvalidContextSet.size());
+
+ if (!mState.contextSet.empty())
+ {
+ // There was atleast 1 context that was current on some thread, early return.
+ return NoError();
+ }
+
+ mMemoryProgramCache.clear();
+ mMemoryShaderCache.clear();
+ mBlobCache.setBlobCacheFuncs(nullptr, nullptr);
+
+ // The global texture and semaphore managers should be deleted with the last context that uses
+ // it.
+ ASSERT(mGlobalTextureShareGroupUsers == 0 && mTextureManager == nullptr);
+ ASSERT(mGlobalSemaphoreShareGroupUsers == 0 && mSemaphoreManager == nullptr);
+
+ // Clean up all invalid objects
+ ANGLE_TRY(destroyInvalidEglObjects());
+
+ mConfigSet.clear();
+
+ if (mDevice != nullptr && mDevice->getOwningDisplay() != nullptr)
+ {
+ // Don't delete the device if it was created externally using eglCreateDeviceANGLE
+ // We also shouldn't set it to null in case eglInitialize() is called again later
+ SafeDelete(mDevice);
+ }
+
+ mImplementation->terminate();
+
+ mDeviceLost = false;
+
+ mInitialized = false;
+
+ gl::UninitializeDebugAnnotations();
+
+ // TODO(jmadill): Store Platform in Display and deinit here.
+ ANGLEResetDisplayPlatform(this);
+
+ return NoError();
+}
+
+Error Display::prepareForCall()
+{
+ return mImplementation->prepareForCall();
+}
+
+Error Display::releaseThread()
+{
+ ANGLE_TRY(mImplementation->releaseThread());
+ return destroyInvalidEglObjects();
+}
+
+void Display::addActiveThread(Thread *thread)
+{
+ mActiveThreads.insert(thread);
+}
+
+void Display::threadCleanup(Thread *thread)
+{
+ mActiveThreads.erase(thread);
+ const bool noActiveThreads = mActiveThreads.size() == 0;
+
+ (void)terminate(thread, noActiveThreads ? TerminateReason::NoActiveThreads
+ : TerminateReason::InternalCleanup);
+}
+
+std::vector<const Config *> Display::getConfigs(const egl::AttributeMap &attribs) const
+{
+ return mConfigSet.filter(attribs);
+}
+
+std::vector<const Config *> Display::chooseConfig(const egl::AttributeMap &attribs) const
+{
+ egl::AttributeMap attribsWithDefaults = AttributeMap();
+
+ // Insert default values for attributes that have either an Exact or Mask selection criteria,
+ // and a default value that matters (e.g. isn't EGL_DONT_CARE):
+ attribsWithDefaults.insert(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
+ attribsWithDefaults.insert(EGL_LEVEL, 0);
+ attribsWithDefaults.insert(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
+ attribsWithDefaults.insert(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
+ attribsWithDefaults.insert(EGL_TRANSPARENT_TYPE, EGL_NONE);
+ if (getExtensions().pixelFormatFloat)
+ {
+ attribsWithDefaults.insert(EGL_COLOR_COMPONENT_TYPE_EXT,
+ EGL_COLOR_COMPONENT_TYPE_FIXED_EXT);
+ }
+
+ // Add the caller-specified values (Note: the poorly-named insert() method will replace any
+ // of the default values from above):
+ for (auto attribIter = attribs.begin(); attribIter != attribs.end(); attribIter++)
+ {
+ attribsWithDefaults.insert(attribIter->first, attribIter->second);
+ }
+
+ return mConfigSet.filter(attribsWithDefaults);
+}
+
+Error Display::createWindowSurface(const Config *configuration,
+ EGLNativeWindowType window,
+ const AttributeMap &attribs,
+ Surface **outSurface)
+{
+ if (mImplementation->testDeviceLost())
+ {
+ ANGLE_TRY(restoreLostDevice());
+ }
+
+ SurfacePointer surface(new WindowSurface(mImplementation, configuration, window, attribs,
+ mFrontendFeatures.forceRobustResourceInit.enabled),
+ this);
+ ANGLE_TRY(surface->initialize(this));
+
+ ASSERT(outSurface != nullptr);
+ *outSurface = surface.release();
+ mState.surfaceSet.insert(*outSurface);
+
+ WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
+ ASSERT(windowSurfaces && windowSurfaces->find(window) == windowSurfaces->end());
+ windowSurfaces->insert(std::make_pair(window, *outSurface));
+
+ mSurface = *outSurface;
+
+ return NoError();
+}
+
+Error Display::createPbufferSurface(const Config *configuration,
+ const AttributeMap &attribs,
+ Surface **outSurface)
+{
+ ASSERT(isInitialized());
+
+ if (mImplementation->testDeviceLost())
+ {
+ ANGLE_TRY(restoreLostDevice());
+ }
+
+ SurfacePointer surface(new PbufferSurface(mImplementation, configuration, attribs,
+ mFrontendFeatures.forceRobustResourceInit.enabled),
+ this);
+ ANGLE_TRY(surface->initialize(this));
+
+ ASSERT(outSurface != nullptr);
+ *outSurface = surface.release();
+ mState.surfaceSet.insert(*outSurface);
+
+ return NoError();
+}
+
+Error Display::createPbufferFromClientBuffer(const Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs,
+ Surface **outSurface)
+{
+ ASSERT(isInitialized());
+
+ if (mImplementation->testDeviceLost())
+ {
+ ANGLE_TRY(restoreLostDevice());
+ }
+
+ SurfacePointer surface(
+ new PbufferSurface(mImplementation, configuration, buftype, clientBuffer, attribs,
+ mFrontendFeatures.forceRobustResourceInit.enabled),
+ this);
+ ANGLE_TRY(surface->initialize(this));
+
+ ASSERT(outSurface != nullptr);
+ *outSurface = surface.release();
+ mState.surfaceSet.insert(*outSurface);
+
+ return NoError();
+}
+
+Error Display::createPixmapSurface(const Config *configuration,
+ NativePixmapType nativePixmap,
+ const AttributeMap &attribs,
+ Surface **outSurface)
+{
+ ASSERT(isInitialized());
+
+ if (mImplementation->testDeviceLost())
+ {
+ ANGLE_TRY(restoreLostDevice());
+ }
+
+ SurfacePointer surface(new PixmapSurface(mImplementation, configuration, nativePixmap, attribs,
+ mFrontendFeatures.forceRobustResourceInit.enabled),
+ this);
+ ANGLE_TRY(surface->initialize(this));
+
+ ASSERT(outSurface != nullptr);
+ *outSurface = surface.release();
+ mState.surfaceSet.insert(*outSurface);
+
+ return NoError();
+}
+
+Error Display::createImage(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const AttributeMap &attribs,
+ Image **outImage)
+{
+ ASSERT(isInitialized());
+
+ if (mImplementation->testDeviceLost())
+ {
+ ANGLE_TRY(restoreLostDevice());
+ }
+
+ egl::ImageSibling *sibling = nullptr;
+ if (IsTextureTarget(target))
+ {
+ sibling = context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
+ }
+ else if (IsRenderbufferTarget(target))
+ {
+ sibling = context->getRenderbuffer({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
+ }
+ else if (IsExternalImageTarget(target))
+ {
+ sibling = new ExternalImageSibling(mImplementation, context, target, buffer, attribs);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ ASSERT(sibling != nullptr);
+
+ angle::UniqueObjectPointer<Image, Display> imagePtr(
+ new Image(mImplementation, context, target, sibling, attribs), this);
+ ANGLE_TRY(imagePtr->initialize(this));
+
+ Image *image = imagePtr.release();
+
+ ASSERT(outImage != nullptr);
+ *outImage = image;
+
+ // Add this image to the list of all images and hold a ref to it.
+ image->addRef();
+ mImageSet.insert(image);
+
+ return NoError();
+}
+
+Error Display::createStream(const AttributeMap &attribs, Stream **outStream)
+{
+ ASSERT(isInitialized());
+
+ Stream *stream = new Stream(this, attribs);
+
+ ASSERT(stream != nullptr);
+ mStreamSet.insert(stream);
+
+ ASSERT(outStream != nullptr);
+ *outStream = stream;
+
+ return NoError();
+}
+
+Error Display::createContext(const Config *configuration,
+ gl::Context *shareContext,
+ EGLenum clientType,
+ const AttributeMap &attribs,
+ gl::Context **outContext)
+{
+ ASSERT(!mTerminatedByApi);
+ ASSERT(isInitialized());
+
+ if (mImplementation->testDeviceLost())
+ {
+ ANGLE_TRY(restoreLostDevice());
+ }
+
+ // This display texture sharing will allow the first context to create the texture share group.
+ bool usingDisplayTextureShareGroup =
+ attribs.get(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE;
+ gl::TextureManager *shareTextures = nullptr;
+
+ if (usingDisplayTextureShareGroup)
+ {
+ ASSERT((mTextureManager == nullptr) == (mGlobalTextureShareGroupUsers == 0));
+ if (mTextureManager == nullptr)
+ {
+ mTextureManager = new gl::TextureManager();
+ }
+
+ mGlobalTextureShareGroupUsers++;
+ shareTextures = mTextureManager;
+ }
+
+ // This display semaphore sharing will allow the first context to create the semaphore share
+ // group.
+ bool usingDisplaySemaphoreShareGroup =
+ attribs.get(EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE, EGL_FALSE) == EGL_TRUE;
+ gl::SemaphoreManager *shareSemaphores = nullptr;
+ if (usingDisplaySemaphoreShareGroup)
+ {
+ ASSERT((mSemaphoreManager == nullptr) == (mGlobalSemaphoreShareGroupUsers == 0));
+ if (mSemaphoreManager == nullptr)
+ {
+ mSemaphoreManager = new gl::SemaphoreManager();
+ }
+
+ mGlobalSemaphoreShareGroupUsers++;
+ shareSemaphores = mSemaphoreManager;
+ }
+
+ gl::MemoryProgramCache *programCachePointer = &mMemoryProgramCache;
+ // Check context creation attributes to see if we are using EGL_ANGLE_program_cache_control.
+ // If not, keep caching enabled for EGL_ANDROID_blob_cache, which can have its callbacks set
+ // at any time.
+ bool usesProgramCacheControl = attribs.contains(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE);
+ if (usesProgramCacheControl)
+ {
+ bool programCacheControlEnabled =
+ (attribs.get(EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE, GL_FALSE) == GL_TRUE);
+ // A program cache size of zero indicates it should be disabled.
+ if (!programCacheControlEnabled || mMemoryProgramCache.maxSize() == 0)
+ {
+ programCachePointer = nullptr;
+ }
+ }
+
+ gl::MemoryShaderCache *shaderCachePointer = &mMemoryShaderCache;
+ // Check if shader caching frontend feature is enabled.
+ if (!mFrontendFeatures.cacheCompiledShader.enabled)
+ {
+ shaderCachePointer = nullptr;
+ }
+
+ gl::Context *context = new gl::Context(
+ this, configuration, shareContext, shareTextures, shareSemaphores, programCachePointer,
+ shaderCachePointer, clientType, attribs, mDisplayExtensions, GetClientExtensions());
+ Error error = context->initialize();
+ if (error.isError())
+ {
+ delete context;
+ return error;
+ }
+
+ if (shareContext != nullptr)
+ {
+ shareContext->setShared();
+ }
+
+ ASSERT(context != nullptr);
+ mState.contextSet.insert(context);
+
+ ASSERT(outContext != nullptr);
+ *outContext = context;
+ return NoError();
+}
+
+Error Display::createSync(const gl::Context *currentContext,
+ EGLenum type,
+ const AttributeMap &attribs,
+ Sync **outSync)
+{
+ ASSERT(isInitialized());
+
+ if (mImplementation->testDeviceLost())
+ {
+ ANGLE_TRY(restoreLostDevice());
+ }
+
+ angle::UniqueObjectPointer<egl::Sync, Display> syncPtr(new Sync(mImplementation, type, attribs),
+ this);
+
+ ANGLE_TRY(syncPtr->initialize(this, currentContext));
+
+ Sync *sync = syncPtr.release();
+
+ sync->addRef();
+ mSyncSet.insert(sync);
+
+ *outSync = sync;
+ return NoError();
+}
+
+Error Display::makeCurrent(Thread *thread,
+ gl::Context *previousContext,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface,
+ gl::Context *context)
+{
+ if (!mInitialized)
+ {
+ return NoError();
+ }
+
+ bool contextChanged = context != previousContext;
+ if (previousContext != nullptr && contextChanged)
+ {
+ previousContext->release();
+ thread->setCurrent(nullptr);
+
+ auto error = previousContext->unMakeCurrent(this);
+ if (previousContext->getRefCount() == 0 && previousContext->isDestroyed())
+ {
+ // The previous Context may have been created with a different Display.
+ Display *previousDisplay = previousContext->getDisplay();
+ ANGLE_TRY(previousDisplay->releaseContext(previousContext, thread));
+ }
+ ANGLE_TRY(error);
+ }
+
+ thread->setCurrent(context);
+
+ ANGLE_TRY(mImplementation->makeCurrent(this, drawSurface, readSurface, context));
+
+ if (context != nullptr)
+ {
+ ANGLE_TRY(context->makeCurrent(this, drawSurface, readSurface));
+ if (contextChanged)
+ {
+ context->addRef();
+ }
+ }
+
+ // Tick all the scratch buffers to make sure they get cleaned up eventually if they stop being
+ // used.
+ {
+ std::lock_guard<std::mutex> lock(mScratchBufferMutex);
+
+ for (angle::ScratchBuffer &scatchBuffer : mScratchBuffers)
+ {
+ scatchBuffer.tick();
+ }
+ for (angle::ScratchBuffer &zeroFilledBuffer : mZeroFilledBuffers)
+ {
+ zeroFilledBuffer.tick();
+ }
+ }
+
+ return NoError();
+}
+
+Error Display::restoreLostDevice()
+{
+ for (ContextSet::iterator ctx = mState.contextSet.begin(); ctx != mState.contextSet.end();
+ ctx++)
+ {
+ if ((*ctx)->isResetNotificationEnabled())
+ {
+ // If reset notifications have been requested, application must delete all contexts
+ // first
+ return EglContextLost();
+ }
+ }
+
+ return mImplementation->restoreLostDevice(this);
+}
+
+Error Display::destroySurfaceImpl(Surface *surface, SurfaceSet *surfaces)
+{
+ if (surface->getType() == EGL_WINDOW_BIT)
+ {
+ WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
+ ASSERT(windowSurfaces);
+
+ bool surfaceRemoved = false;
+ for (WindowSurfaceMap::iterator iter = windowSurfaces->begin();
+ iter != windowSurfaces->end(); iter++)
+ {
+ if (iter->second == surface)
+ {
+ windowSurfaces->erase(iter);
+ surfaceRemoved = true;
+ break;
+ }
+ }
+
+ ASSERT(surfaceRemoved);
+ }
+
+ auto iter = surfaces->find(surface);
+ ASSERT(iter != surfaces->end());
+ surfaces->erase(iter);
+ ANGLE_TRY(surface->onDestroy(this));
+ return NoError();
+}
+
+void Display::destroyImageImpl(Image *image, ImageSet *images)
+{
+ auto iter = images->find(image);
+ ASSERT(iter != images->end());
+ (*iter)->release(this);
+ images->erase(iter);
+}
+
+void Display::destroyStreamImpl(Stream *stream, StreamSet *streams)
+{
+ streams->erase(stream);
+ SafeDelete(stream);
+}
+
+// releaseContext must be called with the context being deleted as current.
+// To do that we can only call this in two places, Display::makeCurrent at the point where this
+// context is being made uncurrent and in Display::destroyContext where we make the context current
+// as part of destruction.
+Error Display::releaseContext(gl::Context *context, Thread *thread)
+{
+ return releaseContextImpl(context, &mState.contextSet);
+}
+
+Error Display::releaseContextImpl(gl::Context *context, ContextSet *contexts)
+{
+ ASSERT(context->getRefCount() == 0);
+
+ // Use scoped_ptr to make sure the context is always freed.
+ std::unique_ptr<gl::Context> unique_context(context);
+ ASSERT(contexts->find(context) != contexts->end());
+ contexts->erase(context);
+
+ if (context->usingDisplayTextureShareGroup())
+ {
+ ASSERT(mGlobalTextureShareGroupUsers >= 1 && mTextureManager != nullptr);
+ if (mGlobalTextureShareGroupUsers == 1)
+ {
+ // If this is the last context using the global share group, destroy the global
+ // texture manager so that the textures can be destroyed while a context still
+ // exists
+ mTextureManager->release(context);
+ mTextureManager = nullptr;
+ }
+ mGlobalTextureShareGroupUsers--;
+ }
+
+ if (context->usingDisplaySemaphoreShareGroup())
+ {
+ ASSERT(mGlobalSemaphoreShareGroupUsers >= 1 && mSemaphoreManager != nullptr);
+ if (mGlobalSemaphoreShareGroupUsers == 1)
+ {
+ // If this is the last context using the global share group, destroy the global
+ // semaphore manager so that the semaphores can be destroyed while a context still
+ // exists
+ mSemaphoreManager->release(context);
+ mSemaphoreManager = nullptr;
+ }
+ mGlobalSemaphoreShareGroupUsers--;
+ }
+
+ ANGLE_TRY(context->onDestroy(this));
+
+ return NoError();
+}
+
+Error Display::destroyContext(Thread *thread, gl::Context *context)
+{
+ auto *currentContext = thread->getContext();
+ auto *currentDrawSurface = thread->getCurrentDrawSurface();
+ auto *currentReadSurface = thread->getCurrentReadSurface();
+
+ context->setIsDestroyed();
+
+ // If the context is still current on at least 1 thread, just return since it'll be released
+ // once no threads have it current anymore.
+ if (context->getRefCount() > 0)
+ {
+ return NoError();
+ }
+
+ // For external context, we cannot change the current native context, and the API user should
+ // make sure the native context is current.
+ if (context->isExternal())
+ {
+ ANGLE_TRY(releaseContext(context, thread));
+ }
+ else
+ {
+ // Keep |currentContext| alive, while releasing |context|.
+ gl::ScopedContextRef scopedContextRef(currentContext);
+
+ // keep |currentDrawSurface| and |currentReadSurface| alive as well
+ // while releasing |context|.
+ ScopedSurfaceRef drawSurfaceRef(currentDrawSurface);
+ ScopedSurfaceRef readSurfaceRef(
+ currentReadSurface == currentDrawSurface ? nullptr : currentReadSurface);
+
+ // Make the context current, so we can release resources belong to the context, and then
+ // when context is released from the current, it will be destroyed.
+ // TODO(http://www.anglebug.com/6322): Don't require a Context to be current in order to
+ // destroy it.
+ ANGLE_TRY(makeCurrent(thread, currentContext, nullptr, nullptr, context));
+ ANGLE_TRY(
+ makeCurrent(thread, context, currentDrawSurface, currentReadSurface, currentContext));
+ }
+
+ // If eglTerminate() has previously been called and this is the last Context the Display owns,
+ // we can now fully terminate the display and release all of its resources.
+ if (mTerminatedByApi)
+ {
+ for (const gl::Context *ctx : mState.contextSet)
+ {
+ if (ctx->getRefCount() > 0)
+ {
+ return NoError();
+ }
+ }
+
+ return terminate(thread, TerminateReason::InternalCleanup);
+ }
+
+ return NoError();
+}
+
+void Display::destroySyncImpl(Sync *sync, SyncSet *syncs)
+{
+ auto iter = syncs->find(sync);
+ ASSERT(iter != syncs->end());
+ (*iter)->release(this);
+ syncs->erase(iter);
+}
+
+void Display::destroyImage(Image *image)
+{
+ return destroyImageImpl(image, &mImageSet);
+}
+
+void Display::destroyStream(Stream *stream)
+{
+ return destroyStreamImpl(stream, &mStreamSet);
+}
+
+Error Display::destroySurface(Surface *surface)
+{
+ return destroySurfaceImpl(surface, &mState.surfaceSet);
+}
+
+void Display::destroySync(Sync *sync)
+{
+ return destroySyncImpl(sync, &mSyncSet);
+}
+
+bool Display::isDeviceLost() const
+{
+ ASSERT(isInitialized());
+ return mDeviceLost;
+}
+
+bool Display::testDeviceLost()
+{
+ ASSERT(isInitialized());
+
+ if (!mDeviceLost && mImplementation->testDeviceLost())
+ {
+ notifyDeviceLost();
+ }
+
+ return mDeviceLost;
+}
+
+void Display::notifyDeviceLost()
+{
+ if (mDeviceLost)
+ {
+ return;
+ }
+
+ for (ContextSet::iterator context = mState.contextSet.begin();
+ context != mState.contextSet.end(); context++)
+ {
+ (*context)->markContextLost(gl::GraphicsResetStatus::UnknownContextReset);
+ }
+
+ mDeviceLost = true;
+}
+
+void Display::setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get)
+{
+ mBlobCache.setBlobCacheFuncs(set, get);
+ mImplementation->setBlobCacheFuncs(set, get);
+}
+
+// static
+EGLClientBuffer Display::GetNativeClientBuffer(const AHardwareBuffer *buffer)
+{
+ return angle::android::AHardwareBufferToClientBuffer(buffer);
+}
+
+// static
+Error Display::CreateNativeClientBuffer(const egl::AttributeMap &attribMap,
+ EGLClientBuffer *eglClientBuffer)
+{
+ int androidHardwareBufferFormat = gl::GetAndroidHardwareBufferFormatFromChannelSizes(attribMap);
+ int width = attribMap.getAsInt(EGL_WIDTH, 0);
+ int height = attribMap.getAsInt(EGL_HEIGHT, 0);
+ int usage = attribMap.getAsInt(EGL_NATIVE_BUFFER_USAGE_ANDROID, 0);
+
+ // https://developer.android.com/ndk/reference/group/a-hardware-buffer#ahardwarebuffer_lock
+ // for AHardwareBuffer_lock()
+ // The passed AHardwareBuffer must have one layer, otherwise the call will fail.
+ constexpr int kLayerCount = 1;
+
+ *eglClientBuffer = angle::android::CreateEGLClientBufferFromAHardwareBuffer(
+ width, height, kLayerCount, androidHardwareBufferFormat, usage);
+
+ return (*eglClientBuffer == nullptr)
+ ? egl::EglBadParameter() << "native client buffer allocation failed."
+ : NoError();
+}
+
+Error Display::waitClient(const gl::Context *context)
+{
+ return mImplementation->waitClient(context);
+}
+
+Error Display::waitNative(const gl::Context *context, EGLint engine)
+{
+ return mImplementation->waitNative(context, engine);
+}
+
+const Caps &Display::getCaps() const
+{
+ return mCaps;
+}
+
+bool Display::isInitialized() const
+{
+ return mInitialized;
+}
+
+bool Display::isValidConfig(const Config *config) const
+{
+ return mConfigSet.contains(config);
+}
+
+bool Display::isValidContext(const gl::Context *context) const
+{
+ return mState.contextSet.find(const_cast<gl::Context *>(context)) != mState.contextSet.end();
+}
+
+bool Display::isValidSurface(const Surface *surface) const
+{
+ return mState.surfaceSet.find(const_cast<Surface *>(surface)) != mState.surfaceSet.end();
+}
+
+bool Display::isValidImage(const Image *image) const
+{
+ return mImageSet.find(const_cast<Image *>(image)) != mImageSet.end();
+}
+
+bool Display::isValidStream(const Stream *stream) const
+{
+ return mStreamSet.find(const_cast<Stream *>(stream)) != mStreamSet.end();
+}
+
+bool Display::isValidSync(const Sync *sync) const
+{
+ return mSyncSet.find(const_cast<Sync *>(sync)) != mSyncSet.end();
+}
+
+bool Display::hasExistingWindowSurface(EGLNativeWindowType window)
+{
+ WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
+ ASSERT(windowSurfaces);
+
+ return windowSurfaces->find(window) != windowSurfaces->end();
+}
+
+static ClientExtensions GenerateClientExtensions()
+{
+ ClientExtensions extensions;
+
+ extensions.clientExtensions = true;
+ extensions.platformBase = true;
+ extensions.platformANGLE = true;
+
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+ extensions.platformANGLED3D = true;
+ extensions.platformDevice = true;
+#endif
+
+#if defined(ANGLE_USE_GBM)
+ extensions.platformGbmKHR = true;
+#endif
+
+#if defined(ANGLE_USE_WAYLAND)
+ extensions.platformWaylandEXT = true;
+#endif
+
+#if defined(ANGLE_ENABLE_D3D11)
+# if defined(ANGLE_ENABLE_WINDOWS_UWP)
+ extensions.platformANGLED3D11ON12 = true;
+# else
+ extensions.platformANGLED3D11ON12 = IsWindows10OrGreater();
+# endif
+ extensions.platformANGLEDeviceId = true;
+#endif
+
+#if defined(ANGLE_ENABLE_OPENGL)
+ extensions.platformANGLEOpenGL = true;
+#endif
+
+#if defined(ANGLE_ENABLE_NULL)
+ extensions.platformANGLENULL = true;
+#endif
+
+#if defined(ANGLE_ENABLE_D3D11)
+ extensions.deviceCreation = true;
+ extensions.deviceCreationD3D11 = true;
+ extensions.experimentalPresentPath = true;
+#endif
+
+#if defined(ANGLE_ENABLE_VULKAN)
+ extensions.platformANGLEVulkan = true;
+ extensions.platformANGLEDeviceId = true;
+#endif
+
+#if defined(ANGLE_ENABLE_SWIFTSHADER)
+ extensions.platformANGLEDeviceTypeSwiftShader = true;
+#endif
+
+#if defined(ANGLE_ENABLE_METAL)
+ extensions.platformANGLEMetal = true;
+ extensions.platformANGLEDeviceId = true;
+#endif
+
+#if defined(ANGLE_USE_X11)
+ extensions.x11Visual = true;
+#endif
+
+#if defined(ANGLE_PLATFORM_LINUX)
+ extensions.platformANGLEDeviceTypeEGLANGLE = true;
+#endif
+
+#if (defined(ANGLE_PLATFORM_IOS) && !defined(ANGLE_PLATFORM_MACCATALYST)) || \
+ (defined(ANGLE_PLATFORM_MACCATALYST) && defined(ANGLE_CPU_ARM64))
+ extensions.platformANGLEDeviceContextVolatileEagl = true;
+#endif
+
+#if defined(ANGLE_PLATFORM_MACOS) || defined(ANGLE_PLATFORM_MACCATALYST)
+ extensions.platformANGLEDeviceContextVolatileCgl = true;
+#endif
+
+#if defined(ANGLE_ENABLE_METAL)
+ extensions.displayPowerPreferenceANGLE = true;
+#endif
+
+ extensions.clientGetAllProcAddresses = true;
+ extensions.debug = true;
+ extensions.featureControlANGLE = true;
+ extensions.deviceQueryEXT = true;
+
+ return extensions;
+}
+
+template <typename T>
+static std::string GenerateExtensionsString(const T &extensions)
+{
+ std::vector<std::string> extensionsVector = extensions.getStrings();
+
+ std::ostringstream stream;
+ std::copy(extensionsVector.begin(), extensionsVector.end(),
+ std::ostream_iterator<std::string>(stream, " "));
+ return stream.str();
+}
+
+// static
+const ClientExtensions &Display::GetClientExtensions()
+{
+ static const ClientExtensions clientExtensions = GenerateClientExtensions();
+ return clientExtensions;
+}
+
+// static
+const std::string &Display::GetClientExtensionString()
+{
+ static const angle::base::NoDestructor<std::string> clientExtensionsString(
+ GenerateExtensionsString(GetClientExtensions()));
+ return *clientExtensionsString;
+}
+
+void Display::initDisplayExtensions()
+{
+ mDisplayExtensions = mImplementation->getExtensions();
+
+ // Some extensions are always available because they are implemented in the EGL layer.
+ mDisplayExtensions.createContext = true;
+ mDisplayExtensions.createContextNoError = !mFrontendFeatures.forceGlErrorChecking.enabled;
+ mDisplayExtensions.createContextWebGLCompatibility = true;
+ mDisplayExtensions.createContextBindGeneratesResource = true;
+ mDisplayExtensions.createContextClientArrays = true;
+ mDisplayExtensions.pixelFormatFloat = true;
+ mDisplayExtensions.reusableSyncKHR = true;
+
+ // Force EGL_KHR_get_all_proc_addresses on.
+ mDisplayExtensions.getAllProcAddresses = true;
+
+ // Enable program cache control since it is not back-end dependent.
+ mDisplayExtensions.programCacheControlANGLE = true;
+
+ // Request extension is implemented in the ANGLE frontend
+ mDisplayExtensions.createContextExtensionsEnabled = true;
+
+ // Blob cache extension is provided by the ANGLE frontend
+ mDisplayExtensions.blobCache = true;
+
+ // The EGL_ANDROID_recordable extension is provided by the ANGLE frontend, and will always
+ // say that ANativeWindow is not recordable.
+ mDisplayExtensions.recordable = true;
+
+ // All backends support specific context versions
+ mDisplayExtensions.createContextBackwardsCompatible = true;
+
+ mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions);
+}
+
+bool Display::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ return mImplementation->isValidNativeWindow(window);
+}
+
+Error Display::validateClientBuffer(const Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs) const
+{
+ return mImplementation->validateClientBuffer(configuration, buftype, clientBuffer, attribs);
+}
+
+Error Display::validateImageClientBuffer(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const
+{
+ return mImplementation->validateImageClientBuffer(context, target, clientBuffer, attribs);
+}
+
+Error Display::valdiatePixmap(const Config *config,
+ EGLNativePixmapType pixmap,
+ const AttributeMap &attributes) const
+{
+ return mImplementation->validatePixmap(config, pixmap, attributes);
+}
+
+bool Display::isValidDisplay(const egl::Display *display)
+{
+ const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap();
+ for (const auto &displayPair : *anglePlatformDisplayMap)
+ {
+ if (displayPair.second == display)
+ {
+ return true;
+ }
+ }
+
+ const DevicePlatformDisplayMap *devicePlatformDisplayMap = GetDevicePlatformDisplayMap();
+ for (const auto &displayPair : *devicePlatformDisplayMap)
+ {
+ if (displayPair.second == display)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool Display::isValidNativeDisplay(EGLNativeDisplayType display)
+{
+ // TODO(jmadill): handle this properly
+ if (display == EGL_DEFAULT_DISPLAY)
+ {
+ return true;
+ }
+
+#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(ANGLE_ENABLE_WINDOWS_UWP)
+ if (display == EGL_SOFTWARE_DISPLAY_ANGLE || display == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
+ display == EGL_D3D11_ONLY_DISPLAY_ANGLE)
+ {
+ return true;
+ }
+ return (WindowFromDC(display) != nullptr);
+#else
+ return true;
+#endif
+}
+
+void Display::initVendorString()
+{
+ mVendorString = "Google Inc.";
+ std::string vendorStringImpl = mImplementation->getVendorString();
+ if (!vendorStringImpl.empty())
+ {
+ mVendorString += " (" + vendorStringImpl + ")";
+ }
+}
+
+void Display::initVersionString()
+{
+ mVersionString = mImplementation->getVersionString(true);
+}
+
+void Display::initClientAPIString()
+{
+ // If the max supported desktop version is not None, we support a desktop GL frontend.
+ if (mImplementation->getMaxSupportedDesktopVersion().valid())
+ {
+ mClientAPIString = "OpenGL_ES OpenGL";
+ }
+ else
+ {
+ mClientAPIString = "OpenGL_ES";
+ }
+}
+
+void Display::initializeFrontendFeatures()
+{
+ // Enable on all Impls
+ ANGLE_FEATURE_CONDITION((&mFrontendFeatures), loseContextOnOutOfMemory, true);
+ ANGLE_FEATURE_CONDITION((&mFrontendFeatures), allowCompressedFormats, true);
+
+ // No longer enable this on any Impl - crbug.com/1165751
+ ANGLE_FEATURE_CONDITION((&mFrontendFeatures), scalarizeVecAndMatConstructorArgs, false);
+
+ // Disabled by default. To reduce the risk, create a feature to enable
+ // compressing pipeline cache in multi-thread pool.
+ ANGLE_FEATURE_CONDITION(&mFrontendFeatures, enableCompressingPipelineCacheInThreadPool, false);
+
+ // Disabled by default until work on the extension is complete - anglebug.com/7279.
+ ANGLE_FEATURE_CONDITION(&mFrontendFeatures, emulatePixelLocalStorage, false);
+
+ mImplementation->initializeFrontendFeatures(&mFrontendFeatures);
+
+ rx::ApplyFeatureOverrides(&mFrontendFeatures, mState);
+}
+
+const DisplayExtensions &Display::getExtensions() const
+{
+ return mDisplayExtensions;
+}
+
+const std::string &Display::getExtensionString() const
+{
+ return mDisplayExtensionString;
+}
+
+const std::string &Display::getVendorString() const
+{
+ return mVendorString;
+}
+
+const std::string &Display::getVersionString() const
+{
+ return mVersionString;
+}
+
+const std::string &Display::getClientAPIString() const
+{
+ return mClientAPIString;
+}
+
+std::string Display::getBackendRendererDescription() const
+{
+ return mImplementation->getRendererDescription();
+}
+
+std::string Display::getBackendVendorString() const
+{
+ return mImplementation->getVendorString();
+}
+
+std::string Display::getBackendVersionString(bool includeFullVersion) const
+{
+ return mImplementation->getVersionString(includeFullVersion);
+}
+
+Device *Display::getDevice() const
+{
+ return mDevice;
+}
+
+Surface *Display::getWGLSurface() const
+{
+ return mSurface;
+}
+
+gl::Version Display::getMaxSupportedESVersion() const
+{
+ return mImplementation->getMaxSupportedESVersion();
+}
+
+EGLint Display::programCacheGetAttrib(EGLenum attrib) const
+{
+ switch (attrib)
+ {
+ case EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE:
+ return static_cast<EGLint>(BlobCache::kKeyLength);
+
+ case EGL_PROGRAM_CACHE_SIZE_ANGLE:
+ return static_cast<EGLint>(mMemoryProgramCache.entryCount());
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+Error Display::programCacheQuery(EGLint index,
+ void *key,
+ EGLint *keysize,
+ void *binary,
+ EGLint *binarysize)
+{
+ ASSERT(index >= 0 && index < static_cast<EGLint>(mMemoryProgramCache.entryCount()));
+
+ const BlobCache::Key *programHash = nullptr;
+ BlobCache::Value programBinary;
+ // TODO(jmadill): Make this thread-safe.
+ bool result =
+ mMemoryProgramCache.getAt(static_cast<size_t>(index), &programHash, &programBinary);
+ if (!result)
+ {
+ return EglBadAccess() << "Program binary not accessible.";
+ }
+
+ ASSERT(keysize && binarysize);
+
+ if (key)
+ {
+ ASSERT(*keysize == static_cast<EGLint>(BlobCache::kKeyLength));
+ memcpy(key, programHash->data(), BlobCache::kKeyLength);
+ }
+
+ if (binary)
+ {
+ // Note: we check the size here instead of in the validation code, since we need to
+ // access the cache as atomically as possible. It's possible that the cache contents
+ // could change between the validation size check and the retrieval.
+ if (programBinary.size() > static_cast<size_t>(*binarysize))
+ {
+ return EglBadAccess() << "Program binary too large or changed during access.";
+ }
+
+ memcpy(binary, programBinary.data(), programBinary.size());
+ }
+
+ *binarysize = static_cast<EGLint>(programBinary.size());
+ *keysize = static_cast<EGLint>(BlobCache::kKeyLength);
+
+ return NoError();
+}
+
+Error Display::programCachePopulate(const void *key,
+ EGLint keysize,
+ const void *binary,
+ EGLint binarysize)
+{
+ ASSERT(keysize == static_cast<EGLint>(BlobCache::kKeyLength));
+
+ BlobCache::Key programHash;
+ memcpy(programHash.data(), key, BlobCache::kKeyLength);
+
+ if (!mMemoryProgramCache.putBinary(programHash, reinterpret_cast<const uint8_t *>(binary),
+ static_cast<size_t>(binarysize)))
+ {
+ return EglBadAccess() << "Failed to copy program binary into the cache.";
+ }
+
+ return NoError();
+}
+
+EGLint Display::programCacheResize(EGLint limit, EGLenum mode)
+{
+ switch (mode)
+ {
+ case EGL_PROGRAM_CACHE_RESIZE_ANGLE:
+ {
+ size_t initialSize = mMemoryProgramCache.size();
+ mMemoryProgramCache.resize(static_cast<size_t>(limit));
+ return static_cast<EGLint>(initialSize);
+ }
+
+ case EGL_PROGRAM_CACHE_TRIM_ANGLE:
+ return static_cast<EGLint>(mMemoryProgramCache.trim(static_cast<size_t>(limit)));
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+void Display::overrideFrontendFeatures(const std::vector<std::string> &featureNames, bool enabled)
+{
+ mFrontendFeatures.overrideFeatures(featureNames, enabled);
+}
+
+const char *Display::queryStringi(const EGLint name, const EGLint index)
+{
+ const char *result = nullptr;
+ switch (name)
+ {
+ case EGL_FEATURE_NAME_ANGLE:
+ result = mFeatures[index]->name;
+ break;
+ case EGL_FEATURE_CATEGORY_ANGLE:
+ result = angle::FeatureCategoryToString(mFeatures[index]->category);
+ break;
+ case EGL_FEATURE_DESCRIPTION_ANGLE:
+ result = mFeatures[index]->description;
+ break;
+ case EGL_FEATURE_BUG_ANGLE:
+ result = mFeatures[index]->bug;
+ break;
+ case EGL_FEATURE_STATUS_ANGLE:
+ result = angle::FeatureStatusToString(mFeatures[index]->enabled);
+ break;
+ case EGL_FEATURE_CONDITION_ANGLE:
+ result = mFeatures[index]->condition;
+ break;
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+ return result;
+}
+
+EGLAttrib Display::queryAttrib(const EGLint attribute)
+{
+ EGLAttrib value = 0;
+ switch (attribute)
+ {
+ case EGL_DEVICE_EXT:
+ value = reinterpret_cast<EGLAttrib>(mDevice);
+ break;
+
+ case EGL_FEATURE_COUNT_ANGLE:
+ value = mFeatures.size();
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+ return value;
+}
+
+angle::ScratchBuffer Display::requestScratchBuffer()
+{
+ return requestScratchBufferImpl(&mScratchBuffers);
+}
+
+void Display::returnScratchBuffer(angle::ScratchBuffer scratchBuffer)
+{
+ returnScratchBufferImpl(std::move(scratchBuffer), &mScratchBuffers);
+}
+
+angle::ScratchBuffer Display::requestZeroFilledBuffer()
+{
+ return requestScratchBufferImpl(&mZeroFilledBuffers);
+}
+
+void Display::returnZeroFilledBuffer(angle::ScratchBuffer zeroFilledBuffer)
+{
+ returnScratchBufferImpl(std::move(zeroFilledBuffer), &mZeroFilledBuffers);
+}
+
+angle::ScratchBuffer Display::requestScratchBufferImpl(
+ std::vector<angle::ScratchBuffer> *bufferVector)
+{
+ std::lock_guard<std::mutex> lock(mScratchBufferMutex);
+ if (!bufferVector->empty())
+ {
+ angle::ScratchBuffer buffer = std::move(bufferVector->back());
+ bufferVector->pop_back();
+ return buffer;
+ }
+
+ return angle::ScratchBuffer(kScratchBufferLifetime);
+}
+
+void Display::returnScratchBufferImpl(angle::ScratchBuffer scratchBuffer,
+ std::vector<angle::ScratchBuffer> *bufferVector)
+{
+ std::lock_guard<std::mutex> lock(mScratchBufferMutex);
+ bufferVector->push_back(std::move(scratchBuffer));
+}
+
+Error Display::handleGPUSwitch()
+{
+ ANGLE_TRY(mImplementation->handleGPUSwitch());
+ initVendorString();
+ return NoError();
+}
+
+Error Display::forceGPUSwitch(EGLint gpuIDHigh, EGLint gpuIDLow)
+{
+ ANGLE_TRY(mImplementation->forceGPUSwitch(gpuIDHigh, gpuIDLow));
+ initVendorString();
+ return NoError();
+}
+
+bool Display::supportsDmaBufFormat(EGLint format) const
+{
+ return mImplementation->supportsDmaBufFormat(format);
+}
+
+Error Display::queryDmaBufFormats(EGLint max_formats, EGLint *formats, EGLint *num_formats)
+{
+ ANGLE_TRY(mImplementation->queryDmaBufFormats(max_formats, formats, num_formats));
+ return NoError();
+}
+
+Error Display::queryDmaBufModifiers(EGLint format,
+ EGLint max_modifiers,
+ EGLuint64KHR *modifiers,
+ EGLBoolean *external_only,
+ EGLint *num_modifiers)
+{
+ ANGLE_TRY(mImplementation->queryDmaBufModifiers(format, max_modifiers, modifiers, external_only,
+ num_modifiers));
+ return NoError();
+}
+
+} // namespace egl
diff --git a/gfx/angle/checkout/src/libANGLE/Display.h b/gfx/angle/checkout/src/libANGLE/Display.h
new file mode 100644
index 0000000000..da00026e7b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Display.h
@@ -0,0 +1,427 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Display.h: Defines the egl::Display class, representing the abstract
+// display on which graphics are drawn. Implements EGLDisplay.
+// [EGL 1.4] section 2.1.2 page 3.
+
+#ifndef LIBANGLE_DISPLAY_H_
+#define LIBANGLE_DISPLAY_H_
+
+#include <mutex>
+#include <set>
+#include <vector>
+
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/BlobCache.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/LoggingAnnotator.h"
+#include "libANGLE/MemoryProgramCache.h"
+#include "libANGLE/MemoryShaderCache.h"
+#include "libANGLE/Observer.h"
+#include "libANGLE/Version.h"
+#include "platform/Feature.h"
+#include "platform/FrontendFeatures_autogen.h"
+
+namespace angle
+{
+class FrameCaptureShared;
+} // namespace angle
+
+namespace gl
+{
+class Context;
+class TextureManager;
+class SemaphoreManager;
+} // namespace gl
+
+namespace rx
+{
+class DisplayImpl;
+class EGLImplFactory;
+class ShareGroupImpl;
+} // namespace rx
+
+namespace egl
+{
+class Device;
+class Image;
+class Stream;
+class Surface;
+class Sync;
+class Thread;
+
+using ContextSet = angle::HashSet<gl::Context *>;
+using SurfaceSet = angle::HashSet<Surface *>;
+using ThreadSet = angle::HashSet<Thread *>;
+
+struct DisplayState final : private angle::NonCopyable
+{
+ DisplayState(EGLNativeDisplayType nativeDisplayId);
+ ~DisplayState();
+
+ EGLLabelKHR label;
+ ContextSet contextSet;
+ SurfaceSet surfaceSet;
+ std::vector<std::string> featureOverridesEnabled;
+ std::vector<std::string> featureOverridesDisabled;
+ bool featuresAllDisabled;
+ EGLNativeDisplayType displayId;
+};
+
+class ShareGroup final : angle::NonCopyable
+{
+ public:
+ ShareGroup(rx::EGLImplFactory *factory);
+
+ void addRef();
+
+ void release(const egl::Display *display);
+
+ rx::ShareGroupImpl *getImplementation() const { return mImplementation; }
+
+ rx::Serial generateFramebufferSerial() { return mFramebufferSerialFactory.generate(); }
+
+ angle::FrameCaptureShared *getFrameCaptureShared() { return mFrameCaptureShared.get(); }
+
+ void finishAllContexts();
+
+ const ContextSet &getContexts() const { return mContexts; }
+ void addSharedContext(gl::Context *context);
+ void removeSharedContext(gl::Context *context);
+
+ size_t getShareGroupContextCount() const { return mContexts.size(); }
+
+ protected:
+ ~ShareGroup();
+
+ private:
+ size_t mRefCount;
+ rx::ShareGroupImpl *mImplementation;
+ rx::SerialFactory mFramebufferSerialFactory;
+
+ // Note: we use a raw pointer here so we can exclude frame capture sources from the build.
+ std::unique_ptr<angle::FrameCaptureShared> mFrameCaptureShared;
+
+ // The list of contexts within the share group
+ ContextSet mContexts;
+};
+
+// Constant coded here as a reasonable limit.
+constexpr EGLAttrib kProgramCacheSizeAbsoluteMax = 0x4000000;
+
+class Display final : public LabeledObject,
+ public angle::ObserverInterface,
+ public angle::NonCopyable
+{
+ public:
+ ~Display() override;
+
+ void setLabel(EGLLabelKHR label) override;
+ EGLLabelKHR getLabel() const override;
+
+ // Observer implementation.
+ void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
+
+ Error initialize();
+
+ enum class TerminateReason
+ {
+ Api,
+ InternalCleanup,
+ NoActiveThreads,
+
+ InvalidEnum,
+ EnumCount = InvalidEnum,
+ };
+ Error terminate(Thread *thread, TerminateReason terminateReason);
+ // Called before all display state dependent EGL functions. Backends can set up, for example,
+ // thread-specific backend state through this function. Not called for functions that do not
+ // need the state.
+ Error prepareForCall();
+ // Called on eglReleaseThread. Backends can tear down thread-specific backend state through
+ // this function.
+ Error releaseThread();
+
+ // Helpers to maintain active thread set to assist with freeing invalid EGL objects.
+ void addActiveThread(Thread *thread);
+ void threadCleanup(Thread *thread);
+
+ static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap);
+ static Display *GetDisplayFromNativeDisplay(EGLenum platform,
+ EGLNativeDisplayType nativeDisplay,
+ const AttributeMap &attribMap);
+ static Display *GetExistingDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay);
+
+ using EglDisplaySet = angle::HashSet<Display *>;
+ static EglDisplaySet GetEglDisplaySet();
+
+ static const ClientExtensions &GetClientExtensions();
+ static const std::string &GetClientExtensionString();
+
+ std::vector<const Config *> getConfigs(const AttributeMap &attribs) const;
+ std::vector<const Config *> chooseConfig(const AttributeMap &attribs) const;
+
+ Error createWindowSurface(const Config *configuration,
+ EGLNativeWindowType window,
+ const AttributeMap &attribs,
+ Surface **outSurface);
+ Error createPbufferSurface(const Config *configuration,
+ const AttributeMap &attribs,
+ Surface **outSurface);
+ Error createPbufferFromClientBuffer(const Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs,
+ Surface **outSurface);
+ Error createPixmapSurface(const Config *configuration,
+ NativePixmapType nativePixmap,
+ const AttributeMap &attribs,
+ Surface **outSurface);
+
+ Error createImage(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const AttributeMap &attribs,
+ Image **outImage);
+
+ Error createStream(const AttributeMap &attribs, Stream **outStream);
+
+ Error createContext(const Config *configuration,
+ gl::Context *shareContext,
+ const EGLenum clientType,
+ const AttributeMap &attribs,
+ gl::Context **outContext);
+
+ Error createSync(const gl::Context *currentContext,
+ EGLenum type,
+ const AttributeMap &attribs,
+ Sync **outSync);
+
+ Error makeCurrent(Thread *thread,
+ gl::Context *previousContext,
+ Surface *drawSurface,
+ Surface *readSurface,
+ gl::Context *context);
+
+ Error destroySurface(Surface *surface);
+ void destroyImage(Image *image);
+ void destroyStream(Stream *stream);
+ Error destroyContext(Thread *thread, gl::Context *context);
+
+ void destroySync(Sync *sync);
+
+ bool isInitialized() const;
+ bool isValidConfig(const Config *config) const;
+ bool isValidContext(const gl::Context *context) const;
+ bool isValidSurface(const Surface *surface) const;
+ bool isValidImage(const Image *image) const;
+ bool isValidStream(const Stream *stream) const;
+ bool isValidSync(const Sync *sync) const;
+ bool isValidNativeWindow(EGLNativeWindowType window) const;
+
+ Error validateClientBuffer(const Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs) const;
+ Error validateImageClientBuffer(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const;
+ Error valdiatePixmap(const Config *config,
+ EGLNativePixmapType pixmap,
+ const AttributeMap &attributes) const;
+
+ static bool isValidDisplay(const Display *display);
+ static bool isValidNativeDisplay(EGLNativeDisplayType display);
+ static bool hasExistingWindowSurface(EGLNativeWindowType window);
+
+ bool isDeviceLost() const;
+ bool testDeviceLost();
+ void notifyDeviceLost();
+
+ void setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+ bool areBlobCacheFuncsSet() const { return mBlobCache.areBlobCacheFuncsSet(); }
+ BlobCache &getBlobCache() { return mBlobCache; }
+
+ static EGLClientBuffer GetNativeClientBuffer(const struct AHardwareBuffer *buffer);
+ static Error CreateNativeClientBuffer(const egl::AttributeMap &attribMap,
+ EGLClientBuffer *eglClientBuffer);
+
+ Error waitClient(const gl::Context *context);
+ Error waitNative(const gl::Context *context, EGLint engine);
+
+ const Caps &getCaps() const;
+
+ const DisplayExtensions &getExtensions() const;
+ const std::string &getExtensionString() const;
+ const std::string &getVendorString() const;
+ const std::string &getVersionString() const;
+ const std::string &getClientAPIString() const;
+
+ std::string getBackendRendererDescription() const;
+ std::string getBackendVendorString() const;
+ std::string getBackendVersionString(bool includeFullVersion) const;
+
+ EGLint programCacheGetAttrib(EGLenum attrib) const;
+ Error programCacheQuery(EGLint index,
+ void *key,
+ EGLint *keysize,
+ void *binary,
+ EGLint *binarysize);
+ Error programCachePopulate(const void *key,
+ EGLint keysize,
+ const void *binary,
+ EGLint binarysize);
+ EGLint programCacheResize(EGLint limit, EGLenum mode);
+
+ const AttributeMap &getAttributeMap() const { return mAttributeMap; }
+ EGLNativeDisplayType getNativeDisplayId() const { return mState.displayId; }
+
+ rx::DisplayImpl *getImplementation() const { return mImplementation; }
+ Device *getDevice() const;
+ Surface *getWGLSurface() const;
+ EGLenum getPlatform() const { return mPlatform; }
+
+ gl::Version getMaxSupportedESVersion() const;
+
+ const DisplayState &getState() const { return mState; }
+
+ const angle::FrontendFeatures &getFrontendFeatures() { return mFrontendFeatures; }
+ void overrideFrontendFeatures(const std::vector<std::string> &featureNames, bool enabled);
+
+ const angle::FeatureList &getFeatures() const { return mFeatures; }
+
+ const char *queryStringi(const EGLint name, const EGLint index);
+
+ EGLAttrib queryAttrib(const EGLint attribute);
+
+ angle::ScratchBuffer requestScratchBuffer();
+ void returnScratchBuffer(angle::ScratchBuffer scratchBuffer);
+
+ angle::ScratchBuffer requestZeroFilledBuffer();
+ void returnZeroFilledBuffer(angle::ScratchBuffer zeroFilledBuffer);
+
+ egl::Error handleGPUSwitch();
+ egl::Error forceGPUSwitch(EGLint gpuIDHigh, EGLint gpuIDLow);
+
+ std::mutex &getDisplayGlobalMutex() { return mDisplayGlobalMutex; }
+ std::mutex &getProgramCacheMutex() { return mProgramCacheMutex; }
+
+ gl::MemoryShaderCache *getMemoryShaderCache() { return &mMemoryShaderCache; }
+
+ // Installs LoggingAnnotator as the global DebugAnnotator, for back-ends that do not implement
+ // their own DebugAnnotator.
+ void setGlobalDebugAnnotator() { gl::InitializeDebugAnnotations(&mAnnotator); }
+
+ bool supportsDmaBufFormat(EGLint format) const;
+ Error queryDmaBufFormats(EGLint max_formats, EGLint *formats, EGLint *num_formats);
+ Error queryDmaBufModifiers(EGLint format,
+ EGLint max_modifiers,
+ EGLuint64KHR *modifiers,
+ EGLBoolean *external_only,
+ EGLint *num_modifiers);
+
+ private:
+ Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice);
+
+ void setAttributes(const AttributeMap &attribMap) { mAttributeMap = attribMap; }
+
+ void setupDisplayPlatform(rx::DisplayImpl *impl);
+
+ void updateAttribsFromEnvironment(const AttributeMap &attribMap);
+
+ Error restoreLostDevice();
+ Error releaseContext(gl::Context *context, Thread *thread);
+ Error releaseContextImpl(gl::Context *context, ContextSet *contexts);
+
+ void initDisplayExtensions();
+ void initVendorString();
+ void initVersionString();
+ void initClientAPIString();
+ void initializeFrontendFeatures();
+
+ angle::ScratchBuffer requestScratchBufferImpl(std::vector<angle::ScratchBuffer> *bufferVector);
+ void returnScratchBufferImpl(angle::ScratchBuffer scratchBuffer,
+ std::vector<angle::ScratchBuffer> *bufferVector);
+
+ Error destroyInvalidEglObjects();
+
+ DisplayState mState;
+ rx::DisplayImpl *mImplementation;
+ angle::ObserverBinding mGPUSwitchedBinding;
+
+ AttributeMap mAttributeMap;
+
+ ConfigSet mConfigSet;
+
+ typedef angle::HashSet<Image *> ImageSet;
+ ImageSet mImageSet;
+
+ typedef angle::HashSet<Stream *> StreamSet;
+ StreamSet mStreamSet;
+
+ typedef angle::HashSet<Sync *> SyncSet;
+ SyncSet mSyncSet;
+
+ void destroyImageImpl(Image *image, ImageSet *images);
+ void destroyStreamImpl(Stream *stream, StreamSet *streams);
+ Error destroySurfaceImpl(Surface *surface, SurfaceSet *surfaces);
+ void destroySyncImpl(Sync *sync, SyncSet *syncs);
+
+ ContextSet mInvalidContextSet;
+ ImageSet mInvalidImageSet;
+ StreamSet mInvalidStreamSet;
+ SurfaceSet mInvalidSurfaceSet;
+ SyncSet mInvalidSyncSet;
+
+ bool mInitialized;
+ bool mDeviceLost;
+
+ Caps mCaps;
+
+ DisplayExtensions mDisplayExtensions;
+ std::string mDisplayExtensionString;
+
+ std::string mVendorString;
+ std::string mVersionString;
+ std::string mClientAPIString;
+
+ Device *mDevice;
+ Surface *mSurface;
+ EGLenum mPlatform;
+ angle::LoggingAnnotator mAnnotator;
+
+ gl::TextureManager *mTextureManager;
+ gl::SemaphoreManager *mSemaphoreManager;
+ BlobCache mBlobCache;
+ gl::MemoryProgramCache mMemoryProgramCache;
+ gl::MemoryShaderCache mMemoryShaderCache;
+ size_t mGlobalTextureShareGroupUsers;
+ size_t mGlobalSemaphoreShareGroupUsers;
+
+ angle::FrontendFeatures mFrontendFeatures;
+
+ angle::FeatureList mFeatures;
+
+ std::mutex mScratchBufferMutex;
+ std::vector<angle::ScratchBuffer> mScratchBuffers;
+ std::vector<angle::ScratchBuffer> mZeroFilledBuffers;
+
+ std::mutex mDisplayGlobalMutex;
+ std::mutex mProgramCacheMutex;
+
+ bool mTerminatedByApi;
+ ThreadSet mActiveThreads;
+};
+
+} // namespace egl
+
+#endif // LIBANGLE_DISPLAY_H_
diff --git a/gfx/angle/checkout/src/libANGLE/EGLSync.cpp b/gfx/angle/checkout/src/libANGLE/EGLSync.cpp
new file mode 100644
index 0000000000..ddca5de902
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/EGLSync.cpp
@@ -0,0 +1,114 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// EGLSync.cpp: Implements the egl::Sync class.
+
+#include "libANGLE/EGLSync.h"
+
+#include "angle_gl.h"
+
+#include "common/utilities.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
+#include "libANGLE/renderer/EGLReusableSync.h"
+#include "libANGLE/renderer/EGLSyncImpl.h"
+
+namespace egl
+{
+
+Sync::Sync(rx::EGLImplFactory *factory, EGLenum type, const AttributeMap &attribs)
+ : mLabel(nullptr),
+ mType(type),
+ mCondition(EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR),
+ mNativeFenceFD(
+ attribs.getAsInt(EGL_SYNC_NATIVE_FENCE_FD_ANDROID, EGL_NO_NATIVE_FENCE_FD_ANDROID))
+{
+ switch (type)
+ {
+ case EGL_SYNC_FENCE:
+ case EGL_SYNC_NATIVE_FENCE_ANDROID:
+ case EGL_SYNC_METAL_SHARED_EVENT_ANGLE:
+ mFence = std::unique_ptr<rx::EGLSyncImpl>(factory->createSync(attribs));
+ break;
+
+ case EGL_SYNC_REUSABLE_KHR:
+ mFence = std::unique_ptr<rx::EGLSyncImpl>(new rx::ReusableSync(attribs));
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+
+ // Per extension spec: Signaling Condition.
+ // "If the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute is not
+ // EGL_NO_NATIVE_FENCE_FD_ANDROID then the EGL_SYNC_CONDITION_KHR attribute
+ // is set to EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID and the EGL_SYNC_STATUS_KHR
+ // attribute is set to reflect the signal status of the native fence object.
+ if ((mType == EGL_SYNC_NATIVE_FENCE_ANDROID) &&
+ (mNativeFenceFD != EGL_NO_NATIVE_FENCE_FD_ANDROID))
+ {
+ mCondition = EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID;
+ }
+}
+
+void Sync::onDestroy(const Display *display)
+{
+ ASSERT(mFence);
+ mFence->onDestroy(display);
+ mFence.reset();
+}
+
+Sync::~Sync() {}
+
+Error Sync::initialize(const Display *display, const gl::Context *context)
+{
+ return mFence->initialize(display, context, mType);
+}
+
+void Sync::setLabel(EGLLabelKHR label)
+{
+ mLabel = label;
+}
+
+EGLLabelKHR Sync::getLabel() const
+{
+ return mLabel;
+}
+
+Error Sync::clientWait(const Display *display,
+ const gl::Context *context,
+ EGLint flags,
+ EGLTime timeout,
+ EGLint *outResult)
+{
+ return mFence->clientWait(display, context, flags, timeout, outResult);
+}
+
+Error Sync::serverWait(const Display *display, const gl::Context *context, EGLint flags)
+{
+ return mFence->serverWait(display, context, flags);
+}
+
+Error Sync::signal(const Display *display, const gl::Context *context, EGLint mode)
+{
+ return mFence->signal(display, context, mode);
+}
+
+Error Sync::getStatus(const Display *display, EGLint *outStatus) const
+{
+ return mFence->getStatus(display, outStatus);
+}
+
+Error Sync::copyMetalSharedEventANGLE(const Display *display, void **result) const
+{
+ return mFence->copyMetalSharedEventANGLE(display, result);
+}
+
+Error Sync::dupNativeFenceFD(const Display *display, EGLint *result) const
+{
+ return mFence->dupNativeFenceFD(display, result);
+}
+
+} // namespace egl
diff --git a/gfx/angle/checkout/src/libANGLE/EGLSync.h b/gfx/angle/checkout/src/libANGLE/EGLSync.h
new file mode 100644
index 0000000000..2f97e9c3da
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/EGLSync.h
@@ -0,0 +1,72 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// EGLSync.h: Defines the egl::Sync classes, which support the EGL_KHR_fence_sync,
+// EGL_KHR_wait_sync and EGL 1.5 sync objects.
+
+#ifndef LIBANGLE_EGLSYNC_H_
+#define LIBANGLE_EGLSYNC_H_
+
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+#include "common/angleutils.h"
+
+namespace rx
+{
+class EGLImplFactory;
+class EGLSyncImpl;
+} // namespace rx
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace egl
+{
+class Sync final : public angle::RefCountObject<Display, angle::Result>, public LabeledObject
+{
+ public:
+ Sync(rx::EGLImplFactory *factory, EGLenum type, const AttributeMap &attribs);
+ ~Sync() override;
+
+ void setLabel(EGLLabelKHR label) override;
+ EGLLabelKHR getLabel() const override;
+
+ void onDestroy(const Display *display) override;
+
+ Error initialize(const Display *display, const gl::Context *context);
+ Error clientWait(const Display *display,
+ const gl::Context *context,
+ EGLint flags,
+ EGLTime timeout,
+ EGLint *outResult);
+ Error serverWait(const Display *display, const gl::Context *context, EGLint flags);
+ Error signal(const Display *display, const gl::Context *context, EGLint mode);
+ Error getStatus(const Display *display, EGLint *outStatus) const;
+
+ Error copyMetalSharedEventANGLE(const Display *display, void **result) const;
+ Error dupNativeFenceFD(const Display *display, EGLint *result) const;
+
+ EGLenum getType() const { return mType; }
+ EGLint getCondition() const { return mCondition; }
+ EGLint getNativeFenceFD() const { return mNativeFenceFD; }
+
+ private:
+ std::unique_ptr<rx::EGLSyncImpl> mFence;
+
+ EGLLabelKHR mLabel;
+
+ EGLenum mType;
+ EGLint mCondition;
+ EGLint mNativeFenceFD;
+};
+
+} // namespace egl
+
+#endif // LIBANGLE_FENCE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Error.cpp b/gfx/angle/checkout/src/libANGLE/Error.cpp
new file mode 100644
index 0000000000..977e8d66e0
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Error.cpp
@@ -0,0 +1,67 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Error.cpp: Implements the egl::Error and gl::Error classes which encapsulate API errors
+// and optional error messages.
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "common/utilities.h"
+
+#include <cstdarg>
+
+namespace
+{
+std::unique_ptr<std::string> EmplaceErrorString(std::string &&message)
+{
+ return message.empty() ? std::unique_ptr<std::string>()
+ : std::unique_ptr<std::string>(new std::string(std::move(message)));
+}
+} // anonymous namespace
+
+namespace egl
+{
+
+Error::Error(EGLint errorCode, std::string &&message)
+ : mCode(errorCode), mID(errorCode), mMessage(EmplaceErrorString(std::move(message)))
+{}
+
+Error::Error(EGLint errorCode, EGLint id, std::string &&message)
+ : mCode(errorCode), mID(id), mMessage(EmplaceErrorString(std::move(message)))
+{}
+
+void Error::createMessageString() const
+{
+ if (!mMessage)
+ {
+ mMessage.reset(new std::string(GetGenericErrorMessage(mCode)));
+ }
+}
+
+const std::string &Error::getMessage() const
+{
+ createMessageString();
+ return *mMessage;
+}
+
+std::ostream &operator<<(std::ostream &os, const Error &err)
+{
+ return gl::FmtHex(os, err.getCode());
+}
+} // namespace egl
+
+namespace angle
+{
+egl::Error ResultToEGL(Result result)
+{
+ if (result == Result::Continue)
+ return egl::NoError();
+
+ return egl::Error(EGL_BAD_ACCESS);
+}
+} // namespace angle
diff --git a/gfx/angle/checkout/src/libANGLE/Error.h b/gfx/angle/checkout/src/libANGLE/Error.h
new file mode 100644
index 0000000000..7f075352cc
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Error.h
@@ -0,0 +1,206 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Error.h: Defines the egl::Error and gl::Error classes which encapsulate API errors
+// and optional error messages.
+
+#ifndef LIBANGLE_ERROR_H_
+#define LIBANGLE_ERROR_H_
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+#include <memory>
+#include <ostream>
+#include <string>
+
+namespace angle
+{
+template <typename ErrorT, typename ErrorBaseT, ErrorBaseT NoErrorVal, typename CodeT, CodeT EnumT>
+class ErrorStreamBase : angle::NonCopyable
+{
+ public:
+ ErrorStreamBase() : mID(EnumT) {}
+ ErrorStreamBase(GLuint id) : mID(id) {}
+
+ template <typename T>
+ ErrorStreamBase &operator<<(T value)
+ {
+ mErrorStream << value;
+ return *this;
+ }
+
+ operator ErrorT() { return ErrorT(EnumT, mID, mErrorStream.str()); }
+
+ private:
+ GLuint mID;
+ std::ostringstream mErrorStream;
+};
+} // namespace angle
+
+namespace egl
+{
+class Error;
+} // namespace egl
+
+namespace egl
+{
+
+class [[nodiscard]] Error final
+{
+ public:
+ explicit inline Error(EGLint errorCode);
+ Error(EGLint errorCode, std::string &&message);
+ Error(EGLint errorCode, EGLint id, std::string &&message);
+ inline Error(const Error &other);
+ inline Error(Error &&other);
+ inline ~Error() = default;
+
+ inline Error &operator=(const Error &other);
+ inline Error &operator=(Error &&other);
+
+ inline EGLint getCode() const;
+ inline EGLint getID() const;
+ inline bool isError() const;
+
+ const std::string &getMessage() const;
+
+ static inline Error NoError();
+
+ private:
+ void createMessageString() const;
+
+ friend std::ostream &operator<<(std::ostream &os, const Error &err);
+
+ EGLint mCode;
+ EGLint mID;
+ mutable std::unique_ptr<std::string> mMessage;
+};
+
+namespace priv
+{
+
+template <EGLint EnumT>
+using ErrorStream = angle::ErrorStreamBase<Error, EGLint, EGL_SUCCESS, EGLint, EnumT>;
+
+} // namespace priv
+
+using EglBadAccess = priv::ErrorStream<EGL_BAD_ACCESS>;
+using EglBadAlloc = priv::ErrorStream<EGL_BAD_ALLOC>;
+using EglBadAttribute = priv::ErrorStream<EGL_BAD_ATTRIBUTE>;
+using EglBadConfig = priv::ErrorStream<EGL_BAD_CONFIG>;
+using EglBadContext = priv::ErrorStream<EGL_BAD_CONTEXT>;
+using EglBadCurrentSurface = priv::ErrorStream<EGL_BAD_CURRENT_SURFACE>;
+using EglBadDevice = priv::ErrorStream<EGL_BAD_DEVICE_EXT>;
+using EglBadDisplay = priv::ErrorStream<EGL_BAD_DISPLAY>;
+using EglBadMatch = priv::ErrorStream<EGL_BAD_MATCH>;
+using EglBadNativeWindow = priv::ErrorStream<EGL_BAD_NATIVE_WINDOW>;
+using EglBadNativePixmap = priv::ErrorStream<EGL_BAD_NATIVE_PIXMAP>;
+using EglBadParameter = priv::ErrorStream<EGL_BAD_PARAMETER>;
+using EglBadState = priv::ErrorStream<EGL_BAD_STATE_KHR>;
+using EglBadStream = priv::ErrorStream<EGL_BAD_STREAM_KHR>;
+using EglBadSurface = priv::ErrorStream<EGL_BAD_SURFACE>;
+using EglContextLost = priv::ErrorStream<EGL_CONTEXT_LOST>;
+using EglNotInitialized = priv::ErrorStream<EGL_NOT_INITIALIZED>;
+
+inline Error NoError()
+{
+ return Error::NoError();
+}
+
+} // namespace egl
+
+#define ANGLE_CONCAT1(x, y) x##y
+#define ANGLE_CONCAT2(x, y) ANGLE_CONCAT1(x, y)
+#define ANGLE_LOCAL_VAR ANGLE_CONCAT2(_localVar, __LINE__)
+
+#define ANGLE_TRY_TEMPLATE(EXPR, FUNC) \
+ do \
+ { \
+ auto ANGLE_LOCAL_VAR = EXPR; \
+ if (ANGLE_UNLIKELY(IsError(ANGLE_LOCAL_VAR))) \
+ { \
+ FUNC(ANGLE_LOCAL_VAR); \
+ } \
+ } while (0)
+
+#define ANGLE_RETURN(X) return X;
+#define ANGLE_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_RETURN)
+
+// TODO(jmadill): Remove after EGL error refactor. http://anglebug.com/3041
+#define ANGLE_SWALLOW_ERR(EXPR) \
+ do \
+ { \
+ auto ANGLE_LOCAL_VAR = EXPR; \
+ if (ANGLE_UNLIKELY(IsError(ANGLE_LOCAL_VAR))) \
+ { \
+ ERR() << "Unhandled internal error: " << ANGLE_LOCAL_VAR; \
+ } \
+ } while (0)
+
+#undef ANGLE_LOCAL_VAR
+#undef ANGLE_CONCAT2
+#undef ANGLE_CONCAT1
+
+#define ANGLE_CHECK(CONTEXT, EXPR, MESSAGE, ERROR) \
+ do \
+ { \
+ if (ANGLE_UNLIKELY(!(EXPR))) \
+ { \
+ CONTEXT->handleError(ERROR, MESSAGE, __FILE__, ANGLE_FUNCTION, __LINE__); \
+ return angle::Result::Stop; \
+ } \
+ } while (0)
+
+namespace angle
+{
+// Result signals if calling code should continue running or early exit. A value of Stop can
+// either indicate an Error or a non-Error early exit condition such as a detected no-op.
+// Incomplete signals special cases that are neither success nor failure but require
+// special attention.
+enum class [[nodiscard]] Result{
+ Continue,
+ Stop,
+ Incomplete,
+};
+
+// TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041
+egl::Error ResultToEGL(Result result);
+} // namespace angle
+
+// TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041
+inline bool IsError(angle::Result result)
+{
+ return result == angle::Result::Stop;
+}
+
+// TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041
+inline bool IsError(const egl::Error &err)
+{
+ return err.isError();
+}
+
+// TODO(jmadill): Remove this when refactor is complete. http://anglebug.com/3041
+inline bool IsError(bool value)
+{
+ return !value;
+}
+
+// Utility macro for handling implementation methods inside Validation.
+#define ANGLE_HANDLE_VALIDATION_ERR(X) \
+ do \
+ { \
+ (void)(X); \
+ return false; \
+ } while (0)
+
+#define ANGLE_VALIDATION_TRY(EXPR) ANGLE_TRY_TEMPLATE(EXPR, ANGLE_HANDLE_VALIDATION_ERR)
+
+#include "Error.inc"
+
+#endif // LIBANGLE_ERROR_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Error.inc b/gfx/angle/checkout/src/libANGLE/Error.inc
new file mode 100644
index 0000000000..e6a8032895
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Error.inc
@@ -0,0 +1,91 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Error.inc: Inline definitions of egl::Error and gl::Error classes which encapsulate API errors
+// and optional error messages.
+
+#include "common/angleutils.h"
+
+#include <cstdarg>
+
+namespace egl
+{
+
+Error::Error(EGLint errorCode)
+ : mCode(errorCode),
+ mID(0)
+{
+}
+
+Error::Error(const Error &other)
+ : mCode(other.mCode),
+ mID(other.mID)
+{
+ if (other.mMessage)
+ {
+ createMessageString();
+ *mMessage = *(other.mMessage);
+ }
+}
+
+Error::Error(Error &&other)
+ : mCode(other.mCode),
+ mID(other.mID),
+ mMessage(std::move(other.mMessage))
+{
+}
+
+Error &Error::operator=(const Error &other)
+{
+ mCode = other.mCode;
+ mID = other.mID;
+
+ if (other.mMessage)
+ {
+ createMessageString();
+ *mMessage = *(other.mMessage);
+ }
+ else
+ {
+ mMessage.reset();
+ }
+
+ return *this;
+}
+
+Error &Error::operator=(Error &&other)
+{
+ if (this != &other)
+ {
+ mCode = other.mCode;
+ mID = other.mID;
+ mMessage = std::move(other.mMessage);
+ }
+
+ return *this;
+}
+
+EGLint Error::getCode() const
+{
+ return mCode;
+}
+
+EGLint Error::getID() const
+{
+ return mID;
+}
+
+bool Error::isError() const
+{
+ return (mCode != EGL_SUCCESS);
+}
+
+// Static
+Error Error::NoError()
+{
+ return Error(EGL_SUCCESS);
+}
+
+}
diff --git a/gfx/angle/checkout/src/libANGLE/ErrorStrings.h b/gfx/angle/checkout/src/libANGLE/ErrorStrings.h
new file mode 100644
index 0000000000..df352b8114
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/ErrorStrings.h
@@ -0,0 +1,627 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ErrorStrings.h: Contains mapping of commonly used error messages
+
+#ifndef LIBANGLE_ERRORSTRINGS_H_
+#define LIBANGLE_ERRORSTRINGS_H_
+
+namespace gl
+{
+namespace err
+{
+#define MSG constexpr const char *
+
+// clang-format off
+MSG k3DDepthStencil = "Format cannot be GL_DEPTH_COMPONENT or GL_DEPTH_STENCIL if target is GL_TEXTURE_3D";
+MSG kANGLECopyTexture3DUnavailable = "GL_ANGLE_copy_texture_3d extension not available.";
+MSG kANGLECopyTextureMissingRequiredExtension = "Copy*TextureCHROMIUM from EXTERNAL_OES to integer format requires OES_EGL_image_external_essl3";
+MSG kAdvancedBlendEquationWithMRT = "Advanced blend equation can only be used when only one draw buffer is not NONE";
+MSG kAdvancedBlendExtensionNotEnabled = "GL_KHR_blend_equation_advanced extension not enabled.";
+MSG kAtomicCounterResourceName = "Active atomic counter resources are not assigned name strings.";
+MSG kAttributeListNotNull = "Attribute list must be NULL or GL_NONE";
+MSG kAttributeZeroRequiresDivisorLimitation = "The current context doesn't support setting a non-zero divisor on the attribute with index zero. Please reorder the attributes in your vertex shader so that attribute zero can have a zero divisor.";
+MSG kBaseLevelNegative = "Base level must be at least 0.";
+MSG kBaseLevelNonZero = "Base level must be 0.";
+MSG kBaseLevelOutOfRange = "Texture base level out of range";
+MSG kBlendEquationNotEnabled = "Active fragment shader does not include the layout qualifier matching the blend equation";
+MSG kBlitDepthOrStencilFormatMismatch = "Depth/stencil buffer format combination not allowed for blit.";
+MSG kBlitDimensionsOutOfRange = "BlitFramebuffer dimensions out of 32-bit integer range.";
+MSG kBlitExtensionDepthStencilWholeBufferBlit = "Only whole-buffer depth and stencil blits are supported by this extension.";
+MSG kBlitExtensionFormatMismatch = "Attempting to blit and the read and draw buffer formats don't match. read: 0x%04X draw: 0x%04X";
+MSG kBlitExtensionFromInvalidAttachmentType = "Blits are only supported from 2D texture, renderbuffer or default framebuffer attachments in this extension.";
+MSG kBlitExtensionLinear = "Linear blit not supported in this extension.";
+MSG kBlitExtensionMultisampledDepthOrStencil = "Multisampled depth/stencil blit is not supported by this extension.";
+MSG kBlitExtensionMultisampledWholeBufferBlit = "Only whole-buffer blit is supported from a multisampled read buffer in this extension.";
+MSG kBlitExtensionNotAvailable = "Blit extension not available.";
+MSG kBlitExtensionScaleOrFlip = "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation.";
+MSG kBlitExtensionToInvalidAttachmentType = "Blits are only supported to 2D texture, renderbuffer or default framebuffer attachments in this extension.";
+MSG kBlitFeedbackLoop = "Blit feedback loop: the read and draw framebuffers are the same.";
+MSG kBlitFramebufferMissing = "Read and draw framebuffers must both exist for a blit to succeed.";
+MSG kBlitFromMultiview = "Attempt to read from a multi-view framebuffer.";
+MSG kBlitIntegerWithLinearFilter = "Cannot use GL_LINEAR filter when blitting a integer framebuffer.";
+MSG kBlitInvalidFilter = "Invalid blit filter.";
+MSG kBlitInvalidMask = "Invalid blit mask.";
+MSG kBlitMissingColor = "Attempt to read from a missing color attachment of a complete framebuffer.";
+MSG kBlitMissingDepthOrStencil = "Attempt to read from a missing depth/stencil attachment of a complete framebuffer.";
+MSG kBlitMultisampledBoundsMismatch = "Attempt to blit from a multisampled framebuffer and the bounds don't match with the draw framebuffer.";
+MSG kBlitMultisampledFormatOrBoundsMismatch = "Attempt to blit from a multisampled framebuffer and the bounds or format of the color buffer don't match with the draw framebuffer.";
+MSG kBlitOnlyNearestForNonColor = "Only nearest filtering can be used when blitting buffers other than the color buffer.";
+MSG kBlitSameImageColor = "Read and write color attachments cannot be the same image.";
+MSG kBlitSameImageDepthOrStencil = "Read and write depth stencil attachments cannot be the same image.";
+MSG kBlitToMultiview = "Attempt to write to a multi-view framebuffer.";
+MSG kBlitTypeMismatchFixedOrFloat = "If the read buffer contains fixed-point or floating-point values, the draw buffer must as well.";
+MSG kBlitTypeMismatchFixedPoint = "If the read buffer contains fixed-point values, the draw buffer must as well.";
+MSG kBlitTypeMismatchSignedInteger = "If the read buffer contains signed integer values the draw buffer must as well.";
+MSG kBlitTypeMismatchUnsignedInteger = "If the read buffer contains unsigned integer values the draw buffer must as well.";
+MSG kBlitYUVFramebuffer = "Blitting to or from a YUV framebuffer is disallowed.";
+MSG kBufferAlreadyMapped = "Buffer is already mapped.";
+MSG kBufferBoundForTransformFeedback = "Buffer is bound for transform feedback.";
+MSG kBufferImmutable = "Buffer is immutable.";
+MSG kBufferMapped = "An active buffer is mapped";
+MSG kBufferNotBound = "A buffer must be bound.";
+MSG kBufferNotMappable = "Attempted to map buffer object zero.";
+MSG kBufferNotMapped = "Buffer is not mapped.";
+MSG kBufferNotUpdatable = "Buffer is not updatable.";
+MSG kBufferOffsetOverflow = "Buffer offset overflow.";
+MSG kBufferPointerNotAvailable = "Can not get pointer for reserved buffer name zero.";
+MSG kCannotPopDefaultDebugGroup = "Cannot pop the default debug group.";
+MSG kClientBufferInvalid = "Size must not exceed the size of clientbuffer";
+MSG kClientDataInVertexArray = "Client data cannot be used with a non-default vertex array object.";
+MSG kColorNumberGreaterThanMaxDrawBuffers = "Color number for primary color greater than or equal to MAX_DRAW_BUFFERS";
+MSG kColorNumberGreaterThanMaxDualSourceDrawBuffers = "Color number for secondary color greater than or equal to MAX_DUAL_SOURCE_DRAW_BUFFERS";
+MSG kCompressedDataSizeTooSmall = "dataSize is too small";
+MSG kCompressedMismatch = "Compressed data is valid if-and-only-if the texture is compressed.";
+MSG kCompressedTextureDimensionsMustMatchData = "Compressed texture dimensions must exactly match the dimensions of the data passed in.";
+MSG kCompressedTexturesNotAttachable = "Compressed textures cannot be attached to a framebuffer.";
+MSG kConstantColorAlphaLimitation = "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR as color factors is not supported by this implementation.";
+MSG kContextLost = "Context has been lost.";
+MSG kCopyAlias = "The read and write copy regions alias memory.";
+MSG kCopyFromYUVFramebuffer = "Copying from a YUV framebuffer is disallowed.";
+MSG kCubemapFacesEqualDimensions = "Each cubemap face must have equal width and height.";
+MSG kCubemapIncomplete = "Texture is not cubemap complete. All cubemaps faces must be defined and be the same size.";
+MSG kCubemapInvalidDepth = "The cubemap depth must be a multiple of 6.";
+MSG kDataTypeNotAligned = "Data is not evenly divisible into the number of bytes needed to store in memory a datum indicated by type.";
+MSG kDefaultFramebuffer = "Default framebuffer is bound.";
+MSG kDefaultFramebufferAttachmentOnUserFBO = "Invalid attachment when a user framebuffer is bound.";
+MSG kDefaultFramebufferInvalidAttachment = "Invalid attachment when the default framebuffer is bound.";
+MSG kDefaultFramebufferInvalidDrawBuffer = "Only NONE or BACK are valid draw buffers for the default framebuffer";
+MSG kDefaultFramebufferTarget = "It is invalid to change default FBO's attachments";
+MSG kDefaultVertexArray = "Default vertex array object is bound.";
+MSG kDestinationImmutable = "Destination texture cannot be immutable.";
+MSG kDestinationLevelNotDefined = "The destination level of the destination texture must be defined.";
+MSG kDestinationTextureTooSmall = "Destination texture too small.";
+MSG kDimensionsMustBePow2 = "Texture dimensions must be power-of-two.";
+MSG kDispatchIndirectBufferNotBound = "Dispatch indirect buffer must be bound.";
+MSG kDrawBufferMaskMismatch = "Active draw buffers with missing fragment shader outputs.";
+MSG kDrawBuffersIndexedExtensionNotAvailable = "EXT/OES_draw_buffers_indexed is not available.";
+MSG kES31OrDrawBuffersIndexedExtensionNotAvailable = "EXT/OES_draw_buffers_indexed or ES 3.1 are required but not available.";
+MSG kDrawBufferTypeMismatch = "Fragment shader output type does not match the bound framebuffer attachment type.";
+MSG kDrawFramebufferIncomplete = "Draw framebuffer is incomplete";
+MSG kDrawIndirectBufferNotBound = "Draw indirect buffer must be bound.";
+MSG kEGLImageCannotCreate2DMultisampled = "Cannot create a 2D texture from a multisampled EGL image.";
+MSG kEGLImageRenderbufferFormatNotSupported = "EGL image internal format is not supported as a renderbuffer.";
+MSG kEGLImageTextureFormatNotSupported = "EGL image internal format is not supported as a texture.";
+MSG kEGLImageTextureTargetMismatch = "The source EGL image is incompatible with the target texture type.";
+MSG kElementArrayBufferBoundForTransformFeedback = "It is undefined behavior to use an element array buffer that is bound for transform feedback.";
+MSG kElementArrayNoBufferOrPointer = "No element array buffer and no pointer.";
+MSG kEnumInvalid = "Invalid enum provided.";
+MSG kEnumNotSupported = "Enum 0x%04X is currently not supported.";
+MSG kEnumRequiresGLES30 = "Enum requires GLES 3.0";
+MSG kEnumRequiresGLES31 = "Enum requires GLES 3.1";
+MSG kES1or32Required = "OpenGL ES 1.x or 3.2 Required";
+MSG kES31Required = "OpenGL ES 3.1 Required";
+MSG kES32Required = "OpenGL ES 3.2 Required";
+MSG kES3Required = "OpenGL ES 3.0 Required.";
+MSG kExceedsComputeWorkGroupCountX = "num_groups_x cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[0]";
+MSG kExceedsComputeWorkGroupCountY = "num_groups_y cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[1]";
+MSG kExceedsComputeWorkGroupCountZ = "num_groups_z cannot be greater than MAX_COMPUTE_WORK_GROUP_COUNT[2]";
+MSG kExceedsElementRange = "Element value exceeds element range.";
+MSG kExceedsFramebufferHeight = "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_HEIGHT.";
+MSG kExceedsFramebufferSamples = "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_SAMPLES.";
+MSG kExceedsFramebufferWidth = "Params less than 0 or greater than GL_MAX_FRAMEBUFFER_WIDTH.";
+MSG kExceedsMaxColorAttachments = "Index is greater than the maximum supported color attachments";
+MSG kExceedsMaxDebugGroupStackDepth = "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.";
+MSG kExceedsMaxDebugMessageLength = "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.";
+MSG kExceedsMaxDrawBuffers = "Draw buffer greater than MAX_DRAW_BUFFERS.";
+MSG kExceedsMaxElement = "Element value exceeds maximum element index.";
+MSG kExceedsMaxImageUnits = "Index must be within [0, MAX_IMAGE_UNITS).";
+MSG kExceedsMaxLabelLength = "Label length is larger than GL_MAX_LABEL_LENGTH.";
+MSG kExceedsMaxShaderStorageBufferBindings = "Index must be within [0, MAX_SHADER_STORAGE_BUFFER_BINDINGS).";
+MSG kExceedsMaxVertexAttribBindings = "Index must be within [0, MAX_VERTEX_ATTRIB_BINDINGS).";
+MSG kExceedsMaxVertexAttribStride = "Stride must be within [0, MAX_VERTEX_ATTRIB_STRIDE).";
+MSG kExceedsNumExtensions = "Index must be within [0, NUM_EXTENSIONS).";
+MSG kExceedsNumRequestableExtensions = "Index must be within [0, NUM_REQUESTABLE_EXTENSIONS_ANGLE).";
+MSG kExpectedProgramName = "Expected a program name, but found a shader name.";
+MSG kExpectedShaderName = "Expected a shader name, but found a program name.";
+MSG kExtensionNotEnabled = "Extension is not enabled.";
+MSG kExtensionNotDisablable = "Extension is not disablable.";
+MSG kExtensionNotRequestable = "Extension is not requestable.";
+MSG kExternalBufferInvalidOffset = "Offset must be zero for external buffers";
+MSG kExternalTextureAttachmentNotYUV = "External texture attached to framebuffer is not YUV.";
+MSG kExternalTextureNotSupported = "External texture extension not enabled";
+MSG kFeedbackLoop = "Feedback loop formed between Framebuffer and active Texture.";
+MSG kFixedNotInWebGL = "GL_FIXED is not supported in WebGL.";
+MSG kFormatNotRenderable = "Internal format is not renderable.";
+MSG kFragDataBindingIndexOutOfRange = "Fragment output color index must be zero or one.";
+MSG kFragmentInputTypeNotFloatingPoint = "Fragment input type is not a floating point scalar or vector.";
+MSG kFramebufferFetchNonCoherentExtensionNotEnabled = "GL_EXT_shader_framebuffer_fetch_non_coherent not enabled.";
+MSG kFramebufferIncomplete = "Framebuffer is incomplete.";
+MSG kFramebufferIncompleteAttachment = "Attachment type must be compatible with attachment object.";
+MSG kFramebufferIncompleteAttachmentDepthGreaterThanMaxLayers = "Framebuffer is incomplete: Attachment depth is greater than MAX_FRAMEBUFFER_LAYERS.";
+MSG kFramebufferIncompleteAttachmentInconsistantBitPlanes = "Framebuffer is incomplete: Attachments have inconsistent bit plane counts.";
+MSG kFramebufferIncompleteAttachmentLayerGreaterThanDepth = "Framebuffer is incomplete: Attachment layer is greater than texture layer count.";
+MSG kFramebufferIncompleteAttachmentLevelNotBaseLevelForIncompleteMipTexture = "Framebuffer is incomplete: Attachment level not equal to the base level and the texture is not mipmap complete.";
+MSG kFramebufferIncompleteAttachmentLevelOutOfBaseMaxLevelRange = "Framebuffer is incomplete: Attachment level is not in the [base level, max level] range.";
+MSG kFramebufferIncompleteAttachmentNoDepthBitsInDepthBuffer = "Framebuffer is incomplete: Depth attachment has no depth bits.";
+MSG kFramebufferIncompleteAttachmentNoStencilBitsInStencilBuffer = "Framebuffer is incomplete: Stencil attachment has no stencil bits.";
+MSG kFramebufferIncompleteAttachmentNotCubeComplete = "Framebuffer is incomplete: Attachment is an incomplete cube map.";
+MSG kFramebufferIncompleteAttachmentNotRenderable = "Framebuffer is incomplete: Attachment is not renderable.";
+MSG kFramebufferIncompleteAttachmentSamplesGreaterThanMaxSupportedSamples = "Framebuffer is incomplete: Attachment samples are greater than the maximum supported samples for this format.";
+MSG kFramebufferIncompleteAttachmentsNotUnique = "Framebuffer is incomplete: All attachments must be unique.";
+MSG kFramebufferIncompleteAttachmentWebGLDepthBufferHasStencilBits = "Framebuffer is incomplete: Stencil attachment has depth bits.";
+MSG kFramebufferIncompleteAttachmentWebGLDepthStencilNoDepthOrStencilBits = "Framebuffer is incomplete: Depth stencil attachment has no depth bits or no stencil bits.";
+MSG kFramebufferIncompleteAttachmentWebGLStencilBufferHasDepthBits = "Framebuffer is incomplete: Stencil attachment has depth bits.";
+MSG kFramebufferIncompleteAttachmentZeroSize = "Framebuffer is incomplete: Attachment has zero size.";
+MSG kFramebufferIncompleteColorBitsUsedExceedsMaxColorBitsSupported = "Framebuffer is incomplete: The total number of color bits exceeds the number of output bits supported.";
+MSG kFramebufferIncompleteDefaultZeroSize = "Framebuffer is incomplete: No attachments and default size is zero.";
+MSG kFramebufferIncompleteDepthAndStencilBuffersNotTheSame = "Framebuffer is incomplete: Depth and stencil attachments are not the same.";
+MSG kFramebufferIncompleteDepthStencilInColorBuffer = "Framebuffer is incomplete: Depth stencil texture in color attachment.";
+MSG kFramebufferIncompleteDriverUnsupported = "Framebuffer is incomplete: Driver does not support this framebuffer configuration.";
+MSG kFramebufferIncompleteInconsistantAttachmentSizes = "Framebuffer is incomplete: Attachments are not all the same size.";
+MSG kFramebufferIncompleteInternalError = "Framebuffer is incomplete: Internal error.";
+MSG kFramebufferIncompleteMismatchedLayeredAttachments = "Framebuffer is incomplete: If one attachment is layered, all must be layered.";
+MSG kFramebufferIncompleteMismatchedLayeredTexturetypes = "Framebuffer is incomplete: If an attachments are layered, they must all be the same texture type.";
+MSG kFramebufferIncompleteMultisampleDepthStencilSampleCountDivisibleByColorSampleCount = "Framebuffer is incomplete: Depth stencil sample count must be divisible by the color sample count.";
+MSG kFramebufferIncompleteMultisampleInconsistentFixedSampleLocations = "Framebuffer is incomplete: Attachments have inconsistent fixed sample locations.";
+MSG kFramebufferIncompleteMultisampleInconsistentSampleCounts = "Framebuffer is incomplete: Attachments have different sample counts.";
+MSG kFramebufferIncompleteMultisampleNonFixedSamplesWithRenderbuffers = "Framebuffer is incomplete: All textures must have fixed samples if paired with multisample renderbuffers.";
+MSG kFramebufferIncompleteMultiviewBaseViewMismatch = "Framebuffer is incomplete: Attachments have inconsistent multiview base view.";
+MSG kFramebufferIncompleteMultiviewMismatch = "Framebuffer is incomplete: Attachments have inconsistent multiview enabled state.";
+MSG kFramebufferIncompleteMultiviewViewsMismatch = "Framebuffer is incomplete: Attachments have inconsistent multiview view counts.";
+MSG kFramebufferIncompleteSurfaceless = "Framebuffer is incomplete: Framebuffer is surfaceless.";
+MSG kFramebufferIncompleteUnsupportedMissmatchedDimensions = "Framebuffer is incomplete: Mismatched attachment sizes are unsupported.";
+MSG kFramebufferIncompleteUnsupportedNonUniqueAttachments = "Framebuffer is incomplete: Non-unique attachments are unsupported.";
+MSG kFramebufferIncompleteUnsupportedSeparateDepthStencilBuffers = "Framebuffer is incomplete: Separate depth and stencil buffers are unsupported.";
+MSG kFramebufferIncompleteWebGLDepthStencilInconsistant = "Framebuffer is incomplete: WebGL depth stencil state is inconsistent.";
+MSG kFramebufferTextureInvalidLayer = "Layer invalid for framebuffer texture attachment.";
+MSG kFramebufferTextureInvalidMipLevel = "Mip level invalid for framebuffer texture attachment.";
+MSG kFramebufferTextureLayerIncorrectTextureType = "Texture is not a three-dimensional, two-dimensional array, two-dimensional multisample array, cube map, or cube map array texture.";
+MSG kGenerateMipmapNotAllowed = "Texture format does not support mipmap generation.";
+MSG kGenerateMipmapZeroSize = "Cannot generate mipmaps for a zero-size texture in a WebGL context.";
+MSG kGeometryShaderExtensionNotEnabled = "GL_EXT_geometry_shader or GL_OES_geometry_shader extension not enabled.";
+MSG kGetImageExtensionNotEnabled = "GL_ANGLE_get_image extension not enabled.";
+MSG kGetImageCompressed = "Texture is compressed, call GetCompressedTexImage instead.";
+MSG kGetImageNotCompressed = "Texture is not compressed, call GetTexImage instead.";
+MSG kGLES1Only = "GLES1-only function.";
+MSG kImageSizeMustBeZero = "imageSize must be 0 if no texture data is provided.";
+MSG kImageSizeTooSmall = "imageSize is too small.";
+MSG kImmutableMemoryObject = "The memory object is immutable.";
+MSG kImmutableTextureBound = "The value of TEXTURE_IMMUTABLE_FORMAT for the texture currently bound to target on the active texture unit is true.";
+MSG kIncompatibleDrawModeAgainstGeometryShader = "Primitive mode is incompatible with the input primitive type of the geometry shader.";
+MSG kIncompatibleDrawModeWithTessellationShader = "When tessellation is active the primitive mode must be GL_PATCHES.";
+MSG kIncompatibleDrawModeWithoutTessellationShader = "When tessellation is not active the primitive mode must not be GL_PATCHES.";
+MSG kIncompatibleTextures = "Texture formats are not compatible";
+MSG kIndexExceedsActiveUniformBlockCount = "Index exceeds active uniform block count.";
+MSG kIndexExceedsMaxActiveUniform = "Index must be less than program active uniform count.";
+MSG kIndexExceedsMaxActiveUniformBlock = "Index must be less than program active uniform block count.";
+MSG kIndexExceedsMaxAtomicCounterBufferBindings = "Index must be less than MAX_ATOMIC_COUNTER_BUFFER_BINDINGS.";
+MSG kIndexExceedsMaxDrawBuffer = "Index must be less than MAX_DRAW_BUFFERS.";
+MSG kIndexExceedsMaxTransformFeedbackAttribs = "Index must be less than MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS.";
+MSG kIndexExceedsMaxUniformBufferBindings = "Index must be less than MAX_UNIFORM_BUFFER_BINDINGS.";
+MSG kIndexExceedsMaxVertexAttribute = "Index must be less than MAX_VERTEX_ATTRIBS.";
+MSG kIndexExceedsMaxWorkgroupDimensions = "Index must be less than the number of workgroup dimensions (3).";
+MSG kIndexExceedsSamples = "Index must be less than the value of SAMPLES.";
+MSG kIndexExceedsTransformFeedbackBufferBindings = "Index is greater than or equal to the number of TRANSFORM_FEEDBACK_BUFFER indexed binding points.";
+MSG kInsufficientBufferSize = "Insufficient buffer size.";
+MSG kInsufficientParams = "More parameters are required than were provided.";
+MSG kInsufficientVertexBufferSize = "Vertex buffer is not big enough for the draw call";
+MSG kIntegerOverflow = "Integer overflow.";
+MSG kInternalFormatRequiresTexture2D = "internalformat is an ETC1 or PVRTC1 format.";
+MSG kInternalFormatRequiresTexture2DArray = "internalformat is an ETC2/EAC format and target is not GL_TEXTURE_2D_ARRAY.";
+MSG kInternalFormatRequiresTexture2DArrayS3TC = "internalformat is an S3TC format and target is not GL_TEXTURE_2D_ARRAY.";
+MSG kInternalFormatRequiresTexture2DArrayRGTC = "internalformat is an RGTC format and target is not GL_TEXTURE_2D_ARRAY.";
+MSG kInternalFormatRequiresTexture2DArrayBPTC = "internalformat is a BPTC format and target is not GL_TEXTURE_2D_ARRAY.";
+MSG kInternalFormatRequiresTexture2DArrayASTC = "internalformat is an ASTC format and target is not GL_TEXTURE_2D_ARRAY.";
+MSG kInvalidAccessBits = "Invalid access bits.";
+MSG kInvalidAccessBitsFlush = "The explicit flushing bit may only be set if the buffer is mapped for writing.";
+MSG kInvalidAccessBitsRead = "Invalid access bits when mapping buffer for reading";
+MSG kInvalidAccessBitsReadWrite = "Need to map buffer for either reading or writing.";
+MSG kInvalidAttachment = "Invalid Attachment Type.";
+MSG kInvalidBindBufferSize = "Invalid buffer binding size.";
+MSG kInvalidBindUniformLocation = "Location must be less than (MAX_VERTEX_UNIFORM_VECTORS + MAX_FRAGMENT_UNIFORM_VECTORS) * 4";
+MSG kInvalidBlendEquation = "Invalid blend equation.";
+MSG kInvalidBlendFunction = "Invalid blend function.";
+MSG kInvalidBlendStateForYUV = "Blending must be disabled when writing to YUV framebuffers.";
+MSG kInvalidBooleanValue = "Invalid boolean value. Must be GL_FALSE or GL_TRUE.";
+MSG kInvalidBorder = "Border must be 0.";
+MSG kInvalidBufferName = "name is not a valid buffer.";
+MSG kInvalidBufferTypes = "Invalid buffer target.";
+MSG kInvalidBufferUsage = "Invalid buffer usage enum.";
+MSG kInvalidBufferUsageFlags = "Invalid buffer usage flags.";
+MSG kInvalidClearMask = "Invalid mask bits.";
+MSG kInvalidClientState = "Invalid client vertex array type.";
+MSG kInvalidClipPlane = "Invalid clip plane.";
+MSG kInvalidColorMaskForYUV = "Red, green and blue color writes must be enabled when writing to YUV framebuffers.";
+MSG kInvalidCombinedImageUnit = "Specified unit must be in [GL_TEXTURE0, GL_TEXTURE0 + GL_MAX_COMBINED_IMAGE_UNITS)";
+MSG kInvalidComponents = "Invalid components.";
+MSG kInvalidCompressedFormat = "Not a valid compressed texture format.";
+MSG kInvalidCompressedImageSize = "Invalid compressed image size.";
+MSG kInvalidCompressedRegionSize = "Invalid region for compressed texture format.";
+MSG kInvalidConstantColor = "CONSTANT_COLOR (or ONE_MINUS_CONSTANT_COLOR) and CONSTANT_ALPHA (or ONE_MINUS_CONSTANT_ALPHA) cannot be used together as source and destination color factors in the blend function.";
+MSG kInvalidCopyCombination = "Invalid copy texture format combination.";
+MSG kInvalidCoverageComponents = "components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.";
+MSG kInvalidCoverMode = "Invalid cover mode.";
+MSG kInvalidExternalCreateFlags = "Create flags must only include bits defined by GL_ANGLE_external_objects_flags";
+MSG kInvalidCullMode = "Cull mode not recognized.";
+MSG kInvalidDebugSeverity = "Invalid debug severity.";
+MSG kInvalidDebugSource = "Invalid debug source.";
+MSG kInvalidDebugSourceType = "If count is greater than zero, source and type cannot be GL_DONT_CARE.";
+MSG kInvalidDebugType = "Invalid debug type.";
+MSG kInvalidDefaultReadBuffer = "Read buffer must be GL_NONE or GL_BACK when reading from the default framebuffer.";
+MSG kInvalidDepthEnum = "Invalid depth enum.";
+MSG kInvalidDepthRange = "Near value cannot be greater than far.";
+MSG kInvalidDepthStencilDrawBuffer = "Draw buffer must be zero when using depth or stencil.";
+MSG kInvalidDestinationTexture = "Destination texture is not a valid texture object.";
+MSG kInvalidDestinationTextureType = "Invalid destination texture type.";
+MSG kInvalidDrawBuffer = "Invalid draw buffer.";
+MSG kInvalidDrawBufferCountForDefault = "The default framebuffer must have exactly one draw buffer.";
+MSG kInvalidDrawBufferValue = "Ith value does not match COLOR_ATTACHMENTi or NONE.";
+MSG kInvalidDrawMode = "Invalid draw mode.";
+MSG kInvalidDrawModeTransformFeedback = "Draw mode must match current transform feedback object's draw mode.";
+MSG kInvalidEGLImage = "EGL image is not valid.";
+MSG kInvalidElementRange = "Invalid element range.";
+MSG kInvalidEmulatedFormat = "Implementation format is emulated.";
+MSG kInvalidFence = "Invalid fence object.";
+MSG kInvalidFenceCondition = "Invalid value for condition.";
+MSG kInvalidFenceState = "Fence must be set.";
+MSG kInvalidFillMode = "Invalid fill mode.";
+MSG kInvalidFilterTexture = "Texture only supports NEAREST and LINEAR filtering.";
+MSG kInvalidFlags = "Invalid value for flags.";
+MSG kInvalidFlushOutOfRange = "Flushed range does not fit into buffer mapping dimensions.";
+MSG kInvalidFlushTarget = "Attempted to flush a buffer not mapped for explicit flushing.";
+MSG kInvalidFlushZero = "Attempted to flush buffer object zero.";
+MSG kInvalidFogDensity = "Invalid fog density (must be nonnegative).";
+MSG kInvalidFogMode = "Invalid fog mode.";
+MSG kInvalidFogParameter = "Invalid fog parameter.";
+MSG kInvalidFormat = "Invalid format.";
+MSG kInvalidFormatCombination = "Invalid combination of format, type and internalFormat.";
+MSG kInvalidFragmentInputBinding = "No such binding.";
+MSG kInvalidFramebufferAttachmentParameter = "Invalid parameter name for framebuffer attachment.";
+MSG kInvalidFramebufferLayer = "Framebuffer layer cannot be less than 0 or greater than GL_MAX_FRAMEBUFFER_LAYERS_EXT.";
+MSG kInvalidFramebufferName = "name is not a valid framebuffer.";
+MSG kInvalidFramebufferTarget = "Invalid framebuffer target.";
+MSG kInvalidFramebufferTextureLevel = "Mipmap level must be 0 when attaching a texture.";
+MSG kInvalidHandleType = "Invalid handle type.";
+MSG kInvalidImageAccess = "access is not one of the supported tokens.";
+MSG kInvalidImageLayout = "Invalid image layout.";
+MSG kInvalidImageFormat = "format is not one of supported image unit formats.";
+MSG kInvalidIndentifier = "Invalid identifier.";
+MSG kInvalidIndirectOffset = "indirect must be a multiple of the size of uint in basic machine units.";
+MSG kInvalidInternalFormat = "Invalid internal format 0x%04X.";
+MSG kInvalidLight = "Invalid light.";
+MSG kInvalidLightModelParameter = "Invalid light model parameter.";
+MSG kInvalidLightParameter = "Invalid light parameter.";
+MSG kInvalidLogicOp = "Invalid logical operation.";
+MSG kInvalidMapPointerQuery = "GL_BUFFER_MAP_POINTER can only be queried with GetBufferPointerv.";
+MSG kInvalidMaterialFace = "Invalid material face.";
+MSG kInvalidMaterialParameter = "Invalid material parameter.";
+MSG kInvalidMatrixMode = "Invalid matrix mode.";
+MSG kInvalidMemoryBarrierBit = "Invalid memory barrier bit.";
+MSG kInvalidMemoryObject = "Invalid memory object.";
+MSG kInvalidMemoryObjectParameter = "Invalid memory object parameter.";
+MSG kInvalidMipLevel = "Level of detail outside of range.";
+MSG kInvalidMipLevels = "Invalid level count.";
+MSG kInvalidMultisampledFramebufferOperation = "Invalid operation on multisampled framebuffer";
+MSG kInvalidMultitextureUnit = "Specified unit must be in [GL_TEXTURE0, GL_TEXTURE0 + GL_MAX_TEXTURE_UNITS)";
+MSG kInvalidName = "Invalid name.";
+MSG kInvalidNameCharacters = "Name contains invalid characters.";
+MSG kInvalidOriginEnum = "Invalid origin enum.";
+MSG kInvalidPackParametersForWebGL = "Invalid combination of pack parameters for WebGL.";
+MSG kInvalidPerfMonitor = "Invalid perf monitor.";
+MSG kInvalidPerfMonitorCounter = "Invalid perf monitor counter.";
+MSG kInvalidPerfMonitorGroup = "Invalid perf monitor counter group.";
+MSG kInvalidPname = "Invalid pname.";
+MSG kInvalidPointerQuery = "Invalid pointer query.";
+MSG kInvalidPointParameter = "Invalid point parameter.";
+MSG kInvalidPointParameterValue = "Invalid point parameter value (must be non-negative).";
+MSG kInvalidPointSizeValue = "Invalid point size (must be positive).";
+MSG kInvalidPrecision = "Invalid or unsupported precision type.";
+MSG kInvalidPrimitiveMode = "Invalid primitive mode.";
+MSG kInvalidProgramBinaryFormat = "Program binary format is not valid.";
+MSG kInvalidProgramInterface = "Invalid program interface.";
+MSG kInvalidProgramName = "Program object expected.";
+MSG kInvalidProgramPipelineName = "name is not a valid program pipeline.";
+MSG kInvalidProgramResourceIndex = "Invalid program resource index.";
+MSG kInvalidProgramResourceProperty = "Invalid program resource property.";
+MSG kInvalidProjectionMatrix = "Invalid projection matrix. Left/right, top/bottom, near/far intervals cannot be zero, and near/far cannot be less than zero.";
+MSG kInvalidPropCount = "Invalid propCount.";
+MSG kInvalidPropertyForProgramInterface = "Not an allowed program resource property for this program interface";
+MSG kInvalidProvokingVertex = "Invalid provoking vertex.";
+MSG kInvalidQueryId = "Invalid query Id.";
+MSG kInvalidQueryName = "name is not a valid query.";
+MSG kInvalidQueryTarget = "Invalid query target.";
+MSG kInvalidQueryType = "Invalid query type.";
+MSG kInvalidRange = "Invalid range.";
+MSG kInvalidReadBuffer = "Invalid read buffer";
+MSG kInvalidRenderbufferInternalFormat = "Invalid renderbuffer internalformat.";
+MSG kInvalidRenderbufferName = "name is not a valid renderbuffer.";
+MSG kInvalidRenderbufferTarget = "Invalid renderbuffer target.";
+MSG kInvalidRenderbufferTextureParameter = "Invalid parameter name for renderbuffer attachment.";
+MSG kInvalidRenderbufferWidthHeight = "Renderbuffer width and height cannot be negative and cannot exceed maximum texture size.";
+MSG kInvalidResetStatus = "Reset status is not valid";
+MSG kInvalidSampleMaskNumber = "MaskNumber cannot be greater than or equal to the value of MAX_SAMPLE_MASK_WORDS.";
+MSG kInvalidSampler = "Sampler is not valid";
+MSG kInvalidSamplerName = "name is not a valid sampler.";
+MSG kInvalidShaderBinaryFormat = "Invalid shader binary format.";
+MSG kInvalidShaderName = "Shader object expected.";
+MSG kInvalidShaderType = "Invalid shader type.";
+MSG kInvalidShadingModel = "Invalid shading model.";
+MSG kInvalidShadingRate = "Invalid shading rate.";
+MSG kInvalidSourceTexture = "Source texture is not a valid texture object.";
+MSG kInvalidSourceTextureInternalFormat = "Source texture internal format is invalid.";
+MSG kInvalidSourceTextureLevel = "Invalid source texture level.";
+MSG kInvalidSourceTextureSize = "Invalid source texture height or width.";
+MSG kInvalidSourceTextureType = "Source texture must be a valid texture type.";
+MSG kInvalidStencil = "Invalid stencil.";
+MSG kInvalidStencilBitMask = "Invalid stencil bit mask.";
+MSG kInvalidSyncPointer = "Not a valid sync pointer.";
+MSG kInvalidTarget = "Invalid target.";
+MSG kInvalidTextureCombine = "Invalid texture combine mode.";
+MSG kInvalidTextureCombineOp = "Invalid texture combine operand.";
+MSG kInvalidTextureCombineSrc = "Invalid texture combine source.";
+MSG kInvalidTextureEnvMode = "Invalid texture environment mode.";
+MSG kInvalidTextureEnvParameter = "Invalid texture environment parameter.";
+MSG kInvalidTextureEnvScale = "Invalid texture environment scale.";
+MSG kInvalidTextureEnvTarget = "Invalid texture environment target.";
+MSG kInvalidTextureFilterParam = "Texture filter not recognized.";
+MSG kInvalidTextureLevel = "Texture level does not exist.";
+MSG kInvalidTextureName = "Not a valid texture object name.";
+MSG kInvalidTextureRange = "Cannot be less than 0 or greater than maximum number of textures.";
+MSG kInvalidTextureTarget = "Invalid or unsupported texture target.";
+MSG kInvalidTextureType = "Texture has incompatible target.";
+MSG kInvalidTextureWrap = "Texture wrap mode not recognized.";
+MSG kInvalidTimeout = "Invalid value for timeout.";
+MSG kInvalidTransformation = "Invalid transformation.";
+MSG kInvalidTransformFeedbackAttribsCount = "Count exceeds MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS.";
+MSG kInvalidTransformFeedbackName = "name is not a valid transform feedback.";
+MSG kInvalidType = "Invalid type.";
+MSG kInvalidUniformCount = "Only array uniforms may have count > 1.";
+MSG kInvalidUniformLocation = "Invalid uniform location";
+MSG kInvalidUnpackAlignment = "Unpack alignment must be 1, 2, 4 or 8.";
+MSG kInvalidUnpackParametersForWebGL = "Invalid combination of unpack parameters for WebGL.";
+MSG kInvalidExternalUsageFlags = "Usage flags must only include bits defined by GL_ANGLE_external_objects_flags";
+MSG kInvalidValueExceedsMaxPatchSize = "Value must be less than or equal to MAX_PATCH_SIZE.";
+MSG kInvalidValueNonPositive = "Value must be greater than zero.";
+MSG kInvalidVaryingLocation = "Location exceeds max varying.";
+MSG kInvalidVertexArray = "Vertex array does not exist.";
+MSG kInvalidVertexArrayName = "name is not a valid vertex array.";
+MSG kInvalidVertexAttribSize2101010 = "Type is INT_2_10_10_10_REV or UNSIGNED_INT_2_10_10_10_REV and size is not 4.";
+MSG kInvalidVertexAttribSize1010102 = "Type is INT_10_10_10_2_OES or UNSIGNED_INT_10_10_10_2_OES and size is not 3 or 4.";
+MSG kInvalidVertexAttrSize = "Vertex attribute size must be 1, 2, 3, or 4.";
+MSG kInvalidVertexPointerSize = "Size for built-in vertex attribute is outside allowed range.";
+MSG kInvalidVertexPointerStride = "Invalid stride for built-in vertex attribute.";
+MSG kInvalidVertexPointerType = "Invalid type for built-in vertex attribute.";
+MSG kInvalidWidth = "Invalid width.";
+MSG kInvalidWrapModeTexture = "Invalid wrap mode for texture type.";
+MSG kInvalidZOffset = "zoffset is larger than MAX_3D_TEXTURE_SIZE-1";
+MSG kLengthZero = "Length must not be zero.";
+MSG kLevelNotZero = "Texture level must be zero.";
+MSG kLightParameterOutOfRange = "Light parameter out of range.";
+MSG kMapOutOfRange = "Mapped range does not fit into buffer dimensions.";
+MSG kMaterialParameterOutOfRange = "Material parameter out of range.";
+MSG kMatrixStackOverflow = "Current matrix stack is full.";
+MSG kMatrixStackUnderflow = "Current matrix stack has only a single matrix.";
+MSG kMaxActiveVariablesInterface = "MAX_NUM_ACTIVE_VARIABLES requires a buffer or block interface.";
+MSG kMismatchedFormat = "Format must match internal format.";
+MSG kMismatchedTargetAndFormat = "Invalid texture target and format combination.";
+MSG kMismatchedTypeAndFormat = "Invalid format and type combination.";
+MSG kMismatchedVariableProgram = "Variable is not part of the current program.";
+MSG kMissingName = "No name given.";
+MSG kMissingReadAttachment = "Missing read attachment.";
+MSG kMissingTexture = "No Texture is bound to the specified target.";
+MSG kMissingTextureName = "texture is not the name of an existing texture object.";
+MSG kMultisampleArrayExtensionRequired = "GL_ANGLE_texture_multisample_array not enabled.";
+MSG kMultisampleTextureExtensionOrES31Required = "GL_ANGLE_texture_multisample or GLES 3.1 required.";
+MSG kMultisampleTextureExtensionOrGetTexLevelParameterExtensionOrES31Required = "GL_ANGLE_texture_multisample, GL_ANGLE_get_tex_level_parameter or GLES 3.1 required.";
+MSG kMultiviewActive = "The number of views in the active draw framebuffer is greater than 1.";
+MSG kMultiviewMismatch = "The number of views in the active program and draw framebuffer does not match.";
+MSG kMultiviewNotAvailable = "ANGLE_multiview is not available.";
+MSG kMultiviewReadFramebuffer = "The active read framebuffer object has multiview attachments.";
+MSG kMultiviewTimerQuery = "There is an active query for target GL_TIME_ELAPSED_EXT when the number of views in the active draw framebuffer is greater than 1.";
+MSG kMultiviewTransformFeedback = "There is an active transform feedback object when the number of views in the active draw framebuffer is greater than 1.";
+MSG kMultiviewViewsTooLarge = "numViews cannot be greater than GL_MAX_VIEWS_ANGLE.";
+MSG kMultiviewViewsTooSmall = "numViews cannot be less than 1.";
+MSG kMustHaveElementArrayBinding = "Must have element array buffer bound.";
+MSG kNameBeginsWithGL = "Attributes that begin with 'gl_' are not allowed.";
+MSG kNegativeAttachments = "Negative number of attachments.";
+MSG kNegativeBaseViewIndex = "Negative baseViewIndex.";
+MSG kNegativeBufferSize = "Negative buffer size.";
+MSG kNegativeBufSize = "Invalid bufSize.";
+MSG kNegativeCount = "Negative count.";
+MSG kNegativeHeightWidthDepth = "Cannot have negative height, width, or depth.";
+MSG kNegativeLayer = "Negative layer.";
+MSG kNegativeLength = "Negative length.";
+MSG kNegativeLevel = "Level is negative.";
+MSG kNegativeLocation = "Location cannot be less than 0.";
+MSG kNegativeMaxCount = "Negative maxcount.";
+MSG kNegativeOffset = "Negative offset.";
+MSG kNegativeParam = "param is negative.";
+MSG kNegativePrimcount = "Primcount must be greater than or equal to zero.";
+MSG kNegativeSize = "Negative size.";
+MSG kNegativeStart = "Cannot have negative start.";
+MSG kNegativeStride = "Cannot have negative stride.";
+MSG kNegativeXYZ = "x = y = or z cannot be negative.";
+MSG kNoActiveComputeShaderStage = "No active compute shader stage in this program.";
+MSG kNoActiveGeometryShaderStage = "No active geometry shader stage in this program.";
+MSG kNoActiveGraphicsShaderStage = "It is a undefined behaviour to render without vertex shader stage or fragment shader stage.";
+MSG kNoActiveProgramWithComputeShader = "No active program for the compute shader stage.";
+MSG kNoDefinedClearConversion = "No defined conversion between clear value and attachment format.";
+MSG kNonPositiveDrawTextureDimension = "Both width and height argument of drawn texture must be positive.";
+MSG kNonPositiveSize = "Size must be greater than 0";
+MSG kNoProgramBinaryFormats = "No program binary formats supported.";
+MSG kNoReadFramebuffer = "No active read framebuffer.";
+MSG kNoSampleAlphaToCoveragesLimitation = "Current renderer doesn't support alpha-to-coverage.";
+MSG kNotTextureComplete = "The texture is not complete.";
+MSG kNoTransformArray = "No transform array given.";
+MSG kNoTransformFeedbackOutputVariables = "The active program has specified no output variables to record.";
+MSG kNoZeroDivisor = "At least one enabled attribute must have a divisor of zero.";
+MSG kNVFenceNotSupported = "GL_NV_fence is not supported";
+MSG kObjectNotGenerated = "Object cannot be used because it has not been generated.";
+MSG kOffsetAlignment = "offset must be a multiple of 4.";
+MSG kOffsetAndSizeAlignment = "Offset and size must be multiple of 4.";
+MSG kOffsetMustBeMultipleOfType = "Offset must be a multiple of the passed in datatype.";
+MSG kOffsetMustBeMultipleOfUint = "Offset must be a multiple of sizeof(uint) in basic machine units.";
+MSG kOffsetOverflow = "Offset overflows texture dimensions.";
+MSG kOtherQueryActive = "Other query is active.";
+MSG kOutsideOfBounds = "Parameter outside of bounds.";
+MSG kParamOverflow = "The provided parameters overflow with the provided buffer.";
+MSG kPixelDataNotNull = "Pixel data must be null.";
+MSG kPixelDataNull = "Pixel data cannot be null.";
+MSG kPixelPackBufferBoundForTransformFeedback = "It is undefined behavior to use a pixel pack buffer that is bound for transform feedback.";
+MSG kPixelUnpackBufferBoundForTransformFeedback = "It is undefined behavior to use a pixel unpack buffer that is bound for transform feedback.";
+MSG kPLSActive = "Operation not permitted while pixel local storage is active.";
+MSG kPLSDefaultFramebufferBound = "Default framebuffer object name 0 does not support pixel local storage.";
+MSG kPLSDitherEnabled = "Attempted to begin pixel local storage with GL_DITHER enabled.";
+MSG kPLSDimensionsDontMatchRenderingArea = "Pixel local storage backing texture dimensions not equal to the rendering area.";
+MSG kPLSEnablingDeinitializedPlane = "Attempted to enable a pixel local storage plane that is in a deinitialized state.";
+MSG kPLSExtensionNotEnabled = "GL_ANGLE_shader_pixel_local_storage not enabled.";
+MSG kPLSInactive = "Pixel local storage is not active.";
+MSG kPLSInvalidInternalformat = "Invalid pixel local storage internal format.";
+MSG kPLSInvalidLoadOperation = "Invalid pixel local storage Load Operation.";
+MSG kPLSInvalidTextureType = "Invalid pixel local storage texture type.";
+MSG kPLSKeepingMemorylessPlane = "Load Operation GL_KEEP is invalid for memoryless planes.";
+MSG kPLSMaxColorAttachmentsExceded = "Framebuffer cannot have images attached to color attachment points on or after COLOR_ATTACHMENT0 + MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE.";
+MSG kPLSMaxCombinedDrawBuffersAndPlanesExceded = "Framebuffer cannot have images attached to color attachment points on or after COLOR_ATTACHMENT0 + MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE - <planes>.";
+MSG kPLSMismatchedBackingTextureSizes = "Mismatched pixel local storage backing texture sizes.";
+MSG kPLSMultisamplingEnabled = "Attempted to begin pixel local storage with a multisampled framebuffer.";
+MSG kPLSNoAttachmentsNoTextureBacked = "Draw framebuffer has no attachments and no enabled, texture-backed pixel local storage planes.";
+MSG kPLSNullClearData = "cleardata cannot null if Load Operation GL_CLEAR_ANGLE is specified.";
+MSG kPLSNullLoadOps = "loadops cannot null.";
+MSG kPLSPlaneLessThanZero = "Plane cannot be less than 0.";
+MSG kPLSPlaneOutOfRange = "Plane must be less than GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.";
+MSG kPLSPlanesLessThanOne = "Planes must be greater than 0.";
+MSG kPLSPlanesOutOfRange = "Planes must be less than or equal to GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.";
+MSG kPLSRasterizerDiscardEnabled = "Attempted to begin pixel local storage with GL_RASTERIZER_DISCARD enabled.";
+MSG kPLSReservedDrawBufferInUse = "When beginning pixel local storage, glDrawBuffers must all be GL_NONE at indices greater than or equal to: min(GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PLS_ANGLE, GL_MAX_COMBINED_DRAW_BUFFERS_AND_PLS_PLANES_ANGLE - <planes>).";
+MSG kPLSSampleAlphaToCoverageEnabled = "Attempted to begin pixel local storage with GL_SAMPLE_ALPHA_TO_COVERAGE enabled.";
+MSG kPLSSampleCoverageEnabled = "Attempted to begin pixel local storage with GL_SAMPLE_COVERAGE enabled.";
+MSG kPointSizeArrayExtensionNotEnabled = "GL_OES_point_size_array not enabled.";
+MSG kProgramDoesNotExist = "Program doesn't exist.";
+MSG kProgramInterfaceMustBeProgramOutput = "programInterface must be set to GL_PROGRAM_OUTPUT.";
+MSG kProgramNotBound = "A program must be bound.";
+MSG kProgramNotLinked = "Program not linked.";
+MSG kQueryActive = "Query is active.";
+MSG kQueryExtensionNotEnabled = "Query extension not enabled.";
+MSG kQueryInactive = "Query is not active.";
+MSG kQueryTargetMismatch = "Query type does not match target.";
+MSG kReadBufferNone = "Read buffer is GL_NONE.";
+MSG kReadBufferNotAttached = "Read buffer has no attachment.";
+MSG kRectangleTextureCompressed = "Rectangle texture cannot have a compressed format.";
+MSG kRelativeOffsetTooLarge = "relativeOffset cannot be greater than MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.";
+MSG kRenderableInternalFormat = "SizedInternalformat must be color-renderable, depth-renderable, or stencil-renderable.";
+MSG kRenderbufferNotBound = "A renderbuffer must be bound.";
+MSG kResourceMaxRenderbufferSize = "Desired resource size is greater than max renderbuffer size.";
+MSG kResourceMaxTextureSize = "Desired resource size is greater than max texture size.";
+MSG kRobustResourceInitializationExtensionRequired = "EGL_ANGLE_robust_resource_initialization not enabled.";
+MSG kSamplerFormatMismatch = "Mismatch between texture format and sampler type (signed/unsigned/float/shadow).";
+MSG kSamplerUniformValueOutOfRange = "Sampler uniform value out of range.";
+MSG kSamplesOutOfRange = "Samples must not be greater than maximum supported value for the format.";
+MSG kSamplesZero = "Samples may not be zero.";
+MSG kShaderAttachmentHasShader = "Shader attachment already has a shader.";
+MSG kShaderSourceInvalidCharacters = "Shader source contains invalid characters.";
+MSG kShaderStorageBufferOffsetAlignment = "Offset must be multiple of value of SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT.";
+MSG kShaderToDetachMustBeAttached = "Shader to be detached must be currently attached to the program.";
+MSG kShadingRateExtensionNotAvailable = "GL_QCOM_shading_rate extension not available.";
+MSG kSourceLevelNotDefined = "The source level of the source texture must be defined.";
+MSG kSourceTextureLevelZeroDefined = "Source texture must level 0 defined.";
+MSG kSourceTextureMustBeCompressed = "Source texture must have a compressed internal format.";
+MSG kSourceTextureTooSmall = "The specified dimensions are outside of the bounds of the texture.";
+MSG kStencilReferenceMaskOrMismatch = "Stencil reference and mask values must be the same for front facing and back facing triangles.";
+MSG kStrideExceedsWebGLLimit = "Stride is over the maximum stride allowed by WebGL.";
+MSG kStrideMustBeMultipleOfType = "Stride must be a multiple of the passed in datatype.";
+MSG kSyncMissing = "Sync object does not exist.";
+MSG kTargetMustBeTexture2DMultisampleArrayOES = "Target must be TEXTURE_2D_MULTISAMPLE_ARRAY_OES.";
+MSG kTessellationShaderExtensionNotEnabled = "GL_EXT_tessellation_shader extension not enabled.";
+MSG kTessellationShaderRequiresBothControlAndEvaluation = "Tessellation requires both control and evaluation shaders.";
+MSG kTessellationShaderRequiresVertexShader = "Any command that transfers vertices to the GL requires a vertex shader if the current program uses a tessellation shader.";
+MSG kTextureBufferExtensionNotAvailable = "Texture buffer extension not available.";
+MSG kTextureBufferOffsetAlignment = "Offset must be multiple of value of TEXTURE_BUFFER_OFFSET_ALIGNMENT.";
+MSG kTextureBufferSize = "Texture buffer size must be a positive integer.";
+MSG kTextureBufferSizeOffset = "Texture buffer offset + size must be less than or equal to BUFFER_SIZE.";
+MSG kTextureBufferTarget = "Target must be TEXTURE_BUFFER.";
+MSG kTextureBufferInternalFormat = "Internal format is not an accepted sized internal format.";
+MSG kTextureBufferInvalidBuffer = "If buffer is nonzero, it must match the name of an existing buffer object.";
+MSG kTextureFormatMismatch = "Passed in texture target and format must match the one originally used to define the texture.";
+MSG kTextureIsImmutable = "Texture is immutable.";
+MSG kTextureIsNotImmutable = "Texture is not immutable.";
+MSG kTextureIsNeitherImmutableNorTextureBuffer = "Texture is not the name of an immutable texture object or a buffer texture.";
+MSG kTextureLayerOutOfRange = "Layer is larger than texture depth.";
+MSG kTextureLevelOutOfRange = "Level is larger than texture level count.";
+MSG kTextureNotBound = "A texture must be bound.";
+MSG kTextureNotPow2 = "The texture is a non-power-of-two texture.";
+MSG kTextureRectangleNotSupported = "Context does not support GL_ANGLE_texture_rectangle";
+MSG kTextureSizeTooSmall = "Texture dimensions must all be greater than zero.";
+MSG kTextureTargetMismatch = "Textarget must match the texture target type.";
+MSG kTextureTargetMismatchWithLabel = "Textarget must match the texture target type. Requested: %d Texture's: %d label: %s";
+MSG kTextureTargetRequiresES31 = "Texture target requires at least OpenGL ES 3.1.";
+MSG kTextureTypeConflict = "Two textures of different types use the same sampler location.";
+MSG kTextureTypeMismatch = "Passed in texture type must match the one originally used to define the texture.";
+MSG kTextureWidthOrHeightOutOfRange = "Width and height must be less than or equal to GL_MAX_TEXTURE_SIZE.";
+MSG kTextureDepthOutOfRange = "Depth must be less than or equal to MAX_ARRAY_TEXTURE_LAYERS";
+MSG kTransfomFeedbackAlreadyActive = "Transform feedback is already active.";
+MSG kTransformFeedbackActiveDelete = "Attempt to delete an active transform feedback.";
+MSG kTransformFeedbackActiveDuringLink = "Cannot link program while program is associated with an active transform feedback object.";
+MSG kTransformFeedbackBufferDoubleBound = "A transform feedback buffer that would be written to is also bound to a non-transform-feedback target, which would cause undefined behavior.";
+MSG kTransformFeedbackBufferMissing = "Every binding point used in transform feedback mode must have a buffer object bound.";
+MSG kTransformFeedbackBufferMultipleOutputs = "Transform feedback has a buffer bound to multiple outputs.";
+MSG kTransformFeedbackBufferTooSmall = "Not enough space in bound transform feedback buffers.";
+MSG kTransformFeedbackDoesNotExist = "Transform feedback object that does not exist.";
+MSG kTransformFeedbackNotActive = "No Transform Feedback object is active.";
+MSG kTransformFeedbackNotPaused = "The active Transform Feedback object is not paused.";
+MSG kTransformFeedbackPaused = "The active Transform Feedback object is paused.";
+MSG kTransformFeedbackProgramBinary = "Cannot change program binary while program is associated with an active transform feedback object.";
+MSG kTransformFeedbackTargetActive = "Target is TRANSFORM_FEEDBACK_BUFFER and transform feedback is currently active.";
+MSG kTransformFeedbackUseProgram = "Cannot change active program while transform feedback is unpaused.";
+MSG kTransformFeedbackVaryingIndexOutOfRange = "Index must be less than the transform feedback varying count in the program.";
+MSG kTypeNotUnsignedShortByte = "Only UNSIGNED_SHORT and UNSIGNED_BYTE types are supported.";
+MSG kUniformBufferBoundForTransformFeedback = "It is undefined behavior to use an uniform buffer that is bound for transform feedback.";
+MSG kUniformBufferOffsetAlignment = "Offset must be multiple of value of UNIFORM_BUFFER_OFFSET_ALIGNMENT.";
+MSG kUniformBufferTooSmall = "It is undefined behaviour to use a uniform buffer that is too small.";
+MSG kUniformBufferUnbound = "It is undefined behaviour to have a used but unbound uniform buffer.";
+MSG kUniformSizeMismatch = "Uniform size does not match uniform method.";
+MSG kUniformTypeMismatch = "Uniform type does not match uniform method.";
+MSG kUnimplementedComputeShaderPrecision = "Compute shader precision not yet implemented.";
+MSG kUnknownParameter = "Unknown parameter value.";
+MSG kUnsizedInternalFormatUnsupported = "Internalformat is one of the unsupported unsized base internalformats.";
+MSG kUnsupportedDrawModeForTransformFeedback = "The draw command is unsupported when transform feedback is active and not paused.";
+MSG kUnsupportedFloatBlending = "GL_BLEND with floating-point color attachments requires the EXT_float_blend extension.";
+MSG kVertexArrayNoBuffer = "An enabled vertex array has no buffer.";
+MSG kVertexArrayNoBufferPointer = "An enabled vertex array has no buffer and no pointer.";
+MSG kVertexBufferBoundForTransformFeedback = "It is undefined behavior to use a vertex buffer that is bound for transform feedback.";
+MSG kVertexShaderTypeMismatch = "Vertex shader input type does not match the type of the bound vertex attribute.";
+MSG kViewportNegativeSize = "Viewport size cannot be negative.";
+MSG kViewsExceedMaxArrayLayers = "baseViewIndex+numViews cannot be greater than GL_MAX_ARRAY_TEXTURE_LAYERS.";
+MSG kWebgl2NameLengthLimitExceeded = "Location lengths must not be greater than 1024 characters.";
+MSG kWebglBindAttribLocationReservedPrefix = "Attributes that begin with 'webgl_', or '_webgl_' are not allowed.";
+MSG kWebglNameLengthLimitExceeded = "Location name lengths must not be greater than 256 characters.";
+MSG kYUVOutputMissmatch = "Program and framebuffer YUV output state does not match.";
+MSG kYUVTargetExtensionRequired = "GL_EXT_YUV_target not enabled.";
+MSG kZeroBoundToTarget = "Zero is bound to target.";
+MSG kUnrecognizedShaderStageBit = "Unrecognized shader stage bit.";
+MSG kProgramNotSeparable = "Program object was not linked with its PROGRAM_SEPARABLE status set.";
+MSG kProgramPipelineDoesNotExist = "Program pipeline does not exist.";
+MSG kNotAllStagesOfSeparableProgramUsed = "A program object is active for at least one, but not all of the shader stages that were present when the program was linked.";
+MSG kNoExecutableCodeInstalled = "There is no current program object specified by UseProgram, there is a current program pipeline object, and that object is empty (no executable code is installed for any stage).";
+MSG kProgramPipelineLinkFailed = "Program pipeline link failed";
+MSG kProtectedTexturesExtensionRequired = "GL_EXT_protected_textures not enabled.";
+
+// clang-format on
+
+#undef MSG
+} // namespace err
+} // namespace gl
+#endif // LIBANGLE_ERRORSTRINGS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Fence.cpp b/gfx/angle/checkout/src/libANGLE/Fence.cpp
new file mode 100644
index 0000000000..af173dff29
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Fence.cpp
@@ -0,0 +1,124 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Fence.cpp: Implements the gl::FenceNV and gl::Sync classes.
+
+#include "libANGLE/Fence.h"
+
+#include "angle_gl.h"
+
+#include "common/utilities.h"
+#include "libANGLE/renderer/FenceNVImpl.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/SyncImpl.h"
+
+namespace gl
+{
+
+FenceNV::FenceNV(rx::GLImplFactory *factory)
+ : mFence(factory->createFenceNV()), mIsSet(false), mStatus(GL_FALSE), mCondition(GL_NONE)
+{}
+
+FenceNV::~FenceNV()
+{
+ SafeDelete(mFence);
+}
+
+void FenceNV::onDestroy(const gl::Context *context)
+{
+ mFence->onDestroy(context);
+}
+
+angle::Result FenceNV::set(const Context *context, GLenum condition)
+{
+ ANGLE_TRY(mFence->set(context, condition));
+
+ mCondition = condition;
+ mStatus = GL_FALSE;
+ mIsSet = true;
+
+ return angle::Result::Continue;
+}
+
+angle::Result FenceNV::test(const Context *context, GLboolean *outResult)
+{
+ // Flush the command buffer by default
+ ANGLE_TRY(mFence->test(context, &mStatus));
+
+ *outResult = mStatus;
+ return angle::Result::Continue;
+}
+
+angle::Result FenceNV::finish(const Context *context)
+{
+ ASSERT(mIsSet);
+
+ ANGLE_TRY(mFence->finish(context));
+
+ mStatus = GL_TRUE;
+
+ return angle::Result::Continue;
+}
+
+Sync::Sync(rx::GLImplFactory *factory, GLuint id)
+ : RefCountObject(factory->generateSerial(), id),
+ mFence(factory->createSync()),
+ mLabel(),
+ mCondition(GL_SYNC_GPU_COMMANDS_COMPLETE),
+ mFlags(0)
+{}
+
+void Sync::onDestroy(const Context *context)
+{
+ ASSERT(mFence);
+ mFence->onDestroy(context);
+}
+
+Sync::~Sync()
+{
+ SafeDelete(mFence);
+}
+
+angle::Result Sync::setLabel(const Context *context, const std::string &label)
+{
+ mLabel = label;
+ return angle::Result::Continue;
+}
+
+const std::string &Sync::getLabel() const
+{
+ return mLabel;
+}
+
+angle::Result Sync::set(const Context *context, GLenum condition, GLbitfield flags)
+{
+ ANGLE_TRY(mFence->set(context, condition, flags));
+
+ mCondition = condition;
+ mFlags = flags;
+ return angle::Result::Continue;
+}
+
+angle::Result Sync::clientWait(const Context *context,
+ GLbitfield flags,
+ GLuint64 timeout,
+ GLenum *outResult)
+{
+ ASSERT(mCondition != GL_NONE);
+ return mFence->clientWait(context, flags, timeout, outResult);
+}
+
+angle::Result Sync::serverWait(const Context *context, GLbitfield flags, GLuint64 timeout)
+{
+ return mFence->serverWait(context, flags, timeout);
+}
+
+angle::Result Sync::getStatus(const Context *context, GLint *outResult) const
+{
+ return mFence->getStatus(context, outResult);
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Fence.h b/gfx/angle/checkout/src/libANGLE/Fence.h
new file mode 100644
index 0000000000..2852b328fd
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Fence.h
@@ -0,0 +1,88 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Fence.h: Defines the gl::FenceNV and gl::Sync classes, which support the GL_NV_fence
+// extension and GLES3 sync objects.
+
+#ifndef LIBANGLE_FENCE_H_
+#define LIBANGLE_FENCE_H_
+
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+#include "common/angleutils.h"
+
+namespace rx
+{
+class GLImplFactory;
+class FenceNVImpl;
+class SyncImpl;
+} // namespace rx
+
+namespace gl
+{
+
+class FenceNV final : angle::NonCopyable
+{
+ public:
+ explicit FenceNV(rx::GLImplFactory *factory);
+ virtual ~FenceNV();
+
+ void onDestroy(const gl::Context *context);
+ angle::Result set(const Context *context, GLenum condition);
+ angle::Result test(const Context *context, GLboolean *outResult);
+ angle::Result finish(const Context *context);
+
+ bool isSet() const { return mIsSet; }
+ GLboolean getStatus() const { return mStatus; }
+ GLenum getCondition() const { return mCondition; }
+
+ private:
+ rx::FenceNVImpl *mFence;
+
+ bool mIsSet;
+
+ GLboolean mStatus;
+ GLenum mCondition;
+};
+
+class Sync final : public RefCountObject<GLuint>, public LabeledObject
+{
+ public:
+ Sync(rx::GLImplFactory *factory, GLuint id);
+ ~Sync() override;
+
+ void onDestroy(const Context *context) override;
+
+ angle::Result setLabel(const Context *context, const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ angle::Result set(const Context *context, GLenum condition, GLbitfield flags);
+ angle::Result clientWait(const Context *context,
+ GLbitfield flags,
+ GLuint64 timeout,
+ GLenum *outResult);
+ angle::Result serverWait(const Context *context, GLbitfield flags, GLuint64 timeout);
+ angle::Result getStatus(const Context *context, GLint *outResult) const;
+
+ GLenum getCondition() const { return mCondition; }
+ GLbitfield getFlags() const { return mFlags; }
+
+ rx::SyncImpl *getImplementation() const { return mFence; }
+
+ private:
+ rx::SyncImpl *mFence;
+
+ std::string mLabel;
+
+ GLenum mCondition;
+ GLbitfield mFlags;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_FENCE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Framebuffer.cpp b/gfx/angle/checkout/src/libANGLE/Framebuffer.cpp
new file mode 100644
index 0000000000..08250b0b2d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Framebuffer.cpp
@@ -0,0 +1,2727 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer
+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
+
+#include "libANGLE/Framebuffer.h"
+
+#include "common/Optional.h"
+#include "common/bitset_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/PixelLocalStorage.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/FramebufferImpl.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/RenderbufferImpl.h"
+#include "libANGLE/renderer/SurfaceImpl.h"
+
+using namespace angle;
+
+namespace gl
+{
+
+namespace
+{
+
+// Check the |checkAttachment| in reference to |firstAttachment| for the sake of multiview
+// framebuffer completeness.
+FramebufferStatus CheckMultiviewStateMatchesForCompleteness(
+ const FramebufferAttachment *firstAttachment,
+ const FramebufferAttachment *checkAttachment)
+{
+ ASSERT(firstAttachment && checkAttachment);
+ ASSERT(firstAttachment->isAttached() && checkAttachment->isAttached());
+
+ if (firstAttachment->isMultiview() != checkAttachment->isMultiview())
+ {
+ return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR,
+ err::kFramebufferIncompleteMultiviewMismatch);
+ }
+ if (firstAttachment->getNumViews() != checkAttachment->getNumViews())
+ {
+ return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR,
+ err::kFramebufferIncompleteMultiviewViewsMismatch);
+ }
+ if (checkAttachment->getBaseViewIndex() + checkAttachment->getNumViews() >
+ checkAttachment->getSize().depth)
+ {
+ return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR,
+ err::kFramebufferIncompleteMultiviewBaseViewMismatch);
+ }
+
+ return FramebufferStatus::Complete();
+}
+
+FramebufferStatus CheckAttachmentCompleteness(const Context *context,
+ const FramebufferAttachment &attachment)
+{
+ ASSERT(attachment.isAttached());
+
+ const Extents &size = attachment.getSize();
+ if (size.width == 0 || size.height == 0)
+ {
+ return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+ err::kFramebufferIncompleteAttachmentZeroSize);
+ }
+
+ if (!attachment.isRenderable(context))
+ {
+ return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+ err::kFramebufferIncompleteAttachmentNotRenderable);
+ }
+
+ if (attachment.type() == GL_TEXTURE)
+ {
+ // [EXT_geometry_shader] Section 9.4.1, "Framebuffer Completeness"
+ // If <image> is a three-dimensional texture or a two-dimensional array texture and the
+ // attachment is not layered, the selected layer is less than the depth or layer count,
+ // respectively, of the texture.
+ if (!attachment.isLayered())
+ {
+ if (attachment.layer() >= size.depth)
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+ err::kFramebufferIncompleteAttachmentLayerGreaterThanDepth);
+ }
+ }
+ // If <image> is a three-dimensional texture or a two-dimensional array texture and the
+ // attachment is layered, the depth or layer count, respectively, of the texture is less
+ // than or equal to the value of MAX_FRAMEBUFFER_LAYERS_EXT.
+ else
+ {
+ if (size.depth >= context->getCaps().maxFramebufferLayers)
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+ err::kFramebufferIncompleteAttachmentDepthGreaterThanMaxLayers);
+ }
+ }
+
+ // ES3 specifies that cube map texture attachments must be cube complete.
+ // This language is missing from the ES2 spec, but we enforce it here because some
+ // desktop OpenGL drivers also enforce this validation.
+ // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
+ const Texture *texture = attachment.getTexture();
+ ASSERT(texture);
+ if (texture->getType() == TextureType::CubeMap &&
+ !texture->getTextureState().isCubeComplete())
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+ err::kFramebufferIncompleteAttachmentNotCubeComplete);
+ }
+
+ if (!texture->getImmutableFormat())
+ {
+ GLuint attachmentMipLevel = static_cast<GLuint>(attachment.mipLevel());
+
+ // From the ES 3.0 spec, pg 213:
+ // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
+ // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture,
+ // then the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL must be in the
+ // range[levelbase, q], where levelbase is the value of TEXTURE_BASE_LEVEL and q is
+ // the effective maximum texture level defined in the Mipmapping discussion of
+ // section 3.8.10.4.
+ if (attachmentMipLevel < texture->getBaseLevel() ||
+ attachmentMipLevel > texture->getMipmapMaxLevel())
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+ err::kFramebufferIncompleteAttachmentLevelOutOfBaseMaxLevelRange);
+ }
+
+ // Form the ES 3.0 spec, pg 213/214:
+ // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
+ // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture and
+ // the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is not levelbase, then the
+ // texture must be mipmap complete, and if FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names
+ // a cubemap texture, the texture must also be cube complete.
+ if (attachmentMipLevel != texture->getBaseLevel() && !texture->isMipmapComplete())
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+ err::kFramebufferIncompleteAttachmentLevelNotBaseLevelForIncompleteMipTexture);
+ }
+ }
+ }
+
+ return FramebufferStatus::Complete();
+}
+
+FramebufferStatus CheckAttachmentSampleCounts(const Context *context,
+ GLsizei currAttachmentSamples,
+ GLsizei samples,
+ bool colorAttachment)
+{
+ if (currAttachmentSamples != samples)
+ {
+ if (colorAttachment)
+ {
+ // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
+ // all color attachments have the same number of samples for the FBO to be complete.
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
+ err::kFramebufferIncompleteMultisampleInconsistentSampleCounts);
+ }
+ else
+ {
+ // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be considered complete
+ // when its depth or stencil samples are a multiple of the number of color samples.
+ if (!context->getExtensions().framebufferMixedSamplesCHROMIUM)
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
+ err::kFramebufferIncompleteMultisampleInconsistentSampleCounts);
+ }
+
+ if ((currAttachmentSamples % std::max(samples, 1)) != 0)
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
+ err::
+ kFramebufferIncompleteMultisampleDepthStencilSampleCountDivisibleByColorSampleCount);
+ }
+ }
+ }
+
+ return FramebufferStatus::Complete();
+}
+
+FramebufferStatus CheckAttachmentSampleCompleteness(const Context *context,
+ const FramebufferAttachment &attachment,
+ bool colorAttachment,
+ Optional<int> *samples,
+ Optional<bool> *fixedSampleLocations,
+ Optional<int> *renderToTextureSamples)
+{
+ ASSERT(attachment.isAttached());
+
+ if (attachment.type() == GL_TEXTURE)
+ {
+ const Texture *texture = attachment.getTexture();
+ ASSERT(texture);
+ GLenum sizedInternalFormat = attachment.getFormat().info->sizedInternalFormat;
+ const TextureCaps &formatCaps = context->getTextureCaps().get(sizedInternalFormat);
+ if (static_cast<GLuint>(attachment.getSamples()) > formatCaps.getMaxSamples())
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
+ err::kFramebufferIncompleteAttachmentSamplesGreaterThanMaxSupportedSamples);
+ }
+
+ const ImageIndex &attachmentImageIndex = attachment.getTextureImageIndex();
+ bool fixedSampleloc = texture->getAttachmentFixedSampleLocations(attachmentImageIndex);
+ if (fixedSampleLocations->valid() && fixedSampleloc != fixedSampleLocations->value())
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
+ err::kFramebufferIncompleteMultisampleInconsistentFixedSampleLocations);
+ }
+ else
+ {
+ *fixedSampleLocations = fixedSampleloc;
+ }
+ }
+
+ if (renderToTextureSamples->valid())
+ {
+ // Only check against RenderToTextureSamples if they actually exist.
+ if (renderToTextureSamples->value() !=
+ FramebufferAttachment::kDefaultRenderToTextureSamples)
+ {
+ FramebufferStatus sampleCountStatus =
+ CheckAttachmentSampleCounts(context, attachment.getRenderToTextureSamples(),
+ renderToTextureSamples->value(), colorAttachment);
+ if (!sampleCountStatus.isComplete())
+ {
+ return sampleCountStatus;
+ }
+ }
+ }
+ else
+ {
+ *renderToTextureSamples = attachment.getRenderToTextureSamples();
+ }
+
+ if (samples->valid())
+ {
+ // RenderToTextureSamples takes precedence if they exist.
+ if (renderToTextureSamples->value() ==
+ FramebufferAttachment::kDefaultRenderToTextureSamples)
+ {
+
+ FramebufferStatus sampleCountStatus = CheckAttachmentSampleCounts(
+ context, attachment.getSamples(), samples->value(), colorAttachment);
+ if (!sampleCountStatus.isComplete())
+ {
+ return sampleCountStatus;
+ }
+ }
+ }
+ else
+ {
+ *samples = attachment.getSamples();
+ }
+
+ return FramebufferStatus::Complete();
+}
+
+// Needed to index into the attachment arrays/bitsets.
+static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_DRAW_BUFFERS) ==
+ Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX,
+ "Framebuffer Dirty bit mismatch");
+static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_DRAW_BUFFERS) ==
+ Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT,
+ "Framebuffer Dirty bit mismatch");
+static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_DRAW_BUFFERS + 1) ==
+ Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT,
+ "Framebuffer Dirty bit mismatch");
+
+angle::Result InitAttachment(const Context *context, FramebufferAttachment *attachment)
+{
+ ASSERT(attachment->isAttached());
+ if (attachment->initState() == InitState::MayNeedInit)
+ {
+ ANGLE_TRY(attachment->initializeContents(context));
+ }
+ return angle::Result::Continue;
+}
+
+bool AttachmentOverlapsWithTexture(const FramebufferAttachment &attachment,
+ const Texture *texture,
+ const Sampler *sampler)
+{
+ if (!attachment.isTextureWithId(texture->id()))
+ {
+ return false;
+ }
+
+ const gl::ImageIndex &index = attachment.getTextureImageIndex();
+ GLuint attachmentLevel = static_cast<GLuint>(index.getLevelIndex());
+ GLuint textureEffectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
+ GLuint textureMaxLevel = textureEffectiveBaseLevel;
+ if ((sampler && IsMipmapFiltered(sampler->getSamplerState().getMinFilter())) ||
+ IsMipmapFiltered(texture->getSamplerState().getMinFilter()))
+ {
+ textureMaxLevel = texture->getMipmapMaxLevel();
+ }
+
+ return attachmentLevel >= textureEffectiveBaseLevel && attachmentLevel <= textureMaxLevel;
+}
+
+} // anonymous namespace
+
+bool FramebufferStatus::isComplete() const
+{
+ return status == GL_FRAMEBUFFER_COMPLETE;
+}
+
+FramebufferStatus FramebufferStatus::Complete()
+{
+ FramebufferStatus result;
+ result.status = GL_FRAMEBUFFER_COMPLETE;
+ result.reason = nullptr;
+ return result;
+}
+
+FramebufferStatus FramebufferStatus::Incomplete(GLenum status, const char *reason)
+{
+ ASSERT(status != GL_FRAMEBUFFER_COMPLETE);
+
+ FramebufferStatus result;
+ result.status = status;
+ result.reason = reason;
+ return result;
+}
+
+// This constructor is only used for default framebuffers.
+FramebufferState::FramebufferState(rx::Serial serial)
+ : mId(Framebuffer::kDefaultDrawFramebufferHandle),
+ mFramebufferSerial(serial),
+ mLabel(),
+ mColorAttachments(1),
+ mColorAttachmentsMask(0),
+ mDrawBufferStates(1, GL_BACK),
+ mReadBufferState(GL_BACK),
+ mDrawBufferTypeMask(),
+ mDefaultWidth(0),
+ mDefaultHeight(0),
+ mDefaultSamples(0),
+ mDefaultFixedSampleLocations(GL_FALSE),
+ mDefaultLayers(0),
+ mFlipY(GL_FALSE),
+ mWebGLDepthStencilConsistent(true),
+ mDefaultFramebufferReadAttachmentInitialized(false),
+ mSrgbWriteControlMode(SrgbWriteControlMode::Default)
+{
+ ASSERT(mDrawBufferStates.size() > 0);
+ mEnabledDrawBuffers.set(0);
+}
+
+FramebufferState::FramebufferState(const Caps &caps, FramebufferID id, rx::Serial serial)
+ : mId(id),
+ mFramebufferSerial(serial),
+ mLabel(),
+ mColorAttachments(caps.maxColorAttachments),
+ mColorAttachmentsMask(0),
+ mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
+ mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
+ mDrawBufferTypeMask(),
+ mDefaultWidth(0),
+ mDefaultHeight(0),
+ mDefaultSamples(0),
+ mDefaultFixedSampleLocations(GL_FALSE),
+ mDefaultLayers(0),
+ mFlipY(GL_FALSE),
+ mWebGLDepthStencilConsistent(true),
+ mDefaultFramebufferReadAttachmentInitialized(false),
+ mSrgbWriteControlMode(SrgbWriteControlMode::Default)
+{
+ ASSERT(mId != Framebuffer::kDefaultDrawFramebufferHandle);
+ ASSERT(mDrawBufferStates.size() > 0);
+ mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
+}
+
+FramebufferState::~FramebufferState() {}
+
+const std::string &FramebufferState::getLabel() const
+{
+ return mLabel;
+}
+
+const FramebufferAttachment *FramebufferState::getAttachment(const Context *context,
+ GLenum attachment) const
+{
+ if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
+ {
+ return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
+ }
+
+ // WebGL1 allows a developer to query for attachment parameters even when "inconsistant" (i.e.
+ // multiple conflicting attachment points) and requires us to return the framebuffer attachment
+ // associated with WebGL.
+ switch (attachment)
+ {
+ case GL_COLOR:
+ case GL_BACK:
+ return getColorAttachment(0);
+ case GL_DEPTH:
+ case GL_DEPTH_ATTACHMENT:
+ if (context->isWebGL1())
+ {
+ return getWebGLDepthAttachment();
+ }
+ else
+ {
+ return getDepthAttachment();
+ }
+ case GL_STENCIL:
+ case GL_STENCIL_ATTACHMENT:
+ if (context->isWebGL1())
+ {
+ return getWebGLStencilAttachment();
+ }
+ else
+ {
+ return getStencilAttachment();
+ }
+ case GL_DEPTH_STENCIL:
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (context->isWebGL1())
+ {
+ return getWebGLDepthStencilAttachment();
+ }
+ else
+ {
+ return getDepthStencilAttachment();
+ }
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+
+uint32_t FramebufferState::getReadIndex() const
+{
+ ASSERT(mReadBufferState == GL_BACK ||
+ (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
+ uint32_t readIndex = mReadBufferState == GL_BACK ? 0 : mReadBufferState - GL_COLOR_ATTACHMENT0;
+ ASSERT(readIndex < mColorAttachments.size());
+ return readIndex;
+}
+
+const FramebufferAttachment *FramebufferState::getReadAttachment() const
+{
+ if (mReadBufferState == GL_NONE)
+ {
+ return nullptr;
+ }
+
+ uint32_t readIndex = getReadIndex();
+ const gl::FramebufferAttachment &framebufferAttachment =
+ isDefault() ? mDefaultFramebufferReadAttachment : mColorAttachments[readIndex];
+
+ return framebufferAttachment.isAttached() ? &framebufferAttachment : nullptr;
+}
+
+const FramebufferAttachment *FramebufferState::getReadPixelsAttachment(GLenum readFormat) const
+{
+ switch (readFormat)
+ {
+ case GL_DEPTH_COMPONENT:
+ return getDepthAttachment();
+ case GL_STENCIL_INDEX_OES:
+ return getStencilOrDepthStencilAttachment();
+ case GL_DEPTH_STENCIL_OES:
+ return getDepthStencilAttachment();
+ default:
+ return getReadAttachment();
+ }
+}
+
+const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
+{
+ auto *colorAttachment = getFirstColorAttachment();
+ if (colorAttachment)
+ {
+ return colorAttachment;
+ }
+ return getDepthOrStencilAttachment();
+}
+
+const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
+{
+ for (const FramebufferAttachment &colorAttachment : mColorAttachments)
+ {
+ if (colorAttachment.isAttached())
+ {
+ return &colorAttachment;
+ }
+ }
+
+ return nullptr;
+}
+
+const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
+{
+ if (mDepthAttachment.isAttached())
+ {
+ return &mDepthAttachment;
+ }
+ if (mStencilAttachment.isAttached())
+ {
+ return &mStencilAttachment;
+ }
+ return nullptr;
+}
+
+const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
+{
+ if (mStencilAttachment.isAttached())
+ {
+ return &mStencilAttachment;
+ }
+ return getDepthStencilAttachment();
+}
+
+const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
+{
+ ASSERT(colorAttachment < mColorAttachments.size());
+ return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
+ : nullptr;
+}
+
+const FramebufferAttachment *FramebufferState::getDepthAttachment() const
+{
+ return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
+}
+
+const FramebufferAttachment *FramebufferState::getWebGLDepthAttachment() const
+{
+ return mWebGLDepthAttachment.isAttached() ? &mWebGLDepthAttachment : nullptr;
+}
+
+const FramebufferAttachment *FramebufferState::getWebGLDepthStencilAttachment() const
+{
+ return mWebGLDepthStencilAttachment.isAttached() ? &mWebGLDepthStencilAttachment : nullptr;
+}
+
+const FramebufferAttachment *FramebufferState::getStencilAttachment() const
+{
+ return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
+}
+
+const FramebufferAttachment *FramebufferState::getWebGLStencilAttachment() const
+{
+ return mWebGLStencilAttachment.isAttached() ? &mWebGLStencilAttachment : nullptr;
+}
+
+const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
+{
+ // A valid depth-stencil attachment has the same resource bound to both the
+ // depth and stencil attachment points.
+ if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
+ mDepthAttachment == mStencilAttachment)
+ {
+ return &mDepthAttachment;
+ }
+
+ return nullptr;
+}
+
+const Extents FramebufferState::getAttachmentExtentsIntersection() const
+{
+ int32_t width = std::numeric_limits<int32_t>::max();
+ int32_t height = std::numeric_limits<int32_t>::max();
+ for (const FramebufferAttachment &attachment : mColorAttachments)
+ {
+ if (attachment.isAttached())
+ {
+ width = std::min(width, attachment.getSize().width);
+ height = std::min(height, attachment.getSize().height);
+ }
+ }
+
+ if (mDepthAttachment.isAttached())
+ {
+ width = std::min(width, mDepthAttachment.getSize().width);
+ height = std::min(height, mDepthAttachment.getSize().height);
+ }
+
+ if (mStencilAttachment.isAttached())
+ {
+ width = std::min(width, mStencilAttachment.getSize().width);
+ height = std::min(height, mStencilAttachment.getSize().height);
+ }
+
+ return Extents(width, height, 0);
+}
+
+bool FramebufferState::attachmentsHaveSameDimensions() const
+{
+ Optional<Extents> attachmentSize;
+
+ auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
+ if (!attachment.isAttached())
+ {
+ return false;
+ }
+
+ if (!attachmentSize.valid())
+ {
+ attachmentSize = attachment.getSize();
+ return false;
+ }
+
+ const auto &prevSize = attachmentSize.value();
+ const auto &curSize = attachment.getSize();
+ return (curSize.width != prevSize.width || curSize.height != prevSize.height);
+ };
+
+ for (const auto &attachment : mColorAttachments)
+ {
+ if (hasMismatchedSize(attachment))
+ {
+ return false;
+ }
+ }
+
+ if (hasMismatchedSize(mDepthAttachment))
+ {
+ return false;
+ }
+
+ return !hasMismatchedSize(mStencilAttachment);
+}
+
+bool FramebufferState::hasSeparateDepthAndStencilAttachments() const
+{
+ // if we have both a depth and stencil buffer, they must refer to the same object
+ // since we only support packed_depth_stencil and not separate depth and stencil
+ return (getDepthAttachment() != nullptr && getStencilAttachment() != nullptr &&
+ getDepthStencilAttachment() == nullptr);
+}
+
+const FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
+{
+ ASSERT(drawBufferIdx < mDrawBufferStates.size());
+ if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
+ {
+ // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
+ // must be COLOR_ATTACHMENTi or NONE"
+ ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
+ (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
+
+ if (mDrawBufferStates[drawBufferIdx] == GL_BACK)
+ {
+ return getColorAttachment(0);
+ }
+ else
+ {
+ return getColorAttachment(mDrawBufferStates[drawBufferIdx] - GL_COLOR_ATTACHMENT0);
+ }
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+size_t FramebufferState::getDrawBufferCount() const
+{
+ return mDrawBufferStates.size();
+}
+
+bool FramebufferState::colorAttachmentsAreUniqueImages() const
+{
+ for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
+ firstAttachmentIdx++)
+ {
+ const FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
+ if (!firstAttachment.isAttached())
+ {
+ continue;
+ }
+
+ for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
+ secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
+ {
+ const FramebufferAttachment &secondAttachment = mColorAttachments[secondAttachmentIdx];
+ if (!secondAttachment.isAttached())
+ {
+ continue;
+ }
+
+ if (firstAttachment == secondAttachment)
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool FramebufferState::hasDepth() const
+{
+ return (mDepthAttachment.isAttached() && mDepthAttachment.getDepthSize() > 0);
+}
+
+bool FramebufferState::hasStencil() const
+{
+ return (mStencilAttachment.isAttached() && mStencilAttachment.getStencilSize() > 0);
+}
+
+bool FramebufferState::hasExternalTextureAttachment() const
+{
+ // External textures can only be bound to color attachment 0
+ return (mColorAttachments[0].isAttached() && mColorAttachments[0].isExternalTexture());
+}
+
+bool FramebufferState::hasYUVAttachment() const
+{
+ // The only attachments that can be YUV are external textures and surfaces, both are attached at
+ // color attachment 0.
+ return (mColorAttachments[0].isAttached() && mColorAttachments[0].isYUV());
+}
+
+bool FramebufferState::isMultiview() const
+{
+ const FramebufferAttachment *attachment = getFirstNonNullAttachment();
+ if (attachment == nullptr)
+ {
+ return false;
+ }
+ return attachment->isMultiview();
+}
+
+int FramebufferState::getBaseViewIndex() const
+{
+ const FramebufferAttachment *attachment = getFirstNonNullAttachment();
+ if (attachment == nullptr)
+ {
+ return GL_NONE;
+ }
+ return attachment->getBaseViewIndex();
+}
+
+Box FramebufferState::getDimensions() const
+{
+ Extents extents = getExtents();
+ return Box(0, 0, 0, extents.width, extents.height, extents.depth);
+}
+
+Extents FramebufferState::getExtents() const
+{
+ // OpenGLES3.0 (https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf
+ // section 4.4.4.2) allows attachments have unequal size.
+ const FramebufferAttachment *first = getFirstNonNullAttachment();
+ if (first)
+ {
+ return getAttachmentExtentsIntersection();
+ }
+ return Extents(getDefaultWidth(), getDefaultHeight(), 0);
+}
+
+bool FramebufferState::isDefault() const
+{
+ return mId == Framebuffer::kDefaultDrawFramebufferHandle;
+}
+
+bool FramebufferState::isBoundAsDrawFramebuffer(const Context *context) const
+{
+ return context->getState().getDrawFramebuffer()->id() == mId;
+}
+
+const FramebufferID Framebuffer::kDefaultDrawFramebufferHandle = {0};
+
+Framebuffer::Framebuffer(const Context *context, rx::GLImplFactory *factory)
+ : mState(context->getShareGroup()->generateFramebufferSerial()),
+ mImpl(factory->createFramebuffer(mState)),
+ mCachedStatus(FramebufferStatus::Incomplete(GL_FRAMEBUFFER_UNDEFINED_OES,
+ err::kFramebufferIncompleteSurfaceless)),
+ mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
+ mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
+{
+ mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
+ SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask);
+}
+
+Framebuffer::Framebuffer(const Context *context, rx::GLImplFactory *factory, FramebufferID id)
+ : mState(context->getCaps(), id, context->getShareGroup()->generateFramebufferSerial()),
+ mImpl(factory->createFramebuffer(mState)),
+ mCachedStatus(),
+ mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
+ mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
+{
+ ASSERT(mImpl != nullptr);
+ ASSERT(mState.mColorAttachments.size() ==
+ static_cast<size_t>(context->getCaps().maxColorAttachments));
+
+ for (uint32_t colorIndex = 0;
+ colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
+ {
+ mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
+ }
+ if (context->getClientVersion() >= ES_3_0)
+ {
+ mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
+ }
+}
+
+Framebuffer::~Framebuffer()
+{
+ SafeDelete(mImpl);
+}
+
+void Framebuffer::onDestroy(const Context *context)
+{
+ if (isDefault())
+ {
+ std::ignore = unsetSurfaces(context);
+ }
+
+ for (auto &attachment : mState.mColorAttachments)
+ {
+ attachment.detach(context, mState.mFramebufferSerial);
+ }
+ mState.mDepthAttachment.detach(context, mState.mFramebufferSerial);
+ mState.mStencilAttachment.detach(context, mState.mFramebufferSerial);
+ mState.mWebGLDepthAttachment.detach(context, mState.mFramebufferSerial);
+ mState.mWebGLStencilAttachment.detach(context, mState.mFramebufferSerial);
+ mState.mWebGLDepthStencilAttachment.detach(context, mState.mFramebufferSerial);
+
+ if (mPixelLocalStorage)
+ {
+ mPixelLocalStorage->onFramebufferDestroyed(context);
+ }
+
+ mImpl->destroy(context);
+}
+
+egl::Error Framebuffer::setSurfaces(const Context *context,
+ egl::Surface *surface,
+ egl::Surface *readSurface)
+{
+ // This has to be a default framebuffer.
+ ASSERT(isDefault());
+ ASSERT(mDirtyColorAttachmentBindings.size() == 1);
+ ASSERT(mDirtyColorAttachmentBindings[0].getSubjectIndex() == DIRTY_BIT_COLOR_ATTACHMENT_0);
+
+ ASSERT(!mState.mColorAttachments[0].isAttached());
+ ASSERT(!mState.mDepthAttachment.isAttached());
+ ASSERT(!mState.mStencilAttachment.isAttached());
+
+ if (surface)
+ {
+ setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), surface,
+ FramebufferAttachment::kDefaultNumViews,
+ FramebufferAttachment::kDefaultBaseViewIndex, false,
+ FramebufferAttachment::kDefaultRenderToTextureSamples);
+ mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
+
+ if (surface->getConfig()->depthSize > 0)
+ {
+ setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex(), surface,
+ FramebufferAttachment::kDefaultNumViews,
+ FramebufferAttachment::kDefaultBaseViewIndex, false,
+ FramebufferAttachment::kDefaultRenderToTextureSamples);
+ mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
+ }
+
+ if (surface->getConfig()->stencilSize > 0)
+ {
+ setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex(), surface,
+ FramebufferAttachment::kDefaultNumViews,
+ FramebufferAttachment::kDefaultBaseViewIndex, false,
+ FramebufferAttachment::kDefaultRenderToTextureSamples);
+ mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
+ }
+
+ mState.mSurfaceTextureOffset = surface->getTextureOffset();
+
+ // Ensure the backend has a chance to synchronize its content for a new backbuffer.
+ mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
+ }
+
+ setReadSurface(context, readSurface);
+
+ SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask);
+
+ ASSERT(mCachedStatus.value().status == GL_FRAMEBUFFER_UNDEFINED_OES);
+ ASSERT(mCachedStatus.value().reason == err::kFramebufferIncompleteSurfaceless);
+ if (surface)
+ {
+ mCachedStatus = FramebufferStatus::Complete();
+ ANGLE_TRY(surface->getImplementation()->attachToFramebuffer(context, this));
+ }
+
+ return egl::NoError();
+}
+
+void Framebuffer::setReadSurface(const Context *context, egl::Surface *readSurface)
+{
+ // This has to be a default framebuffer.
+ ASSERT(isDefault());
+ ASSERT(mDirtyColorAttachmentBindings.size() == 1);
+ ASSERT(mDirtyColorAttachmentBindings[0].getSubjectIndex() == DIRTY_BIT_COLOR_ATTACHMENT_0);
+
+ // Read surface is not attached.
+ ASSERT(!mState.mDefaultFramebufferReadAttachment.isAttached());
+
+ // updateAttachment() without mState.mResourceNeedsInit.set()
+ mState.mDefaultFramebufferReadAttachment.attach(
+ context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), readSurface,
+ FramebufferAttachment::kDefaultNumViews, FramebufferAttachment::kDefaultBaseViewIndex,
+ false, FramebufferAttachment::kDefaultRenderToTextureSamples, mState.mFramebufferSerial);
+
+ if (context->getClientVersion() >= ES_3_0)
+ {
+ mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
+ }
+}
+
+egl::Error Framebuffer::unsetSurfaces(const Context *context)
+{
+ // This has to be a default framebuffer.
+ ASSERT(isDefault());
+ ASSERT(mDirtyColorAttachmentBindings.size() == 1);
+ ASSERT(mDirtyColorAttachmentBindings[0].getSubjectIndex() == DIRTY_BIT_COLOR_ATTACHMENT_0);
+
+ if (mState.mColorAttachments[0].isAttached())
+ {
+ const egl::Surface *surface = mState.mColorAttachments[0].getSurface();
+ mState.mColorAttachments[0].detach(context, mState.mFramebufferSerial);
+ mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
+
+ if (mState.mDepthAttachment.isAttached())
+ {
+ mState.mDepthAttachment.detach(context, mState.mFramebufferSerial);
+ mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
+ }
+
+ if (mState.mStencilAttachment.isAttached())
+ {
+ mState.mStencilAttachment.detach(context, mState.mFramebufferSerial);
+ mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
+ }
+
+ ANGLE_TRY(surface->getImplementation()->detachFromFramebuffer(context, this));
+
+ ASSERT(mCachedStatus.value().status == GL_FRAMEBUFFER_COMPLETE);
+ mCachedStatus = FramebufferStatus::Incomplete(GL_FRAMEBUFFER_UNDEFINED_OES,
+ err::kFramebufferIncompleteSurfaceless);
+ }
+ else
+ {
+ ASSERT(!mState.mDepthAttachment.isAttached());
+ ASSERT(!mState.mStencilAttachment.isAttached());
+ ASSERT(mCachedStatus.value().status == GL_FRAMEBUFFER_UNDEFINED_OES);
+ ASSERT(mCachedStatus.value().reason == err::kFramebufferIncompleteSurfaceless);
+ }
+
+ mState.mDefaultFramebufferReadAttachment.detach(context, mState.mFramebufferSerial);
+ mState.mDefaultFramebufferReadAttachmentInitialized = false;
+ return egl::NoError();
+}
+
+angle::Result Framebuffer::setLabel(const Context *context, const std::string &label)
+{
+ mState.mLabel = label;
+
+ if (mImpl)
+ {
+ return mImpl->onLabelUpdate(context);
+ }
+ return angle::Result::Continue;
+}
+
+const std::string &Framebuffer::getLabel() const
+{
+ return mState.mLabel;
+}
+
+bool Framebuffer::detachTexture(const Context *context, TextureID textureId)
+{
+ return detachResourceById(context, GL_TEXTURE, textureId.value);
+}
+
+bool Framebuffer::detachRenderbuffer(const Context *context, RenderbufferID renderbufferId)
+{
+ return detachResourceById(context, GL_RENDERBUFFER, renderbufferId.value);
+}
+
+bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
+{
+ bool found = false;
+
+ for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
+ {
+ if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
+ resourceId))
+ {
+ found = true;
+ }
+ }
+
+ if (context->isWebGL1())
+ {
+ const std::array<FramebufferAttachment *, 3> attachments = {
+ {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
+ &mState.mWebGLStencilAttachment}};
+ for (FramebufferAttachment *attachment : attachments)
+ {
+ if (detachMatchingAttachment(context, attachment, resourceType, resourceId))
+ {
+ found = true;
+ }
+ }
+ }
+ else
+ {
+ if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId))
+ {
+ found = true;
+ }
+ if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId))
+ {
+ found = true;
+ }
+ }
+
+ return found;
+}
+
+bool Framebuffer::detachMatchingAttachment(const Context *context,
+ FramebufferAttachment *attachment,
+ GLenum matchType,
+ GLuint matchId)
+{
+ if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
+ {
+ // We go through resetAttachment to make sure that all the required bookkeeping will be done
+ // such as updating enabled draw buffer state.
+ resetAttachment(context, attachment->getBinding());
+ return true;
+ }
+
+ return false;
+}
+
+const FramebufferAttachment *Framebuffer::getColorAttachment(size_t colorAttachment) const
+{
+ return mState.getColorAttachment(colorAttachment);
+}
+
+const FramebufferAttachment *Framebuffer::getDepthAttachment() const
+{
+ return mState.getDepthAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getStencilAttachment() const
+{
+ return mState.getStencilAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getDepthStencilAttachment() const
+{
+ return mState.getDepthStencilAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getDepthOrStencilAttachment() const
+{
+ return mState.getDepthOrStencilAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
+{
+ return mState.getStencilOrDepthStencilAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getReadColorAttachment() const
+{
+ return mState.getReadAttachment();
+}
+
+GLenum Framebuffer::getReadColorAttachmentType() const
+{
+ const FramebufferAttachment *readAttachment = mState.getReadAttachment();
+ return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
+}
+
+const FramebufferAttachment *Framebuffer::getFirstColorAttachment() const
+{
+ return mState.getFirstColorAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
+{
+ return mState.getFirstNonNullAttachment();
+}
+
+const FramebufferAttachment *Framebuffer::getAttachment(const Context *context,
+ GLenum attachment) const
+{
+ return mState.getAttachment(context, attachment);
+}
+
+size_t Framebuffer::getDrawbufferStateCount() const
+{
+ return mState.mDrawBufferStates.size();
+}
+
+GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
+{
+ ASSERT(drawBuffer < mState.mDrawBufferStates.size());
+ return mState.mDrawBufferStates[drawBuffer];
+}
+
+const DrawBuffersVector<GLenum> &Framebuffer::getDrawBufferStates() const
+{
+ return mState.getDrawBufferStates();
+}
+
+void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
+{
+ auto &drawStates = mState.mDrawBufferStates;
+
+ ASSERT(count <= drawStates.size());
+ std::copy(buffers, buffers + count, drawStates.begin());
+ std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
+ mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
+
+ mState.mEnabledDrawBuffers.reset();
+ mState.mDrawBufferTypeMask.reset();
+
+ for (size_t index = 0; index < count; ++index)
+ {
+ SetComponentTypeMask(getDrawbufferWriteType(index), index, &mState.mDrawBufferTypeMask);
+
+ if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
+ {
+ mState.mEnabledDrawBuffers.set(index);
+ }
+ }
+}
+
+const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
+{
+ return mState.getDrawBuffer(drawBuffer);
+}
+
+ComponentType Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
+{
+ const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
+ if (attachment == nullptr)
+ {
+ return ComponentType::NoType;
+ }
+
+ GLenum componentType = attachment->getFormat().info->componentType;
+ switch (componentType)
+ {
+ case GL_INT:
+ return ComponentType::Int;
+ case GL_UNSIGNED_INT:
+ return ComponentType::UnsignedInt;
+
+ default:
+ return ComponentType::Float;
+ }
+}
+
+ComponentTypeMask Framebuffer::getDrawBufferTypeMask() const
+{
+ return mState.mDrawBufferTypeMask;
+}
+
+DrawBufferMask Framebuffer::getDrawBufferMask() const
+{
+ return mState.mEnabledDrawBuffers;
+}
+
+bool Framebuffer::hasEnabledDrawBuffer() const
+{
+ for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
+ {
+ if (getDrawBuffer(drawbufferIdx) != nullptr)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+GLenum Framebuffer::getReadBufferState() const
+{
+ return mState.mReadBufferState;
+}
+
+void Framebuffer::setReadBuffer(GLenum buffer)
+{
+ ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
+ (buffer >= GL_COLOR_ATTACHMENT0 &&
+ (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
+ if (mState.mReadBufferState != buffer)
+ {
+ mState.mReadBufferState = buffer;
+ mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
+ }
+}
+
+size_t Framebuffer::getNumColorAttachments() const
+{
+ return mState.mColorAttachments.size();
+}
+
+bool Framebuffer::hasDepth() const
+{
+ return mState.hasDepth();
+}
+
+bool Framebuffer::hasStencil() const
+{
+ return mState.hasStencil();
+}
+
+bool Framebuffer::hasExternalTextureAttachment() const
+{
+ return mState.hasExternalTextureAttachment();
+}
+
+bool Framebuffer::hasYUVAttachment() const
+{
+ return mState.hasYUVAttachment();
+}
+
+bool Framebuffer::usingExtendedDrawBuffers() const
+{
+ for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
+ {
+ if (getDrawBuffer(drawbufferIdx) != nullptr)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void Framebuffer::invalidateCompletenessCache()
+{
+ if (!isDefault())
+ {
+ mCachedStatus.reset();
+ }
+ onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
+}
+
+const FramebufferStatus &Framebuffer::checkStatusImpl(const Context *context) const
+{
+ ASSERT(!isDefault());
+ ASSERT(hasAnyDirtyBit() || !mCachedStatus.valid());
+
+ mCachedStatus = checkStatusWithGLFrontEnd(context);
+
+ if (mCachedStatus.value().isComplete())
+ {
+ // We can skip syncState on several back-ends.
+ if (mImpl->shouldSyncStateBeforeCheckStatus())
+ {
+ // This binding is not totally correct. It is ok because the parameter isn't used in
+ // the GL back-end and the GL back-end is the only user of syncStateBeforeCheckStatus.
+ angle::Result err = syncState(context, GL_FRAMEBUFFER, Command::Other);
+ if (err != angle::Result::Continue)
+ {
+ mCachedStatus =
+ FramebufferStatus::Incomplete(0, err::kFramebufferIncompleteInternalError);
+ return mCachedStatus.value();
+ }
+ }
+
+ mCachedStatus = mImpl->checkStatus(context);
+ }
+
+ return mCachedStatus.value();
+}
+
+FramebufferStatus Framebuffer::checkStatusWithGLFrontEnd(const Context *context) const
+{
+ const State &state = context->getState();
+
+ ASSERT(!isDefault());
+
+ bool hasAttachments = false;
+ Optional<unsigned int> colorbufferSize;
+ Optional<int> samples;
+ Optional<bool> fixedSampleLocations;
+ bool hasRenderbuffer = false;
+ Optional<int> renderToTextureSamples;
+
+ const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
+
+ Optional<bool> isLayered;
+ Optional<TextureType> colorAttachmentsTextureType;
+
+ for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
+ {
+ if (colorAttachment.isAttached())
+ {
+ FramebufferStatus attachmentCompleteness =
+ CheckAttachmentCompleteness(context, colorAttachment);
+ if (!attachmentCompleteness.isComplete())
+ {
+ return attachmentCompleteness;
+ }
+
+ const InternalFormat &format = *colorAttachment.getFormat().info;
+ if (format.depthBits > 0 || format.stencilBits > 0)
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+ err::kFramebufferIncompleteDepthStencilInColorBuffer);
+ }
+
+ FramebufferStatus attachmentSampleCompleteness =
+ CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
+ &fixedSampleLocations, &renderToTextureSamples);
+ if (!attachmentSampleCompleteness.isComplete())
+ {
+ return attachmentSampleCompleteness;
+ }
+
+ // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
+ // in GLES 3.0, there is no such restriction
+ if (state.getClientMajorVersion() < 3)
+ {
+ if (colorbufferSize.valid())
+ {
+ if (format.pixelBytes != colorbufferSize.value())
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_UNSUPPORTED,
+ err::kFramebufferIncompleteAttachmentInconsistantBitPlanes);
+ }
+ }
+ else
+ {
+ colorbufferSize = format.pixelBytes;
+ }
+ }
+
+ FramebufferStatus attachmentMultiviewCompleteness =
+ CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment);
+ if (!attachmentMultiviewCompleteness.isComplete())
+ {
+ return attachmentMultiviewCompleteness;
+ }
+
+ hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
+
+ if (!hasAttachments)
+ {
+ isLayered = colorAttachment.isLayered();
+ if (isLayered.value())
+ {
+ colorAttachmentsTextureType = colorAttachment.getTextureImageIndex().getType();
+ }
+ hasAttachments = true;
+ }
+ else
+ {
+ // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
+ // If any framebuffer attachment is layered, all populated attachments
+ // must be layered. Additionally, all populated color attachments must
+ // be from textures of the same target. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
+ ASSERT(isLayered.valid());
+ if (isLayered.value() != colorAttachment.isLayered())
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT,
+ err::kFramebufferIncompleteMismatchedLayeredAttachments);
+ }
+ else if (isLayered.value())
+ {
+ ASSERT(colorAttachmentsTextureType.valid());
+ if (colorAttachmentsTextureType.value() !=
+ colorAttachment.getTextureImageIndex().getType())
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT,
+ err::kFramebufferIncompleteMismatchedLayeredTexturetypes);
+ }
+ }
+ }
+ }
+ }
+
+ const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
+ if (depthAttachment.isAttached())
+ {
+ FramebufferStatus attachmentCompleteness =
+ CheckAttachmentCompleteness(context, depthAttachment);
+ if (!attachmentCompleteness.isComplete())
+ {
+ return attachmentCompleteness;
+ }
+
+ const InternalFormat &format = *depthAttachment.getFormat().info;
+ if (format.depthBits == 0)
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+ err::kFramebufferIncompleteAttachmentNoDepthBitsInDepthBuffer);
+ }
+
+ FramebufferStatus attachmentSampleCompleteness =
+ CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
+ &fixedSampleLocations, &renderToTextureSamples);
+ if (!attachmentSampleCompleteness.isComplete())
+ {
+ return attachmentSampleCompleteness;
+ }
+
+ FramebufferStatus attachmentMultiviewCompleteness =
+ CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment);
+ if (!attachmentMultiviewCompleteness.isComplete())
+ {
+ return attachmentMultiviewCompleteness;
+ }
+
+ hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
+
+ if (!hasAttachments)
+ {
+ isLayered = depthAttachment.isLayered();
+ hasAttachments = true;
+ }
+ else
+ {
+ // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
+ // If any framebuffer attachment is layered, all populated attachments
+ // must be layered. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
+ ASSERT(isLayered.valid());
+ if (isLayered.value() != depthAttachment.isLayered())
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT,
+ err::kFramebufferIncompleteMismatchedLayeredAttachments);
+ }
+ }
+ }
+
+ const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
+ if (stencilAttachment.isAttached())
+ {
+ FramebufferStatus attachmentCompleteness =
+ CheckAttachmentCompleteness(context, stencilAttachment);
+ if (!attachmentCompleteness.isComplete())
+ {
+ return attachmentCompleteness;
+ }
+
+ const InternalFormat &format = *stencilAttachment.getFormat().info;
+ if (format.stencilBits == 0)
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+ err::kFramebufferIncompleteAttachmentNoStencilBitsInStencilBuffer);
+ }
+
+ FramebufferStatus attachmentSampleCompleteness =
+ CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
+ &fixedSampleLocations, &renderToTextureSamples);
+ if (!attachmentSampleCompleteness.isComplete())
+ {
+ return attachmentSampleCompleteness;
+ }
+
+ FramebufferStatus attachmentMultiviewCompleteness =
+ CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment);
+ if (!attachmentMultiviewCompleteness.isComplete())
+ {
+ return attachmentMultiviewCompleteness;
+ }
+
+ hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
+
+ if (!hasAttachments)
+ {
+ hasAttachments = true;
+ }
+ else
+ {
+ // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
+ // If any framebuffer attachment is layered, all populated attachments
+ // must be layered.
+ // {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
+ ASSERT(isLayered.valid());
+ if (isLayered.value() != stencilAttachment.isLayered())
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT,
+ err::kFramebufferIncompleteMismatchedLayeredAttachments);
+ }
+ }
+ }
+
+ // Starting from ES 3.0 stencil and depth, if present, should be the same image
+ if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
+ stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_UNSUPPORTED,
+ err::kFramebufferIncompleteDepthAndStencilBuffersNotTheSame);
+ }
+
+ // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
+ if (state.isWebGL1())
+ {
+ if (!mState.mWebGLDepthStencilConsistent)
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_UNSUPPORTED,
+ err::kFramebufferIncompleteWebGLDepthStencilInconsistant);
+ }
+
+ if (mState.mWebGLDepthStencilAttachment.isAttached())
+ {
+ if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
+ mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+ err::kFramebufferIncompleteAttachmentWebGLDepthStencilNoDepthOrStencilBits);
+ }
+
+ FramebufferStatus attachmentMultiviewCompleteness =
+ CheckMultiviewStateMatchesForCompleteness(firstAttachment,
+ &mState.mWebGLDepthStencilAttachment);
+ if (!attachmentMultiviewCompleteness.isComplete())
+ {
+ return attachmentMultiviewCompleteness;
+ }
+ }
+ else if (mState.mStencilAttachment.isAttached() &&
+ mState.mStencilAttachment.getDepthSize() > 0)
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+ err::kFramebufferIncompleteAttachmentWebGLStencilBufferHasDepthBits);
+ }
+ else if (mState.mDepthAttachment.isAttached() &&
+ mState.mDepthAttachment.getStencilSize() > 0)
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+ err::kFramebufferIncompleteAttachmentWebGLDepthBufferHasStencilBits);
+ }
+ }
+
+ // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
+ // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
+ // is zero, the framebuffer is considered incomplete.
+ GLint defaultWidth = mState.getDefaultWidth();
+ GLint defaultHeight = mState.getDefaultHeight();
+ if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
+ {
+ return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
+ err::kFramebufferIncompleteDefaultZeroSize);
+ }
+
+ // In ES 2.0 and WebGL, all color attachments must have the same width and height.
+ // In ES 3.0, there is no such restriction.
+ if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibilityANGLE) &&
+ !mState.attachmentsHaveSameDimensions())
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
+ err::kFramebufferIncompleteInconsistantAttachmentSizes);
+ }
+
+ // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
+ // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
+ if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
+ {
+ return FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
+ err::kFramebufferIncompleteMultisampleNonFixedSamplesWithRenderbuffers);
+ }
+
+ // The WebGL conformance tests implicitly define that all framebuffer
+ // attachments must be unique. For example, the same level of a texture can
+ // not be attached to two different color attachments.
+ if (state.getExtensions().webglCompatibilityANGLE)
+ {
+ if (!mState.colorAttachmentsAreUniqueImages())
+ {
+ return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_UNSUPPORTED,
+ err::kFramebufferIncompleteAttachmentsNotUnique);
+ }
+ }
+
+ return FramebufferStatus::Complete();
+}
+
+angle::Result Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
+{
+ // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
+ // can be no-ops, so we should probably do that to ensure consistency.
+ // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
+
+ return mImpl->discard(context, count, attachments);
+}
+
+angle::Result Framebuffer::invalidate(const Context *context,
+ size_t count,
+ const GLenum *attachments)
+{
+ // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
+ // can be no-ops, so we should probably do that to ensure consistency.
+ // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
+
+ return mImpl->invalidate(context, count, attachments);
+}
+
+bool Framebuffer::partialClearNeedsInit(const Context *context,
+ bool color,
+ bool depth,
+ bool stencil)
+{
+ const auto &glState = context->getState();
+
+ if (!glState.isRobustResourceInitEnabled())
+ {
+ return false;
+ }
+
+ if (depth && context->getFrontendFeatures().forceDepthAttachmentInitOnClear.enabled)
+ {
+ return true;
+ }
+
+ // Scissors can affect clearing.
+ // TODO(jmadill): Check for complete scissor overlap.
+ if (glState.isScissorTestEnabled())
+ {
+ return true;
+ }
+
+ // If colors masked, we must clear before we clear. Do a simple check.
+ // TODO(jmadill): Filter out unused color channels from the test.
+ if (color && glState.anyActiveDrawBufferChannelMasked())
+ {
+ return true;
+ }
+
+ const auto &depthStencil = glState.getDepthStencilState();
+ if (stencil && (depthStencil.stencilMask != depthStencil.stencilWritemask ||
+ depthStencil.stencilBackMask != depthStencil.stencilBackWritemask))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+angle::Result Framebuffer::invalidateSub(const Context *context,
+ size_t count,
+ const GLenum *attachments,
+ const Rectangle &area)
+{
+ // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
+ // can be no-ops, so we should probably do that to ensure consistency.
+ // TODO(jmadill): Make a invalidate no-op in WebGL 2.0.
+
+ return mImpl->invalidateSub(context, count, attachments, area);
+}
+
+angle::Result Framebuffer::clear(const Context *context, GLbitfield mask)
+{
+ ASSERT(mask && !context->getState().isRasterizerDiscardEnabled());
+
+ return mImpl->clear(context, mask);
+}
+
+angle::Result Framebuffer::clearBufferfv(const Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values)
+{
+ return mImpl->clearBufferfv(context, buffer, drawbuffer, values);
+}
+
+angle::Result Framebuffer::clearBufferuiv(const Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values)
+{
+ return mImpl->clearBufferuiv(context, buffer, drawbuffer, values);
+}
+
+angle::Result Framebuffer::clearBufferiv(const Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values)
+{
+ return mImpl->clearBufferiv(context, buffer, drawbuffer, values);
+}
+
+angle::Result Framebuffer::clearBufferfi(const Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil)
+{
+ const bool clearDepth =
+ getDepthAttachment() != nullptr && context->getState().getDepthStencilState().depthMask;
+ const bool clearStencil = getStencilAttachment() != nullptr &&
+ context->getState().getDepthStencilState().stencilWritemask != 0;
+
+ if (clearDepth && clearStencil)
+ {
+ ASSERT(buffer == GL_DEPTH_STENCIL);
+ ANGLE_TRY(mImpl->clearBufferfi(context, GL_DEPTH_STENCIL, drawbuffer, depth, stencil));
+ }
+ else if (clearDepth && !clearStencil)
+ {
+ ANGLE_TRY(mImpl->clearBufferfv(context, GL_DEPTH, drawbuffer, &depth));
+ }
+ else if (!clearDepth && clearStencil)
+ {
+ ANGLE_TRY(mImpl->clearBufferiv(context, GL_STENCIL, drawbuffer, &stencil));
+ }
+
+ return angle::Result::Continue;
+}
+
+GLenum Framebuffer::getImplementationColorReadFormat(const Context *context)
+{
+ const gl::InternalFormat &format = mImpl->getImplementationColorReadFormat(context);
+ return format.getReadPixelsFormat(context->getExtensions());
+}
+
+GLenum Framebuffer::getImplementationColorReadType(const Context *context)
+{
+ const gl::InternalFormat &format = mImpl->getImplementationColorReadFormat(context);
+ return format.getReadPixelsType(context->getClientVersion());
+}
+
+angle::Result Framebuffer::readPixels(const Context *context,
+ const Rectangle &area,
+ GLenum format,
+ GLenum type,
+ const PixelPackState &pack,
+ Buffer *packBuffer,
+ void *pixels)
+{
+ ANGLE_TRY(mImpl->readPixels(context, area, format, type, pack, packBuffer, pixels));
+
+ if (packBuffer)
+ {
+ packBuffer->onDataChanged();
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Framebuffer::blit(const Context *context,
+ const Rectangle &sourceArea,
+ const Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter)
+{
+ ASSERT(mask != 0);
+
+ ANGLE_TRY(mImpl->blit(context, sourceArea, destArea, mask, filter));
+
+ // Mark the contents of the attachments dirty
+ if ((mask & GL_COLOR_BUFFER_BIT) != 0)
+ {
+ for (size_t colorIndex : mState.mEnabledDrawBuffers)
+ {
+ mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + colorIndex);
+ }
+ }
+ if ((mask & GL_DEPTH_BUFFER_BIT) != 0)
+ {
+ mDirtyBits.set(DIRTY_BIT_DEPTH_BUFFER_CONTENTS);
+ }
+ if ((mask & GL_STENCIL_BUFFER_BIT) != 0)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_BUFFER_CONTENTS);
+ }
+ onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
+
+ return angle::Result::Continue;
+}
+
+int Framebuffer::getSamples(const Context *context) const
+{
+ if (!isComplete(context))
+ {
+ return 0;
+ }
+
+ ASSERT(mCachedStatus.valid() && mCachedStatus.value().isComplete());
+
+ // For a complete framebuffer, all attachments must have the same sample count.
+ // In this case return the first nonzero sample size.
+ const FramebufferAttachment *firstNonNullAttachment = mState.getFirstNonNullAttachment();
+ ASSERT(firstNonNullAttachment == nullptr || firstNonNullAttachment->isAttached());
+
+ return firstNonNullAttachment ? firstNonNullAttachment->getSamples() : 0;
+}
+
+int Framebuffer::getReadBufferResourceSamples(const Context *context) const
+{
+ if (!isComplete(context))
+ {
+ return 0;
+ }
+
+ ASSERT(mCachedStatus.valid() && mCachedStatus.value().isComplete());
+
+ const FramebufferAttachment *readAttachment = mState.getReadAttachment();
+ ASSERT(readAttachment == nullptr || readAttachment->isAttached());
+
+ return readAttachment ? readAttachment->getResourceSamples() : 0;
+}
+
+angle::Result Framebuffer::getSamplePosition(const Context *context,
+ size_t index,
+ GLfloat *xy) const
+{
+ ANGLE_TRY(mImpl->getSamplePosition(context, index, xy));
+ return angle::Result::Continue;
+}
+
+bool Framebuffer::hasValidDepthStencil() const
+{
+ return mState.getDepthStencilAttachment() != nullptr;
+}
+
+const gl::Offset &Framebuffer::getSurfaceTextureOffset() const
+{
+ return mState.getSurfaceTextureOffset();
+}
+
+void Framebuffer::setAttachment(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource)
+{
+ setAttachment(context, type, binding, textureIndex, resource,
+ FramebufferAttachment::kDefaultNumViews,
+ FramebufferAttachment::kDefaultBaseViewIndex, false,
+ FramebufferAttachment::kDefaultRenderToTextureSamples);
+}
+
+void Framebuffer::setAttachmentMultisample(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei samples)
+{
+ setAttachment(context, type, binding, textureIndex, resource,
+ FramebufferAttachment::kDefaultNumViews,
+ FramebufferAttachment::kDefaultBaseViewIndex, false, samples);
+}
+
+void Framebuffer::setAttachment(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ bool isMultiview,
+ GLsizei samplesIn)
+{
+ GLsizei samples = samplesIn;
+ // Match the sample count to the attachment's sample count.
+ if (resource)
+ {
+ const InternalFormat *info = resource->getAttachmentFormat(binding, textureIndex).info;
+ ASSERT(info);
+ GLenum sizedInternalFormat = info->sizedInternalFormat;
+ const TextureCaps &formatCaps = context->getTextureCaps().get(sizedInternalFormat);
+ samples = formatCaps.getNearestSamples(samples);
+ }
+
+ // Context may be null in unit tests.
+ if (!context || !context->isWebGL1())
+ {
+ setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
+ isMultiview, samples);
+ return;
+ }
+
+ switch (binding)
+ {
+ case GL_DEPTH_STENCIL:
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ mState.mWebGLDepthStencilAttachment.attach(
+ context, type, binding, textureIndex, resource, numViews, baseViewIndex,
+ isMultiview, samples, mState.mFramebufferSerial);
+ break;
+ case GL_DEPTH:
+ case GL_DEPTH_ATTACHMENT:
+ mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
+ numViews, baseViewIndex, isMultiview, samples,
+ mState.mFramebufferSerial);
+ break;
+ case GL_STENCIL:
+ case GL_STENCIL_ATTACHMENT:
+ mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
+ numViews, baseViewIndex, isMultiview, samples,
+ mState.mFramebufferSerial);
+ break;
+ default:
+ setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
+ baseViewIndex, isMultiview, samples);
+ return;
+ }
+
+ commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, isMultiview, samples);
+}
+
+void Framebuffer::setAttachmentMultiview(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLint baseViewIndex)
+{
+ setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex, true,
+ FramebufferAttachment::kDefaultRenderToTextureSamples);
+}
+
+void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ bool isMultiview,
+ GLsizei samples)
+{
+ int count = 0;
+
+ std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
+ &mState.mWebGLDepthAttachment,
+ &mState.mWebGLStencilAttachment}};
+ for (FramebufferAttachment *attachment : attachments)
+ {
+ if (attachment->isAttached())
+ {
+ count++;
+ }
+ }
+
+ mState.mWebGLDepthStencilConsistent = (count <= 1);
+ if (!mState.mWebGLDepthStencilConsistent)
+ {
+ // Inconsistent.
+ return;
+ }
+
+ auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
+ if (attachment.type() == GL_TEXTURE)
+ {
+ return attachment.getTextureImageIndex();
+ }
+ else
+ {
+ return ImageIndex();
+ }
+ };
+
+ if (mState.mWebGLDepthAttachment.isAttached())
+ {
+ const auto &depth = mState.mWebGLDepthAttachment;
+ setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
+ getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
+ baseViewIndex, isMultiview, samples);
+ setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
+ baseViewIndex, isMultiview, samples);
+ }
+ else if (mState.mWebGLStencilAttachment.isAttached())
+ {
+ const auto &stencil = mState.mWebGLStencilAttachment;
+ setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
+ baseViewIndex, isMultiview, samples);
+ setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
+ getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
+ numViews, baseViewIndex, isMultiview, samples);
+ }
+ else if (mState.mWebGLDepthStencilAttachment.isAttached())
+ {
+ const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
+ setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
+ getImageIndexIfTextureAttachment(depthStencil),
+ depthStencil.getResource(), numViews, baseViewIndex, isMultiview,
+ samples);
+ setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
+ getImageIndexIfTextureAttachment(depthStencil),
+ depthStencil.getResource(), numViews, baseViewIndex, isMultiview,
+ samples);
+ }
+ else
+ {
+ setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
+ baseViewIndex, isMultiview, samples);
+ setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
+ baseViewIndex, isMultiview, samples);
+ }
+}
+
+void Framebuffer::setAttachmentImpl(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ bool isMultiview,
+ GLsizei samples)
+{
+ switch (binding)
+ {
+ case GL_DEPTH_STENCIL:
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
+ &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
+ numViews, baseViewIndex, isMultiview, samples);
+ updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
+ &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
+ numViews, baseViewIndex, isMultiview, samples);
+ break;
+
+ case GL_DEPTH:
+ case GL_DEPTH_ATTACHMENT:
+ updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
+ &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
+ numViews, baseViewIndex, isMultiview, samples);
+ break;
+
+ case GL_STENCIL:
+ case GL_STENCIL_ATTACHMENT:
+ updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
+ &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
+ numViews, baseViewIndex, isMultiview, samples);
+ break;
+
+ case GL_BACK:
+ updateAttachment(context, &mState.mColorAttachments[0], DIRTY_BIT_COLOR_ATTACHMENT_0,
+ &mDirtyColorAttachmentBindings[0], type, binding, textureIndex,
+ resource, numViews, baseViewIndex, isMultiview, samples);
+ mState.mColorAttachmentsMask.set(0);
+
+ break;
+
+ default:
+ {
+ size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
+ ASSERT(colorIndex < mState.mColorAttachments.size());
+ size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
+ updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
+ &mDirtyColorAttachmentBindings[colorIndex], type, binding,
+ textureIndex, resource, numViews, baseViewIndex, isMultiview, samples);
+
+ if (!resource)
+ {
+ mFloat32ColorAttachmentBits.reset(colorIndex);
+ mState.mColorAttachmentsMask.reset(colorIndex);
+ }
+ else
+ {
+ updateFloat32ColorAttachmentBits(
+ colorIndex, resource->getAttachmentFormat(binding, textureIndex).info);
+ mState.mColorAttachmentsMask.set(colorIndex);
+ }
+
+ bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
+ mState.mEnabledDrawBuffers.set(colorIndex, enabled);
+ SetComponentTypeMask(getDrawbufferWriteType(colorIndex), colorIndex,
+ &mState.mDrawBufferTypeMask);
+ }
+ break;
+ }
+}
+
+void Framebuffer::updateAttachment(const Context *context,
+ FramebufferAttachment *attachment,
+ size_t dirtyBit,
+ angle::ObserverBinding *onDirtyBinding,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ bool isMultiview,
+ GLsizei samples)
+{
+ attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
+ isMultiview, samples, mState.mFramebufferSerial);
+ mDirtyBits.set(dirtyBit);
+ mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
+ onDirtyBinding->bind(resource);
+
+ invalidateCompletenessCache();
+}
+
+void Framebuffer::resetAttachment(const Context *context, GLenum binding)
+{
+ setAttachment(context, GL_NONE, binding, ImageIndex(), nullptr);
+}
+
+void Framebuffer::setWriteControlMode(SrgbWriteControlMode srgbWriteControlMode)
+{
+ if (srgbWriteControlMode != mState.getWriteControlMode())
+ {
+ mState.mSrgbWriteControlMode = srgbWriteControlMode;
+ mDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE);
+ }
+}
+
+angle::Result Framebuffer::syncState(const Context *context,
+ GLenum framebufferBinding,
+ Command command) const
+{
+ if (mDirtyBits.any())
+ {
+ mDirtyBitsGuard = mDirtyBits;
+ ANGLE_TRY(mImpl->syncState(context, framebufferBinding, mDirtyBits, command));
+ mDirtyBits.reset();
+ mDirtyBitsGuard.reset();
+ }
+ return angle::Result::Continue;
+}
+
+void Framebuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
+{
+ if (message != angle::SubjectMessage::SubjectChanged)
+ {
+ // This can be triggered by SubImage calls for Textures.
+ if (message == angle::SubjectMessage::ContentsChanged)
+ {
+ mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + index);
+ onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
+ return;
+ }
+
+ // Swapchain changes should only result in color buffer changes.
+ if (message == angle::SubjectMessage::SwapchainImageChanged)
+ {
+ if (index < DIRTY_BIT_COLOR_ATTACHMENT_MAX)
+ {
+ mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + index);
+ onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
+ }
+ return;
+ }
+
+ ASSERT(message != angle::SubjectMessage::BindingChanged);
+
+ // This can be triggered by external changes to the default framebuffer.
+ if (message == angle::SubjectMessage::SurfaceChanged)
+ {
+ onStateChange(angle::SubjectMessage::SurfaceChanged);
+ return;
+ }
+
+ // This can be triggered by freeing TextureStorage in D3D back-end.
+ if (message == angle::SubjectMessage::StorageReleased)
+ {
+ mDirtyBits.set(index);
+ invalidateCompletenessCache();
+ return;
+ }
+
+ // This can be triggered by the GL back-end TextureGL class.
+ ASSERT(message == angle::SubjectMessage::DirtyBitsFlagged);
+ return;
+ }
+
+ ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
+ mDirtyBits.set(index);
+
+ invalidateCompletenessCache();
+
+ FramebufferAttachment *attachment = getAttachmentFromSubjectIndex(index);
+
+ // Mark the appropriate init flag.
+ mState.mResourceNeedsInit.set(index, attachment->initState() == InitState::MayNeedInit);
+
+ // Update mFloat32ColorAttachmentBits Cache
+ if (index < DIRTY_BIT_COLOR_ATTACHMENT_MAX)
+ {
+ ASSERT(index != DIRTY_BIT_DEPTH_ATTACHMENT);
+ ASSERT(index != DIRTY_BIT_STENCIL_ATTACHMENT);
+ updateFloat32ColorAttachmentBits(index - DIRTY_BIT_COLOR_ATTACHMENT_0,
+ attachment->getFormat().info);
+ }
+}
+
+FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::SubjectIndex index)
+{
+ switch (index)
+ {
+ case DIRTY_BIT_DEPTH_ATTACHMENT:
+ return &mState.mDepthAttachment;
+ case DIRTY_BIT_STENCIL_ATTACHMENT:
+ return &mState.mStencilAttachment;
+ default:
+ size_t colorIndex = (index - DIRTY_BIT_COLOR_ATTACHMENT_0);
+ ASSERT(colorIndex < mState.mColorAttachments.size());
+ return &mState.mColorAttachments[colorIndex];
+ }
+}
+
+bool Framebuffer::formsRenderingFeedbackLoopWith(const Context *context) const
+{
+ const State &glState = context->getState();
+ const ProgramExecutable *executable = glState.getLinkedProgramExecutable(context);
+
+ // In some error cases there may be no bound program or executable.
+ if (!executable)
+ return false;
+
+ const ActiveTextureMask &activeTextures = executable->getActiveSamplersMask();
+ const ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
+
+ for (size_t textureIndex : activeTextures)
+ {
+ unsigned int uintIndex = static_cast<unsigned int>(textureIndex);
+ Texture *texture = glState.getSamplerTexture(uintIndex, textureTypes[textureIndex]);
+ const Sampler *sampler = glState.getSampler(uintIndex);
+ if (texture && texture->isSamplerComplete(context, sampler) &&
+ texture->isBoundToFramebuffer(mState.mFramebufferSerial))
+ {
+ // Check for level overlap.
+ for (const FramebufferAttachment &attachment : mState.mColorAttachments)
+ {
+ if (AttachmentOverlapsWithTexture(attachment, texture, sampler))
+ {
+ return true;
+ }
+ }
+
+ if (AttachmentOverlapsWithTexture(mState.mDepthAttachment, texture, sampler))
+ {
+ return true;
+ }
+
+ if (AttachmentOverlapsWithTexture(mState.mStencilAttachment, texture, sampler))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool Framebuffer::formsCopyingFeedbackLoopWith(TextureID copyTextureID,
+ GLint copyTextureLevel,
+ GLint copyTextureLayer) const
+{
+ if (mState.isDefault())
+ {
+ // It seems impossible to form a texture copying feedback loop with the default FBO.
+ return false;
+ }
+
+ const FramebufferAttachment *readAttachment = getReadColorAttachment();
+ ASSERT(readAttachment);
+
+ if (readAttachment->isTextureWithId(copyTextureID))
+ {
+ const auto &imageIndex = readAttachment->getTextureImageIndex();
+ if (imageIndex.getLevelIndex() == copyTextureLevel)
+ {
+ // Check 3D/Array texture layers.
+ return !imageIndex.hasLayer() || copyTextureLayer == ImageIndex::kEntireLevel ||
+ imageIndex.getLayerIndex() == copyTextureLayer;
+ }
+ }
+ return false;
+}
+
+GLint Framebuffer::getDefaultWidth() const
+{
+ return mState.getDefaultWidth();
+}
+
+GLint Framebuffer::getDefaultHeight() const
+{
+ return mState.getDefaultHeight();
+}
+
+GLint Framebuffer::getDefaultSamples() const
+{
+ return mState.getDefaultSamples();
+}
+
+bool Framebuffer::getDefaultFixedSampleLocations() const
+{
+ return mState.getDefaultFixedSampleLocations();
+}
+
+GLint Framebuffer::getDefaultLayers() const
+{
+ return mState.getDefaultLayers();
+}
+
+bool Framebuffer::getFlipY() const
+{
+ return mState.getFlipY();
+}
+
+void Framebuffer::setDefaultWidth(const Context *context, GLint defaultWidth)
+{
+ mState.mDefaultWidth = defaultWidth;
+ mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
+ invalidateCompletenessCache();
+}
+
+void Framebuffer::setDefaultHeight(const Context *context, GLint defaultHeight)
+{
+ mState.mDefaultHeight = defaultHeight;
+ mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
+ invalidateCompletenessCache();
+}
+
+void Framebuffer::setDefaultSamples(const Context *context, GLint defaultSamples)
+{
+ mState.mDefaultSamples = defaultSamples;
+ mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
+ invalidateCompletenessCache();
+}
+
+void Framebuffer::setDefaultFixedSampleLocations(const Context *context,
+ bool defaultFixedSampleLocations)
+{
+ mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
+ mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
+ invalidateCompletenessCache();
+}
+
+void Framebuffer::setDefaultLayers(GLint defaultLayers)
+{
+ mState.mDefaultLayers = defaultLayers;
+ mDirtyBits.set(DIRTY_BIT_DEFAULT_LAYERS);
+}
+
+void Framebuffer::setFlipY(bool flipY)
+{
+ mState.mFlipY = flipY;
+ mDirtyBits.set(DIRTY_BIT_FLIP_Y);
+ invalidateCompletenessCache();
+}
+
+GLsizei Framebuffer::getNumViews() const
+{
+ return mState.getNumViews();
+}
+
+GLint Framebuffer::getBaseViewIndex() const
+{
+ return mState.getBaseViewIndex();
+}
+
+bool Framebuffer::isMultiview() const
+{
+ return mState.isMultiview();
+}
+
+bool Framebuffer::readDisallowedByMultiview() const
+{
+ return (mState.isMultiview() && mState.getNumViews() > 1);
+}
+
+angle::Result Framebuffer::ensureClearAttachmentsInitialized(const Context *context,
+ GLbitfield mask)
+{
+ const auto &glState = context->getState();
+ if (!context->isRobustResourceInitEnabled() || glState.isRasterizerDiscardEnabled())
+ {
+ return angle::Result::Continue;
+ }
+
+ const DepthStencilState &depthStencil = glState.getDepthStencilState();
+
+ bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !glState.allActiveDrawBufferChannelsMasked();
+ bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !depthStencil.isDepthMaskedOut();
+ bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 && !depthStencil.isStencilMaskedOut();
+
+ if (!color && !depth && !stencil)
+ {
+ return angle::Result::Continue;
+ }
+
+ if (partialClearNeedsInit(context, color, depth, stencil))
+ {
+ ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
+ }
+
+ // If the impl encounters an error during a a full (non-partial) clear, the attachments will
+ // still be marked initialized. This simplifies design, allowing this method to be called before
+ // the clear.
+ markDrawAttachmentsInitialized(color, depth, stencil);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Framebuffer::ensureClearBufferAttachmentsInitialized(const Context *context,
+ GLenum buffer,
+ GLint drawbuffer)
+{
+ if (!context->isRobustResourceInitEnabled() ||
+ context->getState().isRasterizerDiscardEnabled() ||
+ context->isClearBufferMaskedOut(buffer, drawbuffer))
+ {
+ return angle::Result::Continue;
+ }
+
+ if (partialBufferClearNeedsInit(context, buffer))
+ {
+ ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
+ }
+
+ // If the impl encounters an error during a a full (non-partial) clear, the attachments will
+ // still be marked initialized. This simplifies design, allowing this method to be called before
+ // the clear.
+ markBufferInitialized(buffer, drawbuffer);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Framebuffer::ensureDrawAttachmentsInitialized(const Context *context)
+{
+ if (!context->isRobustResourceInitEnabled())
+ {
+ return angle::Result::Continue;
+ }
+
+ // Note: we don't actually filter by the draw attachment enum. Just init everything.
+ for (size_t bit : mState.mResourceNeedsInit)
+ {
+ switch (bit)
+ {
+ case DIRTY_BIT_DEPTH_ATTACHMENT:
+ ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
+ break;
+ case DIRTY_BIT_STENCIL_ATTACHMENT:
+ ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
+ break;
+ default:
+ ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bit]));
+ break;
+ }
+ }
+
+ mState.mResourceNeedsInit.reset();
+ return angle::Result::Continue;
+}
+
+angle::Result Framebuffer::ensureReadAttachmentsInitialized(const Context *context)
+{
+ ASSERT(context->isRobustResourceInitEnabled());
+
+ if (mState.mResourceNeedsInit.none())
+ {
+ return angle::Result::Continue;
+ }
+
+ if (mState.mReadBufferState != GL_NONE)
+ {
+ if (isDefault())
+ {
+ if (!mState.mDefaultFramebufferReadAttachmentInitialized)
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mDefaultFramebufferReadAttachment));
+ mState.mDefaultFramebufferReadAttachmentInitialized = true;
+ }
+ }
+ else
+ {
+ size_t readIndex = mState.getReadIndex();
+ if (mState.mResourceNeedsInit[readIndex])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[readIndex]));
+ mState.mResourceNeedsInit.reset(readIndex);
+ }
+ }
+ }
+
+ // Conservatively init depth since it can be read by BlitFramebuffer.
+ if (hasDepth())
+ {
+ if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
+ }
+ }
+
+ // Conservatively init stencil since it can be read by BlitFramebuffer.
+ if (hasStencil())
+ {
+ if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+void Framebuffer::markDrawAttachmentsInitialized(bool color, bool depth, bool stencil)
+{
+ // Mark attachments as initialized.
+ if (color)
+ {
+ for (auto colorIndex : mState.mEnabledDrawBuffers)
+ {
+ auto &colorAttachment = mState.mColorAttachments[colorIndex];
+ ASSERT(colorAttachment.isAttached());
+ colorAttachment.setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(colorIndex);
+ }
+ }
+
+ if (depth && mState.mDepthAttachment.isAttached())
+ {
+ mState.mDepthAttachment.setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
+ }
+
+ if (stencil && mState.mStencilAttachment.isAttached())
+ {
+ mState.mStencilAttachment.setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
+ }
+}
+
+void Framebuffer::markBufferInitialized(GLenum bufferType, GLint bufferIndex)
+{
+ switch (bufferType)
+ {
+ case GL_COLOR:
+ {
+ ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
+ if (mState.mColorAttachments[bufferIndex].isAttached())
+ {
+ mState.mColorAttachments[bufferIndex].setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(bufferIndex);
+ }
+ break;
+ }
+ case GL_DEPTH:
+ {
+ if (mState.mDepthAttachment.isAttached())
+ {
+ mState.mDepthAttachment.setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
+ }
+ break;
+ }
+ case GL_STENCIL:
+ {
+ if (mState.mStencilAttachment.isAttached())
+ {
+ mState.mStencilAttachment.setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
+ }
+ break;
+ }
+ case GL_DEPTH_STENCIL:
+ {
+ if (mState.mDepthAttachment.isAttached())
+ {
+ mState.mDepthAttachment.setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
+ }
+ if (mState.mStencilAttachment.isAttached())
+ {
+ mState.mStencilAttachment.setInitState(InitState::Initialized);
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+Box Framebuffer::getDimensions() const
+{
+ return mState.getDimensions();
+}
+
+Extents Framebuffer::getExtents() const
+{
+ return mState.getExtents();
+}
+
+angle::Result Framebuffer::ensureBufferInitialized(const Context *context,
+ GLenum bufferType,
+ GLint bufferIndex)
+{
+ ASSERT(context->isRobustResourceInitEnabled());
+
+ if (mState.mResourceNeedsInit.none())
+ {
+ return angle::Result::Continue;
+ }
+
+ switch (bufferType)
+ {
+ case GL_COLOR:
+ {
+ ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
+ if (mState.mResourceNeedsInit[bufferIndex])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bufferIndex]));
+ mState.mResourceNeedsInit.reset(bufferIndex);
+ }
+ break;
+ }
+ case GL_DEPTH:
+ {
+ if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
+ }
+ break;
+ }
+ case GL_STENCIL:
+ {
+ if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
+ }
+ break;
+ }
+ case GL_DEPTH_STENCIL:
+ {
+ if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
+ }
+ if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
+ {
+ ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
+ mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return angle::Result::Continue;
+}
+
+bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType)
+{
+ if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
+ {
+ return false;
+ }
+
+ switch (bufferType)
+ {
+ case GL_COLOR:
+ return partialClearNeedsInit(context, true, false, false);
+ case GL_DEPTH:
+ return partialClearNeedsInit(context, false, true, false);
+ case GL_STENCIL:
+ return partialClearNeedsInit(context, false, false, true);
+ case GL_DEPTH_STENCIL:
+ return partialClearNeedsInit(context, false, true, true);
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+PixelLocalStorage &Framebuffer::getPixelLocalStorage(const Context *context)
+{
+ if (!mPixelLocalStorage)
+ {
+ mPixelLocalStorage = PixelLocalStorage::Make(context);
+ }
+ return *mPixelLocalStorage.get();
+}
+
+std::unique_ptr<PixelLocalStorage> Framebuffer::detachPixelLocalStorage()
+{
+ return std::move(mPixelLocalStorage);
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Framebuffer.h b/gfx/angle/checkout/src/libANGLE/Framebuffer.h
new file mode 100644
index 0000000000..024ad49687
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Framebuffer.h
@@ -0,0 +1,538 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Framebuffer.h: Defines the gl::Framebuffer class. Implements GL framebuffer
+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
+
+#ifndef LIBANGLE_FRAMEBUFFER_H_
+#define LIBANGLE_FRAMEBUFFER_H_
+
+#include <vector>
+
+#include "common/FixedVector.h"
+#include "common/Optional.h"
+#include "common/angleutils.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Observer.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/State.h"
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+class GLImplFactory;
+class FramebufferImpl;
+class RenderbufferImpl;
+class SurfaceImpl;
+} // namespace rx
+
+namespace egl
+{
+class Display;
+class Surface;
+} // namespace egl
+
+namespace gl
+{
+struct Caps;
+class Context;
+struct Extensions;
+class Framebuffer;
+class ImageIndex;
+class PixelLocalStorage;
+class Renderbuffer;
+class TextureCapsMap;
+
+struct FramebufferStatus
+{
+ bool isComplete() const;
+
+ static FramebufferStatus Complete();
+ static FramebufferStatus Incomplete(GLenum status, const char *reason);
+
+ GLenum status = GL_FRAMEBUFFER_COMPLETE;
+ const char *reason = nullptr;
+};
+
+class FramebufferState final : angle::NonCopyable
+{
+ public:
+ explicit FramebufferState(rx::Serial serial);
+ FramebufferState(const Caps &caps, FramebufferID id, rx::Serial serial);
+ ~FramebufferState();
+
+ const std::string &getLabel() const;
+ uint32_t getReadIndex() const;
+
+ const FramebufferAttachment *getAttachment(const Context *context, GLenum attachment) const;
+ const FramebufferAttachment *getReadAttachment() const;
+ const FramebufferAttachment *getFirstNonNullAttachment() const;
+ const FramebufferAttachment *getFirstColorAttachment() const;
+ const FramebufferAttachment *getDepthOrStencilAttachment() const;
+ const FramebufferAttachment *getStencilOrDepthStencilAttachment() const;
+ const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const;
+ const FramebufferAttachment *getDepthAttachment() const;
+ const FramebufferAttachment *getStencilAttachment() const;
+ const FramebufferAttachment *getDepthStencilAttachment() const;
+ const FramebufferAttachment *getReadPixelsAttachment(GLenum readFormat) const;
+
+ const DrawBuffersVector<GLenum> &getDrawBufferStates() const { return mDrawBufferStates; }
+ DrawBufferMask getEnabledDrawBuffers() const { return mEnabledDrawBuffers; }
+ GLenum getReadBufferState() const { return mReadBufferState; }
+
+ const DrawBuffersVector<FramebufferAttachment> &getColorAttachments() const
+ {
+ return mColorAttachments;
+ }
+ const DrawBufferMask getColorAttachmentsMask() const { return mColorAttachmentsMask; }
+
+ const Extents getAttachmentExtentsIntersection() const;
+ bool attachmentsHaveSameDimensions() const;
+ bool hasSeparateDepthAndStencilAttachments() const;
+ bool colorAttachmentsAreUniqueImages() const;
+ Box getDimensions() const;
+ Extents getExtents() const;
+
+ const FramebufferAttachment *getDrawBuffer(size_t drawBufferIdx) const;
+ size_t getDrawBufferCount() const;
+
+ GLint getDefaultWidth() const { return mDefaultWidth; }
+ GLint getDefaultHeight() const { return mDefaultHeight; }
+ GLint getDefaultSamples() const { return mDefaultSamples; }
+ bool getDefaultFixedSampleLocations() const { return mDefaultFixedSampleLocations; }
+ GLint getDefaultLayers() const { return mDefaultLayers; }
+ bool getFlipY() const { return mFlipY; }
+
+ bool hasDepth() const;
+ bool hasStencil() const;
+
+ bool hasExternalTextureAttachment() const;
+ bool hasYUVAttachment() const;
+
+ bool isMultiview() const;
+
+ ANGLE_INLINE GLsizei getNumViews() const
+ {
+ const FramebufferAttachment *attachment = getFirstNonNullAttachment();
+ if (attachment == nullptr)
+ {
+ return FramebufferAttachment::kDefaultNumViews;
+ }
+ return attachment->getNumViews();
+ }
+
+ GLint getBaseViewIndex() const;
+
+ SrgbWriteControlMode getWriteControlMode() const { return mSrgbWriteControlMode; }
+
+ FramebufferID id() const { return mId; }
+
+ bool isDefault() const;
+
+ const Offset &getSurfaceTextureOffset() const { return mSurfaceTextureOffset; }
+
+ rx::Serial getFramebufferSerial() const { return mFramebufferSerial; }
+
+ bool isBoundAsDrawFramebuffer(const Context *context) const;
+
+ private:
+ const FramebufferAttachment *getWebGLDepthStencilAttachment() const;
+ const FramebufferAttachment *getWebGLDepthAttachment() const;
+ const FramebufferAttachment *getWebGLStencilAttachment() const;
+
+ friend class Framebuffer;
+
+ // The Framebuffer ID is unique to a Context.
+ // The Framebuffer Serial is unique to a Share Group.
+ FramebufferID mId;
+ rx::Serial mFramebufferSerial;
+ std::string mLabel;
+
+ DrawBuffersVector<FramebufferAttachment> mColorAttachments;
+ FramebufferAttachment mDepthAttachment;
+ FramebufferAttachment mStencilAttachment;
+
+ // Tracks all the color buffers attached to this FramebufferDesc
+ DrawBufferMask mColorAttachmentsMask;
+
+ DrawBuffersVector<GLenum> mDrawBufferStates;
+ GLenum mReadBufferState;
+ DrawBufferMask mEnabledDrawBuffers;
+ ComponentTypeMask mDrawBufferTypeMask;
+
+ GLint mDefaultWidth;
+ GLint mDefaultHeight;
+ GLint mDefaultSamples;
+ bool mDefaultFixedSampleLocations;
+ GLint mDefaultLayers;
+ bool mFlipY;
+
+ // It's necessary to store all this extra state so we can restore attachments
+ // when DEPTH_STENCIL/DEPTH/STENCIL is unbound in WebGL 1.
+ FramebufferAttachment mWebGLDepthStencilAttachment;
+ FramebufferAttachment mWebGLDepthAttachment;
+ FramebufferAttachment mWebGLStencilAttachment;
+ bool mWebGLDepthStencilConsistent;
+
+ // Tracks if we need to initialize the resources for each attachment.
+ angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 2> mResourceNeedsInit;
+
+ bool mDefaultFramebufferReadAttachmentInitialized;
+ FramebufferAttachment mDefaultFramebufferReadAttachment;
+
+ // EXT_sRGB_write_control
+ SrgbWriteControlMode mSrgbWriteControlMode;
+
+ Offset mSurfaceTextureOffset;
+};
+
+class Framebuffer final : public angle::ObserverInterface,
+ public LabeledObject,
+ public angle::Subject
+{
+ public:
+ // Constructor to build default framebuffers.
+ Framebuffer(const Context *context, rx::GLImplFactory *factory);
+ // Constructor to build application-defined framebuffers
+ Framebuffer(const Context *context, rx::GLImplFactory *factory, FramebufferID id);
+
+ ~Framebuffer() override;
+ void onDestroy(const Context *context);
+
+ egl::Error setSurfaces(const Context *context,
+ egl::Surface *surface,
+ egl::Surface *readSurface);
+ void setReadSurface(const Context *context, egl::Surface *readSurface);
+ egl::Error unsetSurfaces(const Context *context);
+ angle::Result setLabel(const Context *context, const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ rx::FramebufferImpl *getImplementation() const { return mImpl; }
+
+ FramebufferID id() const { return mState.mId; }
+
+ void setAttachment(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource);
+ void setAttachmentMultisample(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei samples);
+ void setAttachmentMultiview(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLint baseViewIndex);
+ void resetAttachment(const Context *context, GLenum binding);
+
+ bool detachTexture(const Context *context, TextureID texture);
+ bool detachRenderbuffer(const Context *context, RenderbufferID renderbuffer);
+
+ const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const;
+ const FramebufferAttachment *getDepthAttachment() const;
+ const FramebufferAttachment *getStencilAttachment() const;
+ const FramebufferAttachment *getDepthStencilAttachment() const;
+ const FramebufferAttachment *getDepthOrStencilAttachment() const;
+ const FramebufferAttachment *getStencilOrDepthStencilAttachment() const;
+ const FramebufferAttachment *getReadColorAttachment() const;
+ GLenum getReadColorAttachmentType() const;
+ const FramebufferAttachment *getFirstColorAttachment() const;
+ const FramebufferAttachment *getFirstNonNullAttachment() const;
+
+ const DrawBuffersVector<FramebufferAttachment> &getColorAttachments() const
+ {
+ return mState.mColorAttachments;
+ }
+
+ const FramebufferState &getState() const { return mState; }
+
+ const FramebufferAttachment *getAttachment(const Context *context, GLenum attachment) const;
+ bool isMultiview() const;
+ bool readDisallowedByMultiview() const;
+ GLsizei getNumViews() const;
+ GLint getBaseViewIndex() const;
+ Extents getExtents() const;
+
+ size_t getDrawbufferStateCount() const;
+ GLenum getDrawBufferState(size_t drawBuffer) const;
+ const DrawBuffersVector<GLenum> &getDrawBufferStates() const;
+ void setDrawBuffers(size_t count, const GLenum *buffers);
+ const FramebufferAttachment *getDrawBuffer(size_t drawBuffer) const;
+ ComponentType getDrawbufferWriteType(size_t drawBuffer) const;
+ ComponentTypeMask getDrawBufferTypeMask() const;
+ DrawBufferMask getDrawBufferMask() const;
+ bool hasEnabledDrawBuffer() const;
+
+ GLenum getReadBufferState() const;
+ void setReadBuffer(GLenum buffer);
+
+ size_t getNumColorAttachments() const;
+ bool hasDepth() const;
+ bool hasStencil() const;
+
+ bool hasExternalTextureAttachment() const;
+ bool hasYUVAttachment() const;
+
+ bool usingExtendedDrawBuffers() const;
+
+ // This method calls checkStatus.
+ int getSamples(const Context *context) const;
+ int getReadBufferResourceSamples(const Context *context) const;
+
+ angle::Result getSamplePosition(const Context *context, size_t index, GLfloat *xy) const;
+
+ GLint getDefaultWidth() const;
+ GLint getDefaultHeight() const;
+ GLint getDefaultSamples() const;
+ bool getDefaultFixedSampleLocations() const;
+ GLint getDefaultLayers() const;
+ bool getFlipY() const;
+ void setDefaultWidth(const Context *context, GLint defaultWidth);
+ void setDefaultHeight(const Context *context, GLint defaultHeight);
+ void setDefaultSamples(const Context *context, GLint defaultSamples);
+ void setDefaultFixedSampleLocations(const Context *context, bool defaultFixedSampleLocations);
+ void setDefaultLayers(GLint defaultLayers);
+ void setFlipY(bool flipY);
+
+ void invalidateCompletenessCache();
+ ANGLE_INLINE bool cachedStatusValid() { return mCachedStatus.valid(); }
+
+ ANGLE_INLINE const FramebufferStatus &checkStatus(const Context *context) const
+ {
+ // The default framebuffer is always complete except when it is surfaceless in which
+ // case it is always unsupported.
+ ASSERT(!isDefault() || mCachedStatus.valid());
+ if (isDefault() || (!hasAnyDirtyBit() && mCachedStatus.valid()))
+ {
+ return mCachedStatus.value();
+ }
+
+ return checkStatusImpl(context);
+ }
+
+ // Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE.
+ ANGLE_INLINE bool isComplete(const Context *context) const
+ {
+ return checkStatus(context).isComplete();
+ }
+
+ bool hasValidDepthStencil() const;
+
+ // Returns the offset into the texture backing the default framebuffer's surface if any. Returns
+ // zero offset otherwise. The renderer will apply the offset to scissor and viewport rects used
+ // for draws, clears, and blits.
+ const Offset &getSurfaceTextureOffset() const;
+
+ angle::Result discard(const Context *context, size_t count, const GLenum *attachments);
+ angle::Result invalidate(const Context *context, size_t count, const GLenum *attachments);
+ angle::Result invalidateSub(const Context *context,
+ size_t count,
+ const GLenum *attachments,
+ const Rectangle &area);
+
+ angle::Result clear(const Context *context, GLbitfield mask);
+ angle::Result clearBufferfv(const Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values);
+ angle::Result clearBufferuiv(const Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values);
+ angle::Result clearBufferiv(const Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values);
+ angle::Result clearBufferfi(const Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil);
+
+ GLenum getImplementationColorReadFormat(const Context *context);
+ GLenum getImplementationColorReadType(const Context *context);
+
+ angle::Result readPixels(const Context *context,
+ const Rectangle &area,
+ GLenum format,
+ GLenum type,
+ const PixelPackState &pack,
+ Buffer *packBuffer,
+ void *pixels);
+
+ angle::Result blit(const Context *context,
+ const Rectangle &sourceArea,
+ const Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter);
+ bool isDefault() const { return mState.isDefault(); }
+
+ enum DirtyBitType : size_t
+ {
+ DIRTY_BIT_COLOR_ATTACHMENT_0,
+ DIRTY_BIT_COLOR_ATTACHMENT_MAX =
+ DIRTY_BIT_COLOR_ATTACHMENT_0 + IMPLEMENTATION_MAX_DRAW_BUFFERS,
+ DIRTY_BIT_DEPTH_ATTACHMENT = DIRTY_BIT_COLOR_ATTACHMENT_MAX,
+ DIRTY_BIT_STENCIL_ATTACHMENT,
+ DIRTY_BIT_COLOR_BUFFER_CONTENTS_0,
+ DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX =
+ DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + IMPLEMENTATION_MAX_DRAW_BUFFERS,
+ DIRTY_BIT_DEPTH_BUFFER_CONTENTS = DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX,
+ DIRTY_BIT_STENCIL_BUFFER_CONTENTS,
+ DIRTY_BIT_DRAW_BUFFERS,
+ DIRTY_BIT_READ_BUFFER,
+ DIRTY_BIT_DEFAULT_WIDTH,
+ DIRTY_BIT_DEFAULT_HEIGHT,
+ DIRTY_BIT_DEFAULT_SAMPLES,
+ DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS,
+ DIRTY_BIT_DEFAULT_LAYERS,
+ DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE,
+ DIRTY_BIT_FLIP_Y,
+ DIRTY_BIT_UNKNOWN,
+ DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN
+ };
+
+ using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
+ bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+
+ DrawBufferMask getActiveFloat32ColorAttachmentDrawBufferMask() const
+ {
+ return mFloat32ColorAttachmentBits & getDrawBufferMask();
+ }
+
+ bool hasResourceThatNeedsInit() const { return mState.mResourceNeedsInit.any(); }
+
+ angle::Result syncState(const Context *context,
+ GLenum framebufferBinding,
+ Command command) const;
+
+ void setWriteControlMode(SrgbWriteControlMode srgbWriteControlMode);
+
+ // Observer implementation
+ void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
+
+ bool formsRenderingFeedbackLoopWith(const Context *context) const;
+ bool formsCopyingFeedbackLoopWith(TextureID copyTextureID,
+ GLint copyTextureLevel,
+ GLint copyTextureLayer) const;
+
+ angle::Result ensureClearAttachmentsInitialized(const Context *context, GLbitfield mask);
+ angle::Result ensureClearBufferAttachmentsInitialized(const Context *context,
+ GLenum buffer,
+ GLint drawbuffer);
+ angle::Result ensureDrawAttachmentsInitialized(const Context *context);
+
+ // Conservatively initializes both read color and depth. Blit can access the depth buffer.
+ angle::Result ensureReadAttachmentsInitialized(const Context *context);
+ Box getDimensions() const;
+
+ // ANGLE_shader_pixel_local_storage.
+ // Lazily creates a PixelLocalStorage object for this Framebuffer.
+ PixelLocalStorage &getPixelLocalStorage(const Context *);
+ // Returns nullptr if the pixel local storage object has not been created yet.
+ const PixelLocalStorage *peekPixelLocalStorage() const { return mPixelLocalStorage.get(); }
+ // Detaches the the pixel local storage object so the Context can call deleteContextObjects().
+ std::unique_ptr<PixelLocalStorage> detachPixelLocalStorage();
+
+ static const FramebufferID kDefaultDrawFramebufferHandle;
+
+ private:
+ bool detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId);
+ bool detachMatchingAttachment(const Context *context,
+ FramebufferAttachment *attachment,
+ GLenum matchType,
+ GLuint matchId);
+ FramebufferStatus checkStatusWithGLFrontEnd(const Context *context) const;
+ const FramebufferStatus &checkStatusImpl(const Context *context) const;
+ void setAttachment(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ bool isMultiview,
+ GLsizei samplesIn);
+ void commitWebGL1DepthStencilIfConsistent(const Context *context,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ bool isMultiview,
+ GLsizei samples);
+ void setAttachmentImpl(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ bool isMultiview,
+ GLsizei samples);
+ void updateAttachment(const Context *context,
+ FramebufferAttachment *attachment,
+ size_t dirtyBit,
+ angle::ObserverBinding *onDirtyBinding,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ bool isMultiview,
+ GLsizei samples);
+
+ void markDrawAttachmentsInitialized(bool color, bool depth, bool stencil);
+ void markBufferInitialized(GLenum bufferType, GLint bufferIndex);
+ angle::Result ensureBufferInitialized(const Context *context,
+ GLenum bufferType,
+ GLint bufferIndex);
+
+ // Checks that we have a partially masked clear:
+ // * some color channels are masked out
+ // * some stencil values are masked out
+ // * scissor test partially overlaps the framebuffer
+ bool partialClearNeedsInit(const Context *context, bool color, bool depth, bool stencil);
+ bool partialBufferClearNeedsInit(const Context *context, GLenum bufferType);
+
+ FramebufferAttachment *getAttachmentFromSubjectIndex(angle::SubjectIndex index);
+
+ ANGLE_INLINE void updateFloat32ColorAttachmentBits(size_t index, const InternalFormat *format)
+ {
+ mFloat32ColorAttachmentBits.set(index, format->type == GL_FLOAT);
+ }
+
+ FramebufferState mState;
+ rx::FramebufferImpl *mImpl;
+
+ mutable Optional<FramebufferStatus> mCachedStatus;
+ DrawBuffersVector<angle::ObserverBinding> mDirtyColorAttachmentBindings;
+ angle::ObserverBinding mDirtyDepthAttachmentBinding;
+ angle::ObserverBinding mDirtyStencilAttachmentBinding;
+
+ mutable DirtyBits mDirtyBits;
+ DrawBufferMask mFloat32ColorAttachmentBits;
+
+ // The dirty bits guard is checked when we get a dependent state change message. We verify that
+ // we don't set a dirty bit that isn't already set, when inside the dirty bits syncState.
+ mutable Optional<DirtyBits> mDirtyBitsGuard;
+
+ // ANGLE_shader_pixel_local_storage
+ std::unique_ptr<PixelLocalStorage> mPixelLocalStorage;
+};
+
+using UniqueFramebufferPointer = angle::UniqueObjectPointer<Framebuffer, Context>;
+
+} // namespace gl
+
+#endif // LIBANGLE_FRAMEBUFFER_H_
diff --git a/gfx/angle/checkout/src/libANGLE/FramebufferAttachment.cpp b/gfx/angle/checkout/src/libANGLE/FramebufferAttachment.cpp
new file mode 100644
index 0000000000..6a3e88051f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/FramebufferAttachment.cpp
@@ -0,0 +1,350 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FramebufferAttachment.cpp: the gl::FramebufferAttachment class and its derived classes
+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
+
+#include "libANGLE/FramebufferAttachment.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
+#include "libANGLE/renderer/FramebufferImpl.h"
+
+namespace gl
+{
+
+////// FramebufferAttachment::Target Implementation //////
+
+const GLsizei FramebufferAttachment::kDefaultNumViews = 1;
+const GLint FramebufferAttachment::kDefaultBaseViewIndex = 0;
+const GLint FramebufferAttachment::kDefaultRenderToTextureSamples = 0;
+
+FramebufferAttachment::Target::Target() : mBinding(GL_NONE), mTextureIndex() {}
+
+FramebufferAttachment::Target::Target(GLenum binding, const ImageIndex &imageIndex)
+ : mBinding(binding), mTextureIndex(imageIndex)
+{}
+
+FramebufferAttachment::Target::Target(const Target &other)
+ : mBinding(other.mBinding), mTextureIndex(other.mTextureIndex)
+{}
+
+FramebufferAttachment::Target &FramebufferAttachment::Target::operator=(const Target &other)
+{
+ this->mBinding = other.mBinding;
+ this->mTextureIndex = other.mTextureIndex;
+ return *this;
+}
+
+////// FramebufferAttachment Implementation //////
+
+FramebufferAttachment::FramebufferAttachment()
+ : mType(GL_NONE),
+ mResource(nullptr),
+ mNumViews(kDefaultNumViews),
+ mIsMultiview(false),
+ mBaseViewIndex(kDefaultBaseViewIndex),
+ mRenderToTextureSamples(kDefaultRenderToTextureSamples)
+{}
+
+FramebufferAttachment::FramebufferAttachment(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ rx::Serial framebufferSerial)
+ : mResource(nullptr)
+{
+ attach(context, type, binding, textureIndex, resource, kDefaultNumViews, kDefaultBaseViewIndex,
+ false, kDefaultRenderToTextureSamples, framebufferSerial);
+}
+
+FramebufferAttachment::FramebufferAttachment(FramebufferAttachment &&other)
+ : FramebufferAttachment()
+{
+ *this = std::move(other);
+}
+
+FramebufferAttachment &FramebufferAttachment::operator=(FramebufferAttachment &&other)
+{
+ std::swap(mType, other.mType);
+ std::swap(mTarget, other.mTarget);
+ std::swap(mResource, other.mResource);
+ std::swap(mNumViews, other.mNumViews);
+ std::swap(mIsMultiview, other.mIsMultiview);
+ std::swap(mBaseViewIndex, other.mBaseViewIndex);
+ std::swap(mRenderToTextureSamples, other.mRenderToTextureSamples);
+ return *this;
+}
+
+FramebufferAttachment::~FramebufferAttachment()
+{
+ ASSERT(!isAttached());
+}
+
+void FramebufferAttachment::detach(const Context *context, rx::Serial framebufferSerial)
+{
+ mType = GL_NONE;
+ if (mResource != nullptr)
+ {
+ mResource->onDetach(context, framebufferSerial);
+ mResource = nullptr;
+ }
+ mNumViews = kDefaultNumViews;
+ mIsMultiview = false;
+ mBaseViewIndex = kDefaultBaseViewIndex;
+
+ // not technically necessary, could omit for performance
+ mTarget = Target();
+}
+
+void FramebufferAttachment::attach(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ bool isMultiview,
+ GLsizei samples,
+ rx::Serial framebufferSerial)
+{
+ if (resource == nullptr)
+ {
+ detach(context, framebufferSerial);
+ return;
+ }
+
+ mType = type;
+ mTarget = Target(binding, textureIndex);
+ mNumViews = numViews;
+ mBaseViewIndex = baseViewIndex;
+ mIsMultiview = isMultiview;
+ mRenderToTextureSamples = type == GL_RENDERBUFFER ? kDefaultRenderToTextureSamples : samples;
+ resource->onAttach(context, framebufferSerial);
+
+ if (mResource != nullptr)
+ {
+ mResource->onDetach(context, framebufferSerial);
+ }
+
+ mResource = resource;
+}
+
+GLuint FramebufferAttachment::getRedSize() const
+{
+ return getSize().empty() ? 0 : getFormat().info->redBits;
+}
+
+GLuint FramebufferAttachment::getGreenSize() const
+{
+ return getSize().empty() ? 0 : getFormat().info->greenBits;
+}
+
+GLuint FramebufferAttachment::getBlueSize() const
+{
+ return getSize().empty() ? 0 : getFormat().info->blueBits;
+}
+
+GLuint FramebufferAttachment::getAlphaSize() const
+{
+ return getSize().empty() ? 0 : getFormat().info->alphaBits;
+}
+
+GLuint FramebufferAttachment::getDepthSize() const
+{
+ return getSize().empty() ? 0 : getFormat().info->depthBits;
+}
+
+GLuint FramebufferAttachment::getStencilSize() const
+{
+ return getSize().empty() ? 0 : getFormat().info->stencilBits;
+}
+
+GLenum FramebufferAttachment::getComponentType() const
+{
+ return getFormat().info->componentType;
+}
+
+GLenum FramebufferAttachment::getColorEncoding() const
+{
+ return getFormat().info->colorEncoding;
+}
+
+GLuint FramebufferAttachment::id() const
+{
+ return mResource->getId();
+}
+
+TextureTarget FramebufferAttachment::cubeMapFace() const
+{
+ ASSERT(mType == GL_TEXTURE);
+
+ const auto &index = mTarget.textureIndex();
+ return index.getType() == TextureType::CubeMap ? index.getTarget() : TextureTarget::InvalidEnum;
+}
+
+GLint FramebufferAttachment::mipLevel() const
+{
+ ASSERT(type() == GL_TEXTURE);
+ return mTarget.textureIndex().getLevelIndex();
+}
+
+GLint FramebufferAttachment::layer() const
+{
+ ASSERT(mType == GL_TEXTURE);
+
+ const gl::ImageIndex &index = mTarget.textureIndex();
+ return (index.has3DLayer() ? index.getLayerIndex() : 0);
+}
+
+bool FramebufferAttachment::isLayered() const
+{
+ return mTarget.textureIndex().isLayered();
+}
+
+bool FramebufferAttachment::isMultiview() const
+{
+ return mIsMultiview;
+}
+
+GLint FramebufferAttachment::getBaseViewIndex() const
+{
+ return mBaseViewIndex;
+}
+
+bool FramebufferAttachment::isRenderToTexture() const
+{
+ ASSERT(mRenderToTextureSamples == kDefaultRenderToTextureSamples || mType == GL_TEXTURE);
+
+ if (mType == GL_RENDERBUFFER)
+ {
+ return getRenderbuffer()->getMultisamplingMode() ==
+ MultisamplingMode::MultisampledRenderToTexture;
+ }
+ return mRenderToTextureSamples != kDefaultRenderToTextureSamples;
+}
+
+GLsizei FramebufferAttachment::getRenderToTextureSamples() const
+{
+ ASSERT(mRenderToTextureSamples == kDefaultRenderToTextureSamples || mType == GL_TEXTURE);
+
+ if (mType == GL_RENDERBUFFER)
+ {
+ return getRenderbuffer()->getState().getSamples();
+ }
+ return mRenderToTextureSamples;
+}
+
+Texture *FramebufferAttachment::getTexture() const
+{
+ return rx::GetAs<Texture>(mResource);
+}
+
+Renderbuffer *FramebufferAttachment::getRenderbuffer() const
+{
+ return rx::GetAs<Renderbuffer>(mResource);
+}
+
+const egl::Surface *FramebufferAttachment::getSurface() const
+{
+ return rx::GetAs<egl::Surface>(mResource);
+}
+
+FramebufferAttachmentObject *FramebufferAttachment::getResource() const
+{
+ return mResource;
+}
+
+bool FramebufferAttachment::operator==(const FramebufferAttachment &other) const
+{
+ if (mResource != other.mResource || mType != other.mType || mNumViews != other.mNumViews ||
+ mIsMultiview != other.mIsMultiview || mBaseViewIndex != other.mBaseViewIndex ||
+ mRenderToTextureSamples != other.mRenderToTextureSamples)
+ {
+ return false;
+ }
+
+ if (mType == GL_TEXTURE && getTextureImageIndex() != other.getTextureImageIndex())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool FramebufferAttachment::operator!=(const FramebufferAttachment &other) const
+{
+ return !(*this == other);
+}
+
+InitState FramebufferAttachment::initState() const
+{
+ return mResource ? mResource->initState(mTarget.binding(), mTarget.textureIndex())
+ : InitState::Initialized;
+}
+
+angle::Result FramebufferAttachment::initializeContents(const Context *context)
+{
+ ASSERT(mResource);
+ ANGLE_TRY(mResource->initializeContents(context, mTarget.binding(), mTarget.textureIndex()));
+ setInitState(InitState::Initialized);
+ return angle::Result::Continue;
+}
+
+void FramebufferAttachment::setInitState(InitState initState) const
+{
+ ASSERT(mResource);
+ mResource->setInitState(mTarget.binding(), mTarget.textureIndex(), initState);
+}
+
+////// FramebufferAttachmentObject Implementation //////
+
+FramebufferAttachmentObject::FramebufferAttachmentObject() {}
+
+FramebufferAttachmentObject::~FramebufferAttachmentObject() {}
+
+angle::Result FramebufferAttachmentObject::getAttachmentRenderTarget(
+ const Context *context,
+ GLenum binding,
+ const ImageIndex &imageIndex,
+ GLsizei samples,
+ rx::FramebufferAttachmentRenderTarget **rtOut) const
+{
+ return getAttachmentImpl()->getAttachmentRenderTarget(context, binding, imageIndex, samples,
+ rtOut);
+}
+
+angle::Result FramebufferAttachmentObject::initializeContents(const Context *context,
+ GLenum binding,
+ const ImageIndex &imageIndex)
+{
+ ASSERT(context->isRobustResourceInitEnabled());
+
+ // Because gl::Texture cannot support tracking individual layer dirtiness, we only handle
+ // initializing entire mip levels for textures with layers
+ if (imageIndex.usesTex3D() && imageIndex.hasLayer())
+ {
+ // Compute the layer count so we get a correct layer index.
+ const gl::Extents &size = getAttachmentSize(imageIndex);
+
+ ImageIndex fullMipIndex = ImageIndex::MakeFromType(
+ imageIndex.getType(), imageIndex.getLevelIndex(), ImageIndex::kEntireLevel, size.depth);
+ return getAttachmentImpl()->initializeContents(context, binding, fullMipIndex);
+ }
+ else
+ {
+ return getAttachmentImpl()->initializeContents(context, binding, imageIndex);
+ }
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/FramebufferAttachment.h b/gfx/angle/checkout/src/libANGLE/FramebufferAttachment.h
new file mode 100644
index 0000000000..8b4f04ae0b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/FramebufferAttachment.h
@@ -0,0 +1,307 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FramebufferAttachment.h: Defines the wrapper class gl::FramebufferAttachment, as well as the
+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
+
+#ifndef LIBANGLE_FRAMEBUFFERATTACHMENT_H_
+#define LIBANGLE_FRAMEBUFFERATTACHMENT_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/Observer.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
+
+namespace egl
+{
+class Surface;
+}
+
+namespace rx
+{
+// An implementation-specific object associated with an attachment.
+
+class FramebufferAttachmentRenderTarget : angle::NonCopyable
+{
+ public:
+ FramebufferAttachmentRenderTarget() {}
+ virtual ~FramebufferAttachmentRenderTarget() {}
+};
+
+class FramebufferAttachmentObjectImpl;
+} // namespace rx
+
+namespace gl
+{
+class FramebufferAttachmentObject;
+class Renderbuffer;
+class Texture;
+
+// FramebufferAttachment implements a GL framebuffer attachment.
+// Attachments are "light" containers, which store pointers to ref-counted GL objects.
+// We support GL texture (2D/3D/Cube/2D array) and renderbuffer object attachments.
+// Note: Our old naming scheme used the term "Renderbuffer" for both GL renderbuffers and for
+// framebuffer attachments, which confused their usage.
+
+class FramebufferAttachment final
+{
+ public:
+ FramebufferAttachment();
+
+ FramebufferAttachment(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ rx::Serial framebufferSerial);
+
+ FramebufferAttachment(FramebufferAttachment &&other);
+ FramebufferAttachment &operator=(FramebufferAttachment &&other);
+
+ ~FramebufferAttachment();
+
+ void detach(const Context *context, rx::Serial framebufferSerial);
+ void attach(const Context *context,
+ GLenum type,
+ GLenum binding,
+ const ImageIndex &textureIndex,
+ FramebufferAttachmentObject *resource,
+ GLsizei numViews,
+ GLuint baseViewIndex,
+ bool isMultiview,
+ GLsizei samples,
+ rx::Serial framebufferSerial);
+
+ // Helper methods
+ GLuint getRedSize() const;
+ GLuint getGreenSize() const;
+ GLuint getBlueSize() const;
+ GLuint getAlphaSize() const;
+ GLuint getDepthSize() const;
+ GLuint getStencilSize() const;
+ GLenum getComponentType() const;
+ GLenum getColorEncoding() const;
+
+ bool isTextureWithId(TextureID textureId) const
+ {
+ return mType == GL_TEXTURE && id() == textureId.value;
+ }
+ bool isExternalTexture() const
+ {
+ return mType == GL_TEXTURE && getTextureImageIndex().getType() == gl::TextureType::External;
+ }
+ bool isRenderbufferWithId(GLuint renderbufferId) const
+ {
+ return mType == GL_RENDERBUFFER && id() == renderbufferId;
+ }
+
+ GLenum getBinding() const { return mTarget.binding(); }
+ GLuint id() const;
+
+ // These methods are only legal to call on Texture attachments
+ const ImageIndex &getTextureImageIndex() const;
+ TextureTarget cubeMapFace() const;
+ GLint mipLevel() const;
+ GLint layer() const;
+ bool isLayered() const;
+
+ GLsizei getNumViews() const { return mNumViews; }
+
+ bool isMultiview() const;
+ GLint getBaseViewIndex() const;
+
+ bool isRenderToTexture() const;
+ GLsizei getRenderToTextureSamples() const;
+
+ // The size of the underlying resource the attachment points to. The 'depth' value will
+ // correspond to a 3D texture depth or the layer count of a 2D array texture. For Surfaces and
+ // Renderbuffers, it will always be 1.
+ Extents getSize() const;
+ Format getFormat() const;
+ GLsizei getSamples() const;
+ // This will always return the actual sample count of the attachment even if
+ // render_to_texture extension is active on this FBattachment object.
+ GLsizei getResourceSamples() const;
+ GLenum type() const { return mType; }
+ bool isAttached() const { return mType != GL_NONE; }
+ bool isRenderable(const Context *context) const;
+ bool isYUV() const;
+ bool isCreatedWithAHB() const;
+
+ Renderbuffer *getRenderbuffer() const;
+ Texture *getTexture() const;
+ const egl::Surface *getSurface() const;
+ FramebufferAttachmentObject *getResource() const;
+ InitState initState() const;
+ angle::Result initializeContents(const Context *context);
+ void setInitState(InitState initState) const;
+
+ // "T" must be static_castable from FramebufferAttachmentRenderTarget
+ template <typename T>
+ angle::Result getRenderTarget(const Context *context, GLsizei samples, T **rtOut) const
+ {
+ static_assert(std::is_base_of<rx::FramebufferAttachmentRenderTarget, T>(),
+ "Invalid RenderTarget class.");
+ return getRenderTargetImpl(
+ context, samples, reinterpret_cast<rx::FramebufferAttachmentRenderTarget **>(rtOut));
+ }
+
+ bool operator==(const FramebufferAttachment &other) const;
+ bool operator!=(const FramebufferAttachment &other) const;
+
+ static const GLsizei kDefaultNumViews;
+ static const GLint kDefaultBaseViewIndex;
+ static const GLint kDefaultRenderToTextureSamples;
+
+ private:
+ angle::Result getRenderTargetImpl(const Context *context,
+ GLsizei samples,
+ rx::FramebufferAttachmentRenderTarget **rtOut) const;
+
+ // A framebuffer attachment points to one of three types of resources: Renderbuffers,
+ // Textures and egl::Surface. The "Target" struct indicates which part of the
+ // object an attachment references. For the three types:
+ // - a Renderbuffer has a unique renderable target, and needs no target index
+ // - a Texture has targets for every image and uses an ImageIndex
+ // - a Surface has targets for Color and Depth/Stencil, and uses the attachment binding
+ class Target
+ {
+ public:
+ Target();
+ Target(GLenum binding, const ImageIndex &imageIndex);
+ Target(const Target &other);
+ Target &operator=(const Target &other);
+
+ GLenum binding() const { return mBinding; }
+ const ImageIndex &textureIndex() const { return mTextureIndex; }
+
+ private:
+ GLenum mBinding;
+ ImageIndex mTextureIndex;
+ };
+
+ GLenum mType;
+ Target mTarget;
+ FramebufferAttachmentObject *mResource;
+ GLsizei mNumViews;
+ bool mIsMultiview;
+ GLint mBaseViewIndex;
+ // A single-sampled texture can be attached to a framebuffer either as single-sampled or as
+ // multisampled-render-to-texture. In the latter case, |mRenderToTextureSamples| will contain
+ // the number of samples. For renderbuffers, the number of samples is inherited from the
+ // renderbuffer itself.
+ //
+ // Note that textures cannot change storage between single and multisample once attached to a
+ // framebuffer. Renderbuffers instead can, and caching the number of renderbuffer samples here
+ // can lead to stale data.
+ GLsizei mRenderToTextureSamples;
+};
+
+// A base class for objects that FBO Attachments may point to.
+class FramebufferAttachmentObject : public angle::Subject, public angle::ObserverInterface
+{
+ public:
+ FramebufferAttachmentObject();
+ ~FramebufferAttachmentObject() override;
+
+ virtual Extents getAttachmentSize(const ImageIndex &imageIndex) const = 0;
+ virtual Format getAttachmentFormat(GLenum binding, const ImageIndex &imageIndex) const = 0;
+ virtual GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const = 0;
+ virtual bool isRenderable(const Context *context,
+ GLenum binding,
+ const ImageIndex &imageIndex) const = 0;
+ virtual bool isYUV() const = 0;
+ virtual bool isCreatedWithAHB() const = 0;
+ virtual bool hasProtectedContent() const = 0;
+
+ virtual void onAttach(const Context *context, rx::Serial framebufferSerial) = 0;
+ virtual void onDetach(const Context *context, rx::Serial framebufferSerial) = 0;
+ virtual GLuint getId() const = 0;
+
+ // These are used for robust resource initialization.
+ virtual InitState initState(GLenum binding, const ImageIndex &imageIndex) const = 0;
+ virtual void setInitState(GLenum binding,
+ const ImageIndex &imageIndex,
+ InitState initState) = 0;
+
+ angle::Result getAttachmentRenderTarget(const Context *context,
+ GLenum binding,
+ const ImageIndex &imageIndex,
+ GLsizei samples,
+ rx::FramebufferAttachmentRenderTarget **rtOut) const;
+
+ angle::Result initializeContents(const Context *context,
+ GLenum binding,
+ const ImageIndex &imageIndex);
+
+ protected:
+ virtual rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const = 0;
+};
+
+inline const ImageIndex &FramebufferAttachment::getTextureImageIndex() const
+{
+ ASSERT(type() == GL_TEXTURE);
+ return mTarget.textureIndex();
+}
+
+inline Extents FramebufferAttachment::getSize() const
+{
+ ASSERT(mResource);
+ return mResource->getAttachmentSize(mTarget.textureIndex());
+}
+
+inline Format FramebufferAttachment::getFormat() const
+{
+ ASSERT(mResource);
+ return mResource->getAttachmentFormat(mTarget.binding(), mTarget.textureIndex());
+}
+
+inline GLsizei FramebufferAttachment::getSamples() const
+{
+ return isRenderToTexture() ? getRenderToTextureSamples() : getResourceSamples();
+}
+
+inline GLsizei FramebufferAttachment::getResourceSamples() const
+{
+ ASSERT(mResource);
+ return mResource->getAttachmentSamples(mTarget.textureIndex());
+}
+
+inline angle::Result FramebufferAttachment::getRenderTargetImpl(
+ const Context *context,
+ GLsizei samples,
+ rx::FramebufferAttachmentRenderTarget **rtOut) const
+{
+ ASSERT(mResource);
+ return mResource->getAttachmentRenderTarget(context, mTarget.binding(), mTarget.textureIndex(),
+ samples, rtOut);
+}
+
+inline bool FramebufferAttachment::isRenderable(const Context *context) const
+{
+ ASSERT(mResource);
+ return mResource->isRenderable(context, mTarget.binding(), mTarget.textureIndex());
+}
+
+inline bool FramebufferAttachment::isYUV() const
+{
+ ASSERT(mResource);
+ return mResource->isYUV();
+}
+
+inline bool FramebufferAttachment::isCreatedWithAHB() const
+{
+ ASSERT(mResource);
+ return mResource->isCreatedWithAHB();
+}
+
+} // namespace gl
+
+#endif // LIBANGLE_FRAMEBUFFERATTACHMENT_H_
diff --git a/gfx/angle/checkout/src/libANGLE/GLES1Renderer.cpp b/gfx/angle/checkout/src/libANGLE/GLES1Renderer.cpp
new file mode 100644
index 0000000000..4ca3d47189
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/GLES1Renderer.cpp
@@ -0,0 +1,1197 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// GLES1Renderer.cpp: Implements the GLES1Renderer renderer.
+
+#include "libANGLE/GLES1Renderer.h"
+
+#include <string.h>
+#include <iterator>
+#include <sstream>
+#include <vector>
+
+#include "common/hash_utils.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Context.inl.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/State.h"
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace
+{
+#include "libANGLE/GLES1Shaders.inc"
+
+uint32_t GetLogicOpUniform(const gl::FramebufferAttachment *color, gl::LogicalOperation logicOp)
+{
+ const uint32_t red = color->getRedSize();
+ const uint32_t green = color->getGreenSize();
+ const uint32_t blue = color->getBlueSize();
+ const uint32_t alpha = color->getAlphaSize();
+
+ ASSERT(red <= 8 && green <= 8 && blue <= 8 && alpha <= 8);
+
+ return red | green << 4 | blue << 8 | alpha << 12 | static_cast<uint32_t>(logicOp) << 16;
+}
+} // anonymous namespace
+
+namespace gl
+{
+GLES1ShaderState::GLES1ShaderState() = default;
+GLES1ShaderState::~GLES1ShaderState() = default;
+GLES1ShaderState::GLES1ShaderState(const GLES1ShaderState &other)
+{
+ memcpy(this, &other, sizeof(GLES1ShaderState));
+}
+
+bool operator==(const GLES1ShaderState &a, const GLES1ShaderState &b)
+{
+ return memcmp(&a, &b, sizeof(GLES1ShaderState)) == 0;
+}
+bool operator!=(const GLES1ShaderState &a, const GLES1ShaderState &b)
+{
+ return !(a == b);
+}
+
+size_t GLES1ShaderState::hash() const
+{
+ return angle::ComputeGenericHash(*this);
+}
+
+GLES1Renderer::GLES1Renderer() : mRendererProgramInitialized(false) {}
+
+void GLES1Renderer::onDestroy(Context *context, State *state)
+{
+ if (mRendererProgramInitialized)
+ {
+ (void)state->setProgram(context, 0);
+
+ for (const auto &iter : mUberShaderState)
+ {
+ const GLES1UberShaderState &UberShaderState = iter.second;
+ mShaderPrograms->deleteProgram(context, {UberShaderState.programState.program});
+ }
+ mShaderPrograms->release(context);
+ mShaderPrograms = nullptr;
+ mRendererProgramInitialized = false;
+ }
+}
+
+GLES1Renderer::~GLES1Renderer() = default;
+
+angle::Result GLES1Renderer::prepareForDraw(PrimitiveMode mode, Context *context, State *glState)
+{
+ GLES1State &gles1State = glState->gles1();
+
+ GLES1ShaderState::BoolTexArray &tex2DEnables = mShaderState.tex2DEnables;
+ GLES1ShaderState::BoolTexArray &texCubeEnables = mShaderState.texCubeEnables;
+ GLES1ShaderState::IntTexArray &tex2DFormats = mShaderState.tex2DFormats;
+
+ for (int i = 0; i < kTexUnitCount; i++)
+ {
+ // GL_OES_cube_map allows only one of TEXTURE_2D / TEXTURE_CUBE_MAP
+ // to be enabled per unit, thankfully. From the extension text:
+ //
+ // -- Section 3.8.10 "Texture Application"
+ //
+ // Replace the beginning sentences of the first paragraph (page 138)
+ // with:
+ //
+ // "Texturing is enabled or disabled using the generic Enable
+ // and Disable commands, respectively, with the symbolic constants
+ // TEXTURE_2D or TEXTURE_CUBE_MAP_OES to enable the two-dimensional or cube
+ // map texturing respectively. If the cube map texture and the two-
+ // dimensional texture are enabled, then cube map texturing is used. If
+ // texturing is disabled, a rasterized fragment is passed on unaltered to the
+ // next stage of the GL (although its texture coordinates may be discarded).
+ // Otherwise, a texture value is found according to the parameter values of
+ // the currently bound texture image of the appropriate dimensionality.
+
+ texCubeEnables[i] = gles1State.isTextureTargetEnabled(i, TextureType::CubeMap);
+ tex2DEnables[i] =
+ !texCubeEnables[i] && gles1State.isTextureTargetEnabled(i, TextureType::_2D);
+
+ Texture *curr2DTexture = glState->getSamplerTexture(i, TextureType::_2D);
+ if (curr2DTexture)
+ {
+ tex2DFormats[i] = gl::GetUnsizedFormat(
+ curr2DTexture->getFormat(TextureTarget::_2D, 0).info->internalFormat);
+ }
+
+ Texture *currCubeTexture = glState->getSamplerTexture(i, TextureType::CubeMap);
+
+ // > If texturing is enabled for a texture unit at the time a primitive is rasterized, if
+ // > TEXTURE MIN FILTER is one that requires a mipmap, and if the texture image bound to the
+ // > enabled texture target is not complete, then it is as if texture mapping were disabled
+ // > for that texture unit.
+ if (tex2DEnables[i] && curr2DTexture && IsMipmapFiltered(curr2DTexture->getMinFilter()))
+ {
+ tex2DEnables[i] = curr2DTexture->isMipmapComplete();
+ }
+ if (texCubeEnables[i] && currCubeTexture &&
+ IsMipmapFiltered(currCubeTexture->getMinFilter()))
+ {
+ texCubeEnables[i] = curr2DTexture->isMipmapComplete();
+ }
+ }
+
+ GLES1ShaderState::IntTexArray &texEnvModes = mShaderState.texEnvModes;
+ GLES1ShaderState::IntTexArray &texCombineRgbs = mShaderState.texCombineRgbs;
+ GLES1ShaderState::IntTexArray &texCombineAlphas = mShaderState.texCombineAlphas;
+ GLES1ShaderState::IntTexArray &texCombineSrc0Rgbs = mShaderState.texCombineSrc0Rgbs;
+ GLES1ShaderState::IntTexArray &texCombineSrc0Alphas = mShaderState.texCombineSrc0Alphas;
+ GLES1ShaderState::IntTexArray &texCombineSrc1Rgbs = mShaderState.texCombineSrc1Rgbs;
+ GLES1ShaderState::IntTexArray &texCombineSrc1Alphas = mShaderState.texCombineSrc1Alphas;
+ GLES1ShaderState::IntTexArray &texCombineSrc2Rgbs = mShaderState.texCombineSrc2Rgbs;
+ GLES1ShaderState::IntTexArray &texCombineSrc2Alphas = mShaderState.texCombineSrc2Alphas;
+ GLES1ShaderState::IntTexArray &texCombineOp0Rgbs = mShaderState.texCombineOp0Rgbs;
+ GLES1ShaderState::IntTexArray &texCombineOp0Alphas = mShaderState.texCombineOp0Alphas;
+ GLES1ShaderState::IntTexArray &texCombineOp1Rgbs = mShaderState.texCombineOp1Rgbs;
+ GLES1ShaderState::IntTexArray &texCombineOp1Alphas = mShaderState.texCombineOp1Alphas;
+ GLES1ShaderState::IntTexArray &texCombineOp2Rgbs = mShaderState.texCombineOp2Rgbs;
+ GLES1ShaderState::IntTexArray &texCombineOp2Alphas = mShaderState.texCombineOp2Alphas;
+
+ if (gles1State.isDirty(GLES1State::DIRTY_GLES1_TEXTURE_ENVIRONMENT))
+ {
+ for (int i = 0; i < kTexUnitCount; i++)
+ {
+ const auto &env = gles1State.textureEnvironment(i);
+ texEnvModes[i] = ToGLenum(env.mode);
+ texCombineRgbs[i] = ToGLenum(env.combineRgb);
+ texCombineAlphas[i] = ToGLenum(env.combineAlpha);
+ texCombineSrc0Rgbs[i] = ToGLenum(env.src0Rgb);
+ texCombineSrc0Alphas[i] = ToGLenum(env.src0Alpha);
+ texCombineSrc1Rgbs[i] = ToGLenum(env.src1Rgb);
+ texCombineSrc1Alphas[i] = ToGLenum(env.src1Alpha);
+ texCombineSrc2Rgbs[i] = ToGLenum(env.src2Rgb);
+ texCombineSrc2Alphas[i] = ToGLenum(env.src2Alpha);
+ texCombineOp0Rgbs[i] = ToGLenum(env.op0Rgb);
+ texCombineOp0Alphas[i] = ToGLenum(env.op0Alpha);
+ texCombineOp1Rgbs[i] = ToGLenum(env.op1Rgb);
+ texCombineOp1Alphas[i] = ToGLenum(env.op1Alpha);
+ texCombineOp2Rgbs[i] = ToGLenum(env.op2Rgb);
+ texCombineOp2Alphas[i] = ToGLenum(env.op2Alpha);
+ }
+ }
+
+ bool enableClipPlanes = false;
+ GLES1ShaderState::BoolClipPlaneArray &clipPlaneEnables = mShaderState.clipPlaneEnables;
+ for (int i = 0; i < kClipPlaneCount; i++)
+ {
+ clipPlaneEnables[i] = glState->getEnableFeature(GL_CLIP_PLANE0 + i);
+ enableClipPlanes = enableClipPlanes || clipPlaneEnables[i];
+ }
+
+ mShaderState.mGLES1StateEnabled[GLES1StateEnables::ClipPlanes] = enableClipPlanes;
+ mShaderState.mGLES1StateEnabled[GLES1StateEnables::DrawTexture] = mDrawTextureEnabled;
+ mShaderState.mGLES1StateEnabled[GLES1StateEnables::PointRasterization] =
+ mode == PrimitiveMode::Points;
+ mShaderState.mGLES1StateEnabled[GLES1StateEnables::ShadeModelFlat] =
+ gles1State.mShadeModel == ShadingModel::Flat;
+ mShaderState.mGLES1StateEnabled[GLES1StateEnables::AlphaTest] =
+ glState->getEnableFeature(GL_ALPHA_TEST);
+ mShaderState.mGLES1StateEnabled[GLES1StateEnables::Lighting] =
+ glState->getEnableFeature(GL_LIGHTING);
+ mShaderState.mGLES1StateEnabled[GLES1StateEnables::RescaleNormal] =
+ glState->getEnableFeature(GL_RESCALE_NORMAL);
+ mShaderState.mGLES1StateEnabled[GLES1StateEnables::Normalize] =
+ glState->getEnableFeature(GL_NORMALIZE);
+ mShaderState.mGLES1StateEnabled[GLES1StateEnables::Fog] = glState->getEnableFeature(GL_FOG);
+ mShaderState.mGLES1StateEnabled[GLES1StateEnables::PointSprite] =
+ glState->getEnableFeature(GL_POINT_SPRITE_OES);
+ mShaderState.mGLES1StateEnabled[GLES1StateEnables::ColorMaterial] =
+ glState->getEnableFeature(GL_COLOR_MATERIAL);
+
+ // TODO (lfy@google.com): Implement two-sided lighting model (lightModel.twoSided)
+ mShaderState.mGLES1StateEnabled[GLES1StateEnables::LightModelTwoSided] = false;
+
+ GLES1ShaderState::BoolTexArray &pointSpriteCoordReplaces =
+ mShaderState.pointSpriteCoordReplaces;
+ for (int i = 0; i < kTexUnitCount; i++)
+ {
+ const auto &env = gles1State.textureEnvironment(i);
+ pointSpriteCoordReplaces[i] = env.pointSpriteCoordReplace;
+ }
+
+ GLES1ShaderState::BoolLightArray &lightEnables = mShaderState.lightEnables;
+ for (int i = 0; i < kLightCount; i++)
+ {
+ const auto &light = gles1State.mLights[i];
+ lightEnables[i] = light.enabled;
+ }
+
+ mShaderState.alphaTestFunc = gles1State.mAlphaTestFunc;
+ mShaderState.fogMode = gles1State.fogParameters().mode;
+
+ const bool hasLogicOpANGLE = context->getExtensions().logicOpANGLE;
+ const bool hasFramebufferFetch = context->getExtensions().shaderFramebufferFetchEXT ||
+ context->getExtensions().shaderFramebufferFetchNonCoherentEXT;
+
+ if (!hasLogicOpANGLE && hasFramebufferFetch)
+ {
+ mShaderState.mGLES1StateEnabled[GLES1StateEnables::LogicOpThroughFramebufferFetch] =
+ gles1State.mLogicOpEnabled;
+ }
+
+ // All the states set before this spot affect ubershader creation
+
+ ANGLE_TRY(initializeRendererProgram(context, glState));
+
+ GLES1UberShaderState UberShaderState = getUberShaderState();
+
+ const GLES1ProgramState &programState = UberShaderState.programState;
+ GLES1UniformBuffers &uniformBuffers = UberShaderState.uniformBuffers;
+
+ Program *programObject = getProgram(programState.program);
+
+ // If anything is dirty in gles1 or the common parts of gles1/2, just redo these parts
+ // completely for now.
+
+ // Feature enables
+
+ // Texture unit enables and format info
+ std::array<Vec4Uniform, kTexUnitCount> texCropRects;
+ Vec4Uniform *cropRectBuffer = texCropRects.data();
+ for (int i = 0; i < kTexUnitCount; i++)
+ {
+ Texture *curr2DTexture = glState->getSamplerTexture(i, TextureType::_2D);
+ if (curr2DTexture)
+ {
+ const gl::Rectangle &cropRect = curr2DTexture->getCrop();
+
+ GLfloat textureWidth =
+ static_cast<GLfloat>(curr2DTexture->getWidth(TextureTarget::_2D, 0));
+ GLfloat textureHeight =
+ static_cast<GLfloat>(curr2DTexture->getHeight(TextureTarget::_2D, 0));
+
+ if (textureWidth > 0.0f && textureHeight > 0.0f)
+ {
+ cropRectBuffer[i][0] = cropRect.x / textureWidth;
+ cropRectBuffer[i][1] = cropRect.y / textureHeight;
+ cropRectBuffer[i][2] = cropRect.width / textureWidth;
+ cropRectBuffer[i][3] = cropRect.height / textureHeight;
+ }
+ }
+ }
+ setUniform4fv(programObject, programState.drawTextureNormalizedCropRectLoc, kTexUnitCount,
+ reinterpret_cast<GLfloat *>(cropRectBuffer));
+
+ if (gles1State.isDirty(GLES1State::DIRTY_GLES1_LOGIC_OP) && hasLogicOpANGLE)
+ {
+ context->setLogicOpEnabled(gles1State.mLogicOpEnabled);
+ context->setLogicOp(gles1State.mLogicOp);
+ }
+ else if (hasFramebufferFetch)
+ {
+ const Framebuffer *drawFramebuffer = glState->getDrawFramebuffer();
+ const FramebufferAttachment *colorAttachment = drawFramebuffer->getColorAttachment(0);
+
+ if (gles1State.mLogicOpEnabled)
+ {
+ if (gles1State.isDirty(GLES1State::DIRTY_GLES1_LOGIC_OP))
+ {
+ // Set up uniform value for logic op
+ setUniform1ui(programObject, programState.logicOpLoc,
+ GetLogicOpUniform(colorAttachment, gles1State.mLogicOp));
+ }
+
+ // Issue a framebuffer fetch barrier if non-coherent
+ if (!context->getExtensions().shaderFramebufferFetchEXT)
+ {
+ context->framebufferFetchBarrier();
+ }
+ }
+ }
+
+ // Client state / current vector enables
+ if (gles1State.isDirty(GLES1State::DIRTY_GLES1_CLIENT_STATE_ENABLE) ||
+ gles1State.isDirty(GLES1State::DIRTY_GLES1_CURRENT_VECTOR))
+ {
+ if (!gles1State.isClientStateEnabled(ClientVertexArrayType::Normal))
+ {
+ const angle::Vector3 normal = gles1State.getCurrentNormal();
+ context->vertexAttrib3f(kNormalAttribIndex, normal.x(), normal.y(), normal.z());
+ }
+
+ if (!gles1State.isClientStateEnabled(ClientVertexArrayType::Color))
+ {
+ const ColorF color = gles1State.getCurrentColor();
+ context->vertexAttrib4f(kColorAttribIndex, color.red, color.green, color.blue,
+ color.alpha);
+ }
+
+ if (!gles1State.isClientStateEnabled(ClientVertexArrayType::PointSize))
+ {
+ GLfloat pointSize = gles1State.mPointParameters.pointSize;
+ context->vertexAttrib1f(kPointSizeAttribIndex, pointSize);
+ }
+
+ for (int i = 0; i < kTexUnitCount; i++)
+ {
+ if (!gles1State.mTexCoordArrayEnabled[i])
+ {
+ const TextureCoordF texcoord = gles1State.getCurrentTextureCoords(i);
+ context->vertexAttrib4f(kTextureCoordAttribIndexBase + i, texcoord.s, texcoord.t,
+ texcoord.r, texcoord.q);
+ }
+ }
+ }
+
+ // Matrices
+ if (gles1State.isDirty(GLES1State::DIRTY_GLES1_MATRICES))
+ {
+ angle::Mat4 proj = gles1State.mProjectionMatrices.back();
+ setUniformMatrix4fv(programObject, programState.projMatrixLoc, 1, GL_FALSE, proj.data());
+
+ angle::Mat4 modelview = gles1State.mModelviewMatrices.back();
+ setUniformMatrix4fv(programObject, programState.modelviewMatrixLoc, 1, GL_FALSE,
+ modelview.data());
+
+ angle::Mat4 modelviewInvTr = modelview.transpose().inverse();
+ setUniformMatrix4fv(programObject, programState.modelviewInvTrLoc, 1, GL_FALSE,
+ modelviewInvTr.data());
+
+ Mat4Uniform *textureMatrixBuffer = uniformBuffers.textureMatrices.data();
+
+ for (int i = 0; i < kTexUnitCount; i++)
+ {
+ angle::Mat4 textureMatrix = gles1State.mTextureMatrices[i].back();
+ memcpy(textureMatrixBuffer + i, textureMatrix.data(), sizeof(Mat4Uniform));
+ }
+
+ setUniformMatrix4fv(programObject, programState.textureMatrixLoc, kTexUnitCount, GL_FALSE,
+ reinterpret_cast<float *>(uniformBuffers.textureMatrices.data()));
+ }
+
+ if (gles1State.isDirty(GLES1State::DIRTY_GLES1_TEXTURE_ENVIRONMENT))
+ {
+ for (int i = 0; i < kTexUnitCount; i++)
+ {
+ const auto &env = gles1State.textureEnvironment(i);
+
+ uniformBuffers.texEnvColors[i][0] = env.color.red;
+ uniformBuffers.texEnvColors[i][1] = env.color.green;
+ uniformBuffers.texEnvColors[i][2] = env.color.blue;
+ uniformBuffers.texEnvColors[i][3] = env.color.alpha;
+
+ uniformBuffers.texEnvRgbScales[i] = env.rgbScale;
+ uniformBuffers.texEnvAlphaScales[i] = env.alphaScale;
+ }
+
+ setUniform4fv(programObject, programState.textureEnvColorLoc, kTexUnitCount,
+ reinterpret_cast<float *>(uniformBuffers.texEnvColors.data()));
+ setUniform1fv(programObject, programState.rgbScaleLoc, kTexUnitCount,
+ uniformBuffers.texEnvRgbScales.data());
+ setUniform1fv(programObject, programState.alphaScaleLoc, kTexUnitCount,
+ uniformBuffers.texEnvAlphaScales.data());
+ }
+
+ // Alpha test
+ if (gles1State.isDirty(GLES1State::DIRTY_GLES1_ALPHA_TEST))
+ {
+ setUniform1f(programObject, programState.alphaTestRefLoc, gles1State.mAlphaTestRef);
+ }
+
+ // Shading, materials, and lighting
+ if (gles1State.isDirty(GLES1State::DIRTY_GLES1_MATERIAL))
+ {
+ const auto &material = gles1State.mMaterial;
+
+ setUniform4fv(programObject, programState.materialAmbientLoc, 1, material.ambient.data());
+ setUniform4fv(programObject, programState.materialDiffuseLoc, 1, material.diffuse.data());
+ setUniform4fv(programObject, programState.materialSpecularLoc, 1, material.specular.data());
+ setUniform4fv(programObject, programState.materialEmissiveLoc, 1, material.emissive.data());
+ setUniform1f(programObject, programState.materialSpecularExponentLoc,
+ material.specularExponent);
+ }
+
+ if (gles1State.isDirty(GLES1State::DIRTY_GLES1_LIGHTS))
+ {
+ const auto &lightModel = gles1State.mLightModel;
+
+ setUniform4fv(programObject, programState.lightModelSceneAmbientLoc, 1,
+ lightModel.color.data());
+
+ for (int i = 0; i < kLightCount; i++)
+ {
+ const auto &light = gles1State.mLights[i];
+ memcpy(uniformBuffers.lightAmbients.data() + i, light.ambient.data(),
+ sizeof(Vec4Uniform));
+ memcpy(uniformBuffers.lightDiffuses.data() + i, light.diffuse.data(),
+ sizeof(Vec4Uniform));
+ memcpy(uniformBuffers.lightSpeculars.data() + i, light.specular.data(),
+ sizeof(Vec4Uniform));
+ memcpy(uniformBuffers.lightPositions.data() + i, light.position.data(),
+ sizeof(Vec4Uniform));
+ memcpy(uniformBuffers.lightDirections.data() + i, light.direction.data(),
+ sizeof(Vec3Uniform));
+ uniformBuffers.spotlightExponents[i] = light.spotlightExponent;
+ uniformBuffers.spotlightCutoffAngles[i] = light.spotlightCutoffAngle;
+ uniformBuffers.attenuationConsts[i] = light.attenuationConst;
+ uniformBuffers.attenuationLinears[i] = light.attenuationLinear;
+ uniformBuffers.attenuationQuadratics[i] = light.attenuationQuadratic;
+ }
+
+ setUniform4fv(programObject, programState.lightAmbientsLoc, kLightCount,
+ reinterpret_cast<float *>(uniformBuffers.lightAmbients.data()));
+ setUniform4fv(programObject, programState.lightDiffusesLoc, kLightCount,
+ reinterpret_cast<float *>(uniformBuffers.lightDiffuses.data()));
+ setUniform4fv(programObject, programState.lightSpecularsLoc, kLightCount,
+ reinterpret_cast<float *>(uniformBuffers.lightSpeculars.data()));
+ setUniform4fv(programObject, programState.lightPositionsLoc, kLightCount,
+ reinterpret_cast<float *>(uniformBuffers.lightPositions.data()));
+ setUniform3fv(programObject, programState.lightDirectionsLoc, kLightCount,
+ reinterpret_cast<float *>(uniformBuffers.lightDirections.data()));
+ setUniform1fv(programObject, programState.lightSpotlightExponentsLoc, kLightCount,
+ reinterpret_cast<float *>(uniformBuffers.spotlightExponents.data()));
+ setUniform1fv(programObject, programState.lightSpotlightCutoffAnglesLoc, kLightCount,
+ reinterpret_cast<float *>(uniformBuffers.spotlightCutoffAngles.data()));
+ setUniform1fv(programObject, programState.lightAttenuationConstsLoc, kLightCount,
+ reinterpret_cast<float *>(uniformBuffers.attenuationConsts.data()));
+ setUniform1fv(programObject, programState.lightAttenuationLinearsLoc, kLightCount,
+ reinterpret_cast<float *>(uniformBuffers.attenuationLinears.data()));
+ setUniform1fv(programObject, programState.lightAttenuationQuadraticsLoc, kLightCount,
+ reinterpret_cast<float *>(uniformBuffers.attenuationQuadratics.data()));
+ }
+
+ if (gles1State.isDirty(GLES1State::DIRTY_GLES1_FOG))
+ {
+ const FogParameters &fog = gles1State.fogParameters();
+ setUniform1f(programObject, programState.fogDensityLoc, fog.density);
+ setUniform1f(programObject, programState.fogStartLoc, fog.start);
+ setUniform1f(programObject, programState.fogEndLoc, fog.end);
+ setUniform4fv(programObject, programState.fogColorLoc, 1, fog.color.data());
+ }
+
+ // Clip planes
+ if (gles1State.isDirty(GLES1State::DIRTY_GLES1_CLIP_PLANES))
+ {
+ for (int i = 0; i < kClipPlaneCount; i++)
+ {
+ gles1State.getClipPlane(
+ i, reinterpret_cast<float *>(uniformBuffers.clipPlanes.data() + i));
+ }
+
+ setUniform4fv(programObject, programState.clipPlanesLoc, kClipPlaneCount,
+ reinterpret_cast<float *>(uniformBuffers.clipPlanes.data()));
+ }
+
+ // Point rasterization
+ {
+ const PointParameters &pointParams = gles1State.mPointParameters;
+
+ setUniform1f(programObject, programState.pointSizeMinLoc, pointParams.pointSizeMin);
+ setUniform1f(programObject, programState.pointSizeMaxLoc, pointParams.pointSizeMax);
+ setUniform3fv(programObject, programState.pointDistanceAttenuationLoc, 1,
+ pointParams.pointDistanceAttenuation.data());
+ }
+
+ // Draw texture
+ {
+ setUniform4fv(programObject, programState.drawTextureCoordsLoc, 1, mDrawTextureCoords);
+ setUniform2fv(programObject, programState.drawTextureDimsLoc, 1, mDrawTextureDims);
+ }
+
+ gles1State.clearDirty();
+
+ // None of those are changes in sampler, so there is no need to set the GL_PROGRAM dirty.
+ // Otherwise, put the dirtying here.
+
+ return angle::Result::Continue;
+}
+
+// static
+int GLES1Renderer::VertexArrayIndex(ClientVertexArrayType type, const GLES1State &gles1)
+{
+ switch (type)
+ {
+ case ClientVertexArrayType::Vertex:
+ return kVertexAttribIndex;
+ case ClientVertexArrayType::Normal:
+ return kNormalAttribIndex;
+ case ClientVertexArrayType::Color:
+ return kColorAttribIndex;
+ case ClientVertexArrayType::PointSize:
+ return kPointSizeAttribIndex;
+ case ClientVertexArrayType::TextureCoord:
+ return kTextureCoordAttribIndexBase + gles1.getClientTextureUnit();
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+// static
+ClientVertexArrayType GLES1Renderer::VertexArrayType(int attribIndex)
+{
+ switch (attribIndex)
+ {
+ case kVertexAttribIndex:
+ return ClientVertexArrayType::Vertex;
+ case kNormalAttribIndex:
+ return ClientVertexArrayType::Normal;
+ case kColorAttribIndex:
+ return ClientVertexArrayType::Color;
+ case kPointSizeAttribIndex:
+ return ClientVertexArrayType::PointSize;
+ default:
+ if (attribIndex < kTextureCoordAttribIndexBase + kTexUnitCount)
+ {
+ return ClientVertexArrayType::TextureCoord;
+ }
+ UNREACHABLE();
+ return ClientVertexArrayType::InvalidEnum;
+ }
+}
+
+// static
+int GLES1Renderer::TexCoordArrayIndex(unsigned int unit)
+{
+ return kTextureCoordAttribIndexBase + unit;
+}
+
+void GLES1Renderer::drawTexture(Context *context,
+ State *glState,
+ float x,
+ float y,
+ float z,
+ float width,
+ float height)
+{
+
+ // get viewport
+ const gl::Rectangle &viewport = glState->getViewport();
+
+ // Translate from viewport to NDC for feeding the shader.
+ // Recenter, rescale. (e.g., [0, 0, 1080, 1920] -> [-1, -1, 1, 1])
+ float xNdc = scaleScreenCoordinateToNdc(x, static_cast<GLfloat>(viewport.width));
+ float yNdc = scaleScreenCoordinateToNdc(y, static_cast<GLfloat>(viewport.height));
+ float wNdc = scaleScreenDimensionToNdc(width, static_cast<GLfloat>(viewport.width));
+ float hNdc = scaleScreenDimensionToNdc(height, static_cast<GLfloat>(viewport.height));
+
+ float zNdc = 2.0f * clamp(z, 0.0f, 1.0f) - 1.0f;
+
+ mDrawTextureCoords[0] = xNdc;
+ mDrawTextureCoords[1] = yNdc;
+ mDrawTextureCoords[2] = zNdc;
+
+ mDrawTextureDims[0] = wNdc;
+ mDrawTextureDims[1] = hNdc;
+
+ mDrawTextureEnabled = true;
+
+ AttributesMask prevAttributesMask = glState->gles1().getVertexArraysAttributeMask();
+
+ setAttributesEnabled(context, glState, AttributesMask());
+
+ glState->gles1().setAllDirty();
+
+ context->drawArrays(PrimitiveMode::Triangles, 0, 6);
+
+ setAttributesEnabled(context, glState, prevAttributesMask);
+
+ mDrawTextureEnabled = false;
+}
+
+Shader *GLES1Renderer::getShader(ShaderProgramID handle) const
+{
+ return mShaderPrograms->getShader(handle);
+}
+
+Program *GLES1Renderer::getProgram(ShaderProgramID handle) const
+{
+ return mShaderPrograms->getProgram(handle);
+}
+
+angle::Result GLES1Renderer::compileShader(Context *context,
+ ShaderType shaderType,
+ const char *src,
+ ShaderProgramID *shaderOut)
+{
+ rx::ContextImpl *implementation = context->getImplementation();
+ const Limitations &limitations = implementation->getNativeLimitations();
+
+ ShaderProgramID shader = mShaderPrograms->createShader(implementation, limitations, shaderType);
+
+ Shader *shaderObject = getShader(shader);
+ ANGLE_CHECK(context, shaderObject, "Missing shader object", GL_INVALID_OPERATION);
+
+ shaderObject->setSource(1, &src, nullptr);
+ shaderObject->compile(context);
+
+ *shaderOut = shader;
+
+ if (!shaderObject->isCompiled(context))
+ {
+ GLint infoLogLength = shaderObject->getInfoLogLength(context);
+ std::vector<char> infoLog(infoLogLength, 0);
+ shaderObject->getInfoLog(context, infoLogLength - 1, nullptr, infoLog.data());
+
+ ERR() << "Internal GLES 1 shader compile failed. Info log: " << infoLog.data();
+ ANGLE_CHECK(context, false, "GLES1Renderer shader compile failed.", GL_INVALID_OPERATION);
+ return angle::Result::Stop;
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result GLES1Renderer::linkProgram(Context *context,
+ State *glState,
+ ShaderProgramID vertexShader,
+ ShaderProgramID fragmentShader,
+ const angle::HashMap<GLint, std::string> &attribLocs,
+ ShaderProgramID *programOut)
+{
+ ShaderProgramID program = mShaderPrograms->createProgram(context->getImplementation());
+
+ Program *programObject = getProgram(program);
+ ANGLE_CHECK(context, programObject, "Missing program object", GL_INVALID_OPERATION);
+
+ *programOut = program;
+
+ programObject->attachShader(getShader(vertexShader));
+ programObject->attachShader(getShader(fragmentShader));
+
+ for (auto it : attribLocs)
+ {
+ GLint index = it.first;
+ const std::string &name = it.second;
+ programObject->bindAttributeLocation(index, name.c_str());
+ }
+
+ ANGLE_TRY(programObject->link(context));
+ programObject->resolveLink(context);
+
+ ANGLE_TRY(glState->onProgramExecutableChange(context, programObject));
+
+ if (!programObject->isLinked())
+ {
+ GLint infoLogLength = programObject->getExecutable().getInfoLogLength();
+ std::vector<char> infoLog(infoLogLength, 0);
+ programObject->getExecutable().getInfoLog(infoLogLength - 1, nullptr, infoLog.data());
+
+ ERR() << "Internal GLES 1 shader link failed. Info log: " << infoLog.data();
+ ANGLE_CHECK(context, false, "GLES1Renderer program link failed.", GL_INVALID_OPERATION);
+ return angle::Result::Stop;
+ }
+
+ programObject->detachShader(context, getShader(vertexShader));
+ programObject->detachShader(context, getShader(fragmentShader));
+
+ return angle::Result::Continue;
+}
+
+const char *GLES1Renderer::getShaderBool(GLES1StateEnables state)
+{
+ if (mShaderState.mGLES1StateEnabled[state])
+ {
+ return "true";
+ }
+ else
+ {
+ return "false";
+ }
+}
+
+void GLES1Renderer::addShaderDefine(std::stringstream &outStream,
+ GLES1StateEnables state,
+ const char *enableString)
+{
+ outStream << "\n";
+ outStream << "#define " << enableString << " " << getShaderBool(state);
+}
+
+void GLES1Renderer::addShaderInt(std::stringstream &outStream, const char *name, int value)
+{
+ outStream << "\n";
+ outStream << "const int " << name << " = " << value << ";";
+}
+
+void GLES1Renderer::addShaderIntTexArray(std::stringstream &outStream,
+ const char *texString,
+ GLES1ShaderState::IntTexArray &texState)
+{
+ outStream << "\n";
+ outStream << "const int " << texString << "[kMaxTexUnits] = int[kMaxTexUnits](";
+ for (int i = 0; i < kTexUnitCount; i++)
+ {
+ if (i != 0)
+ {
+ outStream << ", ";
+ }
+ outStream << texState[i];
+ }
+ outStream << ");";
+}
+
+void GLES1Renderer::addShaderBoolTexArray(std::stringstream &outStream,
+ const char *name,
+ GLES1ShaderState::BoolTexArray &value)
+{
+ outStream << std::boolalpha;
+ outStream << "\n";
+ outStream << "bool " << name << "[kMaxTexUnits] = bool[kMaxTexUnits](";
+ for (int i = 0; i < kTexUnitCount; i++)
+ {
+ if (i != 0)
+ {
+ outStream << ", ";
+ }
+ outStream << value[i];
+ }
+ outStream << ");";
+}
+
+void GLES1Renderer::addShaderBoolLightArray(std::stringstream &outStream,
+ const char *name,
+ GLES1ShaderState::BoolLightArray &value)
+{
+ outStream << std::boolalpha;
+ outStream << "\n";
+ outStream << "bool " << name << "[kMaxLights] = bool[kMaxLights](";
+ for (int i = 0; i < kLightCount; i++)
+ {
+ if (i != 0)
+ {
+ outStream << ", ";
+ }
+ outStream << value[i];
+ }
+ outStream << ");";
+}
+
+void GLES1Renderer::addShaderBoolClipPlaneArray(std::stringstream &outStream,
+ const char *name,
+ GLES1ShaderState::BoolClipPlaneArray &value)
+{
+ outStream << std::boolalpha;
+ outStream << "\n";
+ outStream << "bool " << name << "[kMaxClipPlanes] = bool[kMaxClipPlanes](";
+ for (int i = 0; i < kClipPlaneCount; i++)
+ {
+ if (i != 0)
+ {
+ outStream << ", ";
+ }
+ outStream << value[i];
+ }
+ outStream << ");";
+}
+
+void GLES1Renderer::addVertexShaderDefs(std::stringstream &outStream)
+{
+ addShaderDefine(outStream, GLES1StateEnables::Lighting, "enable_lighting");
+ addShaderDefine(outStream, GLES1StateEnables::ColorMaterial, "enable_color_material");
+ addShaderDefine(outStream, GLES1StateEnables::DrawTexture, "enable_draw_texture");
+ addShaderDefine(outStream, GLES1StateEnables::PointRasterization, "point_rasterization");
+ addShaderDefine(outStream, GLES1StateEnables::RescaleNormal, "enable_rescale_normal");
+ addShaderDefine(outStream, GLES1StateEnables::Normalize, "enable_normalize");
+ addShaderDefine(outStream, GLES1StateEnables::LightModelTwoSided, "light_model_two_sided");
+
+ // bool light_enables[kMaxLights] = bool[kMaxLights](...);
+ addShaderBoolLightArray(outStream, "light_enables", mShaderState.lightEnables);
+}
+
+void GLES1Renderer::addFragmentShaderDefs(std::stringstream &outStream)
+{
+ addShaderDefine(outStream, GLES1StateEnables::Fog, "enable_fog");
+ addShaderDefine(outStream, GLES1StateEnables::ClipPlanes, "enable_clip_planes");
+ addShaderDefine(outStream, GLES1StateEnables::DrawTexture, "enable_draw_texture");
+ addShaderDefine(outStream, GLES1StateEnables::PointRasterization, "point_rasterization");
+ addShaderDefine(outStream, GLES1StateEnables::PointSprite, "point_sprite_enabled");
+ addShaderDefine(outStream, GLES1StateEnables::AlphaTest, "enable_alpha_test");
+ addShaderDefine(outStream, GLES1StateEnables::ShadeModelFlat, "shade_model_flat");
+
+ // bool enable_texture_2d[kMaxTexUnits] = bool[kMaxTexUnits](...);
+ addShaderBoolTexArray(outStream, "enable_texture_2d", mShaderState.tex2DEnables);
+
+ // bool enable_texture_cube_map[kMaxTexUnits] = bool[kMaxTexUnits](...);
+ addShaderBoolTexArray(outStream, "enable_texture_cube_map", mShaderState.texCubeEnables);
+
+ // int texture_format[kMaxTexUnits] = int[kMaxTexUnits](...);
+ addShaderIntTexArray(outStream, "texture_format", mShaderState.tex2DFormats);
+
+ // bool point_sprite_coord_replace[kMaxTexUnits] = bool[kMaxTexUnits](...);
+ addShaderBoolTexArray(outStream, "point_sprite_coord_replace",
+ mShaderState.pointSpriteCoordReplaces);
+
+ // bool clip_plane_enables[kMaxClipPlanes] = bool[kMaxClipPlanes](...);
+ addShaderBoolClipPlaneArray(outStream, "clip_plane_enables", mShaderState.clipPlaneEnables);
+
+ // int texture_format[kMaxTexUnits] = int[kMaxTexUnits](...);
+ addShaderIntTexArray(outStream, "texture_env_mode", mShaderState.texEnvModes);
+
+ // int combine_rgb[kMaxTexUnits];
+ addShaderIntTexArray(outStream, "combine_rgb", mShaderState.texCombineRgbs);
+
+ // int combine_alpha[kMaxTexUnits];
+ addShaderIntTexArray(outStream, "combine_alpha", mShaderState.texCombineAlphas);
+
+ // int src0_rgb[kMaxTexUnits];
+ addShaderIntTexArray(outStream, "src0_rgb", mShaderState.texCombineSrc0Rgbs);
+
+ // int src0_alpha[kMaxTexUnits];
+ addShaderIntTexArray(outStream, "src0_alpha", mShaderState.texCombineSrc0Alphas);
+
+ // int src1_rgb[kMaxTexUnits];
+ addShaderIntTexArray(outStream, "src1_rgb", mShaderState.texCombineSrc1Rgbs);
+
+ // int src1_alpha[kMaxTexUnits];
+ addShaderIntTexArray(outStream, "src1_alpha", mShaderState.texCombineSrc1Alphas);
+
+ // int src2_rgb[kMaxTexUnits];
+ addShaderIntTexArray(outStream, "src2_rgb", mShaderState.texCombineSrc2Rgbs);
+
+ // int src2_alpha[kMaxTexUnits];
+ addShaderIntTexArray(outStream, "src2_alpha", mShaderState.texCombineSrc2Alphas);
+
+ // int op0_rgb[kMaxTexUnits];
+ addShaderIntTexArray(outStream, "op0_rgb", mShaderState.texCombineOp0Rgbs);
+
+ // int op0_alpha[kMaxTexUnits];
+ addShaderIntTexArray(outStream, "op0_alpha", mShaderState.texCombineOp0Alphas);
+
+ // int op1_rgb[kMaxTexUnits];
+ addShaderIntTexArray(outStream, "op1_rgb", mShaderState.texCombineOp1Rgbs);
+
+ // int op1_alpha[kMaxTexUnits];
+ addShaderIntTexArray(outStream, "op1_alpha", mShaderState.texCombineOp1Alphas);
+
+ // int op2_rgb[kMaxTexUnits];
+ addShaderIntTexArray(outStream, "op2_rgb", mShaderState.texCombineOp2Rgbs);
+
+ // int op2_alpha[kMaxTexUnits];
+ addShaderIntTexArray(outStream, "op2_alpha", mShaderState.texCombineOp2Alphas);
+
+ // int alpha_func;
+ addShaderInt(outStream, "alpha_func", ToGLenum(mShaderState.alphaTestFunc));
+
+ // int fog_mode;
+ addShaderInt(outStream, "fog_mode", ToGLenum(mShaderState.fogMode));
+}
+
+angle::Result GLES1Renderer::initializeRendererProgram(Context *context, State *glState)
+{
+ // See if we have the shader for this combination of states
+ if (mUberShaderState.find(mShaderState) != mUberShaderState.end())
+ {
+ Program *programObject = getProgram(getUberShaderState().programState.program);
+
+ // If this is different than the current program, we need to sync everything
+ // TODO: This could be optimized to only dirty state that differs between the two programs
+ if (glState->getProgram()->id() != programObject->id())
+ {
+ glState->gles1().setAllDirty();
+ }
+
+ ANGLE_TRY(glState->setProgram(context, programObject));
+ return angle::Result::Continue;
+ }
+
+ if (!mRendererProgramInitialized)
+ {
+ mShaderPrograms = new ShaderProgramManager();
+ }
+
+ // If we get here, we don't have a shader for this state, need to create it
+ GLES1ProgramState &programState = mUberShaderState[mShaderState].programState;
+
+ ShaderProgramID vertexShader;
+ ShaderProgramID fragmentShader;
+
+ std::stringstream GLES1DrawVShaderStateDefs;
+ addVertexShaderDefs(GLES1DrawVShaderStateDefs);
+
+ std::stringstream vertexStream;
+ vertexStream << kGLES1DrawVShaderHeader;
+ vertexStream << GLES1DrawVShaderStateDefs.str();
+ vertexStream << kGLES1DrawVShader;
+
+ ANGLE_TRY(
+ compileShader(context, ShaderType::Vertex, vertexStream.str().c_str(), &vertexShader));
+
+ std::stringstream GLES1DrawFShaderStateDefs;
+ addFragmentShaderDefs(GLES1DrawFShaderStateDefs);
+
+ std::stringstream fragmentStream;
+ fragmentStream << kGLES1DrawFShaderVersion;
+ if (mShaderState.mGLES1StateEnabled[GLES1StateEnables::LogicOpThroughFramebufferFetch])
+ {
+ if (context->getExtensions().shaderFramebufferFetchEXT)
+ {
+ fragmentStream << "#extension GL_EXT_shader_framebuffer_fetch : require\n";
+ }
+ else
+ {
+ fragmentStream << "#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require\n";
+ }
+ }
+ fragmentStream << kGLES1DrawFShaderHeader;
+ fragmentStream << GLES1DrawFShaderStateDefs.str();
+ fragmentStream << kGLES1DrawFShaderUniformDefs;
+ if (mShaderState.mGLES1StateEnabled[GLES1StateEnables::LogicOpThroughFramebufferFetch])
+ {
+ if (context->getExtensions().shaderFramebufferFetchEXT)
+ {
+ fragmentStream << kGLES1DrawFShaderFramebufferFetchOutputDef;
+ }
+ else
+ {
+ fragmentStream << kGLES1DrawFShaderFramebufferFetchNonCoherentOutputDef;
+ }
+ fragmentStream << kGLES1DrawFShaderLogicOpFramebufferFetchEnabled;
+ }
+ else
+ {
+ fragmentStream << kGLES1DrawFShaderOutputDef;
+ fragmentStream << kGLES1DrawFShaderLogicOpFramebufferFetchDisabled;
+ }
+ fragmentStream << kGLES1DrawFShaderFunctions;
+ fragmentStream << kGLES1DrawFShaderMultitexturing;
+ fragmentStream << kGLES1DrawFShaderMain;
+
+ ANGLE_TRY(compileShader(context, ShaderType::Fragment, fragmentStream.str().c_str(),
+ &fragmentShader));
+
+ angle::HashMap<GLint, std::string> attribLocs;
+
+ attribLocs[(GLint)kVertexAttribIndex] = "pos";
+ attribLocs[(GLint)kNormalAttribIndex] = "normal";
+ attribLocs[(GLint)kColorAttribIndex] = "color";
+ attribLocs[(GLint)kPointSizeAttribIndex] = "pointsize";
+
+ for (int i = 0; i < kTexUnitCount; i++)
+ {
+ std::stringstream ss;
+ ss << "texcoord" << i;
+ attribLocs[kTextureCoordAttribIndexBase + i] = ss.str();
+ }
+
+ ANGLE_TRY(linkProgram(context, glState, vertexShader, fragmentShader, attribLocs,
+ &programState.program));
+
+ mShaderPrograms->deleteShader(context, vertexShader);
+ mShaderPrograms->deleteShader(context, fragmentShader);
+
+ Program *programObject = getProgram(programState.program);
+
+ programState.projMatrixLoc = programObject->getUniformLocation("projection");
+ programState.modelviewMatrixLoc = programObject->getUniformLocation("modelview");
+ programState.textureMatrixLoc = programObject->getUniformLocation("texture_matrix");
+ programState.modelviewInvTrLoc = programObject->getUniformLocation("modelview_invtr");
+
+ for (int i = 0; i < kTexUnitCount; i++)
+ {
+ std::stringstream ss2d;
+ std::stringstream sscube;
+
+ ss2d << "tex_sampler" << i;
+ sscube << "tex_cube_sampler" << i;
+
+ programState.tex2DSamplerLocs[i] = programObject->getUniformLocation(ss2d.str().c_str());
+ programState.texCubeSamplerLocs[i] =
+ programObject->getUniformLocation(sscube.str().c_str());
+ }
+
+ programState.textureEnvColorLoc = programObject->getUniformLocation("texture_env_color");
+ programState.rgbScaleLoc = programObject->getUniformLocation("texture_env_rgb_scale");
+ programState.alphaScaleLoc = programObject->getUniformLocation("texture_env_alpha_scale");
+
+ programState.alphaTestRefLoc = programObject->getUniformLocation("alpha_test_ref");
+
+ programState.materialAmbientLoc = programObject->getUniformLocation("material_ambient");
+ programState.materialDiffuseLoc = programObject->getUniformLocation("material_diffuse");
+ programState.materialSpecularLoc = programObject->getUniformLocation("material_specular");
+ programState.materialEmissiveLoc = programObject->getUniformLocation("material_emissive");
+ programState.materialSpecularExponentLoc =
+ programObject->getUniformLocation("material_specular_exponent");
+
+ programState.lightModelSceneAmbientLoc =
+ programObject->getUniformLocation("light_model_scene_ambient");
+
+ programState.lightAmbientsLoc = programObject->getUniformLocation("light_ambients");
+ programState.lightDiffusesLoc = programObject->getUniformLocation("light_diffuses");
+ programState.lightSpecularsLoc = programObject->getUniformLocation("light_speculars");
+ programState.lightPositionsLoc = programObject->getUniformLocation("light_positions");
+ programState.lightDirectionsLoc = programObject->getUniformLocation("light_directions");
+ programState.lightSpotlightExponentsLoc =
+ programObject->getUniformLocation("light_spotlight_exponents");
+ programState.lightSpotlightCutoffAnglesLoc =
+ programObject->getUniformLocation("light_spotlight_cutoff_angles");
+ programState.lightAttenuationConstsLoc =
+ programObject->getUniformLocation("light_attenuation_consts");
+ programState.lightAttenuationLinearsLoc =
+ programObject->getUniformLocation("light_attenuation_linears");
+ programState.lightAttenuationQuadraticsLoc =
+ programObject->getUniformLocation("light_attenuation_quadratics");
+
+ programState.fogDensityLoc = programObject->getUniformLocation("fog_density");
+ programState.fogStartLoc = programObject->getUniformLocation("fog_start");
+ programState.fogEndLoc = programObject->getUniformLocation("fog_end");
+ programState.fogColorLoc = programObject->getUniformLocation("fog_color");
+
+ programState.clipPlanesLoc = programObject->getUniformLocation("clip_planes");
+
+ programState.logicOpLoc = programObject->getUniformLocation("logic_op");
+
+ programState.pointSizeMinLoc = programObject->getUniformLocation("point_size_min");
+ programState.pointSizeMaxLoc = programObject->getUniformLocation("point_size_max");
+ programState.pointDistanceAttenuationLoc =
+ programObject->getUniformLocation("point_distance_attenuation");
+
+ programState.drawTextureCoordsLoc = programObject->getUniformLocation("draw_texture_coords");
+ programState.drawTextureDimsLoc = programObject->getUniformLocation("draw_texture_dims");
+ programState.drawTextureNormalizedCropRectLoc =
+ programObject->getUniformLocation("draw_texture_normalized_crop_rect");
+
+ ANGLE_TRY(glState->setProgram(context, programObject));
+
+ for (int i = 0; i < kTexUnitCount; i++)
+ {
+ setUniform1i(context, programObject, programState.tex2DSamplerLocs[i], i);
+ setUniform1i(context, programObject, programState.texCubeSamplerLocs[i], i + kTexUnitCount);
+ }
+ glState->setObjectDirty(GL_PROGRAM);
+
+ // We just created a new program, we need to sync everything
+ glState->gles1().setAllDirty();
+
+ mRendererProgramInitialized = true;
+ return angle::Result::Continue;
+}
+
+void GLES1Renderer::setUniform1i(Context *context,
+ Program *programObject,
+ UniformLocation location,
+ GLint value)
+{
+ if (location.value == -1)
+ return;
+ programObject->setUniform1iv(context, location, 1, &value);
+}
+
+void GLES1Renderer::setUniform1ui(Program *programObject, UniformLocation location, GLuint value)
+{
+ if (location.value == -1)
+ return;
+ programObject->setUniform1uiv(location, 1, &value);
+}
+
+void GLES1Renderer::setUniform1iv(Context *context,
+ Program *programObject,
+ UniformLocation location,
+ GLint count,
+ const GLint *value)
+{
+ if (location.value == -1)
+ return;
+ programObject->setUniform1iv(context, location, count, value);
+}
+
+void GLES1Renderer::setUniformMatrix4fv(Program *programObject,
+ UniformLocation location,
+ GLint count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (location.value == -1)
+ return;
+ programObject->setUniformMatrix4fv(location, count, transpose, value);
+}
+
+void GLES1Renderer::setUniform4fv(Program *programObject,
+ UniformLocation location,
+ GLint count,
+ const GLfloat *value)
+{
+ if (location.value == -1)
+ return;
+ programObject->setUniform4fv(location, count, value);
+}
+
+void GLES1Renderer::setUniform3fv(Program *programObject,
+ UniformLocation location,
+ GLint count,
+ const GLfloat *value)
+{
+ if (location.value == -1)
+ return;
+ programObject->setUniform3fv(location, count, value);
+}
+
+void GLES1Renderer::setUniform2fv(Program *programObject,
+ UniformLocation location,
+ GLint count,
+ const GLfloat *value)
+{
+ if (location.value == -1)
+ return;
+ programObject->setUniform2fv(location, count, value);
+}
+
+void GLES1Renderer::setUniform1f(Program *programObject, UniformLocation location, GLfloat value)
+{
+ if (location.value == -1)
+ return;
+ programObject->setUniform1fv(location, 1, &value);
+}
+
+void GLES1Renderer::setUniform1fv(Program *programObject,
+ UniformLocation location,
+ GLint count,
+ const GLfloat *value)
+{
+ if (location.value == -1)
+ return;
+ programObject->setUniform1fv(location, count, value);
+}
+
+void GLES1Renderer::setAttributesEnabled(Context *context, State *glState, AttributesMask mask)
+{
+ GLES1State &gles1 = glState->gles1();
+
+ ClientVertexArrayType nonTexcoordArrays[] = {
+ ClientVertexArrayType::Vertex,
+ ClientVertexArrayType::Normal,
+ ClientVertexArrayType::Color,
+ ClientVertexArrayType::PointSize,
+ };
+
+ for (const ClientVertexArrayType attrib : nonTexcoordArrays)
+ {
+ int index = VertexArrayIndex(attrib, glState->gles1());
+
+ if (mask.test(index))
+ {
+ gles1.setClientStateEnabled(attrib, true);
+ context->enableVertexAttribArray(index);
+ }
+ else
+ {
+ gles1.setClientStateEnabled(attrib, false);
+ context->disableVertexAttribArray(index);
+ }
+ }
+
+ for (unsigned int i = 0; i < kTexUnitCount; i++)
+ {
+ int index = TexCoordArrayIndex(i);
+
+ if (mask.test(index))
+ {
+ gles1.setTexCoordArrayEnabled(i, true);
+ context->enableVertexAttribArray(index);
+ }
+ else
+ {
+ gles1.setTexCoordArrayEnabled(i, false);
+ context->disableVertexAttribArray(index);
+ }
+ }
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/GLES1Renderer.h b/gfx/angle/checkout/src/libANGLE/GLES1Renderer.h
new file mode 100644
index 0000000000..5694b79752
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/GLES1Renderer.h
@@ -0,0 +1,340 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// GLES1Renderer.h: Defines GLES1 emulation rendering operations on top of a GLES3
+// context. Used by Context.h.
+
+#ifndef LIBANGLE_GLES1_RENDERER_H_
+#define LIBANGLE_GLES1_RENDERER_H_
+
+#include "GLES1State.h"
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+namespace gl
+{
+class Context;
+class GLES1State;
+class Program;
+class State;
+class Shader;
+class ShaderProgramManager;
+
+enum class GLES1StateEnables : uint64_t
+{
+ Lighting = 0,
+ Fog = 1,
+ ClipPlanes = 2,
+ DrawTexture = 3,
+ PointRasterization = 4,
+ PointSprite = 5,
+ RescaleNormal = 6,
+ Normalize = 7,
+ AlphaTest = 8,
+ ShadeModelFlat = 9,
+ ColorMaterial = 10,
+ LightModelTwoSided = 11,
+ LogicOpThroughFramebufferFetch = 12,
+
+ InvalidEnum = 13,
+ EnumCount = 13,
+};
+
+constexpr int kClipPlaneCount = 6;
+constexpr int kTexUnitCount = 4;
+constexpr int kLightCount = 8;
+
+using GLES1StateEnabledBitSet = angle::PackedEnumBitSet<GLES1StateEnables, uint64_t>;
+
+struct GLES1ShaderState
+{
+ GLES1ShaderState();
+ ~GLES1ShaderState();
+ GLES1ShaderState(const GLES1ShaderState &other);
+
+ size_t hash() const;
+
+ GLES1StateEnabledBitSet mGLES1StateEnabled;
+
+ using BoolLightArray = bool[kLightCount];
+ using BoolTexArray = bool[kTexUnitCount];
+ using BoolClipPlaneArray = bool[kClipPlaneCount];
+ using IntTexArray = int[kTexUnitCount];
+
+ BoolTexArray tex2DEnables = {false, false, false, false};
+ BoolTexArray texCubeEnables = {false, false, false, false};
+
+ IntTexArray tex2DFormats = {GL_RGBA, GL_RGBA, GL_RGBA, GL_RGBA};
+
+ IntTexArray texEnvModes = {};
+ IntTexArray texCombineRgbs = {};
+ IntTexArray texCombineAlphas = {};
+ IntTexArray texCombineSrc0Rgbs = {};
+ IntTexArray texCombineSrc0Alphas = {};
+ IntTexArray texCombineSrc1Rgbs = {};
+ IntTexArray texCombineSrc1Alphas = {};
+ IntTexArray texCombineSrc2Rgbs = {};
+ IntTexArray texCombineSrc2Alphas = {};
+ IntTexArray texCombineOp0Rgbs = {};
+ IntTexArray texCombineOp0Alphas = {};
+ IntTexArray texCombineOp1Rgbs = {};
+ IntTexArray texCombineOp1Alphas = {};
+ IntTexArray texCombineOp2Rgbs = {};
+ IntTexArray texCombineOp2Alphas = {};
+
+ BoolTexArray pointSpriteCoordReplaces = {};
+
+ BoolLightArray lightEnables = {};
+
+ BoolClipPlaneArray clipPlaneEnables = {};
+
+ AlphaTestFunc alphaTestFunc = {};
+
+ FogMode fogMode = {};
+};
+
+bool operator==(const GLES1ShaderState &a, const GLES1ShaderState &b);
+bool operator!=(const GLES1ShaderState &a, const GLES1ShaderState &b);
+
+} // namespace gl
+
+namespace std
+{
+template <>
+struct hash<gl::GLES1ShaderState>
+{
+ size_t operator()(const gl::GLES1ShaderState &key) const { return key.hash(); }
+};
+} // namespace std
+
+namespace gl
+{
+
+class GLES1Renderer final : angle::NonCopyable
+{
+ public:
+ GLES1Renderer();
+ ~GLES1Renderer();
+
+ void onDestroy(Context *context, State *state);
+
+ angle::Result prepareForDraw(PrimitiveMode mode, Context *context, State *glState);
+
+ static int VertexArrayIndex(ClientVertexArrayType type, const GLES1State &gles1);
+ static ClientVertexArrayType VertexArrayType(int attribIndex);
+ static int TexCoordArrayIndex(unsigned int unit);
+
+ void drawTexture(Context *context,
+ State *glState,
+ float x,
+ float y,
+ float z,
+ float width,
+ float height);
+
+ private:
+ using Mat4Uniform = float[16];
+ using Vec4Uniform = float[4];
+ using Vec3Uniform = float[3];
+
+ Shader *getShader(ShaderProgramID handle) const;
+ Program *getProgram(ShaderProgramID handle) const;
+
+ angle::Result compileShader(Context *context,
+ ShaderType shaderType,
+ const char *src,
+ ShaderProgramID *shaderOut);
+ angle::Result linkProgram(Context *context,
+ State *glState,
+ ShaderProgramID vshader,
+ ShaderProgramID fshader,
+ const angle::HashMap<GLint, std::string> &attribLocs,
+ ShaderProgramID *programOut);
+ angle::Result initializeRendererProgram(Context *context, State *glState);
+
+ void setUniform1i(Context *context,
+ Program *programObject,
+ UniformLocation location,
+ GLint value);
+ void setUniform1ui(Program *programObject, UniformLocation location, GLuint value);
+ void setUniform1iv(Context *context,
+ Program *programObject,
+ UniformLocation location,
+ GLint count,
+ const GLint *value);
+ void setUniformMatrix4fv(Program *programObject,
+ UniformLocation location,
+ GLint count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniform4fv(Program *programObject,
+ UniformLocation location,
+ GLint count,
+ const GLfloat *value);
+ void setUniform3fv(Program *programObject,
+ UniformLocation location,
+ GLint count,
+ const GLfloat *value);
+ void setUniform2fv(Program *programObject,
+ UniformLocation location,
+ GLint count,
+ const GLfloat *value);
+ void setUniform1f(Program *programObject, UniformLocation location, GLfloat value);
+ void setUniform1fv(Program *programObject,
+ UniformLocation location,
+ GLint count,
+ const GLfloat *value);
+
+ void setAttributesEnabled(Context *context, State *glState, AttributesMask mask);
+
+ static constexpr int kVertexAttribIndex = 0;
+ static constexpr int kNormalAttribIndex = 1;
+ static constexpr int kColorAttribIndex = 2;
+ static constexpr int kPointSizeAttribIndex = 3;
+ static constexpr int kTextureCoordAttribIndexBase = 4;
+
+ bool mRendererProgramInitialized;
+ ShaderProgramManager *mShaderPrograms;
+
+ GLES1ShaderState mShaderState = {};
+
+ const char *getShaderBool(GLES1StateEnables state);
+ void addShaderDefine(std::stringstream &outStream,
+ GLES1StateEnables state,
+ const char *enableString);
+ void addShaderInt(std::stringstream &outStream, const char *name, int value);
+ void addShaderIntTexArray(std::stringstream &outStream,
+ const char *texString,
+ GLES1ShaderState::IntTexArray &texState);
+ void addShaderBoolTexArray(std::stringstream &outStream,
+ const char *texString,
+ GLES1ShaderState::BoolTexArray &texState);
+ void addShaderBoolLightArray(std::stringstream &outStream,
+ const char *name,
+ GLES1ShaderState::BoolLightArray &value);
+ void addShaderBoolClipPlaneArray(std::stringstream &outStream,
+ const char *name,
+ GLES1ShaderState::BoolClipPlaneArray &value);
+ void addVertexShaderDefs(std::stringstream &outStream);
+ void addFragmentShaderDefs(std::stringstream &outStream);
+
+ struct GLES1ProgramState
+ {
+ ShaderProgramID program;
+
+ UniformLocation projMatrixLoc;
+ UniformLocation modelviewMatrixLoc;
+ UniformLocation textureMatrixLoc;
+ UniformLocation modelviewInvTrLoc;
+
+ // Texturing
+ std::array<UniformLocation, kTexUnitCount> tex2DSamplerLocs;
+ std::array<UniformLocation, kTexUnitCount> texCubeSamplerLocs;
+
+ UniformLocation textureEnvColorLoc;
+ UniformLocation rgbScaleLoc;
+ UniformLocation alphaScaleLoc;
+
+ // Alpha test
+ UniformLocation alphaTestRefLoc;
+
+ // Shading, materials, and lighting
+ UniformLocation materialAmbientLoc;
+ UniformLocation materialDiffuseLoc;
+ UniformLocation materialSpecularLoc;
+ UniformLocation materialEmissiveLoc;
+ UniformLocation materialSpecularExponentLoc;
+
+ UniformLocation lightModelSceneAmbientLoc;
+
+ UniformLocation lightAmbientsLoc;
+ UniformLocation lightDiffusesLoc;
+ UniformLocation lightSpecularsLoc;
+ UniformLocation lightPositionsLoc;
+ UniformLocation lightDirectionsLoc;
+ UniformLocation lightSpotlightExponentsLoc;
+ UniformLocation lightSpotlightCutoffAnglesLoc;
+ UniformLocation lightAttenuationConstsLoc;
+ UniformLocation lightAttenuationLinearsLoc;
+ UniformLocation lightAttenuationQuadraticsLoc;
+
+ // Fog
+ UniformLocation fogDensityLoc;
+ UniformLocation fogStartLoc;
+ UniformLocation fogEndLoc;
+ UniformLocation fogColorLoc;
+
+ // Clip planes
+ UniformLocation clipPlanesLoc;
+
+ // Logic op
+ UniformLocation logicOpLoc;
+
+ // Point rasterization
+ UniformLocation pointSizeMinLoc;
+ UniformLocation pointSizeMaxLoc;
+ UniformLocation pointDistanceAttenuationLoc;
+
+ // Draw texture
+ UniformLocation drawTextureCoordsLoc;
+ UniformLocation drawTextureDimsLoc;
+ UniformLocation drawTextureNormalizedCropRectLoc;
+ };
+
+ struct GLES1UniformBuffers
+ {
+ std::array<Mat4Uniform, kTexUnitCount> textureMatrices;
+
+ std::array<Vec4Uniform, kTexUnitCount> texEnvColors;
+ std::array<GLfloat, kTexUnitCount> texEnvRgbScales;
+ std::array<GLfloat, kTexUnitCount> texEnvAlphaScales;
+
+ // Lighting
+ std::array<Vec4Uniform, kLightCount> lightAmbients;
+ std::array<Vec4Uniform, kLightCount> lightDiffuses;
+ std::array<Vec4Uniform, kLightCount> lightSpeculars;
+ std::array<Vec4Uniform, kLightCount> lightPositions;
+ std::array<Vec3Uniform, kLightCount> lightDirections;
+ std::array<GLfloat, kLightCount> spotlightExponents;
+ std::array<GLfloat, kLightCount> spotlightCutoffAngles;
+ std::array<GLfloat, kLightCount> attenuationConsts;
+ std::array<GLfloat, kLightCount> attenuationLinears;
+ std::array<GLfloat, kLightCount> attenuationQuadratics;
+
+ // Clip planes
+ std::array<Vec4Uniform, kClipPlaneCount> clipPlanes;
+
+ // Texture crop rectangles
+ std::array<Vec4Uniform, kTexUnitCount> texCropRects;
+ };
+
+ struct GLES1UberShaderState
+ {
+ GLES1UniformBuffers uniformBuffers;
+ GLES1ProgramState programState;
+ };
+
+ GLES1UberShaderState &getUberShaderState()
+ {
+ ASSERT(mUberShaderState.find(mShaderState) != mUberShaderState.end());
+ return mUberShaderState[mShaderState];
+ }
+
+ angle::HashMap<GLES1ShaderState, GLES1UberShaderState> mUberShaderState;
+
+ bool mDrawTextureEnabled = false;
+ GLfloat mDrawTextureCoords[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ GLfloat mDrawTextureDims[2] = {0.0f, 0.0f};
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_GLES1_RENDERER_H_
diff --git a/gfx/angle/checkout/src/libANGLE/GLES1Shaders.inc b/gfx/angle/checkout/src/libANGLE/GLES1Shaders.inc
new file mode 100644
index 0000000000..1c1ff51927
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/GLES1Shaders.inc
@@ -0,0 +1,1218 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// GLES1Shaders.inc: Defines GLES1 emulation shader.
+
+// The following variables are added in GLES1Renderer::initializeRendererProgram
+// bool clip_plane_enables
+// bool enable_alpha_test
+// bool enable_clip_planes
+// bool enable_color_material
+// bool enable_draw_texture
+// bool enable_fog
+// bool enable_lighting
+// bool enable_normalize
+// bool enable_rescale_normal
+// bool enable_texture_2d[kMaxTexUnits]
+// bool enable_texture_cube_map[kMaxTexUnits]
+// bool light_enables[kMaxLights]
+// bool light_model_two_sided
+// bool point_rasterization
+// bool point_sprite_coord_replace
+// bool point_sprite_enabled
+// bool shade_model_flat
+// int texture_format[kMaxTexUnits];
+// int texture_env_mode[kMaxTexUnits];
+// int combine_rgb[kMaxTexUnits];
+// int combine_alpha[kMaxTexUnits];
+// int src0_rgb[kMaxTexUnits];
+// int src0_alpha[kMaxTexUnits];
+// int src1_rgb[kMaxTexUnits];
+// int src1_alpha[kMaxTexUnits];
+// int src2_rgb[kMaxTexUnits];
+// int src2_alpha[kMaxTexUnits];
+// int op0_rgb[kMaxTexUnits];
+// int op0_alpha[kMaxTexUnits];
+// int op1_rgb[kMaxTexUnits];
+// int op1_alpha[kMaxTexUnits];
+// int op2_rgb[kMaxTexUnits];
+// int op2_alpha[kMaxTexUnits];
+// int alpha_func;
+// int fog_mode;
+
+constexpr char kGLES1DrawVShaderHeader[] = R"(#version 300 es
+precision highp float;
+
+#define kMaxTexUnits 4
+#define kMaxLights 8
+)";
+
+constexpr char kGLES1DrawVShader[] = R"(
+
+in vec4 pos;
+in vec3 normal;
+in vec4 color;
+in float pointsize;
+in vec4 texcoord0;
+in vec4 texcoord1;
+in vec4 texcoord2;
+in vec4 texcoord3;
+
+uniform mat4 projection;
+uniform mat4 modelview;
+uniform mat4 modelview_invtr;
+uniform mat4 texture_matrix[kMaxTexUnits];
+
+// Point rasterization//////////////////////////////////////////////////////////
+
+uniform float point_size_min;
+uniform float point_size_max;
+uniform vec3 point_distance_attenuation;
+
+// Shading: flat shading, lighting, and materials///////////////////////////////
+
+uniform vec4 material_ambient;
+uniform vec4 material_diffuse;
+uniform vec4 material_specular;
+uniform vec4 material_emissive;
+uniform float material_specular_exponent;
+
+uniform vec4 light_model_scene_ambient;
+
+uniform vec4 light_ambients[kMaxLights];
+uniform vec4 light_diffuses[kMaxLights];
+uniform vec4 light_speculars[kMaxLights];
+uniform vec4 light_positions[kMaxLights];
+uniform vec3 light_directions[kMaxLights];
+uniform float light_spotlight_exponents[kMaxLights];
+uniform float light_spotlight_cutoff_angles[kMaxLights];
+uniform float light_attenuation_consts[kMaxLights];
+uniform float light_attenuation_linears[kMaxLights];
+uniform float light_attenuation_quadratics[kMaxLights];
+
+// GL_OES_draw_texture uniforms/////////////////////////////////////////////////
+
+uniform vec4 draw_texture_coords;
+uniform vec2 draw_texture_dims;
+uniform vec4 draw_texture_normalized_crop_rect[kMaxTexUnits];
+
+// Varyings/////////////////////////////////////////////////////////////////////
+
+out vec4 pos_varying;
+out vec3 normal_varying;
+out vec4 color_varying;
+flat out vec4 color_varying_flat;
+out vec4 texcoord0_varying;
+out vec4 texcoord1_varying;
+out vec4 texcoord2_varying;
+out vec4 texcoord3_varying;
+
+float posDot(vec3 a, vec3 b)
+{
+ return max(dot(a, b), 0.0);
+}
+
+vec4 doLighting(vec4 vertexColor)
+{
+ vec4 materialAmbientActual = material_ambient;
+ vec4 materialDiffuseActual = material_diffuse;
+
+ if (enable_color_material)
+ {
+ materialAmbientActual = vertexColor;
+ materialDiffuseActual = vertexColor;
+ }
+
+ vec4 lightingResult = material_emissive + materialAmbientActual * light_model_scene_ambient;
+
+ for (int i = 0; i < kMaxLights; i++)
+ {
+
+ if (!light_enables[i])
+ continue;
+
+ vec4 lightAmbient = light_ambients[i];
+ vec4 lightDiffuse = light_diffuses[i];
+ vec4 lightSpecular = light_speculars[i];
+ vec4 lightPos = light_positions[i];
+ vec3 lightDir = light_directions[i];
+ float attConst = light_attenuation_consts[i];
+ float attLinear = light_attenuation_linears[i];
+ float attQuadratic = light_attenuation_quadratics[i];
+ float spotAngle = light_spotlight_cutoff_angles[i];
+ float spotExponent = light_spotlight_exponents[i];
+
+ vec3 toLight;
+ if (lightPos.w == 0.0)
+ {
+ toLight = lightPos.xyz;
+ }
+ else
+ {
+ toLight = (lightPos.xyz / lightPos.w - pos_varying.xyz);
+ }
+
+ float lightDist = length(toLight);
+ vec3 h = normalize(toLight) + vec3(0.0, 0.0, 1.0);
+ float ndotL = posDot(normal_varying, normalize(toLight));
+ float ndoth = posDot(normal_varying, normalize(h));
+
+ float specAtt;
+
+ if (ndotL != 0.0)
+ {
+ specAtt = 1.0;
+ }
+ else
+ {
+ specAtt = 0.0;
+ }
+
+ float att;
+
+ if (lightPos.w != 0.0)
+ {
+ float attDenom =
+ (attConst + attLinear * lightDist + attQuadratic * lightDist * lightDist);
+ att = 1.0 / attDenom;
+ }
+ else
+ {
+ att = 1.0;
+ }
+
+ float spot;
+
+ float spotAngleCos = cos(radians(spotAngle));
+ vec3 toSurfaceDir = -normalize(toLight);
+ float spotDot = posDot(toSurfaceDir, normalize(lightDir));
+
+ if (spotAngle == 180.0 || lightPos.w == 0.0)
+ {
+ spot = 1.0;
+ }
+ else
+ {
+ if (spotDot < spotAngleCos)
+ {
+ spot = 0.0;
+ }
+ else
+ {
+ spot = pow(spotDot, spotExponent);
+ }
+ }
+
+ vec4 contrib = materialAmbientActual * lightAmbient;
+ contrib += ndotL * materialDiffuseActual * lightDiffuse;
+ if (ndoth > 0.0 && material_specular_exponent > 0.0)
+ {
+ contrib += specAtt * pow(ndoth, material_specular_exponent) * material_specular *
+ lightSpecular;
+ }
+ else
+ {
+ if (ndoth > 0.0)
+ {
+ contrib += specAtt * material_specular * lightSpecular;
+ }
+ }
+ contrib *= att * spot;
+ lightingResult += contrib;
+ }
+
+ return lightingResult;
+}
+
+const vec4 drawTextureVertices[6] = vec4[](
+ vec4(0.0, 0.0, 0.0, 1.0),
+ vec4(1.0, 0.0, 0.0, 1.0),
+ vec4(1.0, 1.0, 0.0, 1.0),
+ vec4(0.0, 0.0, 0.0, 1.0),
+ vec4(1.0, 1.0, 0.0, 1.0),
+ vec4(0.0, 1.0, 0.0, 1.0));
+
+vec4 drawTexturePosition(int vertexId)
+{
+
+ float drawTexX = draw_texture_coords[0];
+ float drawTexY = draw_texture_coords[1];
+ float drawTexZ = draw_texture_coords[2];
+ float drawTexW = draw_texture_dims[0];
+ float drawTexH = draw_texture_dims[1];
+
+ return vec4(drawTexX, drawTexY, drawTexZ, 0.0) +
+ drawTextureVertices[vertexId] *
+ vec4(drawTexW, drawTexH, 1.0, 1.0);
+}
+
+vec4 drawTextureTexCoord(int vertexId, int textureUnit)
+{
+ float texCropU = draw_texture_normalized_crop_rect[textureUnit].x;
+ float texCropV = draw_texture_normalized_crop_rect[textureUnit].y;
+ float texCropW = draw_texture_normalized_crop_rect[textureUnit].z;
+ float texCropH = draw_texture_normalized_crop_rect[textureUnit].w;
+
+ return vec4(texCropU, texCropV, 0.0, 0.0) +
+ drawTextureVertices[vertexId] *
+ vec4(texCropW, texCropH, 0.0, 0.0);
+}
+
+vec4 calcWorldPosition(vec4 posInput)
+{
+ return modelview * posInput;
+}
+
+vec4 calcNdcFromWorldPosition(vec4 worldPos)
+{
+ return projection * worldPos;
+}
+
+float calcPointSize(vec4 ndcPos)
+{
+ float dist = length(ndcPos.z);
+ float attConst = point_distance_attenuation[0];
+ float attLinear = point_distance_attenuation[1];
+ float attQuad = point_distance_attenuation[2];
+ float attPart = attConst + attLinear * dist + attQuad * dist * dist;
+ float attPointSize = pointsize / pow(attPart, 0.5);
+
+ return clamp(attPointSize, point_size_min, point_size_max);
+}
+
+vec3 calcNormal(vec3 normalInput)
+{
+ mat3 mvInvTr3 = mat3(modelview_invtr);
+ vec3 result = mvInvTr3 * normalInput;
+
+ if (enable_rescale_normal)
+ {
+ float rescale = 1.0;
+ vec3 rescaleVec = vec3(mvInvTr3[2]);
+ float len = length(rescaleVec);
+ if (len > 0.0)
+ {
+ rescale = 1.0 / len;
+ }
+ result *= rescale;
+ }
+
+ if (enable_normalize)
+ {
+ result = normalize(result);
+ }
+
+ return result;
+}
+
+void main()
+{
+ if (enable_draw_texture)
+ {
+ int vertexId = gl_VertexID;
+ vec4 posDrawTexture = drawTexturePosition(vertexId);
+
+ gl_Position = posDrawTexture;
+ pos_varying = posDrawTexture;
+
+ normal_varying = normal;
+
+ gl_PointSize = pointsize;
+
+ texcoord0_varying = drawTextureTexCoord(vertexId, 0);
+ texcoord1_varying = drawTextureTexCoord(vertexId, 1);
+ texcoord2_varying = drawTextureTexCoord(vertexId, 2);
+ texcoord3_varying = drawTextureTexCoord(vertexId, 3);
+ }
+ else
+ {
+ vec4 worldPos = calcWorldPosition(pos);
+ vec4 ndcPos = calcNdcFromWorldPosition(worldPos);
+
+ gl_Position = ndcPos;
+ pos_varying = worldPos;
+
+ normal_varying = calcNormal(normal);
+
+ // Avoid calculating point size stuff
+ // if we are not rendering points.
+ if (point_rasterization)
+ {
+ gl_PointSize = calcPointSize(ndcPos);
+ }
+ else
+ {
+ gl_PointSize = pointsize;
+ }
+
+ texcoord0_varying = texture_matrix[0] * texcoord0;
+ texcoord1_varying = texture_matrix[1] * texcoord1;
+ texcoord2_varying = texture_matrix[2] * texcoord2;
+ texcoord3_varying = texture_matrix[3] * texcoord3;
+ }
+
+ vec4 vertex_color = color;
+
+ if (enable_lighting)
+ {
+ vertex_color = doLighting(color);
+ }
+
+ vertex_color = clamp(vertex_color, vec4(0), vec4(1));
+
+ color_varying = vertex_color;
+ color_varying_flat = vertex_color;
+}
+)";
+
+constexpr char kGLES1DrawFShaderVersion[] = R"(#version 300 es
+)";
+
+constexpr char kGLES1DrawFShaderHeader[] = R"(precision highp float;
+
+// Defines for GL constants
+#define kMaxTexUnits 4
+#define kMaxClipPlanes 6
+
+#define kModulate 0x2100
+#define kDecal 0x2101
+#define kCombine 0x8570
+#define kReplace 0x1E01
+#define kBlend 0x0BE2
+#define kAdd 0x0104
+
+#define kAddSigned 0x8574
+#define kInterpolate 0x8575
+#define kSubtract 0x84E7
+#define kDot3Rgb 0x86AE
+#define kDot3Rgba 0x86AF
+
+#define kAlpha 0x1906
+#define kRGB 0x1907
+#define kRGBA 0x1908
+#define kLuminance 0x1909
+#define kLuminanceAlpha 0x190A
+
+#define kTexture 0x1702
+#define kConstant 0x8576
+#define kPrimaryColor 0x8577
+#define kPrevious 0x8578
+
+#define kSrcColor 0x0300
+#define kOneMinusSrcColor 0x0301
+#define kSrcAlpha 0x0302
+#define kOneMinusSrcAlpha 0x0303
+
+#define kLinear 0x2601
+#define kExp 0x0800
+#define kExp2 0x0801
+
+#define kNever 0x0200
+#define kLess 0x0201
+#define kEqual 0x0202
+#define kLequal 0x0203
+#define kGreater 0x0204
+#define kNotequal 0x0205
+#define kGequal 0x0206
+#define kAlways 0x0207
+#define kZero 0x0
+#define kOne 0x1
+
+#define kAnd 0u
+#define kAndInverted 1u
+#define kAndReverse 2u
+#define kClear 3u
+#define kCopy 4u
+#define kCopyInverted 5u
+#define kEquiv 6u
+#define kInvert 7u
+#define kNand 8u
+#define kNoop 9u
+#define kNor 10u
+#define kOr 11u
+#define kOrInverted 12u
+#define kOrReverse 13u
+#define kSet 14u
+#define kXor 15u
+)";
+
+constexpr char kGLES1DrawFShaderUniformDefs[] = R"(
+
+// Texture units ///////////////////////////////////////////////////////////////
+
+// These are not arrays because hw support for arrays
+// of samplers is rather lacking.
+
+uniform sampler2D tex_sampler0;
+uniform samplerCube tex_cube_sampler0;
+
+uniform sampler2D tex_sampler1;
+uniform samplerCube tex_cube_sampler1;
+
+uniform sampler2D tex_sampler2;
+uniform samplerCube tex_cube_sampler2;
+
+uniform sampler2D tex_sampler3;
+uniform samplerCube tex_cube_sampler3;
+
+uniform vec4 texture_env_color[kMaxTexUnits];
+uniform float texture_env_rgb_scale[kMaxTexUnits];
+uniform float texture_env_alpha_scale[kMaxTexUnits];
+
+// Vertex attributes////////////////////////////////////////////////////////////
+
+in vec4 pos_varying;
+in vec3 normal_varying;
+in vec4 color_varying;
+flat in vec4 color_varying_flat;
+in vec4 texcoord0_varying;
+in vec4 texcoord1_varying;
+in vec4 texcoord2_varying;
+in vec4 texcoord3_varying;
+
+// Alpha test///////////////////////////////////////////////////////////////////
+
+uniform float alpha_test_ref;
+
+// Fog /////////////////////////////////////////////////////////////////////////
+
+uniform float fog_density;
+uniform float fog_start;
+uniform float fog_end;
+uniform vec4 fog_color;
+
+// User clip plane /////////////////////////////////////////////////////////////
+
+uniform vec4 clip_planes[kMaxClipPlanes];
+
+// Logic Op ////////////////////////////////////////////////////////////////////
+
+// Format is:
+// - 4x4 bits depicting the bit width of each channel of color output
+// - 4 bits for the op based on LogicalOperation's packing
+uniform highp uint logic_op;
+
+// Point rasterization//////////////////////////////////////////////////////////
+
+// GL_OES_draw_texture//////////////////////////////////////////////////////////
+)";
+
+constexpr char kGLES1DrawFShaderOutputDef[] = R"(
+out vec4 frag_color;
+)";
+
+constexpr char kGLES1DrawFShaderFramebufferFetchOutputDef[] = R"(
+inout vec4 frag_color;
+)";
+
+constexpr char kGLES1DrawFShaderFramebufferFetchNonCoherentOutputDef[] = R"(
+layout(noncoherent) inout vec4 frag_color;
+)";
+
+constexpr char kGLES1DrawFShaderFunctions[] = R"(
+
+bool doAlphaTest(vec4 currentFragment)
+{
+ bool shouldPassAlpha = false;
+ float incAlpha = currentFragment.a;
+
+ switch (alpha_func)
+ {
+ case kNever:
+ shouldPassAlpha = false;
+ break;
+ case kLess:
+ shouldPassAlpha = incAlpha < alpha_test_ref;
+ break;
+ case kLequal:
+ shouldPassAlpha = incAlpha <= alpha_test_ref;
+ break;
+ case kEqual:
+ shouldPassAlpha = incAlpha == alpha_test_ref;
+ break;
+ case kGequal:
+ shouldPassAlpha = incAlpha >= alpha_test_ref;
+ break;
+ case kGreater:
+ shouldPassAlpha = incAlpha > alpha_test_ref;
+ break;
+ case kNotequal:
+ shouldPassAlpha = incAlpha != alpha_test_ref;
+ break;
+ case kAlways:
+ default:
+ shouldPassAlpha = true;
+ break;
+ }
+
+ return shouldPassAlpha;
+}
+
+bool doClipPlaneTest()
+{
+ bool res = true;
+
+ for (int i = 0; i < kMaxClipPlanes; i++)
+ {
+ if (clip_plane_enables[i])
+ {
+ float dist = dot(clip_planes[i].xyz, pos_varying.xyz) + clip_planes[i].w * pos_varying.w;
+ res = res && (dist >= 0.0);
+ }
+ }
+
+ return res;
+}
+
+vec4 doFog(vec4 currentFragment)
+{
+
+ float eyeDist = -pos_varying.z / pos_varying.w;
+ float f = 1.0;
+ switch (fog_mode)
+ {
+ case kExp:
+ f = exp(-fog_density * eyeDist);
+ break;
+ case kExp2:
+ f = exp(-(pow(fog_density * eyeDist, 2.0)));
+ break;
+ case kLinear:
+ f = (fog_end - eyeDist) / (fog_end - fog_start);
+ break;
+ default:
+ break;
+ }
+
+ f = clamp(f, 0.0, 1.0);
+ vec4 result = vec4(f * currentFragment.rgb + (1.0 - f) * fog_color.rgb, currentFragment.a);
+ return result;
+}
+)";
+
+constexpr char kGLES1DrawFShaderLogicOpFramebufferFetchDisabled[] = R"(
+vec4 applyLogicOp(vec4 currentFragment)
+{
+ return currentFragment;
+}
+)";
+
+// applyLogicOp takes logic-op information from a packed uniform and applies it to the color
+// attachment using framebuffer fetch. See the description of logic_op above for the format of the
+// uniform.
+//
+// In particular, 4 bits in logic_op (at offset 16) contain the packed logical operation (of
+// LogicalOperation type). Based on the selected operation, the formula specified in the spec is
+// applied (applied as bitwise operations on unorm values).
+constexpr char kGLES1DrawFShaderLogicOpFramebufferFetchEnabled[] = R"(
+vec4 applyLogicOp(vec4 currentFragment)
+{
+ vec4 previousFragment = frag_color;
+
+ mediump uvec4 channelWidths = uvec4(logic_op & 0xFu,
+ logic_op >> 4u & 0xFu,
+ logic_op >> 8u & 0xFu,
+ logic_op >> 12u & 0xFu);
+
+ mediump uvec4 channelMasks = (uvec4(1) << channelWidths) - 1u;
+
+ mediump uvec4 src = uvec4(round(currentFragment * vec4(channelMasks)));
+ mediump uvec4 dst = uvec4(round(previousFragment * vec4(channelMasks)));
+ mediump uvec4 result;
+
+ switch (logic_op >> 16u & 0xFu)
+ {
+ case kAnd:
+ result = src & dst;
+ break;
+ case kAndInverted:
+ result = ~src & dst;
+ break;
+ case kAndReverse:
+ result = src & ~dst;
+ break;
+ case kClear:
+ result = uvec4(0);
+ break;
+ case kCopy:
+ result = src;
+ break;
+ case kCopyInverted:
+ result = ~src;
+ break;
+ case kEquiv:
+ result = ~(src ^ dst);
+ break;
+ case kInvert:
+ result = ~dst;
+ break;
+ case kNand:
+ result = ~(src & dst);
+ break;
+ case kNoop:
+ result = dst;
+ break;
+ case kNor:
+ result = ~(src | dst);
+ break;
+ case kOr:
+ result = src | dst;
+ break;
+ case kOrInverted:
+ result = ~src | dst;
+ break;
+ case kOrReverse:
+ result = src | ~dst;
+ break;
+ case kSet:
+ result = channelMasks;
+ break;
+ case kXor:
+ result = src ^ dst;
+ break;
+ }
+
+ result &= channelMasks;
+
+ // Avoid division by zero for formats without alpha
+ channelMasks.a = max(channelMasks.a, 1u);
+
+ return vec4(result) / vec4(channelMasks);
+}
+)";
+
+constexpr char kGLES1DrawFShaderMultitexturing[] = R"(
+
+bool isTextureUnitEnabled(int unit)
+{
+ return enable_texture_2d[unit] || enable_texture_cube_map[unit];
+}
+
+vec4 getTextureColor(int unit)
+{
+ vec4 res;
+
+ switch (unit)
+ {
+ case 0:
+ if (enable_texture_2d[0])
+ {
+ res = texture(tex_sampler0, texcoord0_varying.xy);
+ }
+ else if (enable_texture_cube_map[0])
+ {
+ res = texture(tex_cube_sampler0, texcoord0_varying.xyz);
+ }
+ break;
+ case 1:
+ if (enable_texture_2d[1])
+ {
+ res = texture(tex_sampler1, texcoord1_varying.xy);
+ }
+ else if (enable_texture_cube_map[1])
+ {
+ res = texture(tex_cube_sampler1, texcoord1_varying.xyz);
+ }
+ break;
+ case 2:
+ if (enable_texture_2d[2])
+ {
+ res = texture(tex_sampler2, texcoord2_varying.xy);
+ }
+ else if (enable_texture_cube_map[2])
+ {
+ res = texture(tex_cube_sampler2, texcoord2_varying.xyz);
+ }
+ break;
+ case 3:
+ if (enable_texture_2d[3])
+ {
+ res = texture(tex_sampler3, texcoord3_varying.xy);
+ }
+ else if (enable_texture_cube_map[3])
+ {
+ // TODO: Weird stuff happens
+ // res = texture(tex_cube_sampler3, texcoord3_varying.xyz);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return res;
+}
+
+vec4 getPointSpriteTextureColor(int unit)
+{
+ vec4 res;
+
+ switch (unit)
+ {
+ case 0:
+ if (enable_texture_2d[0])
+ {
+ res = texture(tex_sampler0, gl_PointCoord.xy);
+ }
+ break;
+ case 1:
+ if (enable_texture_2d[1])
+ {
+ res = texture(tex_sampler1, gl_PointCoord.xy);
+ }
+ break;
+ case 2:
+ if (enable_texture_2d[2])
+ {
+ res = texture(tex_sampler2, gl_PointCoord.xy);
+ }
+ break;
+ case 3:
+ if (enable_texture_2d[3])
+ {
+ res = texture(tex_sampler3, gl_PointCoord.xy);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return res;
+}
+
+vec3 textureCombineSrcnOpnRgb(int srcnRgb,
+ int opnRgb,
+ vec4 textureEnvColor,
+ vec4 vertexColor,
+ vec4 texturePrevColor,
+ vec4 textureColor)
+{
+ vec3 res;
+ vec4 op;
+
+ switch (srcnRgb)
+ {
+ case kTexture:
+ op = textureColor;
+ break;
+ case kConstant:
+ op = textureEnvColor;
+ break;
+ case kPrimaryColor:
+ op = vertexColor;
+ break;
+ case kPrevious:
+ op = texturePrevColor;
+ break;
+ default:
+ op = texturePrevColor;
+ break;
+ }
+
+ switch (opnRgb)
+ {
+ case kSrcColor:
+ res = op.rgb;
+ break;
+ case kOneMinusSrcColor:
+ res = 1.0 - op.rgb;
+ break;
+ case kSrcAlpha:
+ res = vec3(op.a, op.a, op.a);
+ break;
+ case kOneMinusSrcAlpha:
+ res = vec3(1.0 - op.a, 1.0 - op.a, 1.0 - op.a);
+ break;
+ default:
+ break;
+ }
+
+ return res;
+}
+
+float textureCombineSrcnOpnAlpha(int srcn,
+ int opn,
+ vec4 textureEnvColor,
+ vec4 vertexColor,
+ vec4 texturePrevColor,
+ vec4 textureColor)
+{
+ float res;
+ vec4 op;
+
+ switch (srcn)
+ {
+ case kTexture:
+ op = textureColor;
+ break;
+ case kConstant:
+ op = textureEnvColor;
+ break;
+ case kPrimaryColor:
+ op = vertexColor;
+ break;
+ case kPrevious:
+ op = texturePrevColor;
+ break;
+ default:
+ op = texturePrevColor;
+ break;
+ }
+
+ switch (opn)
+ {
+ case kSrcAlpha:
+ res = op.a;
+ break;
+ case kOneMinusSrcAlpha:
+ res = 1.0 - op.a;
+ break;
+ default:
+ break;
+ }
+
+ return res;
+}
+
+vec4 textureCombine(int combineRgb,
+ int combineAlpha,
+ int src0Rgb,
+ int src0Alpha,
+ int src1Rgb,
+ int src1Alpha,
+ int src2Rgb,
+ int src2Alpha,
+ int op0Rgb,
+ int op0Alpha,
+ int op1Rgb,
+ int op1Alpha,
+ int op2Rgb,
+ int op2Alpha,
+ vec4 textureEnvColor,
+ float rgbScale,
+ float alphaScale,
+ vec4 vertexColor,
+ vec4 texturePrevColor,
+ vec4 textureColor)
+{
+
+ vec3 resRgb;
+ float resAlpha;
+
+ vec3 arg0Rgb;
+ float arg0Alpha;
+ vec3 arg1Rgb;
+ float arg1Alpha;
+ vec3 arg2Rgb;
+ float arg2Alpha;
+ float dotVal;
+
+ arg0Rgb = textureCombineSrcnOpnRgb(src0Rgb, op0Rgb, textureEnvColor, vertexColor,
+ texturePrevColor, textureColor);
+ arg0Alpha = textureCombineSrcnOpnAlpha(src0Alpha, op0Alpha, textureEnvColor, vertexColor,
+ texturePrevColor, textureColor);
+
+ if (combineRgb != kReplace)
+ {
+ arg1Rgb = textureCombineSrcnOpnRgb(src1Rgb, op1Rgb, textureEnvColor, vertexColor,
+ texturePrevColor, textureColor);
+ }
+
+ if (combineAlpha != kReplace)
+ {
+ arg1Alpha = textureCombineSrcnOpnAlpha(src1Alpha, op1Alpha, textureEnvColor, vertexColor,
+ texturePrevColor, textureColor);
+ }
+
+ if (combineRgb == kInterpolate)
+ {
+ arg2Rgb = textureCombineSrcnOpnRgb(src2Rgb, op2Rgb, textureEnvColor, vertexColor,
+ texturePrevColor, textureColor);
+ }
+
+ if (combineAlpha == kInterpolate)
+ {
+ arg2Alpha = textureCombineSrcnOpnAlpha(src2Alpha, op2Alpha, textureEnvColor, vertexColor,
+ texturePrevColor, textureColor);
+ }
+
+ switch (combineRgb)
+ {
+ case kReplace:
+ resRgb = arg0Rgb;
+ break;
+ case kModulate:
+ resRgb = arg0Rgb * arg1Rgb;
+ break;
+ case kAdd:
+ resRgb = arg0Rgb + arg1Rgb;
+ break;
+ case kAddSigned:
+ resRgb = arg0Rgb + arg1Rgb - 0.5;
+ break;
+ case kInterpolate:
+ resRgb = arg0Rgb * arg2Rgb + arg1Rgb * (1.0 - arg2Rgb);
+ break;
+ case kSubtract:
+ resRgb = arg0Rgb - arg1Rgb;
+ break;
+ default:
+ break;
+ }
+
+ switch (combineAlpha)
+ {
+ case kReplace:
+ resAlpha = arg0Alpha;
+ break;
+ case kModulate:
+ resAlpha = arg0Alpha * arg1Alpha;
+ break;
+ case kAdd:
+ resAlpha = arg0Alpha + arg1Alpha;
+ break;
+ case kAddSigned:
+ resAlpha = arg0Alpha + arg1Alpha - 0.5;
+ break;
+ case kInterpolate:
+ resAlpha = arg0Alpha * arg2Alpha + arg1Alpha * (1.0 - arg2Alpha);
+ break;
+ case kSubtract:
+ resAlpha = arg0Alpha - arg1Alpha;
+ break;
+ default:
+ break;
+ }
+
+ if (combineRgb == kDot3Rgb || combineRgb == kDot3Rgba)
+ {
+ dotVal = 4.0 * dot(arg0Rgb - 0.5, arg1Rgb - 0.5);
+
+ if (combineRgb == kDot3Rgb)
+ {
+ return vec4(dotVal, dotVal, dotVal, resAlpha);
+ }
+ else
+ {
+ return vec4(dotVal, dotVal, dotVal, dotVal);
+ }
+ }
+ else
+ {
+ return vec4(resRgb, resAlpha);
+ }
+}
+
+vec4 textureFunction(int unit,
+ int texFormat,
+ int envMode,
+ int combineRgb,
+ int combineAlpha,
+ int src0Rgb,
+ int src0Alpha,
+ int src1Rgb,
+ int src1Alpha,
+ int src2Rgb,
+ int src2Alpha,
+ int op0Rgb,
+ int op0Alpha,
+ int op1Rgb,
+ int op1Alpha,
+ int op2Rgb,
+ int op2Alpha,
+ vec4 textureEnvColor,
+ float rgbScale,
+ float alphaScale,
+ vec4 vertexColor,
+ vec4 texturePrevColor,
+ vec4 textureColor)
+{
+
+ if (!isTextureUnitEnabled(unit))
+ {
+ return texturePrevColor;
+ }
+
+ vec4 res;
+
+ switch (envMode)
+ {
+ case kReplace:
+ switch (texFormat)
+ {
+ case kAlpha:
+ res.rgb = texturePrevColor.rgb;
+ res.a = textureColor.a;
+ break;
+ case kRGBA:
+ case kLuminanceAlpha:
+ res.rgba = textureColor.rgba;
+ break;
+ case kRGB:
+ case kLuminance:
+ default:
+ res.rgb = textureColor.rgb;
+ res.a = texturePrevColor.a;
+ break;
+ }
+ break;
+ case kModulate:
+ switch (texFormat)
+ {
+ case kAlpha:
+ res.rgb = texturePrevColor.rgb;
+ res.a = texturePrevColor.a * textureColor.a;
+ break;
+ case kRGBA:
+ case kLuminanceAlpha:
+ res.rgba = texturePrevColor.rgba * textureColor.rgba;
+ break;
+ case kRGB:
+ case kLuminance:
+ default:
+ res.rgb = texturePrevColor.rgb * textureColor.rgb;
+ res.a = texturePrevColor.a;
+ break;
+ }
+ break;
+ case kDecal:
+ switch (texFormat)
+ {
+ case kRGB:
+ res.rgb = textureColor.rgb;
+ res.a = texturePrevColor.a;
+ break;
+ case kRGBA:
+ res.rgb = texturePrevColor.rgb * (1.0 - textureColor.a) +
+ textureColor.rgb * textureColor.a;
+ res.a = texturePrevColor.a;
+ break;
+ case kAlpha:
+ case kLuminance:
+ case kLuminanceAlpha:
+ default:
+ res.rgb = texturePrevColor.rgb * textureColor.rgb;
+ res.a = texturePrevColor.a;
+ break;
+ }
+ break;
+ case kBlend:
+ switch (texFormat)
+ {
+ case kAlpha:
+ res.rgb = texturePrevColor.rgb;
+ res.a = textureColor.a * texturePrevColor.a;
+ break;
+ case kLuminance:
+ case kRGB:
+ res.rgb = texturePrevColor.rgb * (1.0 - textureColor.rgb) +
+ textureEnvColor.rgb * textureColor.rgb;
+ res.a = texturePrevColor.a;
+ break;
+ case kLuminanceAlpha:
+ case kRGBA:
+ default:
+ res.rgb = texturePrevColor.rgb * (1.0 - textureColor.rgb) +
+ textureEnvColor.rgb * textureColor.rgb;
+ res.a = textureColor.a * texturePrevColor.a;
+ break;
+ }
+ break;
+ case kAdd:
+ switch (texFormat)
+ {
+ case kAlpha:
+ res.rgb = texturePrevColor.rgb;
+ res.a = textureColor.a * texturePrevColor.a;
+ break;
+ case kLuminance:
+ case kRGB:
+ res.rgb = texturePrevColor.rgb + textureColor.rgb;
+ res.a = texturePrevColor.a;
+ break;
+ case kLuminanceAlpha:
+ case kRGBA:
+ default:
+ res.rgb = texturePrevColor.rgb + textureColor.rgb;
+ res.a = textureColor.a * texturePrevColor.a;
+ break;
+ }
+ break;
+ case kCombine:
+ res = textureCombine(combineRgb, combineAlpha, src0Rgb, src0Alpha, src1Rgb, src1Alpha,
+ src2Rgb, src2Alpha, op0Rgb, op0Alpha, op1Rgb, op1Alpha, op2Rgb,
+ op2Alpha, textureEnvColor, rgbScale, alphaScale, vertexColor,
+ texturePrevColor, textureColor);
+ res.rgb *= rgbScale;
+ res.a *= alphaScale;
+ break;
+ default:
+ break;
+ }
+
+ return clamp(res, 0.0, 1.0);
+}
+)";
+
+constexpr char kGLES1DrawFShaderMain[] = R"(
+void main()
+{
+ if (enable_clip_planes && !enable_draw_texture)
+ {
+ if (!doClipPlaneTest())
+ {
+ discard;
+ }
+ }
+
+ vec4 vertex_color;
+
+ if (shade_model_flat)
+ {
+ vertex_color = color_varying_flat;
+ }
+ else
+ {
+ vertex_color = color_varying;
+ }
+
+ vec4 currentFragment = vertex_color;
+
+ vec4 texturePrevColor = currentFragment;
+
+ for (int i = 0; i < kMaxTexUnits; i++)
+ {
+ vec4 textureColor;
+
+ if (point_rasterization && point_sprite_enabled &&
+ point_sprite_coord_replace[i]) {
+ textureColor = getPointSpriteTextureColor(i);
+ } else {
+ textureColor = getTextureColor(i);
+ }
+
+ currentFragment = textureFunction(
+ i, texture_format[i], texture_env_mode[i], combine_rgb[i], combine_alpha[i],
+ src0_rgb[i], src0_alpha[i], src1_rgb[i], src1_alpha[i], src2_rgb[i], src2_alpha[i],
+ op0_rgb[i], op0_alpha[i], op1_rgb[i], op1_alpha[i], op2_rgb[i], op2_alpha[i],
+ texture_env_color[i], texture_env_rgb_scale[i], texture_env_alpha_scale[i],
+ vertex_color, texturePrevColor, textureColor);
+
+ texturePrevColor = currentFragment;
+ }
+
+ if (enable_fog)
+ {
+ currentFragment = doFog(currentFragment);
+ }
+
+ if (enable_alpha_test && !doAlphaTest(currentFragment))
+ {
+ discard;
+ }
+
+ frag_color = applyLogicOp(currentFragment);
+}
+)";
diff --git a/gfx/angle/checkout/src/libANGLE/GLES1State.cpp b/gfx/angle/checkout/src/libANGLE/GLES1State.cpp
new file mode 100644
index 0000000000..17ad0de3ad
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/GLES1State.cpp
@@ -0,0 +1,609 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// GLES1State.cpp: Implements the GLES1State class, tracking state
+// for GLES1 contexts.
+
+#include "libANGLE/GLES1State.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/GLES1Renderer.h"
+
+namespace gl
+{
+
+TextureCoordF::TextureCoordF() = default;
+
+TextureCoordF::TextureCoordF(float _s, float _t, float _r, float _q) : s(_s), t(_t), r(_r), q(_q) {}
+
+bool TextureCoordF::operator==(const TextureCoordF &other) const
+{
+ return s == other.s && t == other.t && r == other.r && q == other.q;
+}
+
+MaterialParameters::MaterialParameters() = default;
+
+LightModelParameters::LightModelParameters() = default;
+
+LightParameters::LightParameters() = default;
+
+LightParameters::LightParameters(const LightParameters &other) = default;
+
+FogParameters::FogParameters() = default;
+
+TextureEnvironmentParameters::TextureEnvironmentParameters() = default;
+
+TextureEnvironmentParameters::TextureEnvironmentParameters(
+ const TextureEnvironmentParameters &other) = default;
+
+PointParameters::PointParameters() = default;
+
+PointParameters::PointParameters(const PointParameters &other) = default;
+
+ClipPlaneParameters::ClipPlaneParameters() = default;
+
+ClipPlaneParameters::ClipPlaneParameters(bool enabled, const angle::Vector4 &equation)
+ : enabled(enabled), equation(equation)
+{}
+
+ClipPlaneParameters::ClipPlaneParameters(const ClipPlaneParameters &other) = default;
+
+ClipPlaneParameters &ClipPlaneParameters::operator=(const ClipPlaneParameters &other) = default;
+
+GLES1State::GLES1State()
+ : mGLState(nullptr),
+ mVertexArrayEnabled(false),
+ mNormalArrayEnabled(false),
+ mColorArrayEnabled(false),
+ mPointSizeArrayEnabled(false),
+ mLineSmoothEnabled(false),
+ mPointSmoothEnabled(false),
+ mPointSpriteEnabled(false),
+ mAlphaTestEnabled(false),
+ mLogicOpEnabled(false),
+ mLightingEnabled(false),
+ mFogEnabled(false),
+ mRescaleNormalEnabled(false),
+ mNormalizeEnabled(false),
+ mColorMaterialEnabled(false),
+ mReflectionMapEnabled(false),
+ mCurrentColor({0.0f, 0.0f, 0.0f, 0.0f}),
+ mCurrentNormal({0.0f, 0.0f, 0.0f}),
+ mClientActiveTexture(0),
+ mMatrixMode(MatrixType::Modelview),
+ mShadeModel(ShadingModel::Smooth),
+ mAlphaTestFunc(AlphaTestFunc::AlwaysPass),
+ mAlphaTestRef(0.0f),
+ mLogicOp(LogicalOperation::Copy),
+ mLineSmoothHint(HintSetting::DontCare),
+ mPointSmoothHint(HintSetting::DontCare),
+ mPerspectiveCorrectionHint(HintSetting::DontCare),
+ mFogHint(HintSetting::DontCare)
+{}
+
+GLES1State::~GLES1State() = default;
+
+// Taken from the GLES 1.x spec which specifies all initial state values.
+void GLES1State::initialize(const Context *context, const State *state)
+{
+ mGLState = state;
+
+ const Caps &caps = context->getCaps();
+
+ mTexUnitEnables.resize(caps.maxMultitextureUnits);
+ for (auto &enables : mTexUnitEnables)
+ {
+ enables.reset();
+ }
+
+ mVertexArrayEnabled = false;
+ mNormalArrayEnabled = false;
+ mColorArrayEnabled = false;
+ mPointSizeArrayEnabled = false;
+ mTexCoordArrayEnabled.resize(caps.maxMultitextureUnits, false);
+
+ mLineSmoothEnabled = false;
+ mPointSmoothEnabled = false;
+ mPointSpriteEnabled = false;
+ mLogicOpEnabled = false;
+ mAlphaTestEnabled = false;
+ mLightingEnabled = false;
+ mFogEnabled = false;
+ mRescaleNormalEnabled = false;
+ mNormalizeEnabled = false;
+ mColorMaterialEnabled = false;
+ mReflectionMapEnabled = false;
+
+ mMatrixMode = MatrixType::Modelview;
+
+ mCurrentColor = {1.0f, 1.0f, 1.0f, 1.0f};
+ mCurrentNormal = {0.0f, 0.0f, 1.0f};
+ mCurrentTextureCoords.resize(caps.maxMultitextureUnits);
+ mClientActiveTexture = 0;
+
+ mTextureEnvironments.resize(caps.maxMultitextureUnits);
+
+ mModelviewMatrices.push_back(angle::Mat4());
+ mProjectionMatrices.push_back(angle::Mat4());
+ mTextureMatrices.resize(caps.maxMultitextureUnits);
+ for (auto &stack : mTextureMatrices)
+ {
+ stack.push_back(angle::Mat4());
+ }
+
+ mMaterial.ambient = {0.2f, 0.2f, 0.2f, 1.0f};
+ mMaterial.diffuse = {0.8f, 0.8f, 0.8f, 1.0f};
+ mMaterial.specular = {0.0f, 0.0f, 0.0f, 1.0f};
+ mMaterial.emissive = {0.0f, 0.0f, 0.0f, 1.0f};
+
+ mMaterial.specularExponent = 0.0f;
+
+ mLightModel.color = {0.2f, 0.2f, 0.2f, 1.0f};
+ mLightModel.twoSided = false;
+
+ mLights.resize(caps.maxLights);
+
+ // GL_LIGHT0 is special and has default state that avoids all-black renderings.
+ mLights[0].diffuse = {1.0f, 1.0f, 1.0f, 1.0f};
+ mLights[0].specular = {1.0f, 1.0f, 1.0f, 1.0f};
+
+ mFog.mode = FogMode::Exp;
+ mFog.density = 1.0f;
+ mFog.start = 0.0f;
+ mFog.end = 1.0f;
+
+ mFog.color = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ mShadeModel = ShadingModel::Smooth;
+
+ mAlphaTestFunc = AlphaTestFunc::AlwaysPass;
+ mAlphaTestRef = 0.0f;
+
+ mLogicOp = LogicalOperation::Copy;
+
+ mClipPlanes.resize(caps.maxClipPlanes,
+ ClipPlaneParameters(false, angle::Vector4(0.0f, 0.0f, 0.0f, 0.0f)));
+
+ mLineSmoothHint = HintSetting::DontCare;
+ mPointSmoothHint = HintSetting::DontCare;
+ mPerspectiveCorrectionHint = HintSetting::DontCare;
+ mFogHint = HintSetting::DontCare;
+
+ // The user-specified point size, GL_POINT_SIZE_MAX,
+ // is initially equal to the implementation maximum.
+ mPointParameters.pointSizeMax = caps.maxAliasedPointSize;
+
+ mDirtyBits.set();
+}
+
+void GLES1State::setAlphaFunc(AlphaTestFunc func, GLfloat ref)
+{
+ setDirty(DIRTY_GLES1_ALPHA_TEST);
+ mAlphaTestFunc = func;
+ mAlphaTestRef = ref;
+}
+
+void GLES1State::setClientTextureUnit(unsigned int unit)
+{
+ setDirty(DIRTY_GLES1_CLIENT_ACTIVE_TEXTURE);
+ mClientActiveTexture = unit;
+}
+
+unsigned int GLES1State::getClientTextureUnit() const
+{
+ return mClientActiveTexture;
+}
+
+void GLES1State::setCurrentColor(const ColorF &color)
+{
+ setDirty(DIRTY_GLES1_CURRENT_VECTOR);
+ mCurrentColor = color;
+
+ // > When enabled, both the ambient (acm) and diffuse (dcm) properties of both the front and
+ // > back material are immediately set to the value of the current color, and will track changes
+ // > to the current color resulting from either the Color commands or drawing vertex arrays with
+ // > the color array enabled.
+ // > The replacements made to material properties are permanent; the replaced values remain
+ // > until changed by either sending a new color or by setting a new material value when
+ // > COLOR_MATERIAL is not currently enabled, to override that particular value.
+ if (isColorMaterialEnabled())
+ {
+ mMaterial.ambient = color;
+ mMaterial.diffuse = color;
+ }
+}
+
+const ColorF &GLES1State::getCurrentColor() const
+{
+ return mCurrentColor;
+}
+
+void GLES1State::setCurrentNormal(const angle::Vector3 &normal)
+{
+ setDirty(DIRTY_GLES1_CURRENT_VECTOR);
+ mCurrentNormal = normal;
+}
+
+const angle::Vector3 &GLES1State::getCurrentNormal() const
+{
+ return mCurrentNormal;
+}
+
+bool GLES1State::shouldHandleDirtyProgram()
+{
+ bool ret = isDirty(DIRTY_GLES1_PROGRAM);
+ clearDirtyBits(DIRTY_GLES1_PROGRAM);
+ return ret;
+}
+
+void GLES1State::setCurrentTextureCoords(unsigned int unit, const TextureCoordF &coords)
+{
+ setDirty(DIRTY_GLES1_CURRENT_VECTOR);
+ mCurrentTextureCoords[unit] = coords;
+}
+
+const TextureCoordF &GLES1State::getCurrentTextureCoords(unsigned int unit) const
+{
+ return mCurrentTextureCoords[unit];
+}
+
+void GLES1State::setMatrixMode(MatrixType mode)
+{
+ setDirty(DIRTY_GLES1_MATRICES);
+ mMatrixMode = mode;
+}
+
+MatrixType GLES1State::getMatrixMode() const
+{
+ return mMatrixMode;
+}
+
+GLint GLES1State::getCurrentMatrixStackDepth(GLenum queryType) const
+{
+ switch (queryType)
+ {
+ case GL_MODELVIEW_STACK_DEPTH:
+ return clampCast<GLint>(mModelviewMatrices.size());
+ case GL_PROJECTION_STACK_DEPTH:
+ return clampCast<GLint>(mProjectionMatrices.size());
+ case GL_TEXTURE_STACK_DEPTH:
+ return clampCast<GLint>(mTextureMatrices[mGLState->getActiveSampler()].size());
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+void GLES1State::pushMatrix()
+{
+ setDirty(DIRTY_GLES1_MATRICES);
+ auto &stack = currentMatrixStack();
+ stack.push_back(stack.back());
+}
+
+void GLES1State::popMatrix()
+{
+ setDirty(DIRTY_GLES1_MATRICES);
+ auto &stack = currentMatrixStack();
+ stack.pop_back();
+}
+
+GLES1State::MatrixStack &GLES1State::currentMatrixStack()
+{
+ setDirty(DIRTY_GLES1_MATRICES);
+ switch (mMatrixMode)
+ {
+ case MatrixType::Modelview:
+ return mModelviewMatrices;
+ case MatrixType::Projection:
+ return mProjectionMatrices;
+ case MatrixType::Texture:
+ return mTextureMatrices[mGLState->getActiveSampler()];
+ default:
+ UNREACHABLE();
+ return mModelviewMatrices;
+ }
+}
+
+const angle::Mat4 &GLES1State::getModelviewMatrix() const
+{
+ return mModelviewMatrices.back();
+}
+
+const GLES1State::MatrixStack &GLES1State::getMatrixStack(MatrixType mode) const
+{
+ switch (mode)
+ {
+ case MatrixType::Modelview:
+ return mModelviewMatrices;
+ case MatrixType::Projection:
+ return mProjectionMatrices;
+ case MatrixType::Texture:
+ return mTextureMatrices[mGLState->getActiveSampler()];
+ default:
+ UNREACHABLE();
+ return mModelviewMatrices;
+ }
+}
+
+const GLES1State::MatrixStack &GLES1State::currentMatrixStack() const
+{
+ return getMatrixStack(mMatrixMode);
+}
+
+void GLES1State::loadMatrix(const angle::Mat4 &m)
+{
+ setDirty(DIRTY_GLES1_MATRICES);
+ currentMatrixStack().back() = m;
+}
+
+void GLES1State::multMatrix(const angle::Mat4 &m)
+{
+ setDirty(DIRTY_GLES1_MATRICES);
+ angle::Mat4 currentMatrix = currentMatrixStack().back();
+ currentMatrixStack().back() = currentMatrix.product(m);
+}
+
+void GLES1State::setLogicOpEnabled(bool enabled)
+{
+ setDirty(DIRTY_GLES1_LOGIC_OP);
+ mLogicOpEnabled = enabled;
+}
+
+void GLES1State::setLogicOp(LogicalOperation opcodePacked)
+{
+ setDirty(DIRTY_GLES1_LOGIC_OP);
+ mLogicOp = opcodePacked;
+}
+
+void GLES1State::setClientStateEnabled(ClientVertexArrayType clientState, bool enable)
+{
+ setDirty(DIRTY_GLES1_CLIENT_STATE_ENABLE);
+ switch (clientState)
+ {
+ case ClientVertexArrayType::Vertex:
+ mVertexArrayEnabled = enable;
+ break;
+ case ClientVertexArrayType::Normal:
+ mNormalArrayEnabled = enable;
+ break;
+ case ClientVertexArrayType::Color:
+ mColorArrayEnabled = enable;
+ break;
+ case ClientVertexArrayType::PointSize:
+ mPointSizeArrayEnabled = enable;
+ break;
+ case ClientVertexArrayType::TextureCoord:
+ mTexCoordArrayEnabled[mClientActiveTexture] = enable;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void GLES1State::setTexCoordArrayEnabled(unsigned int unit, bool enable)
+{
+ setDirty(DIRTY_GLES1_CLIENT_STATE_ENABLE);
+ mTexCoordArrayEnabled[unit] = enable;
+}
+
+bool GLES1State::isClientStateEnabled(ClientVertexArrayType clientState) const
+{
+ switch (clientState)
+ {
+ case ClientVertexArrayType::Vertex:
+ return mVertexArrayEnabled;
+ case ClientVertexArrayType::Normal:
+ return mNormalArrayEnabled;
+ case ClientVertexArrayType::Color:
+ return mColorArrayEnabled;
+ case ClientVertexArrayType::PointSize:
+ return mPointSizeArrayEnabled;
+ case ClientVertexArrayType::TextureCoord:
+ return mTexCoordArrayEnabled[mClientActiveTexture];
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool GLES1State::isTexCoordArrayEnabled(unsigned int unit) const
+{
+ ASSERT(unit < mTexCoordArrayEnabled.size());
+ return mTexCoordArrayEnabled[unit];
+}
+
+bool GLES1State::isTextureTargetEnabled(unsigned int unit, const TextureType type) const
+{
+ if (mTexUnitEnables.empty())
+ {
+ return false;
+ }
+ return mTexUnitEnables[unit].test(type);
+}
+
+LightModelParameters &GLES1State::lightModelParameters()
+{
+ setDirty(DIRTY_GLES1_LIGHTS);
+ return mLightModel;
+}
+
+const LightModelParameters &GLES1State::lightModelParameters() const
+{
+ return mLightModel;
+}
+
+LightParameters &GLES1State::lightParameters(unsigned int light)
+{
+ setDirty(DIRTY_GLES1_LIGHTS);
+ return mLights[light];
+}
+
+const LightParameters &GLES1State::lightParameters(unsigned int light) const
+{
+ return mLights[light];
+}
+
+MaterialParameters &GLES1State::materialParameters()
+{
+ setDirty(DIRTY_GLES1_MATERIAL);
+ return mMaterial;
+}
+
+const MaterialParameters &GLES1State::materialParameters() const
+{
+ return mMaterial;
+}
+
+bool GLES1State::isColorMaterialEnabled() const
+{
+ return mColorMaterialEnabled;
+}
+
+void GLES1State::setShadeModel(ShadingModel model)
+{
+ setDirty(DIRTY_GLES1_SHADE_MODEL);
+ mShadeModel = model;
+}
+
+void GLES1State::setClipPlane(unsigned int plane, const GLfloat *equation)
+{
+ setDirty(DIRTY_GLES1_CLIP_PLANES);
+ assert(plane < mClipPlanes.size());
+ mClipPlanes[plane].equation[0] = equation[0];
+ mClipPlanes[plane].equation[1] = equation[1];
+ mClipPlanes[plane].equation[2] = equation[2];
+ mClipPlanes[plane].equation[3] = equation[3];
+}
+
+void GLES1State::getClipPlane(unsigned int plane, GLfloat *equation) const
+{
+ assert(plane < mClipPlanes.size());
+ equation[0] = mClipPlanes[plane].equation[0];
+ equation[1] = mClipPlanes[plane].equation[1];
+ equation[2] = mClipPlanes[plane].equation[2];
+ equation[3] = mClipPlanes[plane].equation[3];
+}
+
+FogParameters &GLES1State::fogParameters()
+{
+ setDirty(DIRTY_GLES1_FOG);
+ return mFog;
+}
+
+const FogParameters &GLES1State::fogParameters() const
+{
+ return mFog;
+}
+
+TextureEnvironmentParameters &GLES1State::textureEnvironment(unsigned int unit)
+{
+ setDirty(DIRTY_GLES1_TEXTURE_ENVIRONMENT);
+ assert(unit < mTextureEnvironments.size());
+ return mTextureEnvironments[unit];
+}
+
+const TextureEnvironmentParameters &GLES1State::textureEnvironment(unsigned int unit) const
+{
+ assert(unit < mTextureEnvironments.size());
+ return mTextureEnvironments[unit];
+}
+
+bool operator==(const TextureEnvironmentParameters &a, const TextureEnvironmentParameters &b)
+{
+ return a.tie() == b.tie();
+}
+
+bool operator!=(const TextureEnvironmentParameters &a, const TextureEnvironmentParameters &b)
+{
+ return !(a == b);
+}
+
+PointParameters &GLES1State::pointParameters()
+{
+ setDirty(DIRTY_GLES1_POINT_PARAMETERS);
+ return mPointParameters;
+}
+
+const PointParameters &GLES1State::pointParameters() const
+{
+ return mPointParameters;
+}
+
+AttributesMask GLES1State::getVertexArraysAttributeMask() const
+{
+ AttributesMask attribsMask;
+
+ ClientVertexArrayType nonTexcoordArrays[] = {
+ ClientVertexArrayType::Vertex,
+ ClientVertexArrayType::Normal,
+ ClientVertexArrayType::Color,
+ ClientVertexArrayType::PointSize,
+ };
+
+ for (const ClientVertexArrayType attrib : nonTexcoordArrays)
+ {
+ attribsMask.set(GLES1Renderer::VertexArrayIndex(attrib, *this),
+ isClientStateEnabled(attrib));
+ }
+
+ for (unsigned int i = 0; i < kTexUnitCount; i++)
+ {
+ attribsMask.set(GLES1Renderer::TexCoordArrayIndex(i), isTexCoordArrayEnabled(i));
+ }
+
+ return attribsMask;
+}
+
+AttributesMask GLES1State::getActiveAttributesMask() const
+{
+ // The program always has 8 attributes enabled.
+ return AttributesMask(0xFF);
+}
+
+void GLES1State::setHint(GLenum target, GLenum mode)
+{
+ setDirty(DIRTY_GLES1_HINT_SETTING);
+ HintSetting setting = FromGLenum<HintSetting>(mode);
+ switch (target)
+ {
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ mPerspectiveCorrectionHint = setting;
+ break;
+ case GL_POINT_SMOOTH_HINT:
+ mPointSmoothHint = setting;
+ break;
+ case GL_LINE_SMOOTH_HINT:
+ mLineSmoothHint = setting;
+ break;
+ case GL_FOG_HINT:
+ mFogHint = setting;
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+GLenum GLES1State::getHint(GLenum target) const
+{
+ switch (target)
+ {
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ return ToGLenum(mPerspectiveCorrectionHint);
+ case GL_POINT_SMOOTH_HINT:
+ return ToGLenum(mPointSmoothHint);
+ case GL_LINE_SMOOTH_HINT:
+ return ToGLenum(mLineSmoothHint);
+ case GL_FOG_HINT:
+ return ToGLenum(mFogHint);
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/GLES1State.h b/gfx/angle/checkout/src/libANGLE/GLES1State.h
new file mode 100644
index 0000000000..e9c108b58b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/GLES1State.h
@@ -0,0 +1,351 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// GLES1State.h: Defines the GLES1State class holding the state of
+// a GLES1 context.
+
+#ifndef LIBANGLE_GLES1STATE_H_
+#define LIBANGLE_GLES1STATE_H_
+
+#include <unordered_set>
+
+#include "common/FixedVector.h"
+#include "common/angleutils.h"
+#include "common/bitset_utils.h"
+#include "common/matrix_utils.h"
+#include "common/vector_utils.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+
+// State types specific to GLES1 contexts, from the OpenGL ES 1.1 spec "State Tables" section
+struct TextureCoordF
+{
+ TextureCoordF();
+ TextureCoordF(float _s, float _t, float _r, float _q);
+ bool operator==(const TextureCoordF &other) const;
+
+ GLfloat s = 0.0f;
+ GLfloat t = 0.0f;
+ GLfloat r = 0.0f;
+ GLfloat q = 0.0f;
+};
+
+struct MaterialParameters
+{
+ MaterialParameters();
+
+ ColorF ambient;
+ ColorF diffuse;
+ ColorF specular;
+ ColorF emissive;
+ GLfloat specularExponent;
+};
+
+struct LightModelParameters
+{
+ LightModelParameters();
+
+ ColorF color;
+ bool twoSided;
+};
+
+struct LightParameters
+{
+ LightParameters();
+ LightParameters(const LightParameters &other);
+
+ bool enabled = false;
+ ColorF ambient = {0.0f, 0.0f, 0.0f, 1.0f};
+ ColorF diffuse = {0.0f, 0.0f, 0.0f, 1.0f};
+ ColorF specular = {0.0f, 0.0f, 0.0f, 1.0f};
+ angle::Vector4 position = {0.0f, 0.0f, 1.0f, 0.0f};
+ angle::Vector3 direction = {0.0f, 0.0f, -1.0f};
+ GLfloat spotlightExponent = 0.0f;
+ GLfloat spotlightCutoffAngle = 180.0f;
+ GLfloat attenuationConst = 1.0f;
+ GLfloat attenuationLinear = 0.0f;
+ GLfloat attenuationQuadratic = 0.0f;
+};
+
+struct FogParameters
+{
+ FogParameters();
+
+ FogMode mode;
+ GLfloat density;
+ GLfloat start;
+ GLfloat end;
+ ColorF color;
+};
+
+struct TextureEnvironmentParameters
+{
+ TextureEnvironmentParameters();
+ TextureEnvironmentParameters(const TextureEnvironmentParameters &other);
+
+ TextureEnvMode mode = TextureEnvMode::Modulate;
+ TextureCombine combineRgb = TextureCombine::Modulate;
+ TextureCombine combineAlpha = TextureCombine::Modulate;
+
+ TextureSrc src0Rgb = TextureSrc::Texture;
+ TextureSrc src0Alpha = TextureSrc::Texture;
+
+ TextureSrc src1Rgb = TextureSrc::Previous;
+ TextureSrc src1Alpha = TextureSrc::Previous;
+
+ TextureSrc src2Rgb = TextureSrc::Constant;
+ TextureSrc src2Alpha = TextureSrc::Constant;
+
+ TextureOp op0Rgb = TextureOp::SrcColor;
+ TextureOp op0Alpha = TextureOp::SrcAlpha;
+
+ TextureOp op1Rgb = TextureOp::SrcColor;
+ TextureOp op1Alpha = TextureOp::SrcAlpha;
+
+ TextureOp op2Rgb = TextureOp::SrcAlpha;
+ TextureOp op2Alpha = TextureOp::SrcAlpha;
+
+ ColorF color = {0.0f, 0.0f, 0.0f, 0.0f};
+ GLfloat rgbScale = 1.0f;
+ GLfloat alphaScale = 1.0f;
+
+ bool pointSpriteCoordReplace = false;
+
+ auto tie() const
+ {
+ return std::tie(mode, combineRgb, combineAlpha, src0Rgb, src0Alpha, src1Rgb, src1Alpha,
+ src2Rgb, src2Alpha, op0Rgb, op0Alpha, op1Rgb, op1Alpha, op2Rgb, op2Alpha,
+ color, rgbScale, alphaScale, pointSpriteCoordReplace);
+ }
+};
+
+bool operator==(const TextureEnvironmentParameters &a, const TextureEnvironmentParameters &b);
+bool operator!=(const TextureEnvironmentParameters &a, const TextureEnvironmentParameters &b);
+
+struct PointParameters
+{
+ PointParameters();
+ PointParameters(const PointParameters &other);
+
+ GLfloat pointSizeMin = 0.0f;
+ GLfloat pointSizeMax = 1.0f;
+ GLfloat pointFadeThresholdSize = 1.0f;
+ angle::Vector3 pointDistanceAttenuation = {1.0f, 0.0f, 0.0f};
+ GLfloat pointSize = 1.0f;
+};
+
+struct ClipPlaneParameters
+{
+ ClipPlaneParameters();
+ ClipPlaneParameters(bool enabled, const angle::Vector4 &equation);
+ ClipPlaneParameters(const ClipPlaneParameters &other);
+ ClipPlaneParameters &operator=(const ClipPlaneParameters &other);
+
+ bool enabled;
+ angle::Vector4 equation;
+};
+
+class Context;
+class GLES1Renderer;
+class State;
+
+class GLES1State final : angle::NonCopyable
+{
+ public:
+ GLES1State();
+ ~GLES1State();
+
+ void initialize(const Context *context, const State *state);
+
+ void setAlphaFunc(AlphaTestFunc func, GLfloat ref);
+ void setClientTextureUnit(unsigned int unit);
+ unsigned int getClientTextureUnit() const;
+
+ void setCurrentColor(const ColorF &color);
+ const ColorF &getCurrentColor() const;
+
+ void setCurrentNormal(const angle::Vector3 &normal);
+ const angle::Vector3 &getCurrentNormal() const;
+
+ void setCurrentTextureCoords(unsigned int unit, const TextureCoordF &coords);
+ const TextureCoordF &getCurrentTextureCoords(unsigned int unit) const;
+
+ void setMatrixMode(MatrixType mode);
+ MatrixType getMatrixMode() const;
+
+ GLint getCurrentMatrixStackDepth(GLenum param) const;
+
+ void pushMatrix();
+ void popMatrix();
+
+ using MatrixStack = angle::FixedVector<angle::Mat4, Caps::GlobalMatrixStackDepth>;
+ MatrixStack &currentMatrixStack();
+ const MatrixStack &currentMatrixStack() const;
+ const MatrixStack &getMatrixStack(MatrixType mode) const;
+
+ const angle::Mat4 &getModelviewMatrix() const;
+
+ void loadMatrix(const angle::Mat4 &m);
+ void multMatrix(const angle::Mat4 &m);
+
+ void setLogicOpEnabled(bool enabled);
+ void setLogicOp(LogicalOperation opcodePacked);
+
+ void setClientStateEnabled(ClientVertexArrayType clientState, bool enable);
+ void setTexCoordArrayEnabled(unsigned int unit, bool enable);
+ bool isClientStateEnabled(ClientVertexArrayType clientState) const;
+ bool isTexCoordArrayEnabled(unsigned int unit) const;
+ bool isTextureTargetEnabled(unsigned int unit, const TextureType type) const;
+
+ LightModelParameters &lightModelParameters();
+ const LightModelParameters &lightModelParameters() const;
+
+ LightParameters &lightParameters(unsigned int light);
+ const LightParameters &lightParameters(unsigned int light) const;
+
+ MaterialParameters &materialParameters();
+ const MaterialParameters &materialParameters() const;
+ bool isColorMaterialEnabled() const;
+
+ void setShadeModel(ShadingModel model);
+
+ void setClipPlane(unsigned int plane, const GLfloat *equation);
+ void getClipPlane(unsigned int plane, GLfloat *equation) const;
+
+ FogParameters &fogParameters();
+ const FogParameters &fogParameters() const;
+
+ TextureEnvironmentParameters &textureEnvironment(unsigned int unit);
+ const TextureEnvironmentParameters &textureEnvironment(unsigned int unit) const;
+
+ PointParameters &pointParameters();
+ const PointParameters &pointParameters() const;
+
+ AttributesMask getVertexArraysAttributeMask() const;
+ AttributesMask getActiveAttributesMask() const;
+
+ bool shouldHandleDirtyProgram();
+
+ void setHint(GLenum target, GLenum mode);
+ GLenum getHint(GLenum target) const;
+
+ enum DirtyGles1Type
+ {
+ DIRTY_GLES1_TEXTURE_UNIT_ENABLE = 0,
+ DIRTY_GLES1_CLIENT_STATE_ENABLE,
+ DIRTY_GLES1_FEATURE_ENABLE,
+ DIRTY_GLES1_CURRENT_VECTOR,
+ DIRTY_GLES1_CLIENT_ACTIVE_TEXTURE,
+ DIRTY_GLES1_MATRICES,
+ DIRTY_GLES1_TEXTURE_ENVIRONMENT,
+ DIRTY_GLES1_MATERIAL,
+ DIRTY_GLES1_LIGHTS,
+ DIRTY_GLES1_FOG,
+ DIRTY_GLES1_SHADE_MODEL,
+ DIRTY_GLES1_POINT_PARAMETERS,
+ DIRTY_GLES1_ALPHA_TEST,
+ DIRTY_GLES1_LOGIC_OP,
+ DIRTY_GLES1_CLIP_PLANES,
+ DIRTY_GLES1_HINT_SETTING,
+ DIRTY_GLES1_PROGRAM,
+ DIRTY_GLES1_MAX,
+ };
+
+ void setAllDirty() { mDirtyBits.set(); }
+
+ private:
+ friend class State;
+ friend class GLES1Renderer;
+
+ // Back pointer for reading from State.
+ const State *mGLState;
+
+ using DirtyBits = angle::BitSet<DIRTY_GLES1_MAX>;
+ DirtyBits mDirtyBits;
+
+ void setDirty(DirtyGles1Type type) { mDirtyBits.set(type); }
+ void clearDirty() { mDirtyBits.reset(); }
+ void clearDirtyBits(const DirtyGles1Type &bitset) { mDirtyBits &= ~bitset; }
+ bool isDirty(DirtyGles1Type type) const { return mDirtyBits.test(type); }
+
+ // All initial state values come from the
+ // OpenGL ES 1.1 spec.
+ std::vector<angle::PackedEnumBitSet<TextureType>> mTexUnitEnables;
+
+ // Table 6.4, 6.5 (IsEnabled)
+ bool mVertexArrayEnabled;
+ bool mNormalArrayEnabled;
+ bool mColorArrayEnabled;
+ bool mPointSizeArrayEnabled;
+ std::vector<bool> mTexCoordArrayEnabled;
+
+ // Table 6.7-6.16 (IsEnabled)
+ bool mLineSmoothEnabled;
+ bool mPointSmoothEnabled;
+ bool mPointSpriteEnabled;
+ bool mAlphaTestEnabled;
+ bool mLogicOpEnabled;
+ bool mLightingEnabled;
+ bool mFogEnabled;
+ bool mRescaleNormalEnabled;
+ bool mNormalizeEnabled;
+ bool mColorMaterialEnabled;
+ bool mReflectionMapEnabled;
+
+ // Table 6.3
+ ColorF mCurrentColor;
+ angle::Vector3 mCurrentNormal;
+ // Invariant: mCurrentTextureCoords size is == GL_MAX_TEXTURE_UNITS.
+ std::vector<TextureCoordF> mCurrentTextureCoords;
+
+ // Table 6.4
+ unsigned int mClientActiveTexture;
+
+ // Table 6.7
+ MatrixType mMatrixMode;
+ MatrixStack mProjectionMatrices;
+ MatrixStack mModelviewMatrices;
+ std::vector<MatrixStack> mTextureMatrices;
+
+ // Table 6.15
+ using TextureEnvironments = std::vector<TextureEnvironmentParameters>;
+ TextureEnvironments mTextureEnvironments;
+
+ // Table 6.9, 2.8
+ MaterialParameters mMaterial;
+ LightModelParameters mLightModel;
+
+ // Table 6.10
+ std::vector<LightParameters> mLights;
+
+ // Table 6.8
+ FogParameters mFog;
+ ShadingModel mShadeModel;
+
+ // Table 6.11
+ PointParameters mPointParameters;
+
+ // Table 6.16
+ AlphaTestFunc mAlphaTestFunc;
+ GLfloat mAlphaTestRef;
+ LogicalOperation mLogicOp;
+
+ // Table 6.7
+ std::vector<ClipPlaneParameters> mClipPlanes;
+
+ // Table 6.19
+ HintSetting mLineSmoothHint;
+ HintSetting mPointSmoothHint;
+ HintSetting mPerspectiveCorrectionHint;
+ HintSetting mFogHint;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_GLES1STATE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/HandleAllocator.cpp b/gfx/angle/checkout/src/libANGLE/HandleAllocator.cpp
new file mode 100644
index 0000000000..ff49233e1d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/HandleAllocator.cpp
@@ -0,0 +1,184 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// HandleAllocator.cpp: Implements the gl::HandleAllocator class, which is used
+// to allocate GL handles.
+
+#include "libANGLE/HandleAllocator.h"
+
+#include <algorithm>
+#include <functional>
+#include <limits>
+
+#include "common/debug.h"
+
+namespace gl
+{
+
+struct HandleAllocator::HandleRangeComparator
+{
+ bool operator()(const HandleRange &range, GLuint handle) const { return (range.end < handle); }
+};
+
+HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1), mLoggingEnabled(false)
+{
+ mUnallocatedList.push_back(HandleRange(1, std::numeric_limits<GLuint>::max()));
+}
+
+HandleAllocator::HandleAllocator(GLuint maximumHandleValue)
+ : mBaseValue(1), mNextValue(1), mLoggingEnabled(false)
+{
+ mUnallocatedList.push_back(HandleRange(1, maximumHandleValue));
+}
+
+HandleAllocator::~HandleAllocator() {}
+
+void HandleAllocator::setBaseHandle(GLuint value)
+{
+ ASSERT(mBaseValue == mNextValue);
+ mBaseValue = value;
+ mNextValue = value;
+}
+
+GLuint HandleAllocator::allocate()
+{
+ ASSERT(!mUnallocatedList.empty() || !mReleasedList.empty());
+
+ // Allocate from released list, logarithmic time for pop_heap.
+ if (!mReleasedList.empty())
+ {
+ std::pop_heap(mReleasedList.begin(), mReleasedList.end(), std::greater<GLuint>());
+ GLuint reusedHandle = mReleasedList.back();
+ mReleasedList.pop_back();
+
+ if (mLoggingEnabled)
+ {
+ WARN() << "HandleAllocator::allocate reusing " << reusedHandle << std::endl;
+ }
+
+ return reusedHandle;
+ }
+
+ // Allocate from unallocated list, constant time.
+ auto listIt = mUnallocatedList.begin();
+
+ GLuint freeListHandle = listIt->begin;
+ ASSERT(freeListHandle > 0);
+
+ if (listIt->begin == listIt->end)
+ {
+ mUnallocatedList.erase(listIt);
+ }
+ else
+ {
+ listIt->begin++;
+ }
+
+ if (mLoggingEnabled)
+ {
+ WARN() << "HandleAllocator::allocate allocating " << freeListHandle << std::endl;
+ }
+
+ return freeListHandle;
+}
+
+void HandleAllocator::release(GLuint handle)
+{
+ if (mLoggingEnabled)
+ {
+ WARN() << "HandleAllocator::release releasing " << handle << std::endl;
+ }
+
+ // Try consolidating the ranges first.
+ for (HandleRange &handleRange : mUnallocatedList)
+ {
+ if (handleRange.begin - 1 == handle)
+ {
+ handleRange.begin--;
+ return;
+ }
+
+ if (handleRange.end == handle - 1)
+ {
+ handleRange.end++;
+ return;
+ }
+ }
+
+ // Add to released list, logarithmic time for push_heap.
+ mReleasedList.push_back(handle);
+ std::push_heap(mReleasedList.begin(), mReleasedList.end(), std::greater<GLuint>());
+}
+
+void HandleAllocator::reserve(GLuint handle)
+{
+ if (mLoggingEnabled)
+ {
+ WARN() << "HandleAllocator::reserve reserving " << handle << std::endl;
+ }
+
+ // Clear from released list -- might be a slow operation.
+ if (!mReleasedList.empty())
+ {
+ auto releasedIt = std::find(mReleasedList.begin(), mReleasedList.end(), handle);
+ if (releasedIt != mReleasedList.end())
+ {
+ mReleasedList.erase(releasedIt);
+ std::make_heap(mReleasedList.begin(), mReleasedList.end(), std::greater<GLuint>());
+ return;
+ }
+ }
+
+ // Not in released list, reserve in the unallocated list.
+ auto boundIt = std::lower_bound(mUnallocatedList.begin(), mUnallocatedList.end(), handle,
+ HandleRangeComparator());
+
+ ASSERT(boundIt != mUnallocatedList.end());
+
+ GLuint begin = boundIt->begin;
+ GLuint end = boundIt->end;
+
+ if (handle == begin || handle == end)
+ {
+ if (begin == end)
+ {
+ mUnallocatedList.erase(boundIt);
+ }
+ else if (handle == begin)
+ {
+ boundIt->begin++;
+ }
+ else
+ {
+ ASSERT(handle == end);
+ boundIt->end--;
+ }
+ return;
+ }
+
+ ASSERT(begin < handle && handle < end);
+
+ // need to split the range
+ auto placementIt = mUnallocatedList.erase(boundIt);
+ placementIt = mUnallocatedList.insert(placementIt, HandleRange(handle + 1, end));
+ mUnallocatedList.insert(placementIt, HandleRange(begin, handle - 1));
+}
+
+void HandleAllocator::reset()
+{
+ mUnallocatedList.clear();
+ mUnallocatedList.push_back(HandleRange(1, std::numeric_limits<GLuint>::max()));
+ mReleasedList.clear();
+ mBaseValue = 1;
+ mNextValue = 1;
+}
+
+void HandleAllocator::enableLogging(bool enabled)
+{
+ mLoggingEnabled = enabled;
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/HandleAllocator.h b/gfx/angle/checkout/src/libANGLE/HandleAllocator.h
new file mode 100644
index 0000000000..985d1adaba
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/HandleAllocator.h
@@ -0,0 +1,65 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// HandleAllocator.h: Defines the gl::HandleAllocator class, which is used to
+// allocate GL handles.
+
+#ifndef LIBANGLE_HANDLEALLOCATOR_H_
+#define LIBANGLE_HANDLEALLOCATOR_H_
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+namespace gl
+{
+
+class HandleAllocator final : angle::NonCopyable
+{
+ public:
+ // Maximum handle = MAX_UINT-1
+ HandleAllocator();
+ // Specify maximum handle value. Used for testing.
+ HandleAllocator(GLuint maximumHandleValue);
+
+ ~HandleAllocator();
+
+ void setBaseHandle(GLuint value);
+
+ GLuint allocate();
+ void release(GLuint handle);
+ void reserve(GLuint handle);
+ void reset();
+
+ void enableLogging(bool enabled);
+
+ private:
+ GLuint mBaseValue;
+ GLuint mNextValue;
+
+ // Represents an inclusive range [begin, end]
+ struct HandleRange
+ {
+ HandleRange(GLuint beginIn, GLuint endIn) : begin(beginIn), end(endIn) {}
+
+ GLuint begin;
+ GLuint end;
+ };
+
+ struct HandleRangeComparator;
+
+ // The freelist consists of never-allocated handles, stored
+ // as ranges, and handles that were previously allocated and
+ // released, stored in a heap.
+ std::vector<HandleRange> mUnallocatedList;
+ std::vector<GLuint> mReleasedList;
+
+ bool mLoggingEnabled;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_HANDLEALLOCATOR_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Image.cpp b/gfx/angle/checkout/src/libANGLE/Image.cpp
new file mode 100644
index 0000000000..6292b5ee46
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Image.cpp
@@ -0,0 +1,581 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image.cpp: Implements the egl::Image class representing the EGLimage object.
+
+#include "libANGLE/Image.h"
+
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
+#include "libANGLE/renderer/ImageImpl.h"
+
+namespace egl
+{
+
+namespace
+{
+gl::ImageIndex GetImageIndex(EGLenum eglTarget, const egl::AttributeMap &attribs)
+{
+ if (!IsTextureTarget(eglTarget))
+ {
+ return gl::ImageIndex();
+ }
+
+ gl::TextureTarget target = egl_gl::EGLImageTargetToTextureTarget(eglTarget);
+ GLint mip = static_cast<GLint>(attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0));
+ GLint layer = static_cast<GLint>(attribs.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0));
+
+ if (target == gl::TextureTarget::_3D)
+ {
+ return gl::ImageIndex::Make3D(mip, layer);
+ }
+ else
+ {
+ ASSERT(layer == 0);
+ return gl::ImageIndex::MakeFromTarget(target, mip, 1);
+ }
+}
+
+const Display *DisplayFromContext(const gl::Context *context)
+{
+ return (context ? context->getDisplay() : nullptr);
+}
+
+angle::SubjectIndex kExternalImageImplSubjectIndex = 0;
+} // anonymous namespace
+
+ImageSibling::ImageSibling() : FramebufferAttachmentObject(), mSourcesOf(), mTargetOf() {}
+
+ImageSibling::~ImageSibling()
+{
+ // EGL images should hold a ref to their targets and siblings, a Texture should not be deletable
+ // while it is attached to an EGL image.
+ // Child class should orphan images before destruction.
+ ASSERT(mSourcesOf.empty());
+ ASSERT(mTargetOf.get() == nullptr);
+}
+
+void ImageSibling::setTargetImage(const gl::Context *context, egl::Image *imageTarget)
+{
+ ASSERT(imageTarget != nullptr);
+ mTargetOf.set(DisplayFromContext(context), imageTarget);
+ imageTarget->addTargetSibling(this);
+}
+
+angle::Result ImageSibling::orphanImages(const gl::Context *context,
+ RefCountObjectReleaser<Image> *outReleaseImage)
+{
+ ASSERT(outReleaseImage != nullptr);
+
+ if (mTargetOf.get() != nullptr)
+ {
+ // Can't be a target and have sources.
+ ASSERT(mSourcesOf.empty());
+
+ ANGLE_TRY(mTargetOf->orphanSibling(context, this));
+ *outReleaseImage = mTargetOf.set(DisplayFromContext(context), nullptr);
+ }
+ else
+ {
+ for (Image *sourceImage : mSourcesOf)
+ {
+ ANGLE_TRY(sourceImage->orphanSibling(context, this));
+ }
+ mSourcesOf.clear();
+ }
+
+ return angle::Result::Continue;
+}
+
+void ImageSibling::addImageSource(egl::Image *imageSource)
+{
+ ASSERT(imageSource != nullptr);
+ mSourcesOf.insert(imageSource);
+}
+
+void ImageSibling::removeImageSource(egl::Image *imageSource)
+{
+ ASSERT(mSourcesOf.find(imageSource) != mSourcesOf.end());
+ mSourcesOf.erase(imageSource);
+}
+
+bool ImageSibling::isEGLImageTarget() const
+{
+ return (mTargetOf.get() != nullptr);
+}
+
+gl::InitState ImageSibling::sourceEGLImageInitState() const
+{
+ ASSERT(isEGLImageTarget());
+ return mTargetOf->sourceInitState();
+}
+
+void ImageSibling::setSourceEGLImageInitState(gl::InitState initState) const
+{
+ ASSERT(isEGLImageTarget());
+ mTargetOf->setInitState(initState);
+}
+
+bool ImageSibling::isRenderable(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex) const
+{
+ ASSERT(isEGLImageTarget());
+ return mTargetOf->isRenderable(context);
+}
+
+bool ImageSibling::isYUV() const
+{
+ return mTargetOf.get() && mTargetOf->isYUV();
+}
+
+bool ImageSibling::isCreatedWithAHB() const
+{
+ return mTargetOf.get() && mTargetOf->isCreatedWithAHB();
+}
+
+bool ImageSibling::hasProtectedContent() const
+{
+ return mTargetOf.get() && mTargetOf->hasProtectedContent();
+}
+
+void ImageSibling::notifySiblings(angle::SubjectMessage message)
+{
+ if (mTargetOf.get())
+ {
+ mTargetOf->notifySiblings(this, message);
+ }
+ for (Image *source : mSourcesOf)
+ {
+ source->notifySiblings(this, message);
+ }
+}
+
+ExternalImageSibling::ExternalImageSibling(rx::EGLImplFactory *factory,
+ const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const AttributeMap &attribs)
+ : mImplementation(factory->createExternalImageSibling(context, target, buffer, attribs)),
+ mImplObserverBinding(this, kExternalImageImplSubjectIndex)
+{
+ mImplObserverBinding.bind(mImplementation.get());
+}
+
+ExternalImageSibling::~ExternalImageSibling() = default;
+
+void ExternalImageSibling::onDestroy(const egl::Display *display)
+{
+ mImplementation->onDestroy(display);
+}
+
+Error ExternalImageSibling::initialize(const egl::Display *display)
+{
+ return mImplementation->initialize(display);
+}
+
+gl::Extents ExternalImageSibling::getAttachmentSize(const gl::ImageIndex &imageIndex) const
+{
+ return mImplementation->getSize();
+}
+
+gl::Format ExternalImageSibling::getAttachmentFormat(GLenum binding,
+ const gl::ImageIndex &imageIndex) const
+{
+ return mImplementation->getFormat();
+}
+
+GLsizei ExternalImageSibling::getAttachmentSamples(const gl::ImageIndex &imageIndex) const
+{
+ return static_cast<GLsizei>(mImplementation->getSamples());
+}
+
+GLuint ExternalImageSibling::getLevelCount() const
+{
+ return static_cast<GLuint>(mImplementation->getLevelCount());
+}
+
+bool ExternalImageSibling::isRenderable(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex) const
+{
+ return mImplementation->isRenderable(context);
+}
+
+bool ExternalImageSibling::isTextureable(const gl::Context *context) const
+{
+ return mImplementation->isTexturable(context);
+}
+
+bool ExternalImageSibling::isYUV() const
+{
+ return mImplementation->isYUV();
+}
+
+bool ExternalImageSibling::isCubeMap() const
+{
+ return mImplementation->isCubeMap();
+}
+
+bool ExternalImageSibling::hasProtectedContent() const
+{
+ return mImplementation->hasProtectedContent();
+}
+
+void ExternalImageSibling::onAttach(const gl::Context *context, rx::Serial framebufferSerial) {}
+
+void ExternalImageSibling::onDetach(const gl::Context *context, rx::Serial framebufferSerial) {}
+
+GLuint ExternalImageSibling::getId() const
+{
+ UNREACHABLE();
+ return 0;
+}
+
+gl::InitState ExternalImageSibling::initState(GLenum binding,
+ const gl::ImageIndex &imageIndex) const
+{
+ return gl::InitState::Initialized;
+}
+
+void ExternalImageSibling::setInitState(GLenum binding,
+ const gl::ImageIndex &imageIndex,
+ gl::InitState initState)
+{}
+
+rx::ExternalImageSiblingImpl *ExternalImageSibling::getImplementation() const
+{
+ return mImplementation.get();
+}
+
+void ExternalImageSibling::onSubjectStateChange(angle::SubjectIndex index,
+ angle::SubjectMessage message)
+{
+ onStateChange(message);
+}
+
+rx::FramebufferAttachmentObjectImpl *ExternalImageSibling::getAttachmentImpl() const
+{
+ return mImplementation.get();
+}
+
+ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
+ : label(nullptr),
+ target(target),
+ imageIndex(GetImageIndex(target, attribs)),
+ source(buffer),
+ format(GL_NONE),
+ yuv(false),
+ cubeMap(false),
+ size(),
+ samples(),
+ levelCount(1),
+ sourceType(target),
+ colorspace(
+ static_cast<EGLenum>(attribs.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_DEFAULT_EXT))),
+ hasProtectedContent(static_cast<bool>(attribs.get(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE)))
+{}
+
+ImageState::~ImageState() {}
+
+Image::Image(rx::EGLImplFactory *factory,
+ const gl::Context *context,
+ EGLenum target,
+ ImageSibling *buffer,
+ const AttributeMap &attribs)
+ : mState(target, buffer, attribs),
+ mImplementation(factory->createImage(mState, context, target, attribs)),
+ mOrphanedAndNeedsInit(false)
+{
+ ASSERT(mImplementation != nullptr);
+ ASSERT(buffer != nullptr);
+
+ mState.source->addImageSource(this);
+}
+
+void Image::onDestroy(const Display *display)
+{
+ // All targets should hold a ref to the egl image and it should not be deleted until there are
+ // no siblings left.
+ ASSERT([&] {
+ std::unique_lock lock(mState.targetsLock);
+ return mState.targets.empty();
+ }());
+
+ // Make sure the implementation gets a chance to clean up before we delete the source.
+ mImplementation->onDestroy(display);
+
+ // Tell the source that it is no longer used by this image
+ if (mState.source != nullptr)
+ {
+ mState.source->removeImageSource(this);
+
+ // If the source is an external object, delete it
+ if (IsExternalImageTarget(mState.sourceType))
+ {
+ ExternalImageSibling *externalSibling = rx::GetAs<ExternalImageSibling>(mState.source);
+ externalSibling->onDestroy(display);
+ delete externalSibling;
+ }
+
+ mState.source = nullptr;
+ }
+}
+
+Image::~Image()
+{
+ SafeDelete(mImplementation);
+}
+
+void Image::setLabel(EGLLabelKHR label)
+{
+ mState.label = label;
+}
+
+EGLLabelKHR Image::getLabel() const
+{
+ return mState.label;
+}
+
+void Image::addTargetSibling(ImageSibling *sibling)
+{
+ std::unique_lock lock(mState.targetsLock);
+ mState.targets.insert(sibling);
+}
+
+angle::Result Image::orphanSibling(const gl::Context *context, ImageSibling *sibling)
+{
+ ASSERT(sibling != nullptr);
+
+ // notify impl
+ ANGLE_TRY(mImplementation->orphan(context, sibling));
+
+ if (mState.source == sibling)
+ {
+ // The external source of an image cannot be redefined so it cannot be orphaned.
+ ASSERT(!IsExternalImageTarget(mState.sourceType));
+
+ // If the sibling is the source, it cannot be a target.
+ ASSERT([&] {
+ std::unique_lock lock(mState.targetsLock);
+ return mState.targets.find(sibling) == mState.targets.end();
+ }());
+ mState.source = nullptr;
+ mOrphanedAndNeedsInit =
+ (sibling->initState(GL_NONE, mState.imageIndex) == gl::InitState::MayNeedInit);
+ }
+ else
+ {
+ std::unique_lock lock(mState.targetsLock);
+ mState.targets.erase(sibling);
+ }
+
+ return angle::Result::Continue;
+}
+
+const gl::Format &Image::getFormat() const
+{
+ return mState.format;
+}
+
+bool Image::isRenderable(const gl::Context *context) const
+{
+ if (IsTextureTarget(mState.sourceType))
+ {
+ return mState.format.info->textureAttachmentSupport(context->getClientVersion(),
+ context->getExtensions());
+ }
+ else if (IsRenderbufferTarget(mState.sourceType))
+ {
+ return mState.format.info->renderbufferSupport(context->getClientVersion(),
+ context->getExtensions());
+ }
+ else if (IsExternalImageTarget(mState.sourceType))
+ {
+ ASSERT(mState.source != nullptr);
+ return mState.source->isRenderable(context, GL_NONE, gl::ImageIndex());
+ }
+
+ UNREACHABLE();
+ return false;
+}
+
+bool Image::isTexturable(const gl::Context *context) const
+{
+ if (IsTextureTarget(mState.sourceType))
+ {
+ return mState.format.info->textureSupport(context->getClientVersion(),
+ context->getExtensions());
+ }
+ else if (IsRenderbufferTarget(mState.sourceType))
+ {
+ return true;
+ }
+ else if (IsExternalImageTarget(mState.sourceType))
+ {
+ ASSERT(mState.source != nullptr);
+ return rx::GetAs<ExternalImageSibling>(mState.source)->isTextureable(context);
+ }
+
+ UNREACHABLE();
+ return false;
+}
+
+bool Image::isYUV() const
+{
+ return mState.yuv;
+}
+
+bool Image::isCreatedWithAHB() const
+{
+ return mState.target == EGL_NATIVE_BUFFER_ANDROID;
+}
+
+bool Image::isCubeMap() const
+{
+ return mState.cubeMap;
+}
+
+size_t Image::getWidth() const
+{
+ return mState.size.width;
+}
+
+size_t Image::getHeight() const
+{
+ return mState.size.height;
+}
+
+const gl::Extents &Image::getExtents() const
+{
+ return mState.size;
+}
+
+bool Image::isLayered() const
+{
+ return mState.imageIndex.isLayered();
+}
+
+size_t Image::getSamples() const
+{
+ return mState.samples;
+}
+
+GLuint Image::getLevelCount() const
+{
+ return mState.levelCount;
+}
+
+bool Image::hasProtectedContent() const
+{
+ return mState.hasProtectedContent;
+}
+
+rx::ImageImpl *Image::getImplementation() const
+{
+ return mImplementation;
+}
+
+Error Image::initialize(const Display *display)
+{
+ if (IsExternalImageTarget(mState.sourceType))
+ {
+ ExternalImageSibling *externalSibling = rx::GetAs<ExternalImageSibling>(mState.source);
+ ANGLE_TRY(externalSibling->initialize(display));
+
+ mState.hasProtectedContent = externalSibling->hasProtectedContent();
+ mState.levelCount = externalSibling->getLevelCount();
+ mState.cubeMap = externalSibling->isCubeMap();
+
+ // External siblings can be YUV
+ mState.yuv = externalSibling->isYUV();
+ }
+
+ mState.format = mState.source->getAttachmentFormat(GL_NONE, mState.imageIndex);
+
+ if (mState.colorspace != EGL_GL_COLORSPACE_DEFAULT_EXT)
+ {
+ GLenum nonLinearFormat = mState.format.info->sizedInternalFormat;
+ if (!gl::ColorspaceFormatOverride(mState.colorspace, &nonLinearFormat))
+ {
+ // the colorspace format is not supported
+ return egl::EglBadMatch();
+ }
+ mState.format = gl::Format(nonLinearFormat);
+ }
+
+ if (!IsExternalImageTarget(mState.sourceType))
+ {
+ // Account for the fact that GL_ANGLE_yuv_internal_format extension maybe enabled,
+ // in which case the internal format itself could be YUV.
+ mState.yuv = gl::IsYuvFormat(mState.format.info->sizedInternalFormat);
+ }
+
+ mState.size = mState.source->getAttachmentSize(mState.imageIndex);
+ mState.samples = mState.source->getAttachmentSamples(mState.imageIndex);
+
+ if (IsTextureTarget(mState.sourceType))
+ {
+ mState.size.depth = 1;
+ }
+
+ return mImplementation->initialize(display);
+}
+
+bool Image::orphaned() const
+{
+ return (mState.source == nullptr);
+}
+
+gl::InitState Image::sourceInitState() const
+{
+ if (orphaned())
+ {
+ return mOrphanedAndNeedsInit ? gl::InitState::MayNeedInit : gl::InitState::Initialized;
+ }
+
+ return mState.source->initState(GL_NONE, mState.imageIndex);
+}
+
+void Image::setInitState(gl::InitState initState)
+{
+ if (orphaned())
+ {
+ mOrphanedAndNeedsInit = false;
+ }
+
+ return mState.source->setInitState(GL_NONE, mState.imageIndex, initState);
+}
+
+Error Image::exportVkImage(void *vkImage, void *vkImageCreateInfo)
+{
+ return mImplementation->exportVkImage(vkImage, vkImageCreateInfo);
+}
+
+void Image::notifySiblings(const ImageSibling *notifier, angle::SubjectMessage message)
+{
+ if (mState.source && mState.source != notifier)
+ {
+ mState.source->onSubjectStateChange(rx::kTextureImageSiblingMessageIndex, message);
+ }
+
+ std::unique_lock lock(mState.targetsLock);
+ for (ImageSibling *target : mState.targets)
+ {
+ if (target != notifier)
+ {
+ target->onSubjectStateChange(rx::kTextureImageSiblingMessageIndex, message);
+ }
+ }
+}
+
+} // namespace egl
diff --git a/gfx/angle/checkout/src/libANGLE/Image.h b/gfx/angle/checkout/src/libANGLE/Image.h
new file mode 100644
index 0000000000..7c1747f804
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Image.h
@@ -0,0 +1,216 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image.h: Defines the egl::Image class representing the EGLimage object.
+
+#ifndef LIBANGLE_IMAGE_H_
+#define LIBANGLE_IMAGE_H_
+
+#include "common/FastVector.h"
+#include "common/angleutils.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/formatutils.h"
+
+namespace rx
+{
+class EGLImplFactory;
+class ImageImpl;
+class ExternalImageSiblingImpl;
+
+// Used for distinguishing dirty bit messages from gl::Texture/rx::TexureImpl/gl::Image.
+constexpr size_t kTextureImageImplObserverMessageIndex = 0;
+constexpr size_t kTextureImageSiblingMessageIndex = 1;
+} // namespace rx
+
+namespace egl
+{
+class Image;
+class Display;
+
+// Only currently Renderbuffers and Textures can be bound with images. This makes the relationship
+// explicit, and also ensures that an image sibling can determine if it's been initialized or not,
+// which is important for the robust resource init extension with Textures and EGLImages.
+class ImageSibling : public gl::FramebufferAttachmentObject
+{
+ public:
+ ImageSibling();
+ ~ImageSibling() override;
+
+ bool isEGLImageTarget() const;
+ gl::InitState sourceEGLImageInitState() const;
+ void setSourceEGLImageInitState(gl::InitState initState) const;
+
+ bool isRenderable(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex) const override;
+ bool isYUV() const override;
+ bool isCreatedWithAHB() const override;
+ bool hasProtectedContent() const override;
+
+ protected:
+ // Set the image target of this sibling
+ void setTargetImage(const gl::Context *context, egl::Image *imageTarget);
+
+ // Orphan all EGL image sources and targets
+ angle::Result orphanImages(const gl::Context *context,
+ RefCountObjectReleaser<Image> *outReleaseImage);
+
+ void notifySiblings(angle::SubjectMessage message);
+
+ private:
+ friend class Image;
+
+ // Called from Image only to add a new source image
+ void addImageSource(egl::Image *imageSource);
+
+ // Called from Image only to remove a source image when the Image is being deleted
+ void removeImageSource(egl::Image *imageSource);
+
+ static constexpr size_t kSourcesOfSetSize = 2;
+ angle::FlatUnorderedSet<Image *, kSourcesOfSetSize> mSourcesOf;
+ BindingPointer<Image> mTargetOf;
+};
+
+// Wrapper for EGLImage sources that are not owned by ANGLE, these often have to do
+// platform-specific queries for format and size information.
+class ExternalImageSibling : public ImageSibling
+{
+ public:
+ ExternalImageSibling(rx::EGLImplFactory *factory,
+ const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const AttributeMap &attribs);
+ ~ExternalImageSibling() override;
+
+ void onDestroy(const egl::Display *display);
+
+ Error initialize(const Display *display);
+
+ gl::Extents getAttachmentSize(const gl::ImageIndex &imageIndex) const override;
+ gl::Format getAttachmentFormat(GLenum binding, const gl::ImageIndex &imageIndex) const override;
+ GLsizei getAttachmentSamples(const gl::ImageIndex &imageIndex) const override;
+ GLuint getLevelCount() const;
+ bool isRenderable(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex) const override;
+ bool isTextureable(const gl::Context *context) const;
+ bool isYUV() const override;
+ bool isCubeMap() const;
+ bool hasProtectedContent() const override;
+
+ void onAttach(const gl::Context *context, rx::Serial framebufferSerial) override;
+ void onDetach(const gl::Context *context, rx::Serial framebufferSerial) override;
+ GLuint getId() const override;
+
+ gl::InitState initState(GLenum binding, const gl::ImageIndex &imageIndex) const override;
+ void setInitState(GLenum binding,
+ const gl::ImageIndex &imageIndex,
+ gl::InitState initState) override;
+
+ rx::ExternalImageSiblingImpl *getImplementation() const;
+
+ protected:
+ rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
+
+ private:
+ // ObserverInterface implementation.
+ void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
+
+ std::unique_ptr<rx::ExternalImageSiblingImpl> mImplementation;
+ angle::ObserverBinding mImplObserverBinding;
+};
+
+struct ImageState : private angle::NonCopyable
+{
+ ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs);
+ ~ImageState();
+
+ EGLLabelKHR label;
+ EGLenum target;
+ gl::ImageIndex imageIndex;
+ ImageSibling *source;
+
+ gl::Format format;
+ bool yuv;
+ bool cubeMap;
+ gl::Extents size;
+ size_t samples;
+ GLuint levelCount;
+ EGLenum sourceType;
+ EGLenum colorspace;
+ bool hasProtectedContent;
+
+ mutable std::mutex targetsLock;
+
+ static constexpr size_t kTargetsSetSize = 2;
+ angle::FlatUnorderedSet<ImageSibling *, kTargetsSetSize> targets;
+};
+
+class Image final : public RefCountObject, public LabeledObject
+{
+ public:
+ Image(rx::EGLImplFactory *factory,
+ const gl::Context *context,
+ EGLenum target,
+ ImageSibling *buffer,
+ const AttributeMap &attribs);
+
+ void onDestroy(const Display *display) override;
+ ~Image() override;
+
+ void setLabel(EGLLabelKHR label) override;
+ EGLLabelKHR getLabel() const override;
+
+ const gl::Format &getFormat() const;
+ bool isRenderable(const gl::Context *context) const;
+ bool isTexturable(const gl::Context *context) const;
+ bool isYUV() const;
+ bool isCreatedWithAHB() const;
+ // Returns true only if the eglImage contains a complete cubemap
+ bool isCubeMap() const;
+ size_t getWidth() const;
+ size_t getHeight() const;
+ const gl::Extents &getExtents() const;
+ bool isLayered() const;
+ size_t getSamples() const;
+ GLuint getLevelCount() const;
+ bool hasProtectedContent() const;
+
+ Error initialize(const Display *display);
+
+ rx::ImageImpl *getImplementation() const;
+
+ bool orphaned() const;
+ gl::InitState sourceInitState() const;
+ void setInitState(gl::InitState initState);
+
+ Error exportVkImage(void *vkImage, void *vkImageCreateInfo);
+
+ private:
+ friend class ImageSibling;
+
+ // Called from ImageSibling only notify the image that a new target sibling exists for state
+ // tracking.
+ void addTargetSibling(ImageSibling *sibling);
+
+ // Called from ImageSibling only to notify the image that a sibling (source or target) has
+ // been respecified and state tracking should be updated.
+ angle::Result orphanSibling(const gl::Context *context, ImageSibling *sibling);
+
+ void notifySiblings(const ImageSibling *notifier, angle::SubjectMessage message);
+
+ ImageState mState;
+ rx::ImageImpl *mImplementation;
+ bool mOrphanedAndNeedsInit;
+};
+} // namespace egl
+
+#endif // LIBANGLE_IMAGE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/ImageIndex.cpp b/gfx/angle/checkout/src/libANGLE/ImageIndex.cpp
new file mode 100644
index 0000000000..55e0393fa4
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/ImageIndex.cpp
@@ -0,0 +1,388 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ImageIndex.cpp: Implementation for ImageIndex methods.
+
+#include "libANGLE/ImageIndex.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/angletypes.h"
+
+#include <tuple>
+
+namespace gl
+{
+namespace
+{
+GLint TextureTargetToLayer(TextureTarget target)
+{
+ switch (target)
+ {
+ case TextureTarget::CubeMapPositiveX:
+ return 0;
+ case TextureTarget::CubeMapNegativeX:
+ return 1;
+ case TextureTarget::CubeMapPositiveY:
+ return 2;
+ case TextureTarget::CubeMapNegativeY:
+ return 3;
+ case TextureTarget::CubeMapPositiveZ:
+ return 4;
+ case TextureTarget::CubeMapNegativeZ:
+ return 5;
+ case TextureTarget::External:
+ case TextureTarget::Rectangle:
+ case TextureTarget::_2D:
+ case TextureTarget::VideoImage:
+ case TextureTarget::_2DArray:
+ case TextureTarget::_2DMultisample:
+ case TextureTarget::_2DMultisampleArray:
+ case TextureTarget::_3D:
+ case TextureTarget::Buffer:
+ case TextureTarget::CubeMapArray:
+ return ImageIndex::kEntireLevel;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+bool IsArrayTarget(TextureTarget target)
+{
+ switch (target)
+ {
+ case TextureTarget::_2DArray:
+ case TextureTarget::_2DMultisampleArray:
+ case TextureTarget::CubeMapArray:
+ return true;
+ default:
+ return false;
+ }
+}
+} // anonymous namespace
+
+TextureTarget TextureTypeToTarget(TextureType type, GLint layerIndex)
+{
+ if (type == TextureType::CubeMap)
+ {
+ // As GL_TEXTURE_CUBE_MAP cannot be a texture target in texImage*D APIs, so we don't allow
+ // an entire cube map to have a texture target.
+ ASSERT(layerIndex != ImageIndex::kEntireLevel);
+ return CubeFaceIndexToTextureTarget(layerIndex);
+ }
+ else
+ {
+ return NonCubeTextureTypeToTarget(type);
+ }
+}
+
+ImageIndex::ImageIndex()
+ : mType(TextureType::InvalidEnum), mLevelIndex(0), mLayerIndex(0), mLayerCount(kEntireLevel)
+{}
+
+ImageIndex::ImageIndex(const ImageIndex &other) = default;
+
+ImageIndex &ImageIndex::operator=(const ImageIndex &other) = default;
+
+bool ImageIndex::hasLayer() const
+{
+ return mLayerIndex != kEntireLevel;
+}
+
+bool ImageIndex::isLayered() const
+{
+ switch (mType)
+ {
+ case TextureType::_2DArray:
+ case TextureType::_2DMultisampleArray:
+ case TextureType::CubeMap:
+ case TextureType::_3D:
+ case TextureType::CubeMapArray:
+ return mLayerIndex == kEntireLevel;
+ default:
+ return false;
+ }
+}
+
+bool ImageIndex::has3DLayer() const
+{
+ // It's quicker to check != CubeMap than calling usesTex3D, which checks multiple types. This
+ // ASSERT validates the check gives the same result.
+ ASSERT(!hasLayer() || ((mType != TextureType::CubeMap) == usesTex3D()));
+ return (hasLayer() && mType != TextureType::CubeMap);
+}
+
+bool ImageIndex::usesTex3D() const
+{
+ return mType == TextureType::_3D || mType == TextureType::_2DArray ||
+ mType == TextureType::_2DMultisampleArray || mType == TextureType::CubeMapArray;
+}
+
+TextureTarget ImageIndex::getTarget() const
+{
+ return TextureTypeToTarget(mType, mLayerIndex);
+}
+
+gl::TextureTarget ImageIndex::getTargetOrFirstCubeFace() const
+{
+ if (isEntireLevelCubeMap())
+ {
+ return gl::kCubeMapTextureTargetMin;
+ }
+ else
+ {
+ return getTarget();
+ }
+}
+
+GLint ImageIndex::cubeMapFaceIndex() const
+{
+ ASSERT(mType == TextureType::CubeMap);
+ ASSERT(mLayerIndex == kEntireLevel || mLayerIndex < static_cast<GLint>(kCubeFaceCount));
+ return mLayerIndex;
+}
+
+bool ImageIndex::valid() const
+{
+ return mType != TextureType::InvalidEnum;
+}
+
+bool ImageIndex::isEntireLevelCubeMap() const
+{
+ return mType == TextureType::CubeMap && mLayerIndex == ImageIndex::kEntireLevel;
+}
+
+ImageIndex ImageIndex::Make2D(GLint levelIndex)
+{
+ return ImageIndex(TextureType::_2D, levelIndex, kEntireLevel, 1);
+}
+
+ImageIndex ImageIndex::MakeRectangle(GLint levelIndex)
+{
+ return ImageIndex(TextureType::Rectangle, levelIndex, kEntireLevel, 1);
+}
+
+ImageIndex ImageIndex::MakeCubeMapFace(TextureTarget target, GLint levelIndex)
+{
+ ASSERT(IsCubeMapFaceTarget(target));
+ return ImageIndex(TextureType::CubeMap, levelIndex, TextureTargetToLayer(target), 1);
+}
+
+ImageIndex ImageIndex::Make2DArray(GLint levelIndex, GLint layerIndex)
+{
+ return ImageIndex(TextureType::_2DArray, levelIndex, layerIndex, 1);
+}
+
+ImageIndex ImageIndex::Make2DArrayRange(GLint levelIndex, GLint layerIndex, GLint numLayers)
+{
+ return ImageIndex(TextureType::_2DArray, levelIndex, layerIndex, numLayers);
+}
+
+ImageIndex ImageIndex::Make3D(GLint levelIndex, GLint layerIndex)
+{
+ return ImageIndex(TextureType::_3D, levelIndex, layerIndex, 1);
+}
+
+ImageIndex ImageIndex::MakeFromTarget(TextureTarget target, GLint levelIndex, GLint depth)
+{
+ return ImageIndex(TextureTargetToType(target), levelIndex, TextureTargetToLayer(target),
+ IsArrayTarget(target) ? depth : 1);
+}
+
+ImageIndex ImageIndex::MakeFromType(TextureType type,
+ GLint levelIndex,
+ GLint layerIndex,
+ GLint layerCount)
+{
+ GLint overrideLayerCount =
+ (type == TextureType::CubeMap && layerIndex == kEntireLevel ? kCubeFaceCount : layerCount);
+ return ImageIndex(type, levelIndex, layerIndex, overrideLayerCount);
+}
+
+ImageIndex ImageIndex::MakeBuffer()
+{
+ return ImageIndex(TextureType::Buffer, 0, kEntireLevel, 1);
+}
+
+ImageIndex ImageIndex::Make2DMultisample()
+{
+ return ImageIndex(TextureType::_2DMultisample, 0, kEntireLevel, 1);
+}
+
+ImageIndex ImageIndex::Make2DMultisampleArray(GLint layerIndex)
+{
+ return ImageIndex(TextureType::_2DMultisampleArray, 0, layerIndex, 1);
+}
+
+ImageIndex ImageIndex::Make2DMultisampleArrayRange(GLint layerIndex, GLint numLayers)
+{
+ return ImageIndex(TextureType::_2DMultisampleArray, 0, layerIndex, numLayers);
+}
+
+bool ImageIndex::operator<(const ImageIndex &b) const
+{
+ return std::tie(mType, mLevelIndex, mLayerIndex, mLayerCount) <
+ std::tie(b.mType, b.mLevelIndex, b.mLayerIndex, b.mLayerCount);
+}
+
+bool ImageIndex::operator==(const ImageIndex &b) const
+{
+ return std::tie(mType, mLevelIndex, mLayerIndex, mLayerCount) ==
+ std::tie(b.mType, b.mLevelIndex, b.mLayerIndex, b.mLayerCount);
+}
+
+bool ImageIndex::operator!=(const ImageIndex &b) const
+{
+ return !(*this == b);
+}
+
+ImageIndex::ImageIndex(TextureType type, GLint levelIndex, GLint layerIndex, GLint layerCount)
+ : mType(type), mLevelIndex(levelIndex), mLayerIndex(layerIndex), mLayerCount(layerCount)
+{}
+
+ImageIndexIterator ImageIndex::getLayerIterator(GLint layerCount) const
+{
+ ASSERT(mType != TextureType::_2D && !hasLayer());
+ return ImageIndexIterator::MakeGeneric(mType, mLevelIndex, mLevelIndex + 1, 0, layerCount);
+}
+
+ImageIndexIterator::ImageIndexIterator(const ImageIndexIterator &other) = default;
+
+ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip)
+{
+ return ImageIndexIterator(TextureType::_2D, Range<GLint>(minMip, maxMip),
+ Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
+ nullptr);
+}
+
+ImageIndexIterator ImageIndexIterator::MakeRectangle(GLint minMip, GLint maxMip)
+{
+ return ImageIndexIterator(TextureType::Rectangle, Range<GLint>(minMip, maxMip),
+ Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
+ nullptr);
+}
+
+ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip)
+{
+ return ImageIndexIterator(TextureType::CubeMap, Range<GLint>(minMip, maxMip),
+ Range<GLint>(0, 6), nullptr);
+}
+
+ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip,
+ GLint maxMip,
+ GLint minLayer,
+ GLint maxLayer)
+{
+ return ImageIndexIterator(TextureType::_3D, Range<GLint>(minMip, maxMip),
+ Range<GLint>(minLayer, maxLayer), nullptr);
+}
+
+ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip,
+ GLint maxMip,
+ const GLsizei *layerCounts)
+{
+ return ImageIndexIterator(TextureType::_2DArray, Range<GLint>(minMip, maxMip),
+ Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS),
+ layerCounts);
+}
+
+ImageIndexIterator ImageIndexIterator::Make2DMultisample()
+{
+ return ImageIndexIterator(TextureType::_2DMultisample, Range<GLint>(0, 1),
+ Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
+ nullptr);
+}
+
+ImageIndexIterator ImageIndexIterator::MakeBuffer()
+{
+ return ImageIndexIterator(TextureType::Buffer, Range<GLint>(0, 1),
+ Range<GLint>(ImageIndex::kEntireLevel, ImageIndex::kEntireLevel),
+ nullptr);
+}
+
+ImageIndexIterator ImageIndexIterator::Make2DMultisampleArray(const GLsizei *layerCounts)
+{
+ return ImageIndexIterator(TextureType::_2DMultisampleArray, Range<GLint>(0, 1),
+ Range<GLint>(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS),
+ layerCounts);
+}
+
+ImageIndexIterator ImageIndexIterator::MakeGeneric(TextureType type,
+ GLint minMip,
+ GLint maxMip,
+ GLint minLayer,
+ GLint maxLayer)
+{
+ if (type == TextureType::CubeMap)
+ {
+ return MakeCube(minMip, maxMip);
+ }
+
+ return ImageIndexIterator(type, Range<GLint>(minMip, maxMip), Range<GLint>(minLayer, maxLayer),
+ nullptr);
+}
+
+ImageIndexIterator::ImageIndexIterator(TextureType type,
+ const Range<GLint> &mipRange,
+ const Range<GLint> &layerRange,
+ const GLsizei *layerCounts)
+ : mMipRange(mipRange),
+ mLayerRange(layerRange),
+ mLayerCounts(layerCounts),
+ mCurrentIndex(type, mipRange.low(), layerRange.low(), 1)
+{}
+
+GLint ImageIndexIterator::maxLayer() const
+{
+ if (mLayerCounts)
+ {
+ ASSERT(mCurrentIndex.hasLayer());
+ return (mCurrentIndex.getLevelIndex() < mMipRange.high())
+ ? mLayerCounts[mCurrentIndex.getLevelIndex()]
+ : 0;
+ }
+ return mLayerRange.high();
+}
+
+ImageIndex ImageIndexIterator::next()
+{
+ ASSERT(hasNext());
+
+ // Make a copy of the current index to return
+ ImageIndex previousIndex = mCurrentIndex;
+
+ // Iterate layers in the inner loop for now. We can add switchable
+ // layer or mip iteration if we need it.
+
+ if (mCurrentIndex.hasLayer() && mCurrentIndex.getLayerIndex() < maxLayer() - 1)
+ {
+ mCurrentIndex.mLayerIndex++;
+ }
+ else if (mCurrentIndex.mLevelIndex < mMipRange.high() - 1)
+ {
+ mCurrentIndex.mLayerIndex = mLayerRange.low();
+ mCurrentIndex.mLevelIndex++;
+ }
+ else
+ {
+ mCurrentIndex = ImageIndex();
+ }
+
+ return previousIndex;
+}
+
+ImageIndex ImageIndexIterator::current() const
+{
+ return mCurrentIndex;
+}
+
+bool ImageIndexIterator::hasNext() const
+{
+ return mCurrentIndex.valid();
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/ImageIndex.h b/gfx/angle/checkout/src/libANGLE/ImageIndex.h
new file mode 100644
index 0000000000..4625d310d8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/ImageIndex.h
@@ -0,0 +1,133 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ImageIndex.h: A helper struct for indexing into an Image array
+
+#ifndef LIBANGLE_IMAGE_INDEX_H_
+#define LIBANGLE_IMAGE_INDEX_H_
+
+#include "common/PackedEnums.h"
+#include "common/mathutil.h"
+
+#include "angle_gl.h"
+
+namespace gl
+{
+
+class ImageIndexIterator;
+
+class ImageIndex
+{
+ public:
+ ImageIndex();
+ ImageIndex(const ImageIndex &other);
+ ImageIndex &operator=(const ImageIndex &other);
+
+ TextureType getType() const { return mType; }
+ GLint getLevelIndex() const { return mLevelIndex; }
+ GLint getLayerIndex() const { return mLayerIndex; }
+ GLint getLayerCount() const { return mLayerCount; }
+
+ bool hasLayer() const;
+ bool has3DLayer() const;
+ bool usesTex3D() const;
+ GLint cubeMapFaceIndex() const;
+ bool valid() const;
+ // Note that you cannot use this function when the ImageIndex represents an entire level of cube
+ // map.
+ TextureTarget getTarget() const;
+
+ TextureTarget getTargetOrFirstCubeFace() const;
+
+ bool isLayered() const;
+ bool isEntireLevelCubeMap() const;
+
+ static ImageIndex MakeBuffer();
+ static ImageIndex Make2D(GLint levelIndex);
+ static ImageIndex MakeRectangle(GLint levelIndex);
+ static ImageIndex MakeCubeMapFace(TextureTarget target, GLint levelIndex);
+ static ImageIndex Make2DArray(GLint levelIndex, GLint layerIndex = kEntireLevel);
+ static ImageIndex Make2DArrayRange(GLint levelIndex, GLint layerIndex, GLint layerCount);
+ static ImageIndex Make3D(GLint levelIndex, GLint layerIndex = kEntireLevel);
+ static ImageIndex MakeFromTarget(TextureTarget target, GLint levelIndex, GLint depth = 0);
+ static ImageIndex MakeFromType(TextureType type,
+ GLint levelIndex,
+ GLint layerIndex = kEntireLevel,
+ GLint layerCount = 1);
+ static ImageIndex Make2DMultisample();
+ static ImageIndex Make2DMultisampleArray(GLint layerIndex = kEntireLevel);
+ static ImageIndex Make2DMultisampleArrayRange(GLint layerIndex, GLint layerCount);
+
+ static constexpr GLint kEntireLevel = static_cast<GLint>(-1);
+
+ bool operator<(const ImageIndex &b) const;
+ bool operator==(const ImageIndex &b) const;
+ bool operator!=(const ImageIndex &b) const;
+
+ // Only valid for 3D/Cube textures with layers.
+ ImageIndexIterator getLayerIterator(GLint layerCount) const;
+
+ private:
+ friend class ImageIndexIterator;
+
+ ImageIndex(TextureType type, GLint leveIndex, GLint layerIndex, GLint layerCount);
+
+ TextureType mType;
+ GLint mLevelIndex;
+ GLint mLayerIndex;
+ GLint mLayerCount;
+};
+
+// To be used like this:
+//
+// ImageIndexIterator it = ...;
+// while (it.hasNext())
+// {
+// ImageIndex current = it.next();
+// }
+class ImageIndexIterator
+{
+ public:
+ ImageIndexIterator(const ImageIndexIterator &other);
+
+ static ImageIndexIterator MakeBuffer();
+ static ImageIndexIterator Make2D(GLint minMip, GLint maxMip);
+ static ImageIndexIterator MakeRectangle(GLint minMip, GLint maxMip);
+ static ImageIndexIterator MakeCube(GLint minMip, GLint maxMip);
+ static ImageIndexIterator Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer);
+ static ImageIndexIterator Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts);
+ static ImageIndexIterator Make2DMultisample();
+ static ImageIndexIterator Make2DMultisampleArray(const GLsizei *layerCounts);
+ static ImageIndexIterator MakeGeneric(TextureType type,
+ GLint minMip,
+ GLint maxMip,
+ GLint minLayer,
+ GLint maxLayer);
+
+ ImageIndex next();
+ ImageIndex current() const;
+ bool hasNext() const;
+
+ private:
+ ImageIndexIterator(TextureType type,
+ const Range<GLint> &mipRange,
+ const Range<GLint> &layerRange,
+ const GLsizei *layerCounts);
+
+ GLint maxLayer() const;
+
+ const Range<GLint> mMipRange;
+ const Range<GLint> mLayerRange;
+ const GLsizei *const mLayerCounts;
+
+ ImageIndex mCurrentIndex;
+};
+
+TextureTarget TextureTypeToTarget(TextureType type, GLint layerIndex);
+
+} // namespace gl
+
+#endif // LIBANGLE_IMAGE_INDEX_H_
diff --git a/gfx/angle/checkout/src/libANGLE/IndexRangeCache.cpp b/gfx/angle/checkout/src/libANGLE/IndexRangeCache.cpp
new file mode 100644
index 0000000000..d16b2bd9c7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/IndexRangeCache.cpp
@@ -0,0 +1,116 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexRangeCache.cpp: Defines the gl::IndexRangeCache class which stores information about
+// ranges of indices.
+
+#include "libANGLE/IndexRangeCache.h"
+
+#include "common/debug.h"
+#include "libANGLE/formatutils.h"
+
+namespace gl
+{
+
+IndexRangeCache::IndexRangeCache() {}
+
+IndexRangeCache::~IndexRangeCache() {}
+
+void IndexRangeCache::addRange(DrawElementsType type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ const IndexRange &range)
+{
+ mIndexRangeCache[IndexRangeKey(type, offset, count, primitiveRestartEnabled)] = range;
+}
+
+bool IndexRangeCache::findRange(DrawElementsType type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ IndexRange *outRange) const
+{
+ auto i = mIndexRangeCache.find(IndexRangeKey(type, offset, count, primitiveRestartEnabled));
+ if (i != mIndexRangeCache.end())
+ {
+ if (outRange)
+ {
+ *outRange = i->second;
+ }
+ return true;
+ }
+ else
+ {
+ if (outRange)
+ {
+ *outRange = IndexRange();
+ }
+ return false;
+ }
+}
+
+void IndexRangeCache::invalidateRange(size_t offset, size_t size)
+{
+ size_t invalidateStart = offset;
+ size_t invalidateEnd = offset + size;
+
+ auto i = mIndexRangeCache.begin();
+ while (i != mIndexRangeCache.end())
+ {
+ size_t rangeStart = i->first.offset;
+ size_t rangeEnd =
+ i->first.offset + (GetDrawElementsTypeSize(i->first.type) * i->first.count);
+
+ if (invalidateEnd < rangeStart || invalidateStart > rangeEnd)
+ {
+ ++i;
+ }
+ else
+ {
+ mIndexRangeCache.erase(i++);
+ }
+ }
+}
+
+void IndexRangeCache::clear()
+{
+ mIndexRangeCache.clear();
+}
+
+IndexRangeCache::IndexRangeKey::IndexRangeKey()
+ : IndexRangeCache::IndexRangeKey(DrawElementsType::InvalidEnum, 0, 0, false)
+{}
+
+IndexRangeCache::IndexRangeKey::IndexRangeKey(DrawElementsType type_,
+ size_t offset_,
+ size_t count_,
+ bool primitiveRestartEnabled_)
+ : type(type_), offset(offset_), count(count_), primitiveRestartEnabled(primitiveRestartEnabled_)
+{}
+
+bool IndexRangeCache::IndexRangeKey::operator<(const IndexRangeKey &rhs) const
+{
+ if (type != rhs.type)
+ {
+ return type < rhs.type;
+ }
+ if (offset != rhs.offset)
+ {
+ return offset < rhs.offset;
+ }
+ if (count != rhs.count)
+ {
+ return count < rhs.count;
+ }
+ if (primitiveRestartEnabled != rhs.primitiveRestartEnabled)
+ {
+ return primitiveRestartEnabled;
+ }
+ return false;
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/IndexRangeCache.h b/gfx/angle/checkout/src/libANGLE/IndexRangeCache.h
new file mode 100644
index 0000000000..0a0c22fe04
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/IndexRangeCache.h
@@ -0,0 +1,63 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexRangeCache.h: Defines the gl::IndexRangeCache class which stores information about
+// ranges of indices.
+
+#ifndef LIBANGLE_INDEXRANGECACHE_H_
+#define LIBANGLE_INDEXRANGECACHE_H_
+
+#include "angle_gl.h"
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+
+#include <map>
+
+namespace gl
+{
+
+class IndexRangeCache
+{
+ public:
+ IndexRangeCache();
+ ~IndexRangeCache();
+
+ void addRange(DrawElementsType type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ const IndexRange &range);
+ bool findRange(DrawElementsType type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ IndexRange *outRange) const;
+
+ void invalidateRange(size_t offset, size_t size);
+ void clear();
+
+ private:
+ struct IndexRangeKey
+ {
+ IndexRangeKey();
+ IndexRangeKey(DrawElementsType type, size_t offset, size_t count, bool primitiveRestart);
+
+ bool operator<(const IndexRangeKey &rhs) const;
+
+ DrawElementsType type;
+ size_t offset;
+ size_t count;
+ bool primitiveRestartEnabled;
+ };
+
+ typedef std::map<IndexRangeKey, IndexRange> IndexRangeMap;
+ IndexRangeMap mIndexRangeCache;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_INDEXRANGECACHE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/InfoLog.h b/gfx/angle/checkout/src/libANGLE/InfoLog.h
new file mode 100644
index 0000000000..53333ea1aa
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/InfoLog.h
@@ -0,0 +1,90 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// InfoLog.h: Defines the gl::InfoLog class to handle the logs generated when
+// compiling/linking shaders so useful error messages can be returned to the caller.
+
+#ifndef LIBANGLE_INFOLOG_H_
+#define LIBANGLE_INFOLOG_H_
+
+namespace gl
+{
+
+class InfoLog : angle::NonCopyable
+{
+ public:
+ InfoLog();
+ ~InfoLog();
+
+ size_t getLength() const;
+ void getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
+
+ void appendSanitized(const char *message);
+ void reset();
+
+ // This helper class ensures we append a newline after writing a line.
+ class StreamHelper : angle::NonCopyable
+ {
+ public:
+ StreamHelper(StreamHelper &&rhs) : mStream(rhs.mStream) { rhs.mStream = nullptr; }
+
+ StreamHelper &operator=(StreamHelper &&rhs)
+ {
+ std::swap(mStream, rhs.mStream);
+ return *this;
+ }
+
+ ~StreamHelper()
+ {
+ // Write newline when destroyed on the stack
+ if (mStream && !mStream->str().empty())
+ {
+ (*mStream) << std::endl;
+ }
+ }
+
+ template <typename T>
+ StreamHelper &operator<<(const T &value)
+ {
+ (*mStream) << value;
+ return *this;
+ }
+
+ private:
+ friend class InfoLog;
+
+ StreamHelper(std::stringstream *stream) : mStream(stream) { ASSERT(stream); }
+
+ std::stringstream *mStream;
+ };
+
+ template <typename T>
+ StreamHelper operator<<(const T &value)
+ {
+ ensureInitialized();
+ StreamHelper helper(mLazyStream.get());
+ helper << value;
+ return helper;
+ }
+
+ std::string str() const { return mLazyStream ? mLazyStream->str() : ""; }
+
+ bool empty() const;
+
+ private:
+ void ensureInitialized()
+ {
+ if (!mLazyStream)
+ {
+ mLazyStream.reset(new std::stringstream());
+ }
+ }
+
+ std::unique_ptr<std::stringstream> mLazyStream;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_INFOLOG_H_
diff --git a/gfx/angle/checkout/src/libANGLE/LoggingAnnotator.cpp b/gfx/angle/checkout/src/libANGLE/LoggingAnnotator.cpp
new file mode 100644
index 0000000000..4cf999c4a0
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/LoggingAnnotator.cpp
@@ -0,0 +1,63 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// LoggingAnnotator.cpp: DebugAnnotator implementing logging
+//
+
+#include "libANGLE/LoggingAnnotator.h"
+
+#include "libANGLE/trace.h"
+
+namespace angle
+{
+
+bool LoggingAnnotator::getStatus(const gl::Context *context)
+{
+ return false;
+}
+
+void LoggingAnnotator::beginEvent(gl::Context *context,
+ EntryPoint entryPoint,
+ const char *eventName,
+ const char *eventMessage)
+{
+ ANGLE_TRACE_EVENT_BEGIN0("gpu.angle", eventName);
+}
+
+void LoggingAnnotator::endEvent(gl::Context *context, const char *eventName, EntryPoint entryPoint)
+{
+ ANGLE_TRACE_EVENT_END0("gpu.angle", eventName);
+}
+
+void LoggingAnnotator::setMarker(gl::Context *context, const char *markerName)
+{
+ ANGLE_TRACE_EVENT_INSTANT0("gpu.angle", markerName);
+}
+
+void LoggingAnnotator::logMessage(const gl::LogMessage &msg) const
+{
+ auto *plat = ANGLEPlatformCurrent();
+ if (plat != nullptr)
+ {
+ switch (msg.getSeverity())
+ {
+ case gl::LOG_FATAL:
+ case gl::LOG_ERR:
+ plat->logError(plat, msg.getMessage().c_str());
+ break;
+ case gl::LOG_WARN:
+ plat->logWarning(plat, msg.getMessage().c_str());
+ break;
+ case gl::LOG_INFO:
+ plat->logInfo(plat, msg.getMessage().c_str());
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ gl::Trace(msg.getSeverity(), msg.getMessage().c_str());
+}
+
+} // namespace angle
diff --git a/gfx/angle/checkout/src/libANGLE/LoggingAnnotator.h b/gfx/angle/checkout/src/libANGLE/LoggingAnnotator.h
new file mode 100644
index 0000000000..7a86d4e72f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/LoggingAnnotator.h
@@ -0,0 +1,39 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// LoggingAnnotator.h: DebugAnnotator implementing logging
+//
+
+#ifndef LIBANGLE_LOGGINGANNOTATOR_H_
+#define LIBANGLE_LOGGINGANNOTATOR_H_
+
+#include "common/debug.h"
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace angle
+{
+
+class LoggingAnnotator : public gl::DebugAnnotator
+{
+ public:
+ LoggingAnnotator() {}
+ ~LoggingAnnotator() override {}
+ void beginEvent(gl::Context *context,
+ EntryPoint entryPoint,
+ const char *eventName,
+ const char *eventMessage) override;
+ void endEvent(gl::Context *context, const char *eventName, EntryPoint entryPoint) override;
+ void setMarker(gl::Context *context, const char *markerName) override;
+ bool getStatus(const gl::Context *context) override;
+ void logMessage(const gl::LogMessage &msg) const override;
+};
+
+} // namespace angle
+
+#endif // LIBANGLE_LOGGINGANNOTATOR_H_
diff --git a/gfx/angle/checkout/src/libANGLE/MemoryObject.cpp b/gfx/angle/checkout/src/libANGLE/MemoryObject.cpp
new file mode 100644
index 0000000000..a137f265c5
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/MemoryObject.cpp
@@ -0,0 +1,66 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// MemoryObject.h: Implements the gl::MemoryObject class [EXT_external_objects]
+
+#include "libANGLE/MemoryObject.h"
+
+#include "common/angleutils.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/MemoryObjectImpl.h"
+
+namespace gl
+{
+
+MemoryObject::MemoryObject(rx::GLImplFactory *factory, MemoryObjectID id)
+ : RefCountObject(factory->generateSerial(), id),
+ mImplementation(factory->createMemoryObject()),
+ mImmutable(false),
+ mDedicatedMemory(false),
+ mProtectedMemory(false)
+{}
+
+MemoryObject::~MemoryObject() {}
+
+void MemoryObject::onDestroy(const Context *context)
+{
+ mImplementation->onDestroy(context);
+}
+
+angle::Result MemoryObject::setDedicatedMemory(const Context *context, bool dedicatedMemory)
+{
+ ANGLE_TRY(mImplementation->setDedicatedMemory(context, dedicatedMemory));
+ mDedicatedMemory = dedicatedMemory;
+ return angle::Result::Continue;
+}
+
+angle::Result MemoryObject::setProtectedMemory(const Context *context, bool protectedMemory)
+{
+ ANGLE_TRY(mImplementation->setProtectedMemory(context, protectedMemory));
+ mProtectedMemory = protectedMemory;
+ return angle::Result::Continue;
+}
+
+angle::Result MemoryObject::importFd(Context *context,
+ GLuint64 size,
+ HandleType handleType,
+ GLint fd)
+{
+ ANGLE_TRY(mImplementation->importFd(context, size, handleType, fd));
+ mImmutable = true;
+ return angle::Result::Continue;
+}
+
+angle::Result MemoryObject::importZirconHandle(Context *context,
+ GLuint64 size,
+ HandleType handleType,
+ GLuint handle)
+{
+ ANGLE_TRY(mImplementation->importZirconHandle(context, size, handleType, handle));
+ mImmutable = true;
+ return angle::Result::Continue;
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/MemoryObject.h b/gfx/angle/checkout/src/libANGLE/MemoryObject.h
new file mode 100644
index 0000000000..0507f7e2c3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/MemoryObject.h
@@ -0,0 +1,60 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// MemoryObject.h: Defines the gl::MemoryObject class [EXT_external_objects]
+
+#ifndef LIBANGLE_MEMORYOBJECT_H_
+#define LIBANGLE_MEMORYOBJECT_H_
+
+#include "angle_gl.h"
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+namespace rx
+{
+class GLImplFactory;
+class MemoryObjectImpl;
+} // namespace rx
+
+namespace gl
+{
+class Context;
+
+class MemoryObject final : public RefCountObject<MemoryObjectID>
+{
+ public:
+ MemoryObject(rx::GLImplFactory *factory, MemoryObjectID id);
+ ~MemoryObject() override;
+
+ void onDestroy(const Context *context) override;
+
+ rx::MemoryObjectImpl *getImplementation() const { return mImplementation.get(); }
+
+ bool isImmutable() const { return mImmutable; }
+
+ angle::Result setDedicatedMemory(const Context *context, bool dedicatedMemory);
+ bool isDedicatedMemory() const { return mDedicatedMemory; }
+ angle::Result setProtectedMemory(const Context *context, bool protectedMemory);
+ bool isProtectedMemory() const { return mProtectedMemory; }
+
+ angle::Result importFd(Context *context, GLuint64 size, HandleType handleType, GLint fd);
+ angle::Result importZirconHandle(Context *context,
+ GLuint64 size,
+ HandleType handleType,
+ GLuint handle);
+
+ private:
+ std::unique_ptr<rx::MemoryObjectImpl> mImplementation;
+
+ bool mImmutable;
+ bool mDedicatedMemory;
+ bool mProtectedMemory;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_MEMORYOBJECT_H_
diff --git a/gfx/angle/checkout/src/libANGLE/MemoryProgramCache.cpp b/gfx/angle/checkout/src/libANGLE/MemoryProgramCache.cpp
new file mode 100644
index 0000000000..35894913a6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/MemoryProgramCache.cpp
@@ -0,0 +1,283 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// MemoryProgramCache: Stores compiled and linked programs in memory so they don't
+// always have to be re-compiled. Can be used in conjunction with the platform
+// layer to warm up the cache from disk.
+
+// Include zlib first, otherwise FAR gets defined elsewhere.
+#define USE_SYSTEM_ZLIB
+#include "compression_utils_portable.h"
+
+#include "libANGLE/MemoryProgramCache.h"
+
+#include <GLSLANG/ShaderVars.h>
+#include <anglebase/sha1.h>
+
+#include "common/angle_version_info.h"
+#include "common/utilities.h"
+#include "libANGLE/BinaryStream.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/capture/FrameCapture.h"
+#include "libANGLE/histogram_macros.h"
+#include "libANGLE/renderer/ProgramImpl.h"
+#include "platform/PlatformMethods.h"
+
+namespace gl
+{
+
+namespace
+{
+class HashStream final : angle::NonCopyable
+{
+ public:
+ std::string str() { return mStringStream.str(); }
+
+ template <typename T>
+ HashStream &operator<<(T value)
+ {
+ mStringStream << value << kSeparator;
+ return *this;
+ }
+
+ private:
+ static constexpr char kSeparator = ':';
+ std::ostringstream mStringStream;
+};
+
+HashStream &operator<<(HashStream &stream, Shader *shader)
+{
+ if (shader)
+ {
+ stream << shader->getSourceString().c_str() << shader->getSourceString().length()
+ << shader->getCompilerResourcesString().c_str();
+ }
+ return stream;
+}
+
+HashStream &operator<<(HashStream &stream, const ProgramBindings &bindings)
+{
+ for (const auto &binding : bindings.getStableIterationMap())
+ {
+ stream << binding.first << binding.second;
+ }
+ return stream;
+}
+
+HashStream &operator<<(HashStream &stream, const ProgramAliasedBindings &bindings)
+{
+ for (const auto &binding : bindings.getStableIterationMap())
+ {
+ stream << binding.first << binding.second.location;
+ }
+ return stream;
+}
+
+HashStream &operator<<(HashStream &stream, const std::vector<std::string> &strings)
+{
+ for (const auto &str : strings)
+ {
+ stream << str;
+ }
+ return stream;
+}
+
+HashStream &operator<<(HashStream &stream, const std::vector<gl::VariableLocation> &locations)
+{
+ for (const auto &loc : locations)
+ {
+ stream << loc.index << loc.arrayIndex << loc.ignored;
+ }
+ return stream;
+}
+
+} // anonymous namespace
+
+MemoryProgramCache::MemoryProgramCache(egl::BlobCache &blobCache) : mBlobCache(blobCache) {}
+
+MemoryProgramCache::~MemoryProgramCache() {}
+
+void MemoryProgramCache::ComputeHash(const Context *context,
+ const Program *program,
+ egl::BlobCache::Key *hashOut)
+{
+ // Compute the program hash. Start with the shader hashes and resource strings.
+ HashStream hashStream;
+ for (ShaderType shaderType : AllShaderTypes())
+ {
+ hashStream << program->getAttachedShader(shaderType);
+ }
+
+ // Add some ANGLE metadata and Context properties, such as version and back-end.
+ hashStream << angle::GetANGLECommitHash() << context->getClientMajorVersion()
+ << context->getClientMinorVersion() << context->getString(GL_RENDERER);
+
+ // Hash pre-link program properties.
+ hashStream << program->getAttributeBindings() << program->getUniformLocationBindings()
+ << program->getFragmentOutputLocations() << program->getFragmentOutputIndexes()
+ << program->getState().getTransformFeedbackVaryingNames()
+ << program->getState().getTransformFeedbackBufferMode()
+ << program->getState().getOutputLocations()
+ << program->getState().getSecondaryOutputLocations();
+
+ // Include the status of FrameCapture, which adds source strings to the binary
+ hashStream << context->getShareGroup()->getFrameCaptureShared()->enabled();
+
+ // Call the secure SHA hashing function.
+ const std::string &programKey = hashStream.str();
+ angle::base::SHA1HashBytes(reinterpret_cast<const unsigned char *>(programKey.c_str()),
+ programKey.length(), hashOut->data());
+}
+
+angle::Result MemoryProgramCache::getProgram(const Context *context,
+ Program *program,
+ egl::BlobCache::Key *hashOut)
+{
+ // If caching is effectively disabled, don't bother calculating the hash.
+ if (!mBlobCache.isCachingEnabled())
+ {
+ return angle::Result::Incomplete;
+ }
+
+ ComputeHash(context, program, hashOut);
+
+ angle::MemoryBuffer uncompressedData;
+ switch (mBlobCache.getAndDecompress(context->getScratchBuffer(), *hashOut, &uncompressedData))
+ {
+ case egl::BlobCache::GetAndDecompressResult::NotFound:
+ return angle::Result::Incomplete;
+
+ case egl::BlobCache::GetAndDecompressResult::DecompressFailure:
+ ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
+ "Error decompressing program binary data fetched from cache.");
+ return angle::Result::Incomplete;
+
+ case egl::BlobCache::GetAndDecompressResult::GetSuccess:
+ angle::Result result =
+ program->loadBinary(context, GL_PROGRAM_BINARY_ANGLE, uncompressedData.data(),
+ static_cast<int>(uncompressedData.size()));
+ ANGLE_TRY(result);
+
+ if (result == angle::Result::Continue)
+ return angle::Result::Continue;
+
+ // Cache load failed, evict
+ ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
+ "Failed to load program binary from cache.");
+ remove(*hashOut);
+
+ return angle::Result::Incomplete;
+ }
+
+ UNREACHABLE();
+ return angle::Result::Incomplete;
+}
+
+bool MemoryProgramCache::getAt(size_t index,
+ const egl::BlobCache::Key **hashOut,
+ egl::BlobCache::Value *programOut)
+{
+ return mBlobCache.getAt(index, hashOut, programOut);
+}
+
+void MemoryProgramCache::remove(const egl::BlobCache::Key &programHash)
+{
+ mBlobCache.remove(programHash);
+}
+
+angle::Result MemoryProgramCache::putProgram(const egl::BlobCache::Key &programHash,
+ const Context *context,
+ const Program *program)
+{
+ // If caching is effectively disabled, don't bother serializing the program.
+ if (!mBlobCache.isCachingEnabled())
+ {
+ return angle::Result::Incomplete;
+ }
+
+ angle::MemoryBuffer serializedProgram;
+ ANGLE_TRY(program->serialize(context, &serializedProgram));
+
+ angle::MemoryBuffer compressedData;
+ if (!egl::CompressBlobCacheData(serializedProgram.size(), serializedProgram.data(),
+ &compressedData))
+ {
+ ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
+ "Error compressing binary data.");
+ return angle::Result::Incomplete;
+ }
+
+ {
+ std::scoped_lock<std::mutex> lock(mBlobCache.getMutex());
+ // TODO: http://anglebug.com/7568
+ // This was a workaround for Chrome until it added support for EGL_ANDROID_blob_cache,
+ // tracked by http://anglebug.com/2516. This issue has since been closed, but removing this
+ // still causes a test failure.
+ auto *platform = ANGLEPlatformCurrent();
+ platform->cacheProgram(platform, programHash, compressedData.size(), compressedData.data());
+ }
+
+ mBlobCache.put(programHash, std::move(compressedData));
+ return angle::Result::Continue;
+}
+
+angle::Result MemoryProgramCache::updateProgram(const Context *context, const Program *program)
+{
+ egl::BlobCache::Key programHash;
+ ComputeHash(context, program, &programHash);
+ return putProgram(programHash, context, program);
+}
+
+bool MemoryProgramCache::putBinary(const egl::BlobCache::Key &programHash,
+ const uint8_t *binary,
+ size_t length)
+{
+ // Copy the binary.
+ angle::MemoryBuffer newEntry;
+ if (!newEntry.resize(length))
+ {
+ return false;
+ }
+ memcpy(newEntry.data(), binary, length);
+
+ // Store the binary.
+ mBlobCache.populate(programHash, std::move(newEntry));
+
+ return true;
+}
+
+void MemoryProgramCache::clear()
+{
+ mBlobCache.clear();
+}
+
+void MemoryProgramCache::resize(size_t maxCacheSizeBytes)
+{
+ mBlobCache.resize(maxCacheSizeBytes);
+}
+
+size_t MemoryProgramCache::entryCount() const
+{
+ return mBlobCache.entryCount();
+}
+
+size_t MemoryProgramCache::trim(size_t limit)
+{
+ return mBlobCache.trim(limit);
+}
+
+size_t MemoryProgramCache::size() const
+{
+ return mBlobCache.size();
+}
+
+size_t MemoryProgramCache::maxSize() const
+{
+ return mBlobCache.maxSize();
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/MemoryProgramCache.h b/gfx/angle/checkout/src/libANGLE/MemoryProgramCache.h
new file mode 100644
index 0000000000..92f774ebed
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/MemoryProgramCache.h
@@ -0,0 +1,87 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// MemoryProgramCache: Stores compiled and linked programs in memory so they don't
+// always have to be re-compiled. Can be used in conjunction with the platform
+// layer to warm up the cache from disk.
+
+#ifndef LIBANGLE_MEMORY_PROGRAM_CACHE_H_
+#define LIBANGLE_MEMORY_PROGRAM_CACHE_H_
+
+#include <array>
+
+#include "common/MemoryBuffer.h"
+#include "libANGLE/BlobCache.h"
+#include "libANGLE/Error.h"
+
+namespace gl
+{
+class Context;
+class Program;
+class ProgramState;
+
+class MemoryProgramCache final : angle::NonCopyable
+{
+ public:
+ explicit MemoryProgramCache(egl::BlobCache &blobCache);
+ ~MemoryProgramCache();
+
+ static void ComputeHash(const Context *context,
+ const Program *program,
+ egl::BlobCache::Key *hashOut);
+
+ // For querying the contents of the cache.
+ bool getAt(size_t index,
+ const egl::BlobCache::Key **hashOut,
+ egl::BlobCache::Value *programOut);
+
+ // Evict a program from the binary cache.
+ void remove(const egl::BlobCache::Key &programHash);
+
+ // Helper method that serializes a program.
+ angle::Result putProgram(const egl::BlobCache::Key &programHash,
+ const Context *context,
+ const Program *program);
+
+ // Same as putProgram but computes the hash.
+ angle::Result updateProgram(const Context *context, const Program *program);
+
+ // Store a binary directly. TODO(syoussefi): deprecated. Will be removed once Chrome supports
+ // EGL_ANDROID_blob_cache. http://anglebug.com/2516
+ [[nodiscard]] bool putBinary(const egl::BlobCache::Key &programHash,
+ const uint8_t *binary,
+ size_t length);
+
+ // Check the cache, and deserialize and load the program if found. Evict existing hash if load
+ // fails.
+ angle::Result getProgram(const Context *context,
+ Program *program,
+ egl::BlobCache::Key *hashOut);
+
+ // Empty the cache.
+ void clear();
+
+ // Resize the cache. Discards current contents.
+ void resize(size_t maxCacheSizeBytes);
+
+ // Returns the number of entries in the cache.
+ size_t entryCount() const;
+
+ // Reduces the current cache size and returns the number of bytes freed.
+ size_t trim(size_t limit);
+
+ // Returns the current cache size in bytes.
+ size_t size() const;
+
+ // Returns the maximum cache size in bytes.
+ size_t maxSize() const;
+
+ private:
+ egl::BlobCache &mBlobCache;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_MEMORY_PROGRAM_CACHE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/MemoryShaderCache.cpp b/gfx/angle/checkout/src/libANGLE/MemoryShaderCache.cpp
new file mode 100644
index 0000000000..2bd7baef5e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/MemoryShaderCache.cpp
@@ -0,0 +1,155 @@
+//
+// Copyright 2022 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// MemoryShaderCache: Stores compiled shader in memory so they don't
+// always have to be re-compiled. Can be used in conjunction with the platform
+// layer to warm up the cache from disk.
+
+#include "libANGLE/MemoryShaderCache.h"
+
+#include <GLSLANG/ShaderVars.h>
+#include <anglebase/sha1.h>
+
+#include "common/angle_version_info.h"
+#include "common/utilities.h"
+#include "libANGLE/BinaryStream.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/histogram_macros.h"
+#include "libANGLE/renderer/ShaderImpl.h"
+#include "platform/PlatformMethods.h"
+
+namespace gl
+{
+
+namespace
+{
+void ComputeHash(const Context *context,
+ const Shader *shader,
+ const ShCompileOptions &compileOptions,
+ const ShCompilerInstance &compilerInstance,
+ egl::BlobCache::Key *hashOut)
+{
+ BinaryOutputStream hashStream;
+ // Compute the shader hash. Start with the shader hashes and resource strings.
+ hashStream.writeEnum(shader->getType());
+ hashStream.writeString(shader->getSourceString());
+
+ // Include the commit hash
+ hashStream.writeString(angle::GetANGLECommitHash());
+
+ hashStream.writeEnum(Compiler::SelectShaderSpec(context->getState()));
+ hashStream.writeEnum(compilerInstance.getShaderOutputType());
+ hashStream.writeBytes(reinterpret_cast<const uint8_t *>(&compileOptions),
+ sizeof(compileOptions));
+
+ // Include the ShBuiltInResources, which represent the extensions and constants used by the
+ // shader.
+ const ShBuiltInResources resources = compilerInstance.getBuiltInResources();
+ hashStream.writeBytes(reinterpret_cast<const uint8_t *>(&resources), sizeof(resources));
+
+ // Call the secure SHA hashing function.
+ const std::vector<uint8_t> &shaderKey = hashStream.getData();
+ angle::base::SHA1HashBytes(shaderKey.data(), shaderKey.size(), hashOut->data());
+}
+} // namespace
+
+MemoryShaderCache::MemoryShaderCache(egl::BlobCache &blobCache) : mBlobCache(blobCache) {}
+
+MemoryShaderCache::~MemoryShaderCache() {}
+
+angle::Result MemoryShaderCache::getShader(const Context *context,
+ Shader *shader,
+ const ShCompileOptions &compileOptions,
+ const ShCompilerInstance &compilerInstance,
+ egl::BlobCache::Key *hashOut)
+{
+ // If caching is effectively disabled, don't bother calculating the hash.
+ if (!mBlobCache.isCachingEnabled())
+ {
+ return angle::Result::Incomplete;
+ }
+
+ ComputeHash(context, shader, compileOptions, compilerInstance, hashOut);
+
+ angle::MemoryBuffer uncompressedData;
+ switch (mBlobCache.getAndDecompress(context->getScratchBuffer(), *hashOut, &uncompressedData))
+ {
+ case egl::BlobCache::GetAndDecompressResult::DecompressFailure:
+ ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
+ "Error decompressing shader binary data from cache.");
+ return angle::Result::Incomplete;
+
+ case egl::BlobCache::GetAndDecompressResult::NotFound:
+ return angle::Result::Incomplete;
+
+ case egl::BlobCache::GetAndDecompressResult::GetSuccess:
+ angle::Result result = shader->loadBinary(context, uncompressedData.data(),
+ static_cast<int>(uncompressedData.size()));
+
+ {
+ std::scoped_lock<std::mutex> lock(mHistogramMutex);
+ ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.ShaderCache.LoadBinarySuccess",
+ result == angle::Result::Continue);
+ }
+ ANGLE_TRY(result);
+
+ if (result == angle::Result::Continue)
+ return angle::Result::Continue;
+
+ // Cache load failed, evict.
+ ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
+ "Failed to load shader binary from cache.");
+ mBlobCache.remove(*hashOut);
+ return angle::Result::Incomplete;
+ }
+
+ UNREACHABLE();
+ return angle::Result::Incomplete;
+}
+
+angle::Result MemoryShaderCache::putShader(const Context *context,
+ const egl::BlobCache::Key &shaderHash,
+ const Shader *shader)
+{
+ // If caching is effectively disabled, don't bother serializing the shader.
+ if (!mBlobCache.isCachingEnabled())
+ {
+ return angle::Result::Incomplete;
+ }
+
+ angle::MemoryBuffer serializedShader;
+ ANGLE_TRY(shader->serialize(nullptr, &serializedShader));
+
+ size_t compressedSize;
+ if (!mBlobCache.compressAndPut(shaderHash, std::move(serializedShader), &compressedSize))
+ {
+ ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
+ "Error compressing shader binary data for insertion into cache.");
+ return angle::Result::Incomplete;
+ }
+
+ {
+ std::scoped_lock<std::mutex> lock(mHistogramMutex);
+ ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ShaderCache.ShaderBinarySizeBytes",
+ static_cast<int>(compressedSize));
+ }
+
+ return angle::Result::Continue;
+}
+
+void MemoryShaderCache::clear()
+{
+ mBlobCache.clear();
+}
+
+size_t MemoryShaderCache::maxSize() const
+{
+ return mBlobCache.maxSize();
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/MemoryShaderCache.h b/gfx/angle/checkout/src/libANGLE/MemoryShaderCache.h
new file mode 100644
index 0000000000..464201d4c7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/MemoryShaderCache.h
@@ -0,0 +1,60 @@
+//
+// Copyright 2022 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// MemoryShaderCache: Stores compiled shaders in memory so they don't
+// always have to be re-compiled. Can be used in conjunction with the platform
+// layer to warm up the cache from disk.
+
+#ifndef LIBANGLE_MEMORY_SHADER_CACHE_H_
+#define LIBANGLE_MEMORY_SHADER_CACHE_H_
+
+#include <array>
+
+#include "GLSLANG/ShaderLang.h"
+#include "common/MemoryBuffer.h"
+#include "libANGLE/BlobCache.h"
+#include "libANGLE/Error.h"
+
+namespace gl
+{
+class Context;
+class Shader;
+class ShaderState;
+class ShCompilerInstance;
+
+class MemoryShaderCache final : angle::NonCopyable
+{
+ public:
+ explicit MemoryShaderCache(egl::BlobCache &blobCache);
+ ~MemoryShaderCache();
+
+ // Helper method that serializes a shader.
+ angle::Result putShader(const Context *context,
+ const egl::BlobCache::Key &shaderHash,
+ const Shader *shader);
+
+ // Check the cache, and deserialize and load the shader if found. Evict existing hash if load
+ // fails.
+ angle::Result getShader(const Context *context,
+ Shader *shader,
+ const ShCompileOptions &compileOptions,
+ const ShCompilerInstance &compilerInstance,
+ egl::BlobCache::Key *hashOut);
+
+ // Empty the cache.
+ void clear();
+
+ // Returns the maximum cache size in bytes.
+ size_t maxSize() const;
+
+ private:
+ egl::BlobCache &mBlobCache;
+
+ std::mutex mHistogramMutex;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_MEMORY_SHADER_CACHE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Observer.cpp b/gfx/angle/checkout/src/libANGLE/Observer.cpp
new file mode 100644
index 0000000000..75f51648a4
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Observer.cpp
@@ -0,0 +1,113 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Observer:
+// Implements the Observer pattern for sending state change notifications
+// from Subject objects to dependent Observer objects.
+//
+// See design document:
+// https://docs.google.com/document/d/15Edfotqg6_l1skTEL8ADQudF_oIdNa7i8Po43k6jMd4/
+
+#include "libANGLE/Observer.h"
+
+#include <algorithm>
+
+#include "common/debug.h"
+
+namespace angle
+{
+namespace
+{} // anonymous namespace
+
+// Observer implementation.
+ObserverInterface::~ObserverInterface() = default;
+
+// Subject implementation.
+Subject::Subject() {}
+
+Subject::~Subject()
+{
+ resetObservers();
+}
+
+bool Subject::hasObservers() const
+{
+ return !mObservers.empty();
+}
+
+void Subject::onStateChange(SubjectMessage message) const
+{
+ if (mObservers.empty())
+ return;
+
+ for (const ObserverBindingBase *binding : mObservers)
+ {
+ binding->getObserver()->onSubjectStateChange(binding->getSubjectIndex(), message);
+ }
+}
+
+void Subject::resetObservers()
+{
+ for (angle::ObserverBindingBase *binding : mObservers)
+ {
+ binding->onSubjectReset();
+ }
+ mObservers.clear();
+}
+
+// ObserverBinding implementation.
+ObserverBinding::ObserverBinding() : ObserverBindingBase(nullptr, 0), mSubject(nullptr) {}
+
+ObserverBinding::ObserverBinding(ObserverInterface *observer, SubjectIndex index)
+ : ObserverBindingBase(observer, index), mSubject(nullptr)
+{
+ ASSERT(observer);
+}
+
+ObserverBinding::~ObserverBinding()
+{
+ reset();
+}
+
+ObserverBinding::ObserverBinding(const ObserverBinding &other)
+ : ObserverBindingBase(other), mSubject(nullptr)
+{
+ bind(other.mSubject);
+}
+
+ObserverBinding &ObserverBinding::operator=(const ObserverBinding &other)
+{
+ reset();
+ ObserverBindingBase::operator=(other);
+ bind(other.mSubject);
+ return *this;
+}
+
+void ObserverBinding::bind(Subject *subject)
+{
+ ASSERT(getObserver() || !subject);
+ if (mSubject)
+ {
+ mSubject->removeObserver(this);
+ }
+
+ mSubject = subject;
+
+ if (mSubject)
+ {
+ mSubject->addObserver(this);
+ }
+}
+
+void ObserverBinding::onStateChange(SubjectMessage message) const
+{
+ getObserver()->onSubjectStateChange(getSubjectIndex(), message);
+}
+
+void ObserverBinding::onSubjectReset()
+{
+ mSubject = nullptr;
+}
+} // namespace angle
diff --git a/gfx/angle/checkout/src/libANGLE/Observer.h b/gfx/angle/checkout/src/libANGLE/Observer.h
new file mode 100644
index 0000000000..a07a224b99
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Observer.h
@@ -0,0 +1,167 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Observer:
+// Implements the Observer pattern for sending state change notifications
+// from Subject objects to dependent Observer objects.
+//
+// See design document:
+// https://docs.google.com/document/d/15Edfotqg6_l1skTEL8ADQudF_oIdNa7i8Po43k6jMd4/
+
+#ifndef LIBANGLE_OBSERVER_H_
+#define LIBANGLE_OBSERVER_H_
+
+#include "common/FastVector.h"
+#include "common/angleutils.h"
+
+namespace angle
+{
+template <typename HaystackT, typename NeedleT>
+bool IsInContainer(const HaystackT &haystack, const NeedleT &needle)
+{
+ return std::find(haystack.begin(), haystack.end(), needle) != haystack.end();
+}
+
+using SubjectIndex = size_t;
+
+// Messages are used to distinguish different Subject events that get sent to a single Observer.
+// It could be possible to improve the handling by using different callback functions instead
+// of a single handler function. But in some cases we want to share a single binding between
+// Observer and Subject and handle different types of events.
+enum class SubjectMessage
+{
+ // Used by gl::VertexArray to notify gl::Context of a gl::Buffer binding count change. Triggers
+ // a validation cache update. Also used by gl::Texture to notify gl::Framebuffer of loops.
+ BindingChanged,
+
+ // Only the contents (pixels, bytes, etc) changed in this Subject. Distinct from the object
+ // storage.
+ ContentsChanged,
+
+ // Sent by gl::Sampler, gl::Texture, gl::Framebuffer and others to notifiy gl::Context. This
+ // flag indicates to call syncState before next use.
+ DirtyBitsFlagged,
+
+ // Generic state change message. Used in multiple places for different purposes.
+ SubjectChanged,
+
+ // Indicates a bound gl::Buffer is now mapped or unmapped. Passed from gl::Buffer, through
+ // gl::VertexArray, into gl::Context. Used to track validation.
+ SubjectMapped,
+ SubjectUnmapped,
+ // Indicates a bound buffer's storage was reallocated due to glBufferData call or optimizations
+ // to prevent having to flush pending commands and waiting for the GPU to become idle.
+ InternalMemoryAllocationChanged,
+
+ // Indicates an external change to the default framebuffer.
+ SurfaceChanged,
+ // Indicates the system framebuffer's swapchain changed, i.e. color buffer changed but no
+ // depth/stencil buffer change.
+ SwapchainImageChanged,
+
+ // Indicates a separable program's textures or images changed in the ProgramExecutable.
+ ProgramTextureOrImageBindingChanged,
+ // Indicates a separable program was successfully re-linked.
+ ProgramRelinked,
+ // Indicates a separable program's sampler uniforms were updated.
+ SamplerUniformsUpdated,
+ // Other types of uniform change.
+ ProgramUniformUpdated,
+
+ // Indicates a Storage of back-end in gl::Texture has been released.
+ StorageReleased,
+
+ // Indicates that all pending updates are complete in the subject.
+ InitializationComplete,
+};
+
+// The observing class inherits from this interface class.
+class ObserverInterface
+{
+ public:
+ virtual ~ObserverInterface();
+ virtual void onSubjectStateChange(SubjectIndex index, SubjectMessage message) = 0;
+};
+
+class ObserverBindingBase
+{
+ public:
+ ObserverBindingBase(ObserverInterface *observer, SubjectIndex subjectIndex)
+ : mObserver(observer), mIndex(subjectIndex)
+ {}
+ virtual ~ObserverBindingBase() {}
+
+ ObserverBindingBase(const ObserverBindingBase &other) = default;
+ ObserverBindingBase &operator=(const ObserverBindingBase &other) = default;
+
+ ObserverInterface *getObserver() const { return mObserver; }
+ SubjectIndex getSubjectIndex() const { return mIndex; }
+
+ virtual void onSubjectReset() {}
+
+ private:
+ ObserverInterface *mObserver;
+ SubjectIndex mIndex;
+};
+
+constexpr size_t kMaxFixedObservers = 8;
+
+// Maintains a list of observer bindings. Sends update messages to the observer.
+class Subject : NonCopyable
+{
+ public:
+ Subject();
+ virtual ~Subject();
+
+ void onStateChange(SubjectMessage message) const;
+ bool hasObservers() const;
+ void resetObservers();
+ ANGLE_INLINE size_t getObserversCount() const { return mObservers.size(); }
+
+ ANGLE_INLINE void addObserver(ObserverBindingBase *observer)
+ {
+ ASSERT(!IsInContainer(mObservers, observer));
+ mObservers.push_back(observer);
+ }
+ ANGLE_INLINE void removeObserver(ObserverBindingBase *observer)
+ {
+ ASSERT(IsInContainer(mObservers, observer));
+ mObservers.remove_and_permute(observer);
+ }
+
+ private:
+ // Keep a short list of observers so we can allocate/free them quickly. But since we support
+ // unlimited bindings, have a spill-over list of that uses dynamic allocation.
+ angle::FastVector<ObserverBindingBase *, kMaxFixedObservers> mObservers;
+};
+
+// Keeps a binding between a Subject and Observer, with a specific subject index.
+class ObserverBinding final : public ObserverBindingBase
+{
+ public:
+ ObserverBinding();
+ ObserverBinding(ObserverInterface *observer, SubjectIndex index);
+ ~ObserverBinding() override;
+ ObserverBinding(const ObserverBinding &other);
+ ObserverBinding &operator=(const ObserverBinding &other);
+
+ void bind(Subject *subject);
+
+ ANGLE_INLINE void reset() { bind(nullptr); }
+
+ void onStateChange(SubjectMessage message) const;
+ void onSubjectReset() override;
+
+ ANGLE_INLINE const Subject *getSubject() const { return mSubject; }
+
+ ANGLE_INLINE void assignSubject(Subject *subject) { mSubject = subject; }
+
+ private:
+ Subject *mSubject;
+};
+
+} // namespace angle
+
+#endif // LIBANGLE_OBSERVER_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Overlay.cpp b/gfx/angle/checkout/src/libANGLE/Overlay.cpp
new file mode 100644
index 0000000000..e84b125361
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Overlay.cpp
@@ -0,0 +1,103 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Overlay.cpp:
+// Implements the Overlay class.
+//
+
+#include "libANGLE/Overlay.h"
+
+#include "common/string_utils.h"
+#include "common/system_utils.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Overlay_font_autogen.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/OverlayImpl.h"
+
+#include <numeric>
+
+namespace gl
+{
+namespace
+{
+#define ANGLE_WIDGET_NAME_PROC(WIDGET_ID) {ANGLE_STRINGIFY(WIDGET_ID), WidgetId::WIDGET_ID},
+
+constexpr std::pair<const char *, WidgetId> kWidgetNames[] = {
+ ANGLE_WIDGET_ID_X(ANGLE_WIDGET_NAME_PROC)};
+} // namespace
+
+OverlayState::OverlayState() : mEnabledWidgetCount(0), mOverlayWidgets{} {}
+OverlayState::~OverlayState() = default;
+
+Overlay::Overlay(rx::GLImplFactory *factory)
+ : mLastPerSecondUpdate(0), mImplementation(factory->createOverlay(mState))
+{}
+Overlay::~Overlay() = default;
+
+void Overlay::init()
+{
+ initOverlayWidgets();
+ mLastPerSecondUpdate = angle::GetCurrentSystemTime();
+
+ ASSERT(std::all_of(
+ mState.mOverlayWidgets.begin(), mState.mOverlayWidgets.end(),
+ [](const std::unique_ptr<overlay::Widget> &widget) { return widget.get() != nullptr; }));
+
+ enableOverlayWidgetsFromEnvironment();
+}
+
+void Overlay::destroy(const gl::Context *context)
+{
+ ASSERT(mImplementation);
+ mImplementation->onDestroy(context);
+}
+
+void Overlay::enableOverlayWidgetsFromEnvironment()
+{
+ std::vector<std::string> enabledWidgets = angle::GetStringsFromEnvironmentVarOrAndroidProperty(
+ "ANGLE_OVERLAY", "debug.angle.overlay", ":");
+
+ for (const std::pair<const char *, WidgetId> &widgetName : kWidgetNames)
+ {
+ for (const std::string &enabledWidget : enabledWidgets)
+ {
+ if (angle::NamesMatchWithWildcard(enabledWidget.c_str(), widgetName.first))
+ {
+ mState.mOverlayWidgets[widgetName.second]->enabled = true;
+ ++mState.mEnabledWidgetCount;
+ break;
+ }
+ }
+ }
+}
+
+void Overlay::onSwap() const
+{
+ // Increment FPS counter.
+ getPerSecondWidget(WidgetId::FPS)->add(1);
+
+ // Update per second values every second.
+ double currentTime = angle::GetCurrentSystemTime();
+ double timeDiff = currentTime - mLastPerSecondUpdate;
+ if (timeDiff >= 1.0)
+ {
+ for (const std::unique_ptr<overlay::Widget> &widget : mState.mOverlayWidgets)
+ {
+ if (widget->type == WidgetType::PerSecond)
+ {
+ overlay::PerSecond *perSecond =
+ reinterpret_cast<overlay::PerSecond *>(widget.get());
+ perSecond->lastPerSecondCount = static_cast<size_t>(perSecond->count / timeDiff);
+ perSecond->count = 0;
+ }
+ }
+ mLastPerSecondUpdate += 1.0;
+ }
+}
+
+MockOverlay::MockOverlay(rx::GLImplFactory *implFactory) {}
+MockOverlay::~MockOverlay() = default;
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Overlay.h b/gfx/angle/checkout/src/libANGLE/Overlay.h
new file mode 100644
index 0000000000..124e00d3e6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Overlay.h
@@ -0,0 +1,154 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Overlay.h:
+// Defines the Overlay class that handles overlay widgets.
+//
+
+#ifndef LIBANGLE_OVERLAY_H_
+#define LIBANGLE_OVERLAY_H_
+
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/OverlayWidgets.h"
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+class OverlayImpl;
+class GLImplFactory;
+} // namespace rx
+
+namespace gl
+{
+class Context;
+
+class OverlayState : angle::NonCopyable
+{
+ public:
+ OverlayState();
+ ~OverlayState();
+
+ size_t getWidgetCoordinatesBufferSize() const;
+ size_t getTextWidgetsBufferSize() const;
+ size_t getGraphWidgetsBufferSize() const;
+
+ const uint8_t *getFontData() const;
+ void fillWidgetData(const gl::Extents &imageExtents,
+ uint8_t *textData,
+ uint8_t *graphData,
+ uint32_t *activeTextWidgetCountOut,
+ uint32_t *activeGraphWidgetCountOut) const;
+
+ uint32_t getEnabledWidgetCount() const { return mEnabledWidgetCount; }
+
+ private:
+ friend class Overlay;
+
+ uint32_t mEnabledWidgetCount;
+
+ angle::PackedEnumMap<WidgetId, std::unique_ptr<overlay::Widget>> mOverlayWidgets;
+};
+
+class Overlay : angle::NonCopyable
+{
+ public:
+ Overlay(rx::GLImplFactory *implFactory);
+ ~Overlay();
+
+ void init();
+ void destroy(const gl::Context *context);
+
+ void onSwap() const;
+
+ overlay::Text *getTextWidget(WidgetId id) const
+ {
+ return getWidgetAs<overlay::Text, WidgetType::Text>(id);
+ }
+ overlay::Count *getCountWidget(WidgetId id) const
+ {
+ return getWidgetAs<overlay::Count, WidgetType::Count>(id);
+ }
+ overlay::PerSecond *getPerSecondWidget(WidgetId id) const
+ {
+ return getWidgetAs<overlay::PerSecond, WidgetType::PerSecond>(id);
+ }
+ overlay::RunningGraph *getRunningGraphWidget(WidgetId id) const
+ {
+ return getWidgetAs<overlay::RunningGraph, WidgetType::RunningGraph>(id);
+ }
+ overlay::RunningHistogram *getRunningHistogramWidget(WidgetId id) const
+ {
+ return getWidgetAs<overlay::RunningHistogram, WidgetType::RunningHistogram>(id);
+ }
+
+ rx::OverlayImpl *getImplementation() const { return mImplementation.get(); }
+
+ bool isEnabled() const
+ {
+ return mImplementation != nullptr && mState.getEnabledWidgetCount() > 0;
+ }
+
+ private:
+ template <typename Widget, WidgetType Type>
+ Widget *getWidgetAs(WidgetId id) const
+ {
+ ASSERT(mState.mOverlayWidgets[id] != nullptr);
+ ASSERT(mState.mOverlayWidgets[id]->type == Type);
+ return rx::GetAs<Widget>(mState.mOverlayWidgets[id].get());
+ }
+ void initOverlayWidgets();
+ void enableOverlayWidgetsFromEnvironment();
+
+ // Time tracking for PerSecond items.
+ mutable double mLastPerSecondUpdate;
+
+ OverlayState mState;
+ std::unique_ptr<rx::OverlayImpl> mImplementation;
+};
+
+class MockOverlay
+{
+ public:
+ MockOverlay(rx::GLImplFactory *implFactory);
+ ~MockOverlay();
+
+ void init() {}
+ void destroy(const Context *context) {}
+
+ void onSwap() const {}
+
+ const overlay::Mock *getTextWidget(WidgetId id) const { return &mMock; }
+ const overlay::Mock *getCountWidget(WidgetId id) const { return &mMock; }
+ const overlay::Mock *getPerSecondWidget(WidgetId id) const { return &mMock; }
+ const overlay::Mock *getRunningGraphWidget(WidgetId id) const { return &mMock; }
+ const overlay::Mock *getRunningHistogramWidget(WidgetId id) const { return &mMock; }
+
+ bool isEnabled() const { return false; }
+
+ private:
+ overlay::Mock mMock;
+};
+
+#if ANGLE_ENABLE_OVERLAY
+using OverlayType = Overlay;
+using CountWidget = overlay::Count;
+using PerSecondWidget = overlay::PerSecond;
+using RunningGraphWidget = overlay::RunningGraph;
+using RunningHistogramWidget = overlay::RunningHistogram;
+using TextWidget = overlay::Text;
+#else // !ANGLE_ENABLE_OVERLAY
+using OverlayType = MockOverlay;
+using CountWidget = const overlay::Mock;
+using PerSecondWidget = const overlay::Mock;
+using RunningGraphWidget = const overlay::Mock;
+using RunningHistogramWidget = const overlay::Mock;
+using TextWidget = const overlay::Mock;
+#endif // ANGLE_ENABLE_OVERLAY
+
+} // namespace gl
+
+#endif // LIBANGLE_OVERLAY_H_
diff --git a/gfx/angle/checkout/src/libANGLE/OverlayWidgets.cpp b/gfx/angle/checkout/src/libANGLE/OverlayWidgets.cpp
new file mode 100644
index 0000000000..f0581ce9d8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/OverlayWidgets.cpp
@@ -0,0 +1,737 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// OverlayWidgets.cpp:
+// Implements functions that interpret widget data. Data formats and limits correspond to the
+// Vulkan implementation (as the only implementation). They are generic enough so other backends
+// could respect them too, if they implement the overlay.
+//
+
+#include "libANGLE/Overlay.h"
+#include "libANGLE/Overlay_font_autogen.h"
+
+#include <functional>
+
+namespace gl
+{
+namespace
+{
+// Internally, every widget is either Text or Graph.
+enum class WidgetInternalType
+{
+ Text,
+ Graph,
+
+ InvalidEnum,
+ EnumCount = InvalidEnum,
+};
+
+// A map that says how the API-facing widget types map to internal types.
+constexpr angle::PackedEnumMap<WidgetType, WidgetInternalType> kWidgetTypeToInternalMap = {
+ {WidgetType::Count, WidgetInternalType::Text},
+ {WidgetType::Text, WidgetInternalType::Text},
+ {WidgetType::PerSecond, WidgetInternalType::Text},
+ {WidgetType::RunningGraph, WidgetInternalType::Graph},
+ {WidgetType::RunningHistogram, WidgetInternalType::Graph},
+};
+
+// Structures and limits matching uniform buffers in vulkan/shaders/src/OverlayDraw.comp. The size
+// of text and graph widgets is chosen such that they could fit in uniform buffers with minimum
+// required Vulkan size.
+constexpr size_t kMaxRenderableTextWidgets = 32;
+constexpr size_t kMaxRenderableGraphWidgets = 32;
+constexpr size_t kMaxTextLength = 256;
+constexpr size_t kMaxGraphDataSize = 256;
+
+constexpr angle::PackedEnumMap<WidgetInternalType, size_t> kWidgetInternalTypeMaxWidgets = {
+ {WidgetInternalType::Text, kMaxRenderableTextWidgets},
+ {WidgetInternalType::Graph, kMaxRenderableGraphWidgets},
+};
+
+ANGLE_ENABLE_STRUCT_PADDING_WARNINGS
+
+// Structure matching buffer in vulkan/shaders/src/OverlayCull.comp.
+struct WidgetCoordinates
+{
+ uint32_t coordinates[kMaxRenderableTextWidgets + kMaxRenderableGraphWidgets][4];
+};
+
+// Structures matching buffers in vulkan/shaders/src/OverlayDraw.comp.
+struct TextWidgetData
+{
+ uint32_t coordinates[4];
+ float color[4];
+ uint32_t fontSize[3];
+ uint32_t padding;
+ uint8_t text[kMaxTextLength];
+};
+
+struct GraphWidgetData
+{
+ uint32_t coordinates[4];
+ float color[4];
+ uint32_t valueWidth;
+ uint32_t padding[3];
+ uint32_t values[kMaxGraphDataSize];
+};
+
+struct TextWidgets
+{
+ TextWidgetData widgets[kMaxRenderableTextWidgets];
+};
+
+struct GraphWidgets
+{
+ GraphWidgetData widgets[kMaxRenderableGraphWidgets];
+};
+
+ANGLE_DISABLE_STRUCT_PADDING_WARNINGS
+
+uint32_t GetWidgetCoord(int32_t src, uint32_t extent)
+{
+ int32_t dst = src < 0 ? extent + src : src;
+
+ return std::min<uint32_t>(std::max(dst, 0), extent - 1);
+}
+
+void GetWidgetCoordinates(const int32_t srcCoords[4],
+ const gl::Extents &imageExtent,
+ uint32_t dstCoordsOut[4])
+{
+ dstCoordsOut[0] = GetWidgetCoord(srcCoords[0], imageExtent.width);
+ dstCoordsOut[1] = GetWidgetCoord(srcCoords[1], imageExtent.height);
+ dstCoordsOut[2] = GetWidgetCoord(srcCoords[2], imageExtent.width);
+ dstCoordsOut[3] = GetWidgetCoord(srcCoords[3], imageExtent.height);
+}
+
+void GetWidgetColor(const float srcColor[4], float dstColor[4])
+{
+ memcpy(dstColor, srcColor, 4 * sizeof(dstColor[0]));
+}
+
+void GetTextFontSize(int srcFontSize, uint32_t dstFontSize[3])
+{
+ // .xy contains the font glyph width/height
+ dstFontSize[0] = overlay::kFontGlyphWidth >> srcFontSize;
+ dstFontSize[1] = overlay::kFontGlyphHeight >> srcFontSize;
+ // .z contains the mip
+ dstFontSize[2] = srcFontSize;
+}
+
+void GetGraphValueWidth(const int32_t srcCoords[4], size_t valueCount, uint32_t *dstValueWidth)
+{
+ const int32_t graphWidth = std::abs(srcCoords[2] - srcCoords[0]);
+
+ // If valueCount doesn't divide graphWidth, the graph bars won't fit well in its frame.
+ // Fix initOverlayWidgets() in that case.
+ ASSERT(graphWidth % valueCount == 0);
+
+ *dstValueWidth = graphWidth / valueCount;
+}
+
+void GetTextString(const std::string &src, uint8_t textOut[kMaxTextLength])
+{
+ for (size_t i = 0; i < src.length() && i < kMaxTextLength; ++i)
+ {
+ // The font image has 95 ASCII characters starting from ' '.
+ textOut[i] = src[i] - ' ';
+ }
+}
+
+void GetGraphValues(const std::vector<uint64_t> srcValues,
+ size_t startIndex,
+ float scale,
+ uint32_t valuesOut[kMaxGraphDataSize])
+{
+ ASSERT(srcValues.size() <= kMaxGraphDataSize);
+
+ for (size_t i = 0; i < srcValues.size(); ++i)
+ {
+ size_t index = (startIndex + i) % srcValues.size();
+ valuesOut[i] = static_cast<uint32_t>(srcValues[index] * scale);
+ }
+}
+
+std::vector<uint64_t> CreateHistogram(const std::vector<uint64_t> values)
+{
+ std::vector<uint64_t> histogram(values.size(), 0);
+
+ for (uint64_t rank : values)
+ {
+ ++histogram[static_cast<size_t>(rank)];
+ }
+
+ return histogram;
+}
+
+using OverlayWidgetCounts = angle::PackedEnumMap<WidgetInternalType, uint32_t>;
+using AppendWidgetDataFunc = void (*)(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts);
+} // namespace
+
+namespace overlay_impl
+{
+#define ANGLE_DECLARE_APPEND_WIDGET_PROC(WIDGET_ID) \
+ static void Append##WIDGET_ID(const overlay::Widget *widget, const gl::Extents &imageExtent, \
+ TextWidgetData *textWidget, GraphWidgetData *graphWidget, \
+ OverlayWidgetCounts *widgetCounts);
+
+// This class interprets the generic data collected in every element into a human-understandable
+// widget. This often means generating text specific to this item and scaling graph data to
+// something sensible.
+class AppendWidgetDataHelper
+{
+ public:
+ ANGLE_WIDGET_ID_X(ANGLE_DECLARE_APPEND_WIDGET_PROC)
+
+ private:
+ static std::ostream &OutputPerSecond(std::ostream &out, const overlay::PerSecond *perSecond);
+
+ static std::ostream &OutputText(std::ostream &out, const overlay::Text *text);
+
+ static std::ostream &OutputCount(std::ostream &out, const overlay::Count *count);
+
+ static void AppendTextCommon(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ const std::string &text,
+ TextWidgetData *textWidget,
+ OverlayWidgetCounts *widgetCounts);
+
+ using FormatGraphTitleFunc = std::function<std::string(uint64_t curValue, uint64_t maxValue)>;
+ static void AppendRunningGraphCommon(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts,
+ FormatGraphTitleFunc formatFunc);
+
+ using FormatHistogramTitleFunc =
+ std::function<std::string(size_t peakRange, size_t maxValueRange, size_t numRanges)>;
+ static void AppendRunningHistogramCommon(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts,
+ FormatHistogramTitleFunc formatFunc);
+
+ static void AppendGraphCommon(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ const std::vector<uint64_t> runningValues,
+ size_t startIndex,
+ float scale,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts);
+};
+
+void AppendWidgetDataHelper::AppendTextCommon(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ const std::string &text,
+ TextWidgetData *textWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ GetWidgetCoordinates(widget->coords, imageExtent, textWidget->coordinates);
+ GetWidgetColor(widget->color, textWidget->color);
+ GetTextFontSize(widget->fontSize, textWidget->fontSize);
+ GetTextString(text, textWidget->text);
+
+ ++(*widgetCounts)[WidgetInternalType::Text];
+}
+
+void AppendWidgetDataHelper::AppendGraphCommon(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ const std::vector<uint64_t> runningValues,
+ size_t startIndex,
+ float scale,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ const overlay::RunningGraph *widgetAsGraph = static_cast<const overlay::RunningGraph *>(widget);
+
+ GetWidgetCoordinates(widget->coords, imageExtent, graphWidget->coordinates);
+ GetWidgetColor(widget->color, graphWidget->color);
+ GetGraphValueWidth(widget->coords, widgetAsGraph->runningValues.size(),
+ &graphWidget->valueWidth);
+ GetGraphValues(runningValues, startIndex, scale, graphWidget->values);
+
+ ++(*widgetCounts)[WidgetInternalType::Graph];
+}
+
+void AppendWidgetDataHelper::AppendRunningGraphCommon(
+ const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts,
+ AppendWidgetDataHelper::FormatGraphTitleFunc formatFunc)
+{
+ const overlay::RunningGraph *graph = static_cast<const overlay::RunningGraph *>(widget);
+ const overlay::Widget *matchToWidget = widget->matchToWidget;
+
+ if (matchToWidget == nullptr)
+ {
+ matchToWidget = widget;
+ }
+ const overlay::RunningGraph *matchToGraph =
+ static_cast<const overlay::RunningGraph *>(matchToWidget);
+
+ const uint64_t maxValue =
+ *std::max_element(graph->runningValues.begin(), graph->runningValues.end());
+ const uint64_t maxValueInMatchToGraph =
+ *std::max_element(matchToGraph->runningValues.begin(), matchToGraph->runningValues.end());
+ const int32_t graphHeight = std::abs(widget->coords[3] - widget->coords[1]);
+ const float graphScale = static_cast<float>(graphHeight) / maxValueInMatchToGraph;
+
+ const size_t graphSize = graph->runningValues.size();
+ const size_t currentIdx = graph->lastValueIndex - 1;
+
+ const uint64_t curValue = graph->runningValues[(graphSize + currentIdx) % graphSize];
+
+ AppendGraphCommon(widget, imageExtent, graph->runningValues, graph->lastValueIndex + 1,
+ graphScale, graphWidget, widgetCounts);
+
+ if ((*widgetCounts)[WidgetInternalType::Text] <
+ kWidgetInternalTypeMaxWidgets[WidgetInternalType::Text])
+ {
+ std::string text = formatFunc(curValue, maxValue);
+ AppendTextCommon(&graph->description, imageExtent, text, textWidget, widgetCounts);
+ }
+}
+
+// static
+void AppendWidgetDataHelper::AppendRunningHistogramCommon(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts,
+ FormatHistogramTitleFunc formatFunc)
+{
+ const overlay::RunningHistogram *runningHistogram =
+ static_cast<const overlay::RunningHistogram *>(widget);
+
+ std::vector<uint64_t> histogram = CreateHistogram(runningHistogram->runningValues);
+ auto peakRangeIt = std::max_element(histogram.rbegin(), histogram.rend());
+ const uint64_t peakRangeValue = *peakRangeIt;
+ const int32_t graphHeight = std::abs(widget->coords[3] - widget->coords[1]);
+ const float graphScale = static_cast<float>(graphHeight) / peakRangeValue;
+ auto maxValueIter = std::find_if(histogram.rbegin(), histogram.rend(),
+ [](uint64_t value) { return value != 0; });
+
+ AppendGraphCommon(widget, imageExtent, histogram, 0, graphScale, graphWidget, widgetCounts);
+
+ if ((*widgetCounts)[WidgetInternalType::Text] <
+ kWidgetInternalTypeMaxWidgets[WidgetInternalType::Text])
+ {
+ size_t peakRange = std::distance(peakRangeIt, histogram.rend() - 1);
+ size_t maxValueRange = std::distance(maxValueIter, histogram.rend() - 1);
+
+ std::string text = formatFunc(peakRange, maxValueRange, histogram.size());
+ AppendTextCommon(&runningHistogram->description, imageExtent, text, textWidget,
+ widgetCounts);
+ }
+}
+
+void AppendWidgetDataHelper::AppendFPS(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ const overlay::PerSecond *fps = static_cast<const overlay::PerSecond *>(widget);
+ std::ostringstream text;
+ text << "FPS: ";
+ OutputPerSecond(text, fps);
+
+ AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
+}
+
+void AppendWidgetDataHelper::AppendVulkanLastValidationMessage(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ const overlay::Text *lastValidationMessage = static_cast<const overlay::Text *>(widget);
+ std::ostringstream text;
+ text << "Last VVL Message: ";
+ OutputText(text, lastValidationMessage);
+
+ AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
+}
+
+void AppendWidgetDataHelper::AppendVulkanValidationMessageCount(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ const overlay::Count *validationMessageCount = static_cast<const overlay::Count *>(widget);
+ std::ostringstream text;
+ text << "VVL Message Count: ";
+ OutputCount(text, validationMessageCount);
+
+ AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
+}
+
+void AppendWidgetDataHelper::AppendVulkanRenderPassCount(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "RenderPass Count: " << maxValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanSecondaryCommandBufferPoolWaste(
+ const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](size_t peakRange, size_t maxValueRange, size_t numRanges) {
+ std::ostringstream text;
+ size_t peakPercent = (peakRange * 100 + 50) / numRanges;
+ text << "CB Pool Waste (Peak: " << peakPercent << "%)";
+ return text.str();
+ };
+
+ AppendRunningHistogramCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts,
+ format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanRenderPassBufferCount(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "RP VkBuffers (Max: " << maxValue << ")";
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanWriteDescriptorSetCount(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "WriteDescriptorSet Count: " << maxValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanDescriptorSetAllocations(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Descriptor Set Allocations: " << maxValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanShaderResourceDSHitRate(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Shader Resource DS Hit Rate (Max: " << maxValue << "%)";
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanDynamicBufferAllocations(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "DynamicBuffer Allocations (Max: " << maxValue << ")";
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanTextureDescriptorCacheSize(
+ const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Total Texture Descriptor Cache Size: " << curValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanUniformDescriptorCacheSize(
+ const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Total Uniform Descriptor Cache Size: " << curValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanDescriptorCacheSize(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Total Descriptor Cache Size: " << curValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanDescriptorCacheKeySize(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ const overlay::Count *countWidget = static_cast<const overlay::Count *>(widget);
+ std::ostringstream text;
+ double kb = static_cast<double>(countWidget->count) / 1000.0;
+ text << "DS Cache Key Size: " << std::fixed << std::setprecision(1) << kb << " kb";
+
+ AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
+}
+
+void AppendWidgetDataHelper::AppendVulkanAttemptedSubmissions(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Attempted submissions (peak): " << maxValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanActualSubmissions(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Actual submissions (peak): " << maxValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanPipelineCacheLookups(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Pipeline Cache Lookups (peak): " << maxValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanPipelineCacheMisses(const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ auto format = [](uint64_t curValue, uint64_t maxValue) {
+ std::ostringstream text;
+ text << "Pipeline Cache Misses (peak): " << maxValue;
+ return text.str();
+ };
+
+ AppendRunningGraphCommon(widget, imageExtent, textWidget, graphWidget, widgetCounts, format);
+}
+
+void AppendWidgetDataHelper::AppendVulkanTotalPipelineCacheHitTimeMs(
+ const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ const overlay::Count *totalTime = static_cast<const overlay::Count *>(widget);
+ std::ostringstream text;
+ text << "Total Pipeline Cache Hit Time: ";
+ OutputCount(text, totalTime);
+ text << "ms";
+
+ AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
+}
+
+void AppendWidgetDataHelper::AppendVulkanTotalPipelineCacheMissTimeMs(
+ const overlay::Widget *widget,
+ const gl::Extents &imageExtent,
+ TextWidgetData *textWidget,
+ GraphWidgetData *graphWidget,
+ OverlayWidgetCounts *widgetCounts)
+{
+ const overlay::Count *totalTime = static_cast<const overlay::Count *>(widget);
+ std::ostringstream text;
+ text << "Total Pipeline Cache Miss Time: ";
+ OutputCount(text, totalTime);
+ text << "ms";
+
+ AppendTextCommon(widget, imageExtent, text.str(), textWidget, widgetCounts);
+}
+
+std::ostream &AppendWidgetDataHelper::OutputPerSecond(std::ostream &out,
+ const overlay::PerSecond *perSecond)
+{
+ return out << perSecond->lastPerSecondCount;
+}
+
+std::ostream &AppendWidgetDataHelper::OutputText(std::ostream &out, const overlay::Text *text)
+{
+ return out << text->text;
+}
+
+std::ostream &AppendWidgetDataHelper::OutputCount(std::ostream &out, const overlay::Count *count)
+{
+ return out << count->count;
+}
+} // namespace overlay_impl
+
+namespace
+{
+#define ANGLE_APPEND_WIDGET_MAP_PROC(WIDGET_ID) \
+ {WidgetId::WIDGET_ID, overlay_impl::AppendWidgetDataHelper::Append##WIDGET_ID},
+
+constexpr angle::PackedEnumMap<WidgetId, AppendWidgetDataFunc> kWidgetIdToAppendDataFuncMap = {
+ ANGLE_WIDGET_ID_X(ANGLE_APPEND_WIDGET_MAP_PROC)};
+} // namespace
+
+namespace overlay
+{
+const Text *Widget::getDescriptionWidget() const
+{
+ return nullptr;
+}
+RunningGraph::RunningGraph(size_t n) : runningValues(n, 0) {}
+RunningGraph::~RunningGraph() = default;
+const Text *RunningGraph::getDescriptionWidget() const
+{
+ return &description;
+}
+} // namespace overlay
+
+size_t OverlayState::getWidgetCoordinatesBufferSize() const
+{
+ return sizeof(WidgetCoordinates);
+}
+
+size_t OverlayState::getTextWidgetsBufferSize() const
+{
+ return sizeof(TextWidgets);
+}
+
+size_t OverlayState::getGraphWidgetsBufferSize() const
+{
+ return sizeof(GraphWidgets);
+}
+
+void OverlayState::fillWidgetData(const gl::Extents &imageExtents,
+ uint8_t *textData,
+ uint8_t *graphData,
+ uint32_t *activeTextWidgetCountOut,
+ uint32_t *activeGraphWidgetCountOut) const
+{
+ TextWidgets *textWidgets = reinterpret_cast<TextWidgets *>(textData);
+ GraphWidgets *graphWidgets = reinterpret_cast<GraphWidgets *>(graphData);
+
+ memset(textWidgets, overlay::kFontCharacters, sizeof(*textWidgets));
+ memset(graphWidgets, 0, sizeof(*graphWidgets));
+
+ OverlayWidgetCounts widgetCounts = {};
+
+ for (WidgetId id : angle::AllEnums<WidgetId>())
+ {
+ const std::unique_ptr<overlay::Widget> &widget = mOverlayWidgets[id];
+ if (!widget->enabled)
+ {
+ continue;
+ }
+
+ WidgetInternalType internalType = kWidgetTypeToInternalMap[widget->type];
+ ASSERT(internalType != WidgetInternalType::InvalidEnum);
+
+ if (widgetCounts[internalType] >= kWidgetInternalTypeMaxWidgets[internalType])
+ {
+ continue;
+ }
+
+ AppendWidgetDataFunc appendFunc = kWidgetIdToAppendDataFuncMap[id];
+ ASSERT(appendFunc);
+ appendFunc(widget.get(), imageExtents,
+ &textWidgets->widgets[widgetCounts[WidgetInternalType::Text]],
+ &graphWidgets->widgets[widgetCounts[WidgetInternalType::Graph]], &widgetCounts);
+ }
+
+ *activeTextWidgetCountOut = widgetCounts[WidgetInternalType::Text];
+ *activeGraphWidgetCountOut = widgetCounts[WidgetInternalType::Graph];
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/OverlayWidgets.h b/gfx/angle/checkout/src/libANGLE/OverlayWidgets.h
new file mode 100644
index 0000000000..b8a5f01e52
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/OverlayWidgets.h
@@ -0,0 +1,201 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// OverlayWidgets.h:
+// Defines the Overlay* widget classes and corresponding enums.
+//
+
+#ifndef LIBANGLE_OVERLAYWIDGETS_H_
+#define LIBANGLE_OVERLAYWIDGETS_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Overlay_autogen.h"
+
+namespace gl
+{
+class Overlay;
+class OverlayState;
+
+namespace overlay_impl
+{
+class AppendWidgetDataHelper;
+} // namespace overlay_impl
+
+enum class WidgetType
+{
+ // Text types:
+
+ // A total count of some event.
+ Count,
+ // A single line of ASCII text. Retains content until changed.
+ Text,
+ // A per-second value.
+ PerSecond,
+
+ // Graph types:
+
+ // A graph of the last N values.
+ RunningGraph,
+ // A histogram of the last N values (values between 0 and 1).
+ RunningHistogram,
+
+ InvalidEnum,
+ EnumCount = InvalidEnum,
+};
+
+namespace overlay
+{
+class Text;
+class Widget
+{
+ public:
+ virtual ~Widget() {}
+
+ virtual const Text *getDescriptionWidget() const;
+
+ protected:
+ WidgetType type;
+ // Whether this item should be drawn.
+ bool enabled = false;
+
+ // For text items, size of the font. This is a value in [0, overlay::kFontMipCount) which
+ // determines the font size to use.
+ int fontSize;
+
+ // The area covered by the item, predetermined by the overlay class. Negative values
+ // indicate offset from the left/bottom of the image.
+ int32_t coords[4];
+ float color[4];
+
+ // In some cases, a widget may need to match its contents (e.g. graph height scaling) with
+ // another related widget. In such a case, this pointer will point to the widget it needs to
+ // match to.
+ Widget *matchToWidget;
+
+ friend class gl::Overlay;
+ friend class gl::OverlayState;
+ friend class overlay_impl::AppendWidgetDataHelper;
+};
+
+class Count : public Widget
+{
+ public:
+ ~Count() override {}
+ void add(uint64_t n) { count += n; }
+ void set(uint64_t n) { count = n; }
+ void reset() { count = 0; }
+
+ protected:
+ uint64_t count = 0;
+
+ friend class gl::Overlay;
+ friend class overlay_impl::AppendWidgetDataHelper;
+};
+
+class PerSecond : public Count
+{
+ public:
+ ~PerSecond() override {}
+
+ protected:
+ uint64_t lastPerSecondCount = 0;
+
+ friend class gl::Overlay;
+ friend class overlay_impl::AppendWidgetDataHelper;
+};
+
+class Text : public Widget
+{
+ public:
+ ~Text() override {}
+ void set(std::string &&str) { text = std::move(str); }
+
+ protected:
+ std::string text;
+
+ friend class overlay_impl::AppendWidgetDataHelper;
+};
+
+class RunningGraph : public Widget
+{
+ public:
+ // Out of line constructor to satisfy chromium-style.
+ RunningGraph(size_t n);
+ ~RunningGraph() override;
+
+ void add(uint64_t n)
+ {
+ if (!ignoreFirstValue)
+ {
+ runningValues[lastValueIndex] += n;
+ }
+ }
+
+ void next()
+ {
+ if (ignoreFirstValue)
+ {
+ ignoreFirstValue = false;
+ }
+ else
+ {
+ lastValueIndex = (lastValueIndex + 1) % runningValues.size();
+ runningValues[lastValueIndex] = 0;
+ }
+ }
+
+ const Text *getDescriptionWidget() const override;
+
+ protected:
+ std::vector<uint64_t> runningValues;
+ size_t lastValueIndex = 0;
+ Text description;
+ bool ignoreFirstValue = true;
+
+ friend class gl::Overlay;
+ friend class gl::OverlayState;
+ friend class overlay_impl::AppendWidgetDataHelper;
+};
+
+class RunningHistogram : public RunningGraph
+{
+ public:
+ RunningHistogram(size_t n) : RunningGraph(n) {}
+ ~RunningHistogram() override {}
+
+ void set(float n)
+ {
+ ASSERT(n >= 0.0f && n <= 1.0f);
+ uint64_t rank =
+ n == 1.0f ? runningValues.size() - 1 : static_cast<uint64_t>(n * runningValues.size());
+
+ runningValues[lastValueIndex] = rank;
+ }
+
+ private:
+ // Do not use the add() function from RunningGraph
+ using RunningGraph::add;
+};
+
+// If overlay is disabled, all the above classes would be replaced with Mock, turning them into
+// noop.
+class Mock
+{
+ public:
+ void reset() const {}
+ template <typename T>
+ void set(T) const
+ {}
+ template <typename T>
+ void add(T) const
+ {}
+ void next() const {}
+};
+
+} // namespace overlay
+
+} // namespace gl
+
+#endif // LIBANGLE_OVERLAYWIDGETS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Overlay_autogen.cpp b/gfx/angle/checkout/src/libANGLE/Overlay_autogen.cpp
new file mode 100644
index 0000000000..eb2a146188
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Overlay_autogen.cpp
@@ -0,0 +1,824 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_overlay_widgets.py using data from overlay_widgets.json.
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Overlay_autogen.cpp:
+// Autogenerated overlay widget declarations.
+
+#include "libANGLE/Overlay.h"
+#include "libANGLE/OverlayWidgets.h"
+#include "libANGLE/Overlay_font_autogen.h"
+#include "libANGLE/renderer/driver_utils.h"
+
+namespace gl
+{
+using namespace overlay;
+
+namespace
+{
+int GetFontSize(int fontSize, bool largeFont)
+{
+ if (largeFont && fontSize > 0)
+ {
+ return fontSize - 1;
+ }
+ return fontSize;
+}
+} // anonymous namespace
+
+void Overlay::initOverlayWidgets()
+{
+ const bool kLargeFont = rx::IsAndroid();
+
+ {
+ PerSecond *widget = new PerSecond;
+ {
+ const int32_t fontSize = GetFontSize(kFontMipLarge, kLargeFont);
+ const int32_t offsetX = 10;
+ const int32_t offsetY = 10;
+ const int32_t width = 12 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->type = WidgetType::PerSecond;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = offsetX + width;
+ widget->coords[3] = offsetY + height;
+ widget->color[0] = 0.4980392156862745f;
+ widget->color[1] = 0.7490196078431373f;
+ widget->color[2] = 1.0f;
+ widget->color[3] = 1.0f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::FPS].reset(widget);
+ }
+
+ {
+ Text *widget = new Text;
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX = 10;
+ const int32_t offsetY = -10;
+ const int32_t width = 150 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->type = WidgetType::Text;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX;
+ widget->coords[1] = offsetY - height;
+ widget->coords[2] = offsetX + width;
+ widget->coords[3] = offsetY;
+ widget->color[0] = 1.0f;
+ widget->color[1] = 0.0f;
+ widget->color[2] = 0.0f;
+ widget->color[3] = 1.0f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanLastValidationMessage].reset(widget);
+ }
+
+ {
+ Count *widget = new Count;
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX = 10;
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanLastValidationMessage]->coords[1];
+ const int32_t width = 25 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->type = WidgetType::Count;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX;
+ widget->coords[1] = offsetY - height;
+ widget->coords[2] = offsetX + width;
+ widget->coords[3] = offsetY;
+ widget->color[0] = 1.0f;
+ widget->color[1] = 0.0f;
+ widget->color[2] = 0.0f;
+ widget->color[3] = 1.0f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanValidationMessageCount].reset(widget);
+ }
+
+ {
+ RunningGraph *widget = new RunningGraph(60);
+ {
+ const int32_t fontSize = GetFontSize(0, kLargeFont);
+ const int32_t offsetX = 10;
+ const int32_t offsetY = 100;
+ const int32_t width = 5 * static_cast<uint32_t>(widget->runningValues.size());
+ const int32_t height = 100;
+
+ widget->type = WidgetType::RunningGraph;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = offsetX + width;
+ widget->coords[3] = offsetY + height;
+ widget->color[0] = 0.29411764705882354f;
+ widget->color[1] = 0.7843137254901961f;
+ widget->color[2] = 0.0f;
+ widget->color[3] = 0.7843137254901961f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanRenderPassCount].reset(widget);
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanRenderPassCount]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanRenderPassCount]->coords[1];
+ const int32_t width = 40 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->description.type = WidgetType::Text;
+ widget->description.fontSize = fontSize;
+ widget->description.coords[0] = offsetX;
+ widget->description.coords[1] = std::max(offsetY - height, 1);
+ widget->description.coords[2] = offsetX + width;
+ widget->description.coords[3] = offsetY;
+ widget->description.color[0] = 0.29411764705882354f;
+ widget->description.color[1] = 0.7843137254901961f;
+ widget->description.color[2] = 0.0f;
+ widget->description.color[3] = 1.0f;
+ widget->description.matchToWidget = nullptr;
+ }
+ }
+
+ {
+ RunningGraph *widget = new RunningGraph(100);
+ {
+ const int32_t fontSize = GetFontSize(0, kLargeFont);
+ const int32_t offsetX = -50;
+ const int32_t offsetY = 100;
+ const int32_t width = 6 * static_cast<uint32_t>(widget->runningValues.size());
+ const int32_t height = 100;
+
+ widget->type = WidgetType::RunningGraph;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX - width;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = offsetX;
+ widget->coords[3] = offsetY + height;
+ widget->color[0] = 1.0f;
+ widget->color[1] = 0.7843137254901961f;
+ widget->color[2] = 0.29411764705882354f;
+ widget->color[3] = 0.7843137254901961f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanRenderPassBufferCount].reset(widget);
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanRenderPassBufferCount]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanRenderPassBufferCount]->coords[1];
+ const int32_t width = 40 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->description.type = WidgetType::Text;
+ widget->description.fontSize = fontSize;
+ widget->description.coords[0] = offsetX;
+ widget->description.coords[1] = std::max(offsetY - height, 1);
+ widget->description.coords[2] = std::min(offsetX + width, -1);
+ widget->description.coords[3] = offsetY;
+ widget->description.color[0] = 1.0f;
+ widget->description.color[1] = 0.7843137254901961f;
+ widget->description.color[2] = 0.29411764705882354f;
+ widget->description.color[3] = 1.0f;
+ widget->description.matchToWidget = nullptr;
+ }
+ }
+
+ {
+ RunningHistogram *widget = new RunningHistogram(50);
+ {
+ const int32_t fontSize = GetFontSize(0, kLargeFont);
+ const int32_t offsetX = -50;
+ const int32_t offsetY = 100;
+ const int32_t width = 6 * static_cast<uint32_t>(widget->runningValues.size());
+ const int32_t height = 100;
+
+ widget->type = WidgetType::RunningHistogram;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX - width;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = offsetX;
+ widget->coords[3] = offsetY + height;
+ widget->color[0] = 1.0f;
+ widget->color[1] = 0.7843137254901961f;
+ widget->color[2] = 0.29411764705882354f;
+ widget->color[3] = 0.7843137254901961f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanSecondaryCommandBufferPoolWaste].reset(widget);
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanSecondaryCommandBufferPoolWaste]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanSecondaryCommandBufferPoolWaste]->coords[1];
+ const int32_t width = 40 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->description.type = WidgetType::Text;
+ widget->description.fontSize = fontSize;
+ widget->description.coords[0] = offsetX;
+ widget->description.coords[1] = std::max(offsetY - height, 1);
+ widget->description.coords[2] = std::min(offsetX + width, -1);
+ widget->description.coords[3] = offsetY;
+ widget->description.color[0] = 1.0f;
+ widget->description.color[1] = 0.7843137254901961f;
+ widget->description.color[2] = 0.29411764705882354f;
+ widget->description.color[3] = 1.0f;
+ widget->description.matchToWidget = nullptr;
+ }
+ }
+
+ {
+ RunningGraph *widget = new RunningGraph(60);
+ {
+ const int32_t fontSize = GetFontSize(0, kLargeFont);
+ const int32_t offsetX = 10;
+ const int32_t offsetY = 220;
+ const int32_t width = 5 * static_cast<uint32_t>(widget->runningValues.size());
+ const int32_t height = 100;
+
+ widget->type = WidgetType::RunningGraph;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = offsetX + width;
+ widget->coords[3] = offsetY + height;
+ widget->color[0] = 0.29411764705882354f;
+ widget->color[1] = 0.7843137254901961f;
+ widget->color[2] = 0.0f;
+ widget->color[3] = 0.7843137254901961f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanWriteDescriptorSetCount].reset(widget);
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanWriteDescriptorSetCount]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanWriteDescriptorSetCount]->coords[1];
+ const int32_t width = 40 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->description.type = WidgetType::Text;
+ widget->description.fontSize = fontSize;
+ widget->description.coords[0] = offsetX;
+ widget->description.coords[1] = std::max(offsetY - height, 1);
+ widget->description.coords[2] = offsetX + width;
+ widget->description.coords[3] = offsetY;
+ widget->description.color[0] = 0.29411764705882354f;
+ widget->description.color[1] = 0.7843137254901961f;
+ widget->description.color[2] = 0.0f;
+ widget->description.color[3] = 1.0f;
+ widget->description.matchToWidget = nullptr;
+ }
+ }
+
+ {
+ RunningGraph *widget = new RunningGraph(60);
+ {
+ const int32_t fontSize = GetFontSize(0, kLargeFont);
+ const int32_t offsetX = 0;
+ const int32_t offsetY = 250;
+ const int32_t width = 6 * static_cast<uint32_t>(widget->runningValues.size());
+ const int32_t height = 100;
+
+ widget->type = WidgetType::RunningGraph;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = offsetX + width;
+ widget->coords[3] = offsetY + height;
+ widget->color[0] = 1.0f;
+ widget->color[1] = 0.0f;
+ widget->color[2] = 0.29411764705882354f;
+ widget->color[3] = 0.7843137254901961f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanDescriptorSetAllocations].reset(widget);
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanDescriptorSetAllocations]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanDescriptorSetAllocations]->coords[1];
+ const int32_t width = 40 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->description.type = WidgetType::Text;
+ widget->description.fontSize = fontSize;
+ widget->description.coords[0] = offsetX;
+ widget->description.coords[1] = std::max(offsetY - height, 1);
+ widget->description.coords[2] = offsetX + width;
+ widget->description.coords[3] = offsetY;
+ widget->description.color[0] = 1.0f;
+ widget->description.color[1] = 0.0f;
+ widget->description.color[2] = 0.29411764705882354f;
+ widget->description.color[3] = 1.0f;
+ widget->description.matchToWidget = nullptr;
+ }
+ }
+
+ {
+ RunningGraph *widget = new RunningGraph(60);
+ {
+ const int32_t fontSize = GetFontSize(0, kLargeFont);
+ const int32_t offsetX = -50;
+ const int32_t offsetY = 360;
+ const int32_t width = 6 * static_cast<uint32_t>(widget->runningValues.size());
+ const int32_t height = 100;
+
+ widget->type = WidgetType::RunningGraph;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX - width;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = offsetX;
+ widget->coords[3] = offsetY + height;
+ widget->color[0] = 1.0f;
+ widget->color[1] = 0.0f;
+ widget->color[2] = 0.29411764705882354f;
+ widget->color[3] = 0.7843137254901961f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanShaderResourceDSHitRate].reset(widget);
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanShaderResourceDSHitRate]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanShaderResourceDSHitRate]->coords[1];
+ const int32_t width = 40 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->description.type = WidgetType::Text;
+ widget->description.fontSize = fontSize;
+ widget->description.coords[0] = offsetX;
+ widget->description.coords[1] = std::max(offsetY - height, 1);
+ widget->description.coords[2] = std::min(offsetX + width, -1);
+ widget->description.coords[3] = offsetY;
+ widget->description.color[0] = 1.0f;
+ widget->description.color[1] = 0.0f;
+ widget->description.color[2] = 0.29411764705882354f;
+ widget->description.color[3] = 1.0f;
+ widget->description.matchToWidget = nullptr;
+ }
+ }
+
+ {
+ RunningGraph *widget = new RunningGraph(120);
+ {
+ const int32_t fontSize = GetFontSize(0, kLargeFont);
+ const int32_t offsetX = -50;
+ const int32_t offsetY = -50;
+ const int32_t width = 5 * static_cast<uint32_t>(widget->runningValues.size());
+ const int32_t height = 100;
+
+ widget->type = WidgetType::RunningGraph;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX - width;
+ widget->coords[1] = offsetY - height;
+ widget->coords[2] = offsetX;
+ widget->coords[3] = offsetY;
+ widget->color[0] = 0.0f;
+ widget->color[1] = 0.7843137254901961f;
+ widget->color[2] = 0.29411764705882354f;
+ widget->color[3] = 0.7843137254901961f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanDynamicBufferAllocations].reset(widget);
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanDynamicBufferAllocations]->coords[2];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanDynamicBufferAllocations]->coords[1];
+ const int32_t width = 40 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->description.type = WidgetType::Text;
+ widget->description.fontSize = fontSize;
+ widget->description.coords[0] = offsetX - width;
+ widget->description.coords[1] = offsetY - height;
+ widget->description.coords[2] = offsetX;
+ widget->description.coords[3] = offsetY;
+ widget->description.color[0] = 0.0f;
+ widget->description.color[1] = 0.7843137254901961f;
+ widget->description.color[2] = 0.29411764705882354f;
+ widget->description.color[3] = 1.0f;
+ widget->description.matchToWidget = nullptr;
+ }
+ }
+
+ {
+ RunningGraph *widget = new RunningGraph(60);
+ {
+ const int32_t fontSize = GetFontSize(0, kLargeFont);
+ const int32_t offsetX = 0;
+ const int32_t offsetY = 450;
+ const int32_t width = 5 * static_cast<uint32_t>(widget->runningValues.size());
+ const int32_t height = 100;
+
+ widget->type = WidgetType::RunningGraph;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = offsetX + width;
+ widget->coords[3] = offsetY + height;
+ widget->color[0] = 0.0f;
+ widget->color[1] = 0.7843137254901961f;
+ widget->color[2] = 0.7254901960784313f;
+ widget->color[3] = 0.7843137254901961f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanDescriptorCacheSize].reset(widget);
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanDescriptorCacheSize]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanDescriptorCacheSize]->coords[1];
+ const int32_t width = 90 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->description.type = WidgetType::Text;
+ widget->description.fontSize = fontSize;
+ widget->description.coords[0] = offsetX;
+ widget->description.coords[1] = std::max(offsetY - height, 1);
+ widget->description.coords[2] = offsetX + width;
+ widget->description.coords[3] = offsetY;
+ widget->description.color[0] = 0.0f;
+ widget->description.color[1] = 0.7843137254901961f;
+ widget->description.color[2] = 0.29411764705882354f;
+ widget->description.color[3] = 1.0f;
+ widget->description.matchToWidget = nullptr;
+ }
+ }
+
+ {
+ RunningGraph *widget = new RunningGraph(60);
+ {
+ const int32_t fontSize = GetFontSize(0, kLargeFont);
+ const int32_t offsetX = 0;
+ const int32_t offsetY = 450;
+ const int32_t width = 5 * static_cast<uint32_t>(widget->runningValues.size());
+ const int32_t height = 100;
+
+ widget->type = WidgetType::RunningGraph;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = offsetX + width;
+ widget->coords[3] = offsetY + height;
+ widget->color[0] = 0.0f;
+ widget->color[1] = 0.7843137254901961f;
+ widget->color[2] = 0.29411764705882354f;
+ widget->color[3] = 0.7843137254901961f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanTextureDescriptorCacheSize].reset(widget);
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanTextureDescriptorCacheSize]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanTextureDescriptorCacheSize]->coords[1];
+ const int32_t width = 90 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->description.type = WidgetType::Text;
+ widget->description.fontSize = fontSize;
+ widget->description.coords[0] = offsetX;
+ widget->description.coords[1] = std::max(offsetY - height, 1);
+ widget->description.coords[2] = offsetX + width;
+ widget->description.coords[3] = offsetY;
+ widget->description.color[0] = 0.0f;
+ widget->description.color[1] = 0.7843137254901961f;
+ widget->description.color[2] = 0.29411764705882354f;
+ widget->description.color[3] = 1.0f;
+ widget->description.matchToWidget = nullptr;
+ }
+ }
+
+ {
+ RunningGraph *widget = new RunningGraph(60);
+ {
+ const int32_t fontSize = GetFontSize(0, kLargeFont);
+ const int32_t offsetX = 0;
+ const int32_t offsetY = 450;
+ const int32_t width = 5 * static_cast<uint32_t>(widget->runningValues.size());
+ const int32_t height = 100;
+
+ widget->type = WidgetType::RunningGraph;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = offsetX + width;
+ widget->coords[3] = offsetY + height;
+ widget->color[0] = 0.0f;
+ widget->color[1] = 0.7843137254901961f;
+ widget->color[2] = 1.0f;
+ widget->color[3] = 0.7843137254901961f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanUniformDescriptorCacheSize].reset(widget);
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanUniformDescriptorCacheSize]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanUniformDescriptorCacheSize]->coords[1];
+ const int32_t width = 90 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->description.type = WidgetType::Text;
+ widget->description.fontSize = fontSize;
+ widget->description.coords[0] = offsetX;
+ widget->description.coords[1] = std::max(offsetY - height, 1);
+ widget->description.coords[2] = offsetX + width;
+ widget->description.coords[3] = offsetY;
+ widget->description.color[0] = 0.0f;
+ widget->description.color[1] = 0.7843137254901961f;
+ widget->description.color[2] = 0.29411764705882354f;
+ widget->description.color[3] = 1.0f;
+ widget->description.matchToWidget = nullptr;
+ }
+ }
+
+ {
+ Count *widget = new Count;
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX = 10;
+ const int32_t offsetY = 100;
+ const int32_t width = 30 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->type = WidgetType::Count;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = offsetX + width;
+ widget->coords[3] = offsetY + height;
+ widget->color[0] = 1.0f;
+ widget->color[1] = 1.0f;
+ widget->color[2] = 1.0f;
+ widget->color[3] = 1.0f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanDescriptorCacheKeySize].reset(widget);
+ }
+
+ {
+ RunningGraph *widget = new RunningGraph(60);
+ {
+ const int32_t fontSize = GetFontSize(0, kLargeFont);
+ const int32_t offsetX = -50;
+ const int32_t offsetY = 50;
+ const int32_t width = 5 * static_cast<uint32_t>(widget->runningValues.size());
+ const int32_t height = 100;
+
+ widget->type = WidgetType::RunningGraph;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX - width;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = offsetX;
+ widget->coords[3] = offsetY + height;
+ widget->color[0] = 1.0f;
+ widget->color[1] = 0.0f;
+ widget->color[2] = 0.0f;
+ widget->color[3] = 0.39215686274509803f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanAttemptedSubmissions].reset(widget);
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanAttemptedSubmissions]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanAttemptedSubmissions]->coords[1];
+ const int32_t width = 45 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->description.type = WidgetType::Text;
+ widget->description.fontSize = fontSize;
+ widget->description.coords[0] = offsetX;
+ widget->description.coords[1] = std::max(offsetY - height, 1);
+ widget->description.coords[2] = std::min(offsetX + width, -1);
+ widget->description.coords[3] = offsetY;
+ widget->description.color[0] = 0.7843137254901961f;
+ widget->description.color[1] = 0.0f;
+ widget->description.color[2] = 0.29411764705882354f;
+ widget->description.color[3] = 1.0f;
+ widget->description.matchToWidget = nullptr;
+ }
+ }
+
+ {
+ RunningGraph *widget = new RunningGraph(60);
+ {
+ const int32_t fontSize = GetFontSize(0, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanAttemptedSubmissions]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanAttemptedSubmissions]->coords[1];
+ const int32_t width = 5 * static_cast<uint32_t>(widget->runningValues.size());
+ const int32_t height = 100;
+
+ widget->type = WidgetType::RunningGraph;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = std::min(offsetX + width, -1);
+ widget->coords[3] = offsetY + height;
+ widget->color[0] = 0.0f;
+ widget->color[1] = 1.0f;
+ widget->color[2] = 0.0f;
+ widget->color[3] = 0.7843137254901961f;
+ widget->matchToWidget =
+ mState.mOverlayWidgets[WidgetId::VulkanAttemptedSubmissions].get();
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanActualSubmissions].reset(widget);
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanActualSubmissions]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanActualSubmissions]->coords[3];
+ const int32_t width = 45 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->description.type = WidgetType::Text;
+ widget->description.fontSize = fontSize;
+ widget->description.coords[0] = offsetX;
+ widget->description.coords[1] = offsetY;
+ widget->description.coords[2] = std::min(offsetX + width, -1);
+ widget->description.coords[3] = offsetY + height;
+ widget->description.color[0] = 0.0f;
+ widget->description.color[1] = 0.7843137254901961f;
+ widget->description.color[2] = 0.29411764705882354f;
+ widget->description.color[3] = 1.0f;
+ widget->description.matchToWidget = nullptr;
+ }
+ }
+
+ {
+ RunningGraph *widget = new RunningGraph(60);
+ {
+ const int32_t fontSize = GetFontSize(0, kLargeFont);
+ const int32_t offsetX = -50;
+ const int32_t offsetY = -50;
+ const int32_t width = 5 * static_cast<uint32_t>(widget->runningValues.size());
+ const int32_t height = 100;
+
+ widget->type = WidgetType::RunningGraph;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX - width;
+ widget->coords[1] = offsetY - height;
+ widget->coords[2] = offsetX;
+ widget->coords[3] = offsetY;
+ widget->color[0] = 0.0f;
+ widget->color[1] = 1.0f;
+ widget->color[2] = 0.0f;
+ widget->color[3] = 0.39215686274509803f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanPipelineCacheLookups].reset(widget);
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanPipelineCacheLookups]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanPipelineCacheLookups]->coords[1];
+ const int32_t width = 45 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->description.type = WidgetType::Text;
+ widget->description.fontSize = fontSize;
+ widget->description.coords[0] = offsetX;
+ widget->description.coords[1] = offsetY - height;
+ widget->description.coords[2] = std::min(offsetX + width, -1);
+ widget->description.coords[3] = offsetY;
+ widget->description.color[0] = 0.0f;
+ widget->description.color[1] = 0.7843137254901961f;
+ widget->description.color[2] = 0.29411764705882354f;
+ widget->description.color[3] = 1.0f;
+ widget->description.matchToWidget = nullptr;
+ }
+ }
+
+ {
+ RunningGraph *widget = new RunningGraph(60);
+ {
+ const int32_t fontSize = GetFontSize(0, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanPipelineCacheLookups]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanPipelineCacheLookups]->coords[1];
+ const int32_t width = 5 * static_cast<uint32_t>(widget->runningValues.size());
+ const int32_t height = 100;
+
+ widget->type = WidgetType::RunningGraph;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = std::min(offsetX + width, -1);
+ widget->coords[3] = std::min(offsetY + height, -1);
+ widget->color[0] = 1.0f;
+ widget->color[1] = 0.0f;
+ widget->color[2] = 0.0f;
+ widget->color[3] = 0.7843137254901961f;
+ widget->matchToWidget =
+ mState.mOverlayWidgets[WidgetId::VulkanPipelineCacheLookups].get();
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanPipelineCacheMisses].reset(widget);
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX = mState.mOverlayWidgets[WidgetId::VulkanPipelineCacheLookups]
+ ->getDescriptionWidget()
+ ->coords[0];
+ const int32_t offsetY = mState.mOverlayWidgets[WidgetId::VulkanPipelineCacheLookups]
+ ->getDescriptionWidget()
+ ->coords[1];
+ const int32_t width = 45 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->description.type = WidgetType::Text;
+ widget->description.fontSize = fontSize;
+ widget->description.coords[0] = offsetX;
+ widget->description.coords[1] = offsetY - height;
+ widget->description.coords[2] = std::min(offsetX + width, -1);
+ widget->description.coords[3] = offsetY;
+ widget->description.color[0] = 0.7843137254901961f;
+ widget->description.color[1] = 0.0f;
+ widget->description.color[2] = 0.29411764705882354f;
+ widget->description.color[3] = 1.0f;
+ widget->description.matchToWidget = nullptr;
+ }
+ }
+
+ {
+ Count *widget = new Count;
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanPipelineCacheMisses]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanPipelineCacheMisses]->coords[3];
+ const int32_t width = 45 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->type = WidgetType::Count;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = std::min(offsetX + width, -1);
+ widget->coords[3] = std::min(offsetY + height, -1);
+ widget->color[0] = 1.0f;
+ widget->color[1] = 0.0f;
+ widget->color[2] = 0.0f;
+ widget->color[3] = 1.0f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanTotalPipelineCacheMissTimeMs].reset(widget);
+ }
+
+ {
+ Count *widget = new Count;
+ {
+ const int32_t fontSize = GetFontSize(kFontMipSmall, kLargeFont);
+ const int32_t offsetX =
+ mState.mOverlayWidgets[WidgetId::VulkanTotalPipelineCacheMissTimeMs]->coords[0];
+ const int32_t offsetY =
+ mState.mOverlayWidgets[WidgetId::VulkanTotalPipelineCacheMissTimeMs]->coords[3];
+ const int32_t width = 45 * (kFontGlyphWidth >> fontSize);
+ const int32_t height = (kFontGlyphHeight >> fontSize);
+
+ widget->type = WidgetType::Count;
+ widget->fontSize = fontSize;
+ widget->coords[0] = offsetX;
+ widget->coords[1] = offsetY;
+ widget->coords[2] = std::min(offsetX + width, -1);
+ widget->coords[3] = std::min(offsetY + height, -1);
+ widget->color[0] = 0.0f;
+ widget->color[1] = 1.0f;
+ widget->color[2] = 0.0f;
+ widget->color[3] = 1.0f;
+ widget->matchToWidget = nullptr;
+ }
+ mState.mOverlayWidgets[WidgetId::VulkanTotalPipelineCacheHitTimeMs].reset(widget);
+ }
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Overlay_autogen.h b/gfx/angle/checkout/src/libANGLE/Overlay_autogen.h
new file mode 100644
index 0000000000..32ddd88559
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Overlay_autogen.h
@@ -0,0 +1,83 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_overlay_widgets.py using data from overlay_widgets.json.
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Overlay_autogen.cpp:
+// Autogenerated overlay widget declarations.
+
+namespace gl
+{
+enum class WidgetId
+{
+ // Frames per second (Count/Second).
+ FPS,
+ // Last validation error (Text).
+ VulkanLastValidationMessage,
+ // Number of validation errors and warnings (Count).
+ VulkanValidationMessageCount,
+ // Number of RenderPasses in a frame (Count).
+ VulkanRenderPassCount,
+ // Number of buffers used in RenderPasses (Count).
+ VulkanRenderPassBufferCount,
+ // Secondary Command Buffer pool memory waste (Bytes).
+ VulkanSecondaryCommandBufferPoolWaste,
+ // Number of Descriptor Set writes in a frame (Count).
+ VulkanWriteDescriptorSetCount,
+ // Descriptor Set Allocations.
+ VulkanDescriptorSetAllocations,
+ // Shader Resource Descriptor Set Cache Hit Rate.
+ VulkanShaderResourceDSHitRate,
+ // Buffer Allocations Made By vk::DynamicBuffer.
+ VulkanDynamicBufferAllocations,
+ // Total size of all descriptor set caches
+ VulkanDescriptorCacheSize,
+ // Number of cached Texture descriptor sets
+ VulkanTextureDescriptorCacheSize,
+ // Number of cached default uniform descriptor sets
+ VulkanUniformDescriptorCacheSize,
+ // Total size of all keys in the descriptor set caches
+ VulkanDescriptorCacheKeySize,
+ // Number of times the Vulkan backend attempted to submit commands
+ VulkanAttemptedSubmissions,
+ // Number of times the Vulkan backend actually submitted commands
+ VulkanActualSubmissions,
+ // Number of times the Vulkan backend has looked up the pipeline cache
+ VulkanPipelineCacheLookups,
+ // Number of times the Vulkan backend has missed the pipeline cache
+ VulkanPipelineCacheMisses,
+ // Total time spent creating pipelines that missed the cache.
+ VulkanTotalPipelineCacheMissTimeMs,
+ // Total time spent creating pipelines that hit the cache.
+ VulkanTotalPipelineCacheHitTimeMs,
+
+ InvalidEnum,
+ EnumCount = InvalidEnum,
+};
+
+// We can use this "X" macro to generate multiple code patterns.
+#define ANGLE_WIDGET_ID_X(PROC) \
+ PROC(FPS) \
+ PROC(VulkanLastValidationMessage) \
+ PROC(VulkanValidationMessageCount) \
+ PROC(VulkanRenderPassCount) \
+ PROC(VulkanRenderPassBufferCount) \
+ PROC(VulkanSecondaryCommandBufferPoolWaste) \
+ PROC(VulkanWriteDescriptorSetCount) \
+ PROC(VulkanDescriptorSetAllocations) \
+ PROC(VulkanShaderResourceDSHitRate) \
+ PROC(VulkanDynamicBufferAllocations) \
+ PROC(VulkanDescriptorCacheSize) \
+ PROC(VulkanTextureDescriptorCacheSize) \
+ PROC(VulkanUniformDescriptorCacheSize) \
+ PROC(VulkanDescriptorCacheKeySize) \
+ PROC(VulkanAttemptedSubmissions) \
+ PROC(VulkanActualSubmissions) \
+ PROC(VulkanPipelineCacheLookups) \
+ PROC(VulkanPipelineCacheMisses) \
+ PROC(VulkanTotalPipelineCacheMissTimeMs) \
+ PROC(VulkanTotalPipelineCacheHitTimeMs)
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Overlay_font_autogen.cpp b/gfx/angle/checkout/src/libANGLE/Overlay_font_autogen.cpp
new file mode 100644
index 0000000000..7df5893304
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Overlay_font_autogen.cpp
@@ -0,0 +1,5078 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_overlay_fonts.py using images from overlay/DejaVuSansMono-Bold.ttf.
+//
+// Copyright 2022 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Overlay_font_autogen.cpp:
+// Autogenerated overlay font data.
+
+#include "libANGLE/Overlay_font_autogen.h"
+#include "libANGLE/Overlay.h"
+
+#include <numeric>
+
+namespace gl
+{
+using namespace overlay;
+
+// Save binary size if the font images are never to be used.
+#if ANGLE_ENABLE_OVERLAY
+namespace
+{
+constexpr uint8_t kFontData[67830] = {
+ // clang-format off
+// Large
+// ' '
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '!'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x28,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x28,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x28,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x28,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x28,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x28,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x28,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x28,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x28,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x1D,0xFF,0xFF,0xFF,0x95, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x05,0xFE,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xEB,0xFF,0xFF,0x64, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD2,0xFF,0xFF,0x4C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xB9,0xFF,0xFF,0x34, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x28,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x28,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x28,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x28,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '"'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xBC,0xFF,0xFF,0xE4, 0, 0, 0,0x7C,0xFF,0xFF,0xFF,0x24, 0, 0,
+ 0, 0, 0,0xBC,0xFF,0xFF,0xE4, 0, 0, 0,0x7C,0xFF,0xFF,0xFF,0x24, 0, 0,
+ 0, 0, 0,0xBC,0xFF,0xFF,0xE4, 0, 0, 0,0x7C,0xFF,0xFF,0xFF,0x24, 0, 0,
+ 0, 0, 0,0xBC,0xFF,0xFF,0xE4, 0, 0, 0,0x7C,0xFF,0xFF,0xFF,0x24, 0, 0,
+ 0, 0, 0,0xBC,0xFF,0xFF,0xE4, 0, 0, 0,0x7C,0xFF,0xFF,0xFF,0x24, 0, 0,
+ 0, 0, 0,0xBC,0xFF,0xFF,0xE4, 0, 0, 0,0x7C,0xFF,0xFF,0xFF,0x24, 0, 0,
+ 0, 0, 0,0xBC,0xFF,0xFF,0xE4, 0, 0, 0,0x7C,0xFF,0xFF,0xFF,0x24, 0, 0,
+ 0, 0, 0,0xBC,0xFF,0xFF,0xE4, 0, 0, 0,0x7C,0xFF,0xFF,0xFF,0x24, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '#'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x43,0xFF,0xFF,0xE1, 0, 0,0x43,0xFF,0xFF,0xE7, 0,
+ 0, 0, 0, 0, 0, 0,0x87,0xFF,0xFF,0x9C, 0, 0,0x87,0xFF,0xFF,0xA2, 0,
+ 0, 0, 0, 0, 0, 0,0xCC,0xFF,0xFF,0x57, 0, 0,0xCB,0xFF,0xFF,0x5B, 0,
+ 0, 0, 0, 0, 0,0x13,0xFD,0xFF,0xFE,0x14, 0,0x11,0xFD,0xFF,0xFE,0x16, 0,
+ 0, 0, 0, 0, 0,0x56,0xFF,0xFF,0xCE, 0, 0,0x52,0xFF,0xFF,0xCF, 0, 0,
+ 0,0x58,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0,0x58,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0,0x58,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0, 0, 0, 0,0x5F,0xFF,0xFF,0xC1, 0, 0,0x56,0xFF,0xFF,0xC9, 0, 0, 0,
+ 0, 0, 0, 0,0xA3,0xFF,0xFF,0x7E, 0, 0,0x99,0xFF,0xFF,0x86, 0, 0, 0,
+ 0, 0, 0, 0,0xE5,0xFF,0xFF,0x3B, 0, 0,0xDC,0xFF,0xFF,0x43, 0, 0, 0,
+ 0, 0, 0,0x2A,0xFF,0xFF,0xF4,0x05, 0,0x1E,0xFF,0xFF,0xF8,0x08, 0, 0, 0,
+0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8, 0,
+0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8, 0,
+0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC8, 0,
+ 0, 0,0x2F,0xFF,0xFF,0xF1,0x04, 0,0x27,0xFF,0xFF,0xF6,0x07, 0, 0, 0, 0,
+ 0, 0,0x73,0xFF,0xFF,0xB1, 0, 0,0x6B,0xFF,0xFF,0xB9, 0, 0, 0, 0, 0,
+ 0, 0,0xB7,0xFF,0xFF,0x6D, 0, 0,0xAF,0xFF,0xFF,0x75, 0, 0, 0, 0, 0,
+ 0,0x05,0xF4,0xFF,0xFF,0x29, 0,0x03,0xEF,0xFF,0xFF,0x31, 0, 0, 0, 0, 0,
+ 0,0x3E,0xFF,0xFF,0xE5, 0, 0,0x36,0xFF,0xFF,0xEC,0x01, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '$'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2C,0xFF,0xD4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2C,0xFF,0xD5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2C,0xFF,0xD7, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x0E,0x79,0xCA,0xF4,0xFF,0xFF,0xE6,0xBF,0x81,0x32, 0, 0, 0,
+ 0, 0, 0,0x2A,0xE2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x24, 0, 0,
+ 0, 0,0x05,0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x24, 0, 0,
+ 0, 0,0x58,0xFF,0xFF,0xFF,0xB5,0x46,0xFF,0xD4,0x1F,0x63,0xD0,0xFF,0x24, 0, 0,
+ 0, 0,0x94,0xFF,0xFF,0xFF,0x2A,0x2C,0xFF,0xD4, 0, 0,0x02,0x7A,0x21, 0, 0,
+ 0, 0,0xA7,0xFF,0xFF,0xFF,0x1B,0x2C,0xFF,0xD4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x96,0xFF,0xFF,0xFF,0x6B,0x2C,0xFF,0xD4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x58,0xFF,0xFF,0xFF,0xFB,0xA8,0xFF,0xD5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x05,0xD8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0xA6,0x3F, 0, 0, 0, 0,
+ 0, 0, 0,0x25,0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA0,0x06, 0, 0,
+ 0, 0, 0, 0,0x09,0x76,0xDA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x91, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x43,0xFF,0xEF,0xD6,0xFF,0xFF,0xFF,0xFB,0x1A, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2C,0xFF,0xD4,0x04,0xB8,0xFF,0xFF,0xFF,0x5A, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2C,0xFF,0xD4, 0,0x59,0xFF,0xFF,0xFF,0x72, 0,
+ 0, 0,0x77,0x5F,0x02, 0, 0,0x2C,0xFF,0xD4, 0,0x6D,0xFF,0xFF,0xFF,0x62, 0,
+ 0, 0,0x90,0xFF,0xDB,0x76,0x2D,0x35,0xFF,0xD5,0x3C,0xE5,0xFF,0xFF,0xFF,0x24, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA3, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB9,0x0A, 0, 0,
+ 0, 0,0x0A,0x46,0x88,0xBE,0xDC,0xF7,0xFF,0xFF,0xEC,0xB9,0x5A,0x02, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x30,0xFF,0xD6, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2F,0xFF,0xD5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2E,0xFF,0xD4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2D,0xFF,0xD4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '%'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x40,0xBD,0xF4,0xF2,0xB9,0x39, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5E,0xFD,0xFF,0xFF,0xFF,0xFF,0xFB,0x53, 0, 0, 0, 0, 0, 0, 0, 0,
+0x18,0xF5,0xFF,0xCD,0x22,0x26,0xD4,0xFF,0xF2,0x14, 0, 0, 0, 0, 0, 0, 0,
+0x67,0xFF,0xFF,0x3E, 0, 0,0x47,0xFF,0xFF,0x61, 0, 0, 0, 0, 0, 0, 0,
+0x82,0xFF,0xFF,0x15, 0, 0,0x1D,0xFF,0xFF,0x7D, 0, 0, 0, 0, 0, 0, 0,
+0x68,0xFF,0xFF,0x3E, 0, 0,0x46,0xFF,0xFF,0x62, 0, 0, 0, 0, 0, 0, 0,
+0x19,0xF6,0xFF,0xCD,0x22,0x24,0xD2,0xFF,0xF2,0x14, 0, 0, 0, 0, 0,0x02, 0,
+ 0,0x60,0xFD,0xFF,0xFF,0xFF,0xFF,0xFC,0x57, 0, 0, 0, 0,0x19,0x7C,0xE1,0x45,
+ 0, 0,0x42,0xBE,0xF5,0xF3,0xBB,0x3C, 0, 0,0x01,0x47,0xAE,0xFB,0xD4,0x6F,0x11,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x17,0x78,0xDE,0xF5,0xA0,0x3A, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x01,0x43,0xAA,0xFA,0xD0,0x6B,0x0F, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x15,0x75,0xDB,0xF4,0x9C,0x37, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3A,0xA7,0xF9,0xCD,0x68,0x0D, 0, 0, 0,0x67,0xD1,0xF8,0xE9,0x9F,0x1C, 0,
+ 0,0x6F,0x99,0x32, 0, 0, 0, 0, 0,0x9A,0xFF,0xFF,0xFF,0xFF,0xFF,0xE9,0x25,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x4D,0xFF,0xFF,0xA0,0x12,0x49,0xF3,0xFF,0xC6,
+ 0, 0, 0, 0, 0, 0, 0, 0,0xA7,0xFF,0xF3,0x0B, 0, 0,0x89,0xFF,0xFF,
+ 0, 0, 0, 0, 0, 0, 0, 0,0xC2,0xFF,0xD5, 0, 0, 0,0x5D,0xFF,0xFF,
+ 0, 0, 0, 0, 0, 0, 0, 0,0xA8,0xFF,0xF2,0x09, 0, 0,0x87,0xFF,0xFF,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x4F,0xFF,0xFF,0x9B,0x11,0x46,0xF2,0xFF,0xC7,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x9E,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x27,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x01,0x69,0xD2,0xF9,0xEA,0xA1,0x1E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '&'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x01,0x56,0xB0,0xE2,0xF7,0xF8,0xDA,0x95,0x36, 0, 0, 0, 0,
+ 0, 0, 0,0x07,0xB7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0,
+ 0, 0, 0,0x7B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0,
+ 0, 0, 0,0xCF,0xFF,0xFF,0xFF,0x98,0x1B,0x08,0x26,0x5D,0xC4,0x13, 0, 0, 0,
+ 0, 0, 0,0xE1,0xFF,0xFF,0xFF,0x29, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xB6,0xFF,0xFF,0xFF,0x75, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x52,0xFF,0xFF,0xFF,0xF0,0x19, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xC3,0xFF,0xFF,0xFF,0xB8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x5D,0xF5,0xFF,0xFF,0xFF,0xFF,0x66, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x77,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF1,0x1D, 0, 0, 0, 0, 0, 0,
+ 0,0x45,0xFD,0xFF,0xFF,0xCB,0xA3,0xFF,0xFF,0xFF,0xB7, 0, 0,0x18,0xFF,0xFF,0xFF,
+ 0,0xCB,0xFF,0xFF,0xE9,0x14,0x0E,0xE6,0xFF,0xFF,0xFF,0x60, 0,0x0B,0xFF,0xFF,0xFF,
+0x2E,0xFF,0xFF,0xFF,0x89, 0, 0,0x55,0xFF,0xFF,0xFF,0xEF,0x19,0x1D,0xFF,0xFF,0xFF,
+0x59,0xFF,0xFF,0xFF,0x5F, 0, 0, 0,0xB5,0xFF,0xFF,0xFF,0xB1,0x48,0xFF,0xFF,0xEA,
+0x71,0xFF,0xFF,0xFF,0x6B, 0, 0, 0,0x20,0xF5,0xFF,0xFF,0xFF,0xDB,0xFF,0xFF,0xAF,
+0x5F,0xFF,0xFF,0xFF,0xB1, 0, 0, 0, 0,0x76,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x4F,
+0x25,0xFF,0xFF,0xFF,0xFE,0x46, 0, 0, 0,0x04,0xD1,0xFF,0xFF,0xFF,0xFF,0xC7,0x02,
+ 0,0xBE,0xFF,0xFF,0xFF,0xF5,0x6E,0x15,0x09,0x44,0xCB,0xFF,0xFF,0xFF,0xFF,0x5A, 0,
+ 0,0x27,0xEE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD8,0x07,
+ 0, 0,0x31,0xDD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x85,
+ 0, 0, 0,0x09,0x69,0xBB,0xEA,0xFB,0xF3,0xD3,0x94,0x3C,0x55,0xFF,0xFF,0xFF,0xFA,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '''
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0x84, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0x84, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0x84, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0x84, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0x84, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0x84, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0x84, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0x84, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '('
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x77,0xFF,0xFF,0xD4,0x01, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x23,0xF6,0xFF,0xFF,0x5A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0xAE,0xFF,0xFF,0xDB,0x03, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x37,0xFF,0xFF,0xFF,0x69, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFA,0x13, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x1E,0xFD,0xFF,0xFF,0xB3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7C,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xCB,0xFF,0xFF,0xFF,0x1F, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x0F,0xFE,0xFF,0xFF,0xE8, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x42,0xFF,0xFF,0xFF,0xB2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x68,0xFF,0xFF,0xFF,0x95, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x83,0xFF,0xFF,0xFF,0x82, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x8F,0xFF,0xFF,0xFF,0x70, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x8F,0xFF,0xFF,0xFF,0x71, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x83,0xFF,0xFF,0xFF,0x83, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x68,0xFF,0xFF,0xFF,0x95, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x41,0xFF,0xFF,0xFF,0xB4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x0E,0xFE,0xFF,0xFF,0xE9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xCA,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7A,0xFF,0xFF,0xFF,0x5D, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x1D,0xFD,0xFF,0xFF,0xB5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xAF,0xFF,0xFF,0xFB,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x35,0xFF,0xFF,0xFF,0x6B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0xAD,0xFF,0xFF,0xDC,0x03, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x22,0xF6,0xFF,0xFF,0x5A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x76,0xFF,0xFF,0xD4,0x01, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// ')'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x62,0xFF,0xFF,0xE1,0x0C, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x05,0xE0,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x69,0xFF,0xFF,0xFB,0x28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x07,0xEC,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x97,0xFF,0xFF,0xFD,0x27, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3D,0xFF,0xFF,0xFF,0x8F, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x01,0xE3,0xFF,0xFF,0xEB,0x03, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x3E, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x71,0xFF,0xFF,0xFF,0x80, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3B,0xFF,0xFF,0xFF,0xB6, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1E,0xFF,0xFF,0xFF,0xDB, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x0B,0xFF,0xFF,0xFF,0xF6, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0xF8,0xFF,0xFF,0xFF,0x03, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0xF9,0xFF,0xFF,0xFF,0x02, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x0C,0xFF,0xFF,0xFF,0xF5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1E,0xFF,0xFF,0xFF,0xDA, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,0xB5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x73,0xFF,0xFF,0xFF,0x7F, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xA9,0xFF,0xFF,0xFF,0x3C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x01,0xE4,0xFF,0xFF,0xEA,0x03, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3E,0xFF,0xFF,0xFF,0x8F, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x98,0xFF,0xFF,0xFD,0x27, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x07,0xEC,0xFF,0xFF,0xAB, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6A,0xFF,0xFF,0xFB,0x27, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x05,0xE0,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x62,0xFF,0xFF,0xE1,0x0C, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '*'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x84,0xFF,0xE8, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x84,0xFF,0xE8, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x84,0xFF,0xE8, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x7E,0xA7,0x2A, 0, 0,0x84,0xFF,0xE8, 0, 0,0x0B,0x74,0xC7,0x09, 0,
+ 0,0x15,0xF6,0xFF,0xFD,0xAA,0x2D,0x84,0xFF,0xE8,0x0D,0x78,0xEB,0xFF,0xFF,0x73, 0,
+ 0, 0,0x2B,0xA2,0xFB,0xFF,0xFE,0xE8,0xFF,0xF9,0xED,0xFF,0xFF,0xD2,0x5B,0x03, 0,
+ 0, 0, 0, 0,0x1E,0x92,0xF5,0xFF,0xFF,0xFF,0xFF,0xC5,0x4D,0x01, 0, 0, 0,
+ 0, 0, 0, 0,0x1E,0x91,0xF5,0xFF,0xFF,0xFF,0xFF,0xC5,0x4C,0x01, 0, 0, 0,
+ 0, 0,0x2A,0xA1,0xFB,0xFF,0xFD,0xE4,0xFF,0xF8,0xE9,0xFF,0xFF,0xD2,0x5A,0x03, 0,
+ 0,0x15,0xF6,0xFF,0xFD,0xA7,0x28,0x84,0xFF,0xE8,0x0A,0x74,0xE9,0xFF,0xFF,0x73, 0,
+ 0, 0,0x7E,0xA7,0x28, 0, 0,0x84,0xFF,0xE8, 0, 0,0x0A,0x73,0xC8,0x09, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x84,0xFF,0xE8, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x84,0xFF,0xE8, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x84,0xFF,0xE8, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '+'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF4,0xFF,0xFF,0x68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF4,0xFF,0xFF,0x68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF4,0xFF,0xFF,0x68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF4,0xFF,0xFF,0x68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF4,0xFF,0xFF,0x68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF4,0xFF,0xFF,0x68, 0, 0, 0, 0, 0, 0,
+0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,
+0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,
+0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,
+ 0, 0, 0, 0, 0, 0, 0,0xF4,0xFF,0xFF,0x68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF4,0xFF,0xFF,0x68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF4,0xFF,0xFF,0x68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF4,0xFF,0xFF,0x68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF4,0xFF,0xFF,0x68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xF4,0xFF,0xFF,0x68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// ','
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x78,0xFF,0xFF,0xFF,0xF4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x78,0xFF,0xFF,0xFF,0xF4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x78,0xFF,0xFF,0xFF,0xF4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7A,0xFF,0xFF,0xFF,0xEF, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xAD,0xFF,0xFF,0xFF,0x8C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x02,0xEE,0xFF,0xFF,0xF2,0x14, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x35,0xFF,0xFF,0xFF,0x7F, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x7A,0xFF,0xFF,0xEB,0x0D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xBE,0xFF,0xFF,0x73, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '-'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x34, 0, 0, 0,
+ 0, 0, 0, 0,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x34, 0, 0, 0,
+ 0, 0, 0, 0,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x34, 0, 0, 0,
+ 0, 0, 0, 0,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x34, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '.'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '/'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x80,0xFF,0xFF,0xA0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x0A,0xEB,0xFF,0xFE,0x2B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x6D,0xFF,0xFF,0xB2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x04,0xDF,0xFF,0xFF,0x3C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x5B,0xFF,0xFF,0xC5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xD1,0xFF,0xFF,0x4E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x49,0xFF,0xFF,0xD7,0x01, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0xBF,0xFF,0xFF,0x61, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x36,0xFF,0xFF,0xE4,0x06, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0xAD,0xFF,0xFF,0x74, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x26,0xFD,0xFF,0xF0,0x0D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x9B,0xFF,0xFF,0x86, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x18,0xF8,0xFF,0xF8,0x18, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x88,0xFF,0xFF,0x99, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x0E,0xF0,0xFF,0xFD,0x25, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x76,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x06,0xE6,0xFF,0xFF,0x36, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x64,0xFF,0xFF,0xBE, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x02,0xD8,0xFF,0xFF,0x48, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x51,0xFF,0xFF,0xD1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xC8,0xFF,0xFF,0x5A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3F,0xFF,0xFF,0xE0,0x04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xB6,0xFF,0xFF,0x6D, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x2D,0xFF,0xFF,0xEC,0x0A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '0'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x39,0xA2,0xE0,0xF8,0xEB,0xC5,0x6F,0x07, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x81,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD3,0x1C, 0, 0, 0,
+ 0, 0, 0,0x66,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCF,0x06, 0, 0,
+ 0, 0,0x0E,0xED,0xFF,0xFF,0xFF,0x80,0x0D,0x33,0xE0,0xFF,0xFF,0xFF,0x6C, 0, 0,
+ 0, 0,0x69,0xFF,0xFF,0xFF,0xC2, 0, 0, 0,0x4D,0xFF,0xFF,0xFF,0xDA, 0, 0,
+ 0, 0,0xB5,0xFF,0xFF,0xFF,0x69, 0, 0, 0,0x04,0xF0,0xFF,0xFF,0xFF,0x28, 0,
+ 0, 0,0xEC,0xFF,0xFF,0xFF,0x36, 0, 0, 0, 0,0xC1,0xFF,0xFF,0xFF,0x5F, 0,
+ 0,0x14,0xFF,0xFF,0xFF,0xFF,0x15, 0, 0, 0, 0,0x9F,0xFF,0xFF,0xFF,0x86, 0,
+ 0,0x2E,0xFF,0xFF,0xFF,0xFE,0x03,0x61,0xEF,0xBE,0x0B,0x8B,0xFF,0xFF,0xFF,0xA0, 0,
+ 0,0x39,0xFF,0xFF,0xFF,0xF9, 0,0xEF,0xFF,0xFF,0x67,0x83,0xFF,0xFF,0xFF,0xAC, 0,
+ 0,0x41,0xFF,0xFF,0xFF,0xF5, 0,0xF0,0xFF,0xFF,0x68,0x7E,0xFF,0xFF,0xFF,0xB5, 0,
+ 0,0x39,0xFF,0xFF,0xFF,0xF9, 0,0x64,0xEF,0xBE,0x0C,0x83,0xFF,0xFF,0xFF,0xAC, 0,
+ 0,0x2E,0xFF,0xFF,0xFF,0xFE,0x03, 0, 0, 0, 0,0x8B,0xFF,0xFF,0xFF,0xA0, 0,
+ 0,0x14,0xFF,0xFF,0xFF,0xFF,0x15, 0, 0, 0, 0,0x9F,0xFF,0xFF,0xFF,0x86, 0,
+ 0, 0,0xEC,0xFF,0xFF,0xFF,0x36, 0, 0, 0, 0,0xC1,0xFF,0xFF,0xFF,0x5F, 0,
+ 0, 0,0xB5,0xFF,0xFF,0xFF,0x68, 0, 0, 0,0x04,0xF0,0xFF,0xFF,0xFF,0x28, 0,
+ 0, 0,0x69,0xFF,0xFF,0xFF,0xC0, 0, 0, 0,0x4C,0xFF,0xFF,0xFF,0xDB, 0, 0,
+ 0, 0,0x0E,0xED,0xFF,0xFF,0xFF,0x7E,0x0C,0x32,0xDF,0xFF,0xFF,0xFF,0x6D, 0, 0,
+ 0, 0, 0,0x66,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD2,0x07, 0, 0,
+ 0, 0, 0, 0,0x81,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD5,0x1D, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x39,0xA3,0xE0,0xF8,0xED,0xC6,0x70,0x07, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '1'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x1D,0x58,0x92,0xCD,0xFC,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0,0x04,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0,0x04,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0,0x04,0xE2,0xA7,0x6C,0x31,0xAF,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xAC,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xAC,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xAC,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xAC,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xAC,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xAC,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xAC,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xAC,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xAC,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xAC,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xAC,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xAC,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xAC,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xAC,0xFF,0xFF,0xFF,0x68, 0, 0, 0, 0, 0,
+ 0, 0,0x58,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x14,
+ 0, 0,0x58,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x14,
+ 0, 0,0x58,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x14,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '2'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x1A,0x59,0x99,0xCC,0xEC,0xFB,0xF4,0xDE,0xAB,0x55,0x04, 0, 0, 0, 0,
+ 0, 0,0xEC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCD,0x22, 0, 0, 0,
+ 0, 0,0xEC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE1,0x11, 0, 0,
+ 0, 0,0xEC,0xFF,0xBB,0x5E,0x1E,0x08,0x24,0x8C,0xFF,0xFF,0xFF,0xFF,0x89, 0, 0,
+ 0, 0,0xAD,0x32, 0, 0, 0, 0, 0, 0,0x9B,0xFF,0xFF,0xFF,0xDC, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x4C,0xFF,0xFF,0xFF,0xFC,0x02, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x42,0xFF,0xFF,0xFF,0xF9, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x81,0xFF,0xFF,0xFF,0xD0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x12,0xEC,0xFF,0xFF,0xFF,0x7A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0xAE,0xFF,0xFF,0xFF,0xE7,0x0E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x7D,0xFF,0xFF,0xFF,0xFE,0x4B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5F,0xFF,0xFF,0xFF,0xFF,0x77, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x4A,0xFB,0xFF,0xFF,0xFF,0x89, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x38,0xF5,0xFF,0xFF,0xFF,0x93, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x2A,0xED,0xFF,0xFF,0xFF,0x98,0x01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x1E,0xE3,0xFF,0xFF,0xFF,0x9B,0x01, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x13,0xD7,0xFF,0xFF,0xFF,0x9D,0x01, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x0B,0xC9,0xFF,0xFF,0xFF,0xA0,0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x5F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0C, 0,
+ 0,0x60,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0C, 0,
+ 0,0x60,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x0C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '3'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x0B,0x47,0x88,0xC2,0xE7,0xF9,0xF9,0xE8,0xBE,0x79,0x18, 0, 0, 0, 0,
+ 0, 0,0x98,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x5E, 0, 0, 0,
+ 0, 0,0x98,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x4A, 0, 0,
+ 0, 0,0x98,0xFF,0xD6,0x70,0x29,0x08,0x17,0x58,0xE4,0xFF,0xFF,0xFF,0xCB, 0, 0,
+ 0, 0,0x7D,0x59,0x01, 0, 0, 0, 0, 0,0x3E,0xFF,0xFF,0xFF,0xFE,0x05, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x04,0xFD,0xFF,0xFF,0xFF,0x0B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x32,0xFF,0xFF,0xFF,0xD8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x14,0x50,0xDC,0xFF,0xFF,0xFF,0x59, 0, 0,
+ 0, 0, 0, 0, 0,0x78,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x52, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x78,0xFF,0xFF,0xFF,0xFF,0xFF,0xB1,0x24, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x78,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x90,0x03, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x01,0x1C,0x5A,0xE3,0xFF,0xFF,0xFF,0x97, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x23,0xF7,0xFF,0xFF,0xFE,0x27, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0x70, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x7D,0xFF,0xFF,0xFF,0x8D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x93,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x37,0x89,0x0C, 0, 0, 0, 0, 0, 0,0x14,0xE6,0xFF,0xFF,0xFF,0x5E, 0,
+ 0,0x3C,0xFF,0xF0,0x92,0x4B,0x1B,0x07,0x16,0x4E,0xD5,0xFF,0xFF,0xFF,0xF5,0x14, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x73, 0, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x76, 0, 0, 0,
+ 0,0x01,0x30,0x70,0xAF,0xD0,0xE4,0xF7,0xF8,0xE7,0xBD,0x7C,0x1D, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '4'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x08,0xD8,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x8B,0xFF,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x37,0xFC,0xFF,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x07,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x88,0xFF,0xFF,0xF5,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x35,0xFC,0xFF,0xFF,0x73,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0, 0, 0, 0,0x06,0xD4,0xFF,0xFF,0xA3,0x2C,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0, 0, 0, 0,0x85,0xFF,0xFF,0xEB,0x14,0x2C,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0, 0, 0,0x32,0xFB,0xFF,0xFF,0x5C, 0,0x2C,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0, 0,0x05,0xD2,0xFF,0xFF,0xB8, 0, 0,0x2C,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0, 0,0x82,0xFF,0xFF,0xF4,0x20, 0, 0,0x2C,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0,0x30,0xFA,0xFF,0xFF,0x71, 0, 0, 0,0x2C,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0,0x8F,0xFF,0xFF,0xCA,0x03, 0, 0, 0,0x2C,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0,0x90,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,
+ 0,0x90,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,
+ 0,0x90,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x2C,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x2C,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x2C,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x2C,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x2C,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '5'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x44,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38, 0, 0,
+ 0, 0,0x44,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38, 0, 0,
+ 0, 0,0x44,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38, 0, 0,
+ 0, 0,0x44,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x44,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x44,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x44,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x44,0xFF,0xFF,0xFF,0xCC,0xEF,0xFA,0xE9,0xB9,0x65,0x05, 0, 0, 0, 0,
+ 0, 0,0x44,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD5,0x25, 0, 0, 0,
+ 0, 0,0x44,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE4,0x18, 0, 0,
+ 0, 0,0x41,0xBF,0x6B,0x32,0x16,0x07,0x29,0x8E,0xFD,0xFF,0xFF,0xFF,0xA6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x64,0xFF,0xFF,0xFF,0xFE,0x17, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xD6,0xFF,0xFF,0xFF,0x55, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x9F,0xFF,0xFF,0xFF,0x71, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x9F,0xFF,0xFF,0xFF,0x70, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xD1,0xFF,0xFF,0xFF,0x53, 0,
+ 0, 0,0x9F,0x0F, 0, 0, 0, 0, 0, 0,0x56,0xFF,0xFF,0xFF,0xFC,0x13, 0,
+ 0, 0,0xF8,0xEC,0x80,0x30,0x0A,0x08,0x2D,0x89,0xFA,0xFF,0xFF,0xFF,0x9B, 0, 0,
+ 0, 0,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD6,0x12, 0, 0,
+ 0, 0,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB8,0x17, 0, 0, 0,
+ 0, 0,0x20,0x64,0xA7,0xCF,0xE6,0xFA,0xF1,0xD5,0x9C,0x40, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '6'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3D,0x94,0xD3,0xEC,0xF8,0xDD,0xB4,0x60,0x0E, 0, 0,
+ 0, 0, 0, 0,0x0F,0xB0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x94, 0, 0,
+ 0, 0, 0,0x0C,0xCE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x94, 0, 0,
+ 0, 0, 0,0x91,0xFF,0xFF,0xFF,0xE3,0x62,0x19,0x07,0x2D,0x91,0xFA,0x94, 0, 0,
+ 0, 0,0x1A,0xFC,0xFF,0xFF,0xE7,0x1B, 0, 0, 0, 0, 0,0x30,0x72, 0, 0,
+ 0, 0,0x75,0xFF,0xFF,0xFF,0x66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xB9,0xFF,0xFF,0xFE,0x10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE8,0xFF,0xFF,0xDF,0x18,0x90,0xDA,0xF7,0xF3,0xD0,0x81,0x0F, 0, 0, 0,
+ 0,0x08,0xFF,0xFF,0xFF,0xE5,0xE6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x24, 0, 0,
+ 0,0x17,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD1,0x04, 0,
+ 0,0x21,0xFF,0xFF,0xFF,0xFF,0xFF,0x93,0x17,0x0C,0x6A,0xFC,0xFF,0xFF,0xFF,0x55, 0,
+ 0,0x19,0xFF,0xFF,0xFF,0xFF,0xD3, 0, 0, 0, 0,0x9B,0xFF,0xFF,0xFF,0xA2, 0,
+ 0,0x0E,0xFF,0xFF,0xFF,0xFF,0x7B, 0, 0, 0, 0,0x41,0xFF,0xFF,0xFF,0xCE, 0,
+ 0,0x01,0xF6,0xFF,0xFF,0xFF,0x5D, 0, 0, 0, 0,0x22,0xFF,0xFF,0xFF,0xDE, 0,
+ 0, 0,0xD2,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0,0x22,0xFF,0xFF,0xFF,0xD6, 0,
+ 0, 0,0xA1,0xFF,0xFF,0xFF,0x7B, 0, 0, 0, 0,0x41,0xFF,0xFF,0xFF,0xBD, 0,
+ 0, 0,0x55,0xFF,0xFF,0xFF,0xD3, 0, 0, 0, 0,0x9B,0xFF,0xFF,0xFF,0x85, 0,
+ 0, 0,0x09,0xE5,0xFF,0xFF,0xFF,0x92,0x15,0x0C,0x69,0xFC,0xFF,0xFF,0xFE,0x27, 0,
+ 0, 0, 0,0x5B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x95, 0, 0,
+ 0, 0, 0, 0,0x73,0xFA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0x07, 0, 0,
+ 0, 0, 0, 0, 0,0x29,0x91,0xD6,0xF1,0xF9,0xE4,0xAC,0x49, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '7'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x18,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x48, 0,
+ 0,0x18,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x48, 0,
+ 0,0x18,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x47, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x75,0xFF,0xFF,0xFF,0xF9,0x15, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xD6,0xFF,0xFF,0xFF,0xA8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x39,0xFF,0xFF,0xFF,0xFF,0x43, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x9B,0xFF,0xFF,0xFF,0xDC,0x01, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x0A,0xF1,0xFF,0xFF,0xFF,0x78, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x5E,0xFF,0xFF,0xFF,0xFA,0x17, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0xC0,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x22,0xFE,0xFF,0xFF,0xFF,0x47, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x84,0xFF,0xFF,0xFF,0xDF,0x02, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x02,0xE2,0xFF,0xFF,0xFF,0x7B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x47,0xFF,0xFF,0xFF,0xFB,0x1A, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA9,0xFF,0xFF,0xFF,0xB0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x12,0xF8,0xFF,0xFF,0xFF,0x4A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x6C,0xFF,0xFF,0xFF,0xE2,0x02, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xCE,0xFF,0xFF,0xFF,0x7F, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x2F,0xFF,0xFF,0xFF,0xFC,0x1C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x92,0xFF,0xFF,0xFF,0xB4, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x06,0xEC,0xFF,0xFF,0xFF,0x4E, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '8'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x09,0x6A,0xBC,0xE9,0xFA,0xF2,0xD3,0x94,0x2B, 0, 0, 0, 0,
+ 0, 0, 0,0x25,0xDA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x74, 0, 0, 0,
+ 0, 0,0x08,0xDC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x56, 0, 0,
+ 0, 0,0x5F,0xFF,0xFF,0xFF,0xE0,0x47,0x0C,0x1F,0x99,0xFF,0xFF,0xFF,0xD1, 0, 0,
+ 0, 0,0x97,0xFF,0xFF,0xFF,0x49, 0, 0, 0,0x01,0xD0,0xFF,0xFF,0xFF,0x0A, 0,
+ 0, 0,0x9C,0xFF,0xFF,0xFF,0x1A, 0, 0, 0, 0,0xA3,0xFF,0xFF,0xFF,0x0F, 0,
+ 0, 0,0x72,0xFF,0xFF,0xFF,0x4B, 0, 0, 0,0x01,0xD1,0xFF,0xFF,0xE5, 0, 0,
+ 0, 0,0x11,0xEE,0xFF,0xFF,0xE0,0x46,0x0B,0x1F,0x98,0xFF,0xFF,0xFF,0x71, 0, 0,
+ 0, 0, 0,0x31,0xE1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x8A,0x01, 0, 0,
+ 0, 0, 0, 0,0x1C,0xD2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x6E, 0, 0, 0, 0,
+ 0, 0, 0,0x56,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB,0x0A, 0, 0,
+ 0, 0,0x3D,0xFC,0xFF,0xFF,0xDF,0x49,0x0E,0x26,0x9B,0xFF,0xFF,0xFF,0xAF, 0, 0,
+ 0, 0,0xBE,0xFF,0xFF,0xFB,0x29, 0, 0, 0, 0,0xB1,0xFF,0xFF,0xFF,0x35, 0,
+ 0,0x06,0xFD,0xFF,0xFF,0xBE, 0, 0, 0, 0, 0,0x4B,0xFF,0xFF,0xFF,0x7A, 0,
+ 0,0x23,0xFF,0xFF,0xFF,0xA1, 0, 0, 0, 0, 0,0x2E,0xFF,0xFF,0xFF,0x9A, 0,
+ 0,0x1C,0xFF,0xFF,0xFF,0xBF, 0, 0, 0, 0, 0,0x4C,0xFF,0xFF,0xFF,0x92, 0,
+ 0,0x03,0xF0,0xFF,0xFF,0xFB,0x29, 0, 0, 0, 0,0xB5,0xFF,0xFF,0xFF,0x6A, 0,
+ 0, 0,0xA2,0xFF,0xFF,0xFF,0xDF,0x49,0x0E,0x25,0x9D,0xFF,0xFF,0xFF,0xFA,0x1E, 0,
+ 0, 0,0x23,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8C, 0, 0,
+ 0, 0, 0,0x3E,0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9A,0x03, 0, 0,
+ 0, 0, 0, 0,0x10,0x74,0xC0,0xEB,0xFB,0xF3,0xD8,0x9E,0x3A, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '9'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x17,0x86,0xCE,0xF0,0xF8,0xE4,0xB4,0x60,0x03, 0, 0, 0, 0,
+ 0, 0, 0,0x47,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCC,0x16, 0, 0, 0,
+ 0, 0,0x2B,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCD,0x04, 0, 0,
+ 0, 0,0xB2,0xFF,0xFF,0xFF,0xBC,0x26,0x07,0x49,0xEB,0xFF,0xFF,0xFF,0x66, 0, 0,
+ 0,0x11,0xFD,0xFF,0xFF,0xF7,0x14, 0, 0, 0,0x64,0xFF,0xFF,0xFF,0xCD, 0, 0,
+ 0,0x47,0xFF,0xFF,0xFF,0xB3, 0, 0, 0, 0,0x0C,0xFF,0xFF,0xFF,0xFF,0x1A, 0,
+ 0,0x60,0xFF,0xFF,0xFF,0x95, 0, 0, 0, 0, 0,0xED,0xFF,0xFF,0xFF,0x49, 0,
+ 0,0x67,0xFF,0xFF,0xFF,0x94, 0, 0, 0, 0, 0,0xEE,0xFF,0xFF,0xFF,0x70, 0,
+ 0,0x57,0xFF,0xFF,0xFF,0xB3, 0, 0, 0, 0,0x0C,0xFF,0xFF,0xFF,0xFF,0x85, 0,
+ 0,0x2B,0xFF,0xFF,0xFF,0xF7,0x14, 0, 0, 0,0x64,0xFF,0xFF,0xFF,0xFF,0x90, 0,
+ 0,0x01,0xDD,0xFF,0xFF,0xFF,0xBC,0x25,0x06,0x48,0xEB,0xFF,0xFF,0xFF,0xFF,0x98, 0,
+ 0, 0,0x60,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8D, 0,
+ 0, 0, 0,0x91,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD4,0xFF,0xFF,0xFF,0x7F, 0,
+ 0, 0, 0, 0,0x49,0xB2,0xE9,0xFB,0xED,0xBC,0x56,0x69,0xFF,0xFF,0xFF,0x5E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x97,0xFF,0xFF,0xFF,0x2F, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x06,0xE7,0xFF,0xFF,0xE7,0x03, 0,
+ 0, 0,0x1E,0x7E,0x01, 0, 0, 0, 0, 0,0x89,0xFF,0xFF,0xFF,0x8C, 0, 0,
+ 0, 0,0x20,0xFF,0xC9,0x4F,0x0F,0x0A,0x36,0xA4,0xFF,0xFF,0xFF,0xEE,0x17, 0, 0,
+ 0, 0,0x20,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x53, 0, 0, 0,
+ 0, 0,0x20,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x4C, 0, 0, 0, 0,
+ 0, 0, 0,0x39,0x93,0xD0,0xEF,0xF6,0xE2,0xB5,0x6B,0x0B, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// ':'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// ';'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA4,0xFF,0xFF,0xFF,0xFF,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xA5,0xFF,0xFF,0xFF,0xFF,0x10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xCE,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFA,0xFF,0xFF,0xFC,0x28, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3A,0xFF,0xFF,0xFF,0x9D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x70,0xFF,0xFF,0xF8,0x1E, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA5,0xFF,0xFF,0x8F, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '<'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x05,0x54,0xB8,0x35,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x28,0x8C,0xEA,0xFF,0xFF,0x38,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x0A,0x60,0xC4,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,
+ 0, 0, 0, 0, 0, 0,0x34,0x98,0xF1,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC5,0x1F,
+ 0, 0, 0,0x11,0x6C,0xD0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD6,0x7B,0x21, 0, 0,
+ 0,0x39,0xA4,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xE4,0x8C,0x31, 0, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0xFF,0xFF,0xFF,0xEF,0x9D,0x42,0x02, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0xFF,0xFF,0x9C,0x0C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0xFF,0xFF,0xFF,0xEA,0x95,0x3A, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3D,0xA9,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0x85,0x2A, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x13,0x70,0xD3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD0,0x75,0x1C, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x38,0x9B,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xC0,0x1E,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x0B,0x63,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x2A,0x8E,0xEB,0xFF,0xFF,0x38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x06,0x55,0xB9,0x35,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '='
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,
+ 0,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,
+ 0,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,
+ 0,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,
+ 0,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '>'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xA3,0x83,0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0xFE,0xBB,0x57,0x06, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0xFF,0xFF,0xFF,0xEC,0x8F,0x2B, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7C,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC7,0x63,0x0C, 0, 0, 0, 0, 0,
+ 0, 0,0x07,0x51,0xAC,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0x9B,0x37, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x0F,0x62,0xBD,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xD3,0x6F,0x0B,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x1A,0x73,0xCE,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x4B,0xE9,0xFF,0xFF,0xFF,0x38,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x15,0x6B,0xC6,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,
+ 0, 0, 0, 0, 0,0x0B,0x5B,0xB6,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xD7,0x74,0x0C,
+ 0, 0,0x05,0x4B,0xA6,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF,0xF4,0x9F,0x3B, 0, 0, 0,
+ 0,0x79,0xEB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCA,0x66,0x0D, 0, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0xFF,0xFF,0xFF,0xED,0x91,0x2D, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0xFE,0xBC,0x59,0x07, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xA4,0x84,0x21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '?'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x37,0x96,0xD7,0xF4,0xF7,0xE0,0xAB,0x4B, 0, 0, 0, 0,
+ 0, 0, 0,0x27,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAA,0x06, 0, 0,
+ 0, 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x82, 0, 0,
+ 0, 0, 0,0xB4,0xFF,0xB7,0x57,0x1A,0x06,0x23,0xA3,0xFF,0xFF,0xFF,0xE9, 0, 0,
+ 0, 0, 0,0x8A,0x3A, 0, 0, 0, 0, 0,0x0A,0xFD,0xFF,0xFF,0xFF,0x0C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x17,0xFF,0xFF,0xFF,0xF4,0x01, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x01,0xA6,0xFF,0xFF,0xFF,0x98, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x01,0x95,0xFF,0xFF,0xFF,0xD7,0x0E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x01,0x9E,0xFF,0xFF,0xFF,0xD8,0x19, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x90,0xFF,0xFF,0xFF,0xD1,0x16, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3B,0xFF,0xFF,0xFF,0xD8,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x97,0xFF,0xFF,0xFF,0x45, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xBA,0xFF,0xFF,0xFF,0x10, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xC4,0xFF,0xFF,0xFF,0x04, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xC4,0xFF,0xFF,0xFF,0x04, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xC4,0xFF,0xFF,0xFF,0x04, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xC4,0xFF,0xFF,0xFF,0x04, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xC4,0xFF,0xFF,0xFF,0x04, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xC4,0xFF,0xFF,0xFF,0x04, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '@'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x11,0x69,0xB9,0xE0,0xF8,0xEF,0xCA,0x7D,0x10, 0, 0, 0,
+ 0, 0, 0, 0,0x5E,0xEB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE9,0x37, 0, 0,
+ 0, 0, 0,0x82,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x1F, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xDA,0x67,0x1F,0x06,0x16,0x5A,0xE2,0xFF,0xFF,0xA6, 0,
+ 0,0x22,0xF5,0xFF,0xFF,0xAB,0x0A, 0, 0, 0, 0, 0,0x1C,0xEF,0xFF,0xFB,0x0D,
+ 0,0xA1,0xFF,0xFF,0xC4,0x06, 0, 0, 0, 0, 0, 0, 0,0x8F,0xFF,0xFF,0x43,
+0x11,0xF7,0xFF,0xFB,0x29, 0, 0,0x12,0x8C,0xDD,0xF8,0xE1,0x7E,0x68,0xFF,0xFF,0x5C,
+0x5B,0xFF,0xFF,0xAF, 0, 0,0x1A,0xDC,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0x67,
+0x92,0xFF,0xFF,0x58, 0, 0,0xB5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x68,
+0xC1,0xFF,0xFF,0x20, 0,0x28,0xFF,0xFF,0xFF,0x84,0x1A,0x13,0x6A,0xF9,0xFF,0xFF,0x68,
+0xD5,0xFF,0xFC, 0, 0,0x68,0xFF,0xFF,0xB7, 0, 0, 0, 0,0x8D,0xFF,0xFF,0x68,
+0xE4,0xFF,0xEE, 0, 0,0x84,0xFF,0xFF,0x75, 0, 0, 0, 0,0x4A,0xFF,0xFF,0x68,
+0xE2,0xFF,0xF1, 0, 0,0x83,0xFF,0xFF,0x75, 0, 0, 0, 0,0x4B,0xFF,0xFF,0x68,
+0xD0,0xFF,0xFF,0x04, 0,0x67,0xFF,0xFF,0xB7, 0, 0, 0, 0,0x8D,0xFF,0xFF,0x68,
+0xBA,0xFF,0xFF,0x2D, 0,0x26,0xFF,0xFF,0xFF,0x84,0x19,0x13,0x69,0xF9,0xFF,0xFF,0x68,
+0x85,0xFF,0xFF,0x6B, 0, 0,0xB2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x68,
+0x48,0xFF,0xFF,0xCF, 0, 0,0x19,0xDB,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,0xFF,0x68,
+0x05,0xE5,0xFF,0xFF,0x54, 0, 0,0x11,0x8B,0xDE,0xFA,0xE6,0x8C,0x63,0xFF,0xFF,0x68,
+ 0,0x79,0xFF,0xFF,0xEC,0x24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x0A,0xD7,0xFF,0xFF,0xE8,0x3C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x2F,0xF4,0xFF,0xFF,0xFF,0xAD,0x54,0x1D,0x07,0x14,0x31,0x70,0xCE,0x4F, 0,
+ 0, 0, 0,0x35,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDB,0x06,
+ 0, 0, 0, 0,0x1E,0xA6,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCA,0x1A,
+ 0, 0, 0, 0, 0, 0,0x2B,0x7C,0xC1,0xE1,0xF6,0xF6,0xDD,0xA6,0x4D,0x02, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'A'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x04,0xF2,0xFF,0xFF,0xFF,0xFF,0x6A, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x3D,0xFF,0xFF,0xFF,0xFF,0xFF,0xB0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x82,0xFF,0xFF,0xFF,0xFF,0xFF,0xF1,0x04, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xC8,0xFF,0xFF,0xF9,0xFF,0xFF,0xFF,0x3B, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x10,0xFC,0xFF,0xFF,0x9B,0xFF,0xFF,0xFF,0x81, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x53,0xFF,0xFF,0xFF,0x49,0xD8,0xFF,0xFF,0xC7, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x98,0xFF,0xFF,0xFD,0x0F,0x9B,0xFF,0xFF,0xFC,0x10, 0, 0, 0,
+ 0, 0, 0, 0,0xDD,0xFF,0xFF,0xD0, 0,0x5E,0xFF,0xFF,0xFF,0x52, 0, 0, 0,
+ 0, 0, 0,0x23,0xFF,0xFF,0xFF,0x93, 0,0x21,0xFF,0xFF,0xFF,0x98, 0, 0, 0,
+ 0, 0, 0,0x69,0xFF,0xFF,0xFF,0x57, 0, 0,0xE4,0xFF,0xFF,0xDE, 0, 0, 0,
+ 0, 0, 0,0xAE,0xFF,0xFF,0xFF,0x1A, 0, 0,0xA7,0xFF,0xFF,0xFF,0x23, 0, 0,
+ 0, 0,0x03,0xF0,0xFF,0xFF,0xDE, 0, 0, 0,0x6A,0xFF,0xFF,0xFF,0x69, 0, 0,
+ 0, 0,0x39,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAF, 0, 0,
+ 0, 0,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x03, 0,
+ 0, 0,0xC4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3A, 0,
+ 0,0x0E,0xFB,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0,0x61,0xFF,0xFF,0xFF,0x80, 0,
+ 0,0x4F,0xFF,0xFF,0xFF,0x99, 0, 0, 0, 0, 0,0x29,0xFF,0xFF,0xFF,0xC6, 0,
+ 0,0x95,0xFF,0xFF,0xFF,0x62, 0, 0, 0, 0, 0,0x01,0xF0,0xFF,0xFF,0xFC,0x0F,
+ 0,0xDA,0xFF,0xFF,0xFF,0x2C, 0, 0, 0, 0, 0, 0,0xBB,0xFF,0xFF,0xFF,0x51,
+0x1F,0xFF,0xFF,0xFF,0xF3,0x02, 0, 0, 0, 0, 0, 0,0x83,0xFF,0xFF,0xFF,0x97,
+0x65,0xFF,0xFF,0xFF,0xBF, 0, 0, 0, 0, 0, 0, 0,0x4C,0xFF,0xFF,0xFF,0xDD,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'B'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xF3,0xDE,0xB2,0x66,0x09, 0, 0, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE2,0x31, 0, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x0F, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xD0, 0, 0,0x02,0x1B,0x75,0xFE,0xFF,0xFF,0xFF,0x67, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0,0xAD,0xFF,0xFF,0xFF,0x98, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0,0x86,0xFF,0xFF,0xFF,0xA0, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0,0xA9,0xFF,0xFF,0xFF,0x7A, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xD0, 0, 0,0x02,0x18,0x6C,0xFD,0xFF,0xFF,0xF5,0x1E, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x40, 0, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF5,0x9B,0x1C, 0, 0, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0x78, 0, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xD0, 0, 0,0x01,0x14,0x56,0xE6,0xFF,0xFF,0xFF,0x70, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0,0x3F,0xFF,0xFF,0xFF,0xEE,0x08,
+ 0,0x3C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,0xEE,0xFF,0xFF,0xFF,0x3F,
+ 0,0x3C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,0xD8,0xFF,0xFF,0xFF,0x5E,
+ 0,0x3C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,0xE7,0xFF,0xFF,0xFF,0x5F,
+ 0,0x3C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0,0x2A,0xFF,0xFF,0xFF,0xFF,0x45,
+ 0,0x3C,0xFF,0xFF,0xFF,0xD0, 0, 0,0x01,0x10,0x47,0xD5,0xFF,0xFF,0xFF,0xF7,0x0B,
+ 0,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x86, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x9A,0x03, 0,
+ 0,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xE6,0xC1,0x89,0x30, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'C'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x0C,0x6A,0xB4,0xE0,0xF6,0xF0,0xD4,0xA5,0x4A,0x04, 0,
+ 0, 0, 0, 0, 0,0x51,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x50, 0,
+ 0, 0, 0, 0,0x5F,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x50, 0,
+ 0, 0, 0,0x26,0xF7,0xFF,0xFF,0xFF,0xDF,0x56,0x13,0x10,0x59,0xE1,0xFF,0x50, 0,
+ 0, 0, 0,0xB1,0xFF,0xFF,0xFF,0xE4,0x17, 0, 0, 0, 0,0x19,0xD6,0x50, 0,
+ 0, 0,0x1A,0xFC,0xFF,0xFF,0xFF,0x60, 0, 0, 0, 0, 0, 0,0x24,0x40, 0,
+ 0, 0,0x62,0xFF,0xFF,0xFF,0xF7,0x09, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x95,0xFF,0xFF,0xFF,0xC1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xBA,0xFF,0xFF,0xFF,0x9C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xC9,0xFF,0xFF,0xFF,0x8A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xD4,0xFF,0xFF,0xFF,0x82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xC9,0xFF,0xFF,0xFF,0x8A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xBA,0xFF,0xFF,0xFF,0x9C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x96,0xFF,0xFF,0xFF,0xC1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x62,0xFF,0xFF,0xFF,0xF7,0x09, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x1A,0xFC,0xFF,0xFF,0xFF,0x5F, 0, 0, 0, 0, 0, 0,0x24,0x40, 0,
+ 0, 0, 0,0xB2,0xFF,0xFF,0xFF,0xE4,0x17, 0, 0, 0, 0,0x19,0xD5,0x50, 0,
+ 0, 0, 0,0x28,0xF8,0xFF,0xFF,0xFF,0xDE,0x55,0x11,0x10,0x58,0xE1,0xFF,0x50, 0,
+ 0, 0, 0, 0,0x62,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x50, 0,
+ 0, 0, 0, 0, 0,0x54,0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x50, 0,
+ 0, 0, 0, 0, 0, 0,0x0C,0x6C,0xB6,0xE2,0xF7,0xF1,0xD5,0xA6,0x4B,0x04, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'D'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0xFD,0xED,0xDC,0xB0,0x77,0x1D, 0, 0, 0, 0, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x9A,0x0A, 0, 0, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCE,0x0C, 0, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20,0x07,0x29,0x8A,0xFC,0xFF,0xFF,0xFF,0x9B, 0, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0,0x6B,0xFF,0xFF,0xFF,0xFD,0x1F, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0,0x02,0xDE,0xFF,0xFF,0xFF,0x80, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0x93,0xFF,0xFF,0xFF,0xBD, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0x64,0xFF,0xFF,0xFF,0xEE, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0x46,0xFF,0xFF,0xFF,0xFF,0x0B,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0x39,0xFF,0xFF,0xFF,0xFF,0x19,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0x32,0xFF,0xFF,0xFF,0xFF,0x24,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0x39,0xFF,0xFF,0xFF,0xFF,0x19,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0x46,0xFF,0xFF,0xFF,0xFF,0x0B,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0x64,0xFF,0xFF,0xFF,0xED, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0x95,0xFF,0xFF,0xFF,0xBC, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0,0x02,0xDE,0xFF,0xFF,0xFF,0x7E, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0,0x6A,0xFF,0xFF,0xFF,0xFD,0x1E, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20,0x06,0x28,0x8A,0xFC,0xFF,0xFF,0xFF,0x97, 0, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCB,0x0B, 0, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0x9A,0x09, 0, 0, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0xFD,0xEF,0xDD,0xB2,0x77,0x1D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'E'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8C, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8C, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8C, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB4, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB4, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB4, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8C, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8C, 0,
+ 0, 0,0xA0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'F'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x6C,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'G'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x37,0x8F,0xD0,0xEB,0xFB,0xF0,0xCD,0x8D,0x3C,0x02, 0,
+ 0, 0, 0, 0,0x0E,0xA8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x40, 0,
+ 0, 0, 0,0x0F,0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x40, 0,
+ 0, 0, 0,0x9F,0xFF,0xFF,0xFF,0xFF,0x97,0x2D,0x08,0x1D,0x6A,0xE6,0xFF,0x40, 0,
+ 0, 0,0x31,0xFF,0xFF,0xFF,0xFF,0x77, 0, 0, 0, 0, 0,0x1B,0xD5,0x40, 0,
+ 0, 0,0x96,0xFF,0xFF,0xFF,0xD9,0x02, 0, 0, 0, 0, 0, 0,0x28,0x35, 0,
+ 0, 0,0xE2,0xFF,0xFF,0xFF,0x7D, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x15,0xFF,0xFF,0xFF,0xFF,0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3A,0xFF,0xFF,0xFF,0xFF,0x1B, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x49,0xFF,0xFF,0xFF,0xFF,0x0A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x54,0xFF,0xFF,0xFF,0xFF,0x02, 0, 0,0x84,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0,
+ 0,0x49,0xFF,0xFF,0xFF,0xFF,0x0A, 0, 0,0x84,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0,
+ 0,0x3A,0xFF,0xFF,0xFF,0xFF,0x1C, 0, 0,0x84,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0,
+ 0,0x15,0xFF,0xFF,0xFF,0xFF,0x40, 0, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x7D, 0, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF, 0,
+ 0, 0,0x93,0xFF,0xFF,0xFF,0xD8,0x01, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF, 0,
+ 0, 0,0x2F,0xFF,0xFF,0xFF,0xFF,0x6F, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF, 0,
+ 0, 0, 0,0x9C,0xFF,0xFF,0xFF,0xFD,0x89,0x21,0x06,0x27,0xCE,0xFF,0xFF,0xFF, 0,
+ 0, 0, 0,0x0E,0xCC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0,
+ 0, 0, 0, 0,0x0F,0xAD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x9E, 0,
+ 0, 0, 0, 0, 0, 0,0x3D,0x97,0xD7,0xF0,0xFA,0xEA,0xC2,0x82,0x25, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'H'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0x20, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x84, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'I'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'J'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x04,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x48, 0, 0,
+ 0, 0, 0, 0,0x04,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x48, 0, 0,
+ 0, 0, 0, 0,0x04,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x48, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xE8,0xFF,0xFF,0xFF,0x48, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xE8,0xFF,0xFF,0xFF,0x48, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xE8,0xFF,0xFF,0xFF,0x48, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xE8,0xFF,0xFF,0xFF,0x48, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xE8,0xFF,0xFF,0xFF,0x48, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xE8,0xFF,0xFF,0xFF,0x48, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xE8,0xFF,0xFF,0xFF,0x48, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xE8,0xFF,0xFF,0xFF,0x48, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xE8,0xFF,0xFF,0xFF,0x48, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xE8,0xFF,0xFF,0xFF,0x48, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xE8,0xFF,0xFF,0xFF,0x48, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xED,0xFF,0xFF,0xFF,0x41, 0, 0,
+ 0,0x58,0x23, 0, 0, 0, 0, 0, 0,0x0B,0xFE,0xFF,0xFF,0xFF,0x31, 0, 0,
+ 0,0x74,0xE3,0x3A, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xFD,0x0B, 0, 0,
+ 0,0x74,0xFF,0xFC,0x9E,0x3B,0x0E,0x18,0x60,0xF0,0xFF,0xFF,0xFF,0xC5, 0, 0, 0,
+ 0,0x74,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x4F, 0, 0, 0,
+ 0,0x74,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x7D, 0, 0, 0, 0,
+ 0,0x06,0x3E,0x7F,0xBB,0xD7,0xEE,0xFB,0xEF,0xCE,0x94,0x30, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'K'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xD4, 0, 0, 0, 0, 0,0x1C,0xE9,0xFF,0xFF,0xFF,0xB2,0x01,
+0x58,0xFF,0xFF,0xFF,0xD4, 0, 0, 0, 0,0x06,0xC8,0xFF,0xFF,0xFF,0xD7,0x0E, 0,
+0x58,0xFF,0xFF,0xFF,0xD4, 0, 0, 0, 0,0x9A,0xFF,0xFF,0xFF,0xF0,0x26, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,0x63,0xFF,0xFF,0xFF,0xFD,0x4B, 0, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xD4, 0, 0,0x35,0xF8,0xFF,0xFF,0xFF,0x79, 0, 0, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xD4, 0,0x15,0xE2,0xFF,0xFF,0xFF,0xAA, 0, 0, 0, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xD4,0x03,0xBD,0xFF,0xFF,0xFF,0xD1,0x0B, 0, 0, 0, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xD4,0x8C,0xFF,0xFF,0xFF,0xEC,0x21, 0, 0, 0, 0, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0x9C, 0, 0, 0, 0, 0, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x21, 0, 0, 0, 0, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA5, 0, 0, 0, 0, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0xFF,0xFF,0xFF,0xFE,0x32, 0, 0, 0, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xFF,0xDC,0x12,0xCD,0xFF,0xFF,0xFF,0xBB, 0, 0, 0, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xF5,0x2C, 0,0x47,0xFF,0xFF,0xFF,0xFF,0x46, 0, 0, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,0xBF,0xFF,0xFF,0xFF,0xCF,0x01, 0, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,0x37,0xFF,0xFF,0xFF,0xFF,0x5B, 0, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xD4, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0xDF,0x07, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xD4, 0, 0, 0, 0,0x2A,0xFD,0xFF,0xFF,0xFF,0x71, 0, 0,
+0x58,0xFF,0xFF,0xFF,0xD4, 0, 0, 0, 0, 0,0xA0,0xFF,0xFF,0xFF,0xEC,0x0F, 0,
+0x58,0xFF,0xFF,0xFF,0xD4, 0, 0, 0, 0, 0,0x1F,0xF8,0xFF,0xFF,0xFF,0x87, 0,
+0x58,0xFF,0xFF,0xFF,0xD4, 0, 0, 0, 0, 0, 0,0x90,0xFF,0xFF,0xFF,0xF6,0x1B,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'L'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x4C,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x4C,
+ 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x4C,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'M'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xC8,0xFF,0xFF,0xFF,0xFF,0x57, 0, 0, 0, 0,0xE7,0xFF,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xFF,0xFF,0x9F, 0, 0, 0,0x30,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xFF,0xFF,0xE6, 0, 0, 0,0x78,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xFF,0xFF,0xFF,0x2F, 0, 0,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xE4,0xFE,0xFF,0x77, 0,0x0D,0xFA,0xFF,0xE3,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0,0xD3,0xFF,0xBE, 0,0x4F,0xFF,0xFF,0xA3,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0,0x92,0xFF,0xF9,0x0C,0x97,0xFF,0xFB,0x68,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0,0x51,0xFF,0xFF,0x4E,0xDE,0xFF,0xC7,0x5C,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0,0x12,0xFE,0xFF,0xBC,0xFF,0xFF,0x87,0x5C,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0, 0,0xCF,0xFF,0xFF,0xFF,0xFF,0x47,0x5C,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0, 0,0x8E,0xFF,0xFF,0xFF,0xFB,0x0C,0x5C,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0, 0,0x4D,0xFF,0xFF,0xFF,0xC7, 0,0x5C,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0, 0,0x0F,0xFC,0xFF,0xFF,0x87, 0,0x5C,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0x3C,
+ 0,0xC8,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0x3C,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'N'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0, 0,0xF0,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0xFF,0xBF, 0, 0, 0, 0, 0,0xF0,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0xFF,0xFE,0x23, 0, 0, 0, 0,0xF0,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0xFF,0xFF,0x85, 0, 0, 0, 0,0xF0,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0xFF,0xFF,0xE5,0x03, 0, 0, 0,0xF0,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0xFC,0xFF,0xFF,0x4A, 0, 0, 0,0xF0,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0xB4,0xFF,0xFF,0xAD, 0, 0, 0,0xF0,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0x63,0xED,0xFF,0xFA,0x16, 0, 0,0xF0,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0x5C,0x92,0xFF,0xFF,0x73, 0, 0,0xF0,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0x5C,0x2E,0xFF,0xFF,0xD6, 0, 0,0xF0,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0x5C, 0,0xCB,0xFF,0xFF,0x38, 0,0xF0,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0x5C, 0,0x68,0xFF,0xFF,0x9B, 0,0xF0,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0x5C, 0,0x0E,0xF5,0xFF,0xF2,0x0B,0xF0,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0x5C, 0, 0,0xA1,0xFF,0xFF,0x61,0xF0,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0x5C, 0, 0,0x3E,0xFF,0xFF,0xC3,0xF0,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0x5C, 0, 0, 0,0xD9,0xFF,0xFF,0xFD,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0x5C, 0, 0, 0,0x77,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0x5C, 0, 0, 0,0x18,0xFB,0xFF,0xFF,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0,0x4D,0xFF,0xFF,0xFF,0xFF,0xC0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0x5C, 0, 0, 0, 0,0x03,0xE5,0xFF,0xFF,0xFF,0xC0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'O'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4B,0xAA,0xE1,0xF8,0xEC,0xCA,0x7B,0x12, 0, 0, 0, 0,
+ 0, 0, 0,0x07,0xAD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE8,0x3F, 0, 0, 0,
+ 0, 0, 0,0xAA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF1,0x2C, 0, 0,
+ 0, 0,0x4B,0xFF,0xFF,0xFF,0xFB,0x65,0x0C,0x2A,0xC7,0xFF,0xFF,0xFF,0xBE, 0, 0,
+ 0, 0,0xC3,0xFF,0xFF,0xFF,0x8C, 0, 0, 0,0x1C,0xF8,0xFF,0xFF,0xFF,0x36, 0,
+ 0,0x18,0xFD,0xFF,0xFF,0xFF,0x2A, 0, 0, 0, 0,0xB3,0xFF,0xFF,0xFF,0x8A, 0,
+ 0,0x54,0xFF,0xFF,0xFF,0xF0, 0, 0, 0, 0, 0,0x7A,0xFF,0xFF,0xFF,0xC7, 0,
+ 0,0x7E,0xFF,0xFF,0xFF,0xCD, 0, 0, 0, 0, 0,0x56,0xFF,0xFF,0xFF,0xF1, 0,
+ 0,0x9B,0xFF,0xFF,0xFF,0xB7, 0, 0, 0, 0, 0,0x40,0xFF,0xFF,0xFF,0xFF,0x0F,
+ 0,0xA8,0xFF,0xFF,0xFF,0xAD, 0, 0, 0, 0, 0,0x37,0xFF,0xFF,0xFF,0xFF,0x1B,
+ 0,0xB1,0xFF,0xFF,0xFF,0xA9, 0, 0, 0, 0, 0,0x32,0xFF,0xFF,0xFF,0xFF,0x24,
+ 0,0xA8,0xFF,0xFF,0xFF,0xAD, 0, 0, 0, 0, 0,0x37,0xFF,0xFF,0xFF,0xFF,0x1B,
+ 0,0x9B,0xFF,0xFF,0xFF,0xB7, 0, 0, 0, 0, 0,0x40,0xFF,0xFF,0xFF,0xFF,0x0F,
+ 0,0x7E,0xFF,0xFF,0xFF,0xCD, 0, 0, 0, 0, 0,0x56,0xFF,0xFF,0xFF,0xF1, 0,
+ 0,0x54,0xFF,0xFF,0xFF,0xF0, 0, 0, 0, 0, 0,0x7A,0xFF,0xFF,0xFF,0xC7, 0,
+ 0,0x19,0xFD,0xFF,0xFF,0xFF,0x28, 0, 0, 0, 0,0xB2,0xFF,0xFF,0xFF,0x8A, 0,
+ 0, 0,0xC3,0xFF,0xFF,0xFF,0x8A, 0, 0, 0,0x1B,0xF7,0xFF,0xFF,0xFF,0x37, 0,
+ 0, 0,0x4C,0xFF,0xFF,0xFF,0xFA,0x64,0x0B,0x28,0xC6,0xFF,0xFF,0xFF,0xBF, 0, 0,
+ 0, 0, 0,0xAA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF2,0x2C, 0, 0,
+ 0, 0, 0,0x08,0xAD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE8,0x40, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4C,0xAC,0xE3,0xF9,0xED,0xCB,0x7C,0x12, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'P'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0xED,0xD4,0xA9,0x5F,0x0C, 0, 0, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x47, 0, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0x30, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0x78, 0,0x04,0x1E,0x71,0xF7,0xFF,0xFF,0xFF,0xB3, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0,0x7B,0xFF,0xFF,0xFF,0xF8,0x09,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0,0x32,0xFF,0xFF,0xFF,0xFF,0x28,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0,0x20,0xFF,0xFF,0xFF,0xFF,0x37,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0,0x32,0xFF,0xFF,0xFF,0xFF,0x28,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0,0x7B,0xFF,0xFF,0xFF,0xF8,0x09,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0x78, 0,0x04,0x1D,0x70,0xF7,0xFF,0xFF,0xFF,0xB4, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x31, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x47, 0, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFA,0xEF,0xD5,0xA9,0x61,0x0D, 0, 0, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'Q'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4B,0xAA,0xE1,0xF8,0xEC,0xCA,0x7A,0x11, 0, 0, 0, 0,
+ 0, 0, 0,0x07,0xAD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x3C, 0, 0, 0,
+ 0, 0, 0,0xAA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0x28, 0, 0,
+ 0, 0,0x4B,0xFF,0xFF,0xFF,0xFB,0x65,0x0C,0x2A,0xC7,0xFF,0xFF,0xFF,0xB9, 0, 0,
+ 0, 0,0xC3,0xFF,0xFF,0xFF,0x8C, 0, 0, 0,0x1C,0xF8,0xFF,0xFF,0xFF,0x32, 0,
+ 0,0x18,0xFD,0xFF,0xFF,0xFF,0x2A, 0, 0, 0, 0,0xB3,0xFF,0xFF,0xFF,0x86, 0,
+ 0,0x54,0xFF,0xFF,0xFF,0xF0, 0, 0, 0, 0, 0,0x7A,0xFF,0xFF,0xFF,0xC4, 0,
+ 0,0x7E,0xFF,0xFF,0xFF,0xCD, 0, 0, 0, 0, 0,0x56,0xFF,0xFF,0xFF,0xEE, 0,
+ 0,0x9B,0xFF,0xFF,0xFF,0xB7, 0, 0, 0, 0, 0,0x40,0xFF,0xFF,0xFF,0xFF,0x0D,
+ 0,0xA8,0xFF,0xFF,0xFF,0xAD, 0, 0, 0, 0, 0,0x37,0xFF,0xFF,0xFF,0xFF,0x1A,
+ 0,0xB1,0xFF,0xFF,0xFF,0xA9, 0, 0, 0, 0, 0,0x32,0xFF,0xFF,0xFF,0xFF,0x24,
+ 0,0xA8,0xFF,0xFF,0xFF,0xAD, 0, 0, 0, 0, 0,0x37,0xFF,0xFF,0xFF,0xFF,0x1F,
+ 0,0x9B,0xFF,0xFF,0xFF,0xB7, 0, 0, 0, 0, 0,0x40,0xFF,0xFF,0xFF,0xFF,0x13,
+ 0,0x7E,0xFF,0xFF,0xFF,0xCD, 0, 0, 0, 0, 0,0x56,0xFF,0xFF,0xFF,0xF8, 0,
+ 0,0x54,0xFF,0xFF,0xFF,0xF0, 0, 0, 0, 0, 0,0x7A,0xFF,0xFF,0xFF,0xD1, 0,
+ 0,0x19,0xFD,0xFF,0xFF,0xFF,0x28, 0, 0, 0, 0,0xB2,0xFF,0xFF,0xFF,0x99, 0,
+ 0, 0,0xC3,0xFF,0xFF,0xFF,0x8A, 0, 0, 0,0x1B,0xF7,0xFF,0xFF,0xFF,0x4A, 0,
+ 0, 0,0x4C,0xFF,0xFF,0xFF,0xFA,0x64,0x0B,0x28,0xC6,0xFF,0xFF,0xFF,0xDC,0x02, 0,
+ 0, 0, 0,0xAA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x4A, 0, 0,
+ 0, 0, 0,0x07,0xAC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x6B, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4C,0xAB,0xE3,0xFA,0xFF,0xFF,0xFF,0xEC,0x2E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x50,0xFE,0xFF,0xFF,0xEE,0x35, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x86,0xFF,0xFF,0xFF,0xEF,0x16, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x02,0xB9,0xFF,0xF3,0x4F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x12,0xBE,0x2D, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'R'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0xEB,0xC8,0x94,0x3B, 0, 0, 0, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA7,0x06, 0, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x94, 0, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0x10, 0,0x10,0x42,0xD1,0xFF,0xFF,0xFF,0xFB,0x19, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0x10, 0, 0, 0,0x1E,0xFD,0xFF,0xFF,0xFF,0x5A, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0x10, 0, 0, 0, 0,0xD8,0xFF,0xFF,0xFF,0x7B, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0x10, 0, 0, 0, 0,0xC7,0xFF,0xFF,0xFF,0x87, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0x10, 0, 0, 0, 0,0xD9,0xFF,0xFF,0xFF,0x74, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0x10, 0, 0, 0,0x20,0xFD,0xFF,0xFF,0xFF,0x3C, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0x10, 0,0x10,0x42,0xD2,0xFF,0xFF,0xFF,0xCA,0x01, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD5,0x1E, 0, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE9,0x60,0x06, 0, 0, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC7,0x07, 0, 0, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0x10,0x09,0x64,0xFB,0xFF,0xFF,0xFF,0x7F, 0, 0, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0x10, 0, 0,0x73,0xFF,0xFF,0xFF,0xF4,0x17, 0, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0x10, 0, 0,0x04,0xDA,0xFF,0xFF,0xFF,0x92, 0, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0x10, 0, 0, 0,0x5F,0xFF,0xFF,0xFF,0xF9,0x1F, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0x10, 0, 0, 0,0x03,0xDB,0xFF,0xFF,0xFF,0x9E, 0, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0x10, 0, 0, 0, 0,0x5F,0xFF,0xFF,0xFF,0xFC,0x27, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0x10, 0, 0, 0, 0,0x03,0xDB,0xFF,0xFF,0xFF,0xAA, 0,
+0x1C,0xFF,0xFF,0xFF,0xFF,0x10, 0, 0, 0, 0, 0,0x60,0xFF,0xFF,0xFF,0xFE,0x32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'S'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x10,0x73,0xBE,0xEA,0xFA,0xEE,0xD8,0xC0,0x86,0x44,0x09, 0, 0,
+ 0, 0, 0,0x42,0xE8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x88, 0, 0,
+ 0, 0,0x2C,0xF5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x88, 0, 0,
+ 0, 0,0xB3,0xFF,0xFF,0xFF,0xD9,0x4A,0x12,0x10,0x40,0xA6,0xFE,0xFF,0x88, 0, 0,
+ 0,0x09,0xF9,0xFF,0xFF,0xFF,0x2F, 0, 0, 0, 0, 0,0x41,0xE4,0x88, 0, 0,
+ 0,0x22,0xFF,0xFF,0xFF,0xF6, 0, 0, 0, 0, 0, 0, 0,0x20,0x65, 0, 0,
+ 0,0x22,0xFF,0xFF,0xFF,0xFF,0x1F, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x04,0xF4,0xFF,0xFF,0xFF,0xC4,0x1C, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x98,0xFF,0xFF,0xFF,0xFF,0xF6,0x94,0x35,0x01, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x0F,0xCB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0x85,0x17, 0, 0, 0, 0,
+ 0, 0, 0,0x07,0x82,0xF4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF4,0x6A, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x14,0x77,0xD6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x79, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x28,0x87,0xF5,0xFF,0xFF,0xFF,0xFC,0x26, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x37,0xFA,0xFF,0xFF,0xFF,0x81, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0xAC, 0,
+ 0,0x17,0x85,0x02, 0, 0, 0, 0, 0, 0, 0,0x92,0xFF,0xFF,0xFF,0xAE, 0,
+ 0,0x18,0xFF,0xBA,0x23, 0, 0, 0, 0, 0,0x04,0xD2,0xFF,0xFF,0xFF,0x91, 0,
+ 0,0x18,0xFF,0xFF,0xF8,0x9B,0x43,0x16,0x0A,0x32,0xB0,0xFF,0xFF,0xFF,0xFF,0x49, 0,
+ 0,0x18,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF, 0, 0,
+ 0,0x18,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB8,0x10, 0, 0,
+ 0, 0,0x25,0x64,0xA3,0xCB,0xE0,0xF4,0xFA,0xEE,0xCE,0x99,0x42, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'T'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x30,
+ 0,0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x30,
+ 0,0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x30,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'U'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,0xF0, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,0xF0, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,0xF0, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,0xF0, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,0xF0, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,0xF0, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,0xF0, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,0xF0, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,0xF0, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,0xF0, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,0xF0, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,0xF0, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,0xF0, 0,
+ 0,0x7E,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,0xEE, 0,
+ 0,0x72,0xFF,0xFF,0xFF,0xAF, 0, 0, 0, 0, 0,0x3F,0xFF,0xFF,0xFF,0xE0, 0,
+ 0,0x5A,0xFF,0xFF,0xFF,0xCC, 0, 0, 0, 0, 0,0x5E,0xFF,0xFF,0xFF,0xC9, 0,
+ 0,0x27,0xFF,0xFF,0xFF,0xFB,0x27, 0, 0, 0, 0,0xB6,0xFF,0xFF,0xFF,0x96, 0,
+ 0, 0,0xD2,0xFF,0xFF,0xFF,0xD9,0x43,0x0D,0x23,0x95,0xFF,0xFF,0xFF,0xFF,0x41, 0,
+ 0, 0,0x4E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBC, 0, 0,
+ 0, 0, 0,0x6E,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC4,0x15, 0, 0,
+ 0, 0, 0, 0,0x24,0x8B,0xCA,0xED,0xFB,0xF4,0xDE,0xAA,0x54,0x03, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'V'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0x13,0xFE,0xFF,0xFF,0xFF,0x1E, 0, 0, 0, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0x88,
+ 0,0xD4,0xFF,0xFF,0xFF,0x55, 0, 0, 0, 0, 0, 0,0xDE,0xFF,0xFF,0xFF,0x4B,
+ 0,0x97,0xFF,0xFF,0xFF,0x8B, 0, 0, 0, 0, 0,0x14,0xFF,0xFF,0xFF,0xFD,0x10,
+ 0,0x5A,0xFF,0xFF,0xFF,0xC1, 0, 0, 0, 0, 0,0x4B,0xFF,0xFF,0xFF,0xD0, 0,
+ 0,0x1D,0xFF,0xFF,0xFF,0xF3,0x02, 0, 0, 0, 0,0x81,0xFF,0xFF,0xFF,0x93, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x2D, 0, 0, 0, 0,0xB8,0xFF,0xFF,0xFF,0x56, 0,
+ 0, 0,0xA3,0xFF,0xFF,0xFF,0x63, 0, 0, 0, 0,0xED,0xFF,0xFF,0xFF,0x19, 0,
+ 0, 0,0x66,0xFF,0xFF,0xFF,0x99, 0, 0, 0,0x25,0xFF,0xFF,0xFF,0xDB, 0, 0,
+ 0, 0,0x28,0xFF,0xFF,0xFF,0xCF, 0, 0, 0,0x5B,0xFF,0xFF,0xFF,0x9E, 0, 0,
+ 0, 0, 0,0xEA,0xFF,0xFF,0xFB,0x09, 0, 0,0x92,0xFF,0xFF,0xFF,0x60, 0, 0,
+ 0, 0, 0,0xAE,0xFF,0xFF,0xFF,0x3B, 0, 0,0xC8,0xFF,0xFF,0xFF,0x23, 0, 0,
+ 0, 0, 0,0x71,0xFF,0xFF,0xFF,0x71, 0,0x06,0xF8,0xFF,0xFF,0xE6, 0, 0, 0,
+ 0, 0, 0,0x34,0xFF,0xFF,0xFF,0xA7, 0,0x35,0xFF,0xFF,0xFF,0xA8, 0, 0, 0,
+ 0, 0, 0,0x03,0xF3,0xFF,0xFF,0xDD, 0,0x6C,0xFF,0xFF,0xFF,0x6B, 0, 0, 0,
+ 0, 0, 0, 0,0xBA,0xFF,0xFF,0xFF,0x13,0xA2,0xFF,0xFF,0xFF,0x2E, 0, 0, 0,
+ 0, 0, 0, 0,0x7C,0xFF,0xFF,0xFF,0x49,0xD9,0xFF,0xFF,0xEF,0x01, 0, 0, 0,
+ 0, 0, 0, 0,0x3F,0xFF,0xFF,0xFF,0x8F,0xFE,0xFF,0xFF,0xB3, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x08,0xF9,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0x76, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xC5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0x05, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4B,0xFF,0xFF,0xFF,0xFF,0xFF,0xBE, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'W'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0xF0,0xFF,0xFF,0xB4, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x42,0xFF,0xFF,0xFF,
+0xD1,0xFF,0xFF,0xCD, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x56,0xFF,0xFF,0xFF,
+0xB1,0xFF,0xFF,0xE7, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x6A,0xFF,0xFF,0xFF,
+0x91,0xFF,0xFF,0xFD,0x03, 0, 0, 0, 0, 0, 0, 0, 0,0x7E,0xFF,0xFF,0xFF,
+0x71,0xFF,0xFF,0xFF,0x1A, 0, 0, 0, 0, 0, 0, 0, 0,0x92,0xFF,0xFF,0xEE,
+0x51,0xFF,0xFF,0xFF,0x33, 0,0x16,0xFF,0xFF,0xFF,0x92, 0, 0,0xA6,0xFF,0xFF,0xD1,
+0x32,0xFF,0xFF,0xFF,0x4D, 0,0x45,0xFF,0xFF,0xFF,0xC7, 0, 0,0xBA,0xFF,0xFF,0xB3,
+0x12,0xFF,0xFF,0xFF,0x66, 0,0x72,0xFF,0xFF,0xFF,0xF7,0x04, 0,0xCE,0xFF,0xFF,0x96,
+ 0,0xF1,0xFF,0xFF,0x7F, 0,0xA0,0xFF,0xFF,0xFF,0xFF,0x31, 0,0xE2,0xFF,0xFF,0x78,
+ 0,0xD2,0xFF,0xFF,0x99, 0,0xCE,0xFF,0xF9,0xFF,0xFF,0x66, 0,0xF6,0xFF,0xFF,0x5B,
+ 0,0xB2,0xFF,0xFF,0xB2,0x03,0xF7,0xFF,0xA7,0xFF,0xFF,0x9B,0x09,0xFF,0xFF,0xFF,0x3D,
+ 0,0x93,0xFF,0xFF,0xCC,0x29,0xFF,0xFF,0x59,0xE4,0xFF,0xD0,0x1E,0xFF,0xFF,0xFF,0x20,
+ 0,0x73,0xFF,0xFF,0xE5,0x57,0xFF,0xFF,0x27,0xAE,0xFF,0xFB,0x3B,0xFF,0xFF,0xFD,0x05,
+ 0,0x53,0xFF,0xFF,0xFC,0x87,0xFF,0xF2,0x01,0x78,0xFF,0xFF,0x80,0xFF,0xFF,0xE5, 0,
+ 0,0x33,0xFF,0xFF,0xFF,0xCA,0xFF,0xC1, 0,0x41,0xFF,0xFF,0xC9,0xFF,0xFF,0xC7, 0,
+ 0,0x13,0xFF,0xFF,0xFF,0xFD,0xFF,0x8E, 0,0x0D,0xFD,0xFF,0xFD,0xFF,0xFF,0xAA, 0,
+ 0, 0,0xF3,0xFF,0xFF,0xFF,0xFF,0x5C, 0, 0,0xD5,0xFF,0xFF,0xFF,0xFF,0x8C, 0,
+ 0, 0,0xD4,0xFF,0xFF,0xFF,0xFF,0x29, 0, 0,0x9E,0xFF,0xFF,0xFF,0xFF,0x6F, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0xF4,0x02, 0, 0,0x68,0xFF,0xFF,0xFF,0xFF,0x51, 0,
+ 0, 0,0x94,0xFF,0xFF,0xFF,0xC3, 0, 0, 0,0x32,0xFF,0xFF,0xFF,0xFF,0x34, 0,
+ 0, 0,0x74,0xFF,0xFF,0xFF,0x91, 0, 0, 0,0x04,0xF6,0xFF,0xFF,0xFF,0x16, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'X'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0x2D,0xFC,0xFF,0xFF,0xFC,0x2C, 0, 0, 0, 0, 0, 0,0xB3,0xFF,0xFF,0xFF,0x9D,
+ 0,0x94,0xFF,0xFF,0xFF,0xBC, 0, 0, 0, 0, 0,0x46,0xFF,0xFF,0xFF,0xF1,0x17,
+ 0,0x12,0xEC,0xFF,0xFF,0xFF,0x4F, 0, 0, 0,0x04,0xD6,0xFF,0xFF,0xFF,0x74, 0,
+ 0, 0,0x6A,0xFF,0xFF,0xFF,0xDB,0x06, 0, 0,0x70,0xFF,0xFF,0xFF,0xDA,0x06, 0,
+ 0, 0,0x03,0xD1,0xFF,0xFF,0xFF,0x75, 0,0x14,0xEF,0xFF,0xFF,0xFF,0x4B, 0, 0,
+ 0, 0, 0,0x3F,0xFF,0xFF,0xFF,0xF1,0x17,0x98,0xFF,0xFF,0xFF,0xB7, 0, 0, 0,
+ 0, 0, 0, 0,0xAA,0xFF,0xFF,0xFF,0xBC,0xFD,0xFF,0xFF,0xFA,0x28, 0, 0, 0,
+ 0, 0, 0, 0,0x1E,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xEA,0x0F, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x09,0xE1,0xFF,0xFF,0xFF,0xFF,0x65, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x95,0xFF,0xFF,0xFF,0xFC,0x14, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x20,0xF7,0xFF,0xFF,0xFF,0xFF,0x93, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xAD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x2B, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x42,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBB, 0, 0, 0, 0,
+ 0, 0, 0,0x03,0xD3,0xFF,0xFF,0xFF,0x89,0xEF,0xFF,0xFF,0xFF,0x50, 0, 0, 0,
+ 0, 0, 0,0x6C,0xFF,0xFF,0xFF,0xDA,0x06,0x6F,0xFF,0xFF,0xFF,0xDC,0x07, 0, 0,
+ 0, 0,0x13,0xEE,0xFF,0xFF,0xFF,0x4D, 0,0x04,0xD6,0xFF,0xFF,0xFF,0x78, 0, 0,
+ 0, 0,0x96,0xFF,0xFF,0xFF,0xB9, 0, 0, 0,0x45,0xFF,0xFF,0xFF,0xF3,0x19, 0,
+ 0,0x2E,0xFC,0xFF,0xFF,0xFB,0x2A, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0xA1, 0,
+ 0,0xBF,0xFF,0xFF,0xFF,0x91, 0, 0, 0, 0, 0,0x23,0xF8,0xFF,0xFF,0xFE,0x36,
+0x55,0xFF,0xFF,0xFF,0xEC,0x11, 0, 0, 0, 0, 0, 0,0x86,0xFF,0xFF,0xFF,0xC8,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'Y'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0xA3,0xFF,0xFF,0xFF,0xD7,0x02, 0, 0, 0, 0, 0, 0,0x67,0xFF,0xFF,0xFF,0xF8,
+0x23,0xFB,0xFF,0xFF,0xFF,0x56, 0, 0, 0, 0, 0,0x04,0xDF,0xFF,0xFF,0xFF,0x92,
+ 0,0x9C,0xFF,0xFF,0xFF,0xD2,0x01, 0, 0, 0, 0,0x61,0xFF,0xFF,0xFF,0xF6,0x19,
+ 0,0x1F,0xF9,0xFF,0xFF,0xFF,0x50, 0, 0, 0,0x03,0xDA,0xFF,0xFF,0xFF,0x8C, 0,
+ 0, 0,0x95,0xFF,0xFF,0xFF,0xCC, 0, 0, 0,0x5B,0xFF,0xFF,0xFF,0xF3,0x15, 0,
+ 0, 0,0x1A,0xF7,0xFF,0xFF,0xFF,0x49, 0,0x02,0xD6,0xFF,0xFF,0xFF,0x85, 0, 0,
+ 0, 0, 0,0x8F,0xFF,0xFF,0xFF,0xC6, 0,0x56,0xFF,0xFF,0xFF,0xF0,0x11, 0, 0,
+ 0, 0, 0,0x16,0xF4,0xFF,0xFF,0xFF,0x43,0xD1,0xFF,0xFF,0xFF,0x7E, 0, 0, 0,
+ 0, 0, 0, 0,0x88,0xFF,0xFF,0xFF,0xE8,0xFF,0xFF,0xFF,0xED,0x0E, 0, 0, 0,
+ 0, 0, 0, 0,0x13,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x82,0xFF,0xFF,0xFF,0xFF,0xFF,0xE9,0x0B, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x0F,0xEE,0xFF,0xFF,0xFF,0xFF,0x71, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x7F,0xFF,0xFF,0xFF,0xEA,0x08, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'Z'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,
+ 0,0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x37,0xFD,0xFF,0xFF,0xFF,0xFF,0x2C,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x07,0xD5,0xFF,0xFF,0xFF,0xFF,0x98, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x85,0xFF,0xFF,0xFF,0xFF,0xDE,0x0C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x32,0xFB,0xFF,0xFF,0xFF,0xFE,0x3F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x05,0xD0,0xFF,0xFF,0xFF,0xFF,0x8F, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x7F,0xFF,0xFF,0xFF,0xFF,0xD8,0x09, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x2D,0xF9,0xFF,0xFF,0xFF,0xFC,0x37, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x03,0xCB,0xFF,0xFF,0xFF,0xFF,0x86, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x78,0xFF,0xFF,0xFF,0xFF,0xD2,0x06, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x28,0xF8,0xFF,0xFF,0xFF,0xFA,0x31, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x02,0xC6,0xFF,0xFF,0xFF,0xFF,0x7D, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x71,0xFF,0xFF,0xFF,0xFF,0xCB,0x04, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x23,0xF5,0xFF,0xFF,0xFF,0xF8,0x2A, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x01,0xC0,0xFF,0xFF,0xFF,0xFF,0x74, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x50,0xFF,0xFF,0xFF,0xFF,0xC4,0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x60,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x70,
+ 0,0x60,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x70,
+ 0,0x60,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x70,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '['
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x2C, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x2C, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x2C, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x2C, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x2C, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x2C, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '\'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x31,0xFF,0xFF,0xEC,0x0A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xBA,0xFF,0xFF,0x6D, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x44,0xFF,0xFF,0xE0,0x04, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0xFF,0x5A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x56,0xFF,0xFF,0xD0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x03,0xDC,0xFF,0xFF,0x48, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x69,0xFF,0xFF,0xBE, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x08,0xE9,0xFF,0xFF,0x35, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x7C,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x11,0xF3,0xFF,0xFD,0x25, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x8E,0xFF,0xFF,0x99, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x1D,0xFA,0xFF,0xF8,0x17, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xA1,0xFF,0xFF,0x86, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2B,0xFE,0xFF,0xEF,0x0D, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0xB4,0xFF,0xFF,0x74, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x3D,0xFF,0xFF,0xE4,0x06, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0xC6,0xFF,0xFF,0x61, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x50,0xFF,0xFF,0xD6,0x01, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x01,0xD7,0xFF,0xFF,0x4E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x62,0xFF,0xFF,0xC5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x06,0xE5,0xFF,0xFF,0x3C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x75,0xFF,0xFF,0xB2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x0E,0xF0,0xFF,0xFE,0x2B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x87,0xFF,0xFF,0xA0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// ']'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x48,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '^'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x63,0xFF,0xFF,0xFF,0xD0,0x09, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x31,0xF7,0xFF,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x11,0xDE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x66, 0, 0, 0, 0,
+ 0, 0, 0,0x01,0xB3,0xFF,0xFF,0xFF,0xE3,0xFF,0xFF,0xFF,0xF8,0x33, 0, 0, 0,
+ 0, 0, 0,0x7C,0xFF,0xFF,0xFF,0xCA,0x11,0x6D,0xFE,0xFF,0xFF,0xDF,0x12, 0, 0,
+ 0, 0,0x44,0xFD,0xFF,0xFF,0xC4,0x0E, 0, 0,0x64,0xFD,0xFF,0xFF,0xB6,0x01, 0,
+ 0,0x1C,0xEA,0xFF,0xFF,0xBE,0x0B, 0, 0, 0, 0,0x5B,0xFC,0xFF,0xFF,0x7E, 0,
+0x05,0xC7,0xFF,0xFF,0xB7,0x09, 0, 0, 0, 0, 0, 0,0x53,0xFA,0xFF,0xFD,0x47,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '_'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+// '`'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x04,0xA7,0xFF,0xFF,0xFA,0x3B, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x02,0x9E,0xFF,0xFF,0xE7,0x1A, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x01,0x95,0xFF,0xFF,0xC8,0x07, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x8B,0xFF,0xFF,0x9C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x82,0xFF,0xFF,0x69, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'a'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x30,0x7C,0xB3,0xD0,0xE6,0xFA,0xF3,0xE0,0xB1,0x60,0x07, 0, 0, 0,
+ 0, 0,0x18,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD0,0x1A, 0, 0,
+ 0, 0,0x18,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB7, 0, 0,
+ 0, 0,0x17,0xD3,0x8A,0x51,0x31,0x1B,0x06,0x13,0x59,0xF0,0xFF,0xFF,0xFF,0x27, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x83,0xFF,0xFF,0xFF,0x69, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x70,0xFF,0xFF,0xFF,0x93, 0,
+ 0, 0, 0,0x0D,0x6A,0xB1,0xDB,0xF2,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA3, 0,
+ 0, 0,0x40,0xEB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAE, 0,
+ 0,0x18,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB0, 0,
+ 0,0x75,0xFF,0xFF,0xFF,0xFF,0xAA,0x38,0x11,0x03, 0,0x7B,0xFF,0xFF,0xFF,0xB0, 0,
+ 0,0xA0,0xFF,0xFF,0xFF,0xE4,0x01, 0, 0, 0, 0,0xA0,0xFF,0xFF,0xFF,0xB0, 0,
+ 0,0xA2,0xFF,0xFF,0xFF,0xD5, 0, 0, 0, 0,0x19,0xF3,0xFF,0xFF,0xFF,0xB0, 0,
+ 0,0x77,0xFF,0xFF,0xFF,0xFF,0x7E,0x14,0x11,0x48,0xD7,0xFF,0xFF,0xFF,0xFF,0xB0, 0,
+ 0,0x1C,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xB0, 0,
+ 0, 0,0x57,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD6,0x87,0xFF,0xFF,0xFF,0xB0, 0,
+ 0, 0, 0,0x29,0x99,0xDB,0xF7,0xF4,0xCF,0x77,0x08,0x70,0xFF,0xFF,0xFF,0xB0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'b'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44,0x1A,0x9B,0xE6,0xF8,0xDE,0x94,0x19, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x6B,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0x2E, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDE,0x08, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0xFF,0xB7,0x21,0x0E,0x7D,0xFF,0xFF,0xFF,0xFF,0x6A, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0xEA,0x0C, 0, 0, 0,0xAB,0xFF,0xFF,0xFF,0xC1, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x92, 0, 0, 0, 0,0x47,0xFF,0xFF,0xFF,0xF5,0x02,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x5E, 0, 0, 0, 0,0x13,0xFF,0xFF,0xFF,0xFF,0x1A,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x49, 0, 0, 0, 0, 0,0xFD,0xFF,0xFF,0xFF,0x29,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x48, 0, 0, 0, 0, 0,0xFD,0xFF,0xFF,0xFF,0x28,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x5E, 0, 0, 0, 0,0x13,0xFF,0xFF,0xFF,0xFF,0x1B,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x92, 0, 0, 0, 0,0x46,0xFF,0xFF,0xFF,0xF5,0x02,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0xEA,0x0C, 0, 0, 0,0xAB,0xFF,0xFF,0xFF,0xC2, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0xFF,0xB7,0x20,0x0D,0x7C,0xFF,0xFF,0xFF,0xFF,0x6C, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE1,0x09, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x6A,0xEB,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x33, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44,0x1D,0x9B,0xE3,0xF9,0xE3,0x9B,0x1E, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'c'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3F,0x9C,0xD8,0xF1,0xF7,0xDE,0xC2,0x88,0x33, 0, 0,
+ 0, 0, 0, 0,0x0F,0xB2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0, 0,0x08,0xCD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0, 0,0x8A,0xFF,0xFF,0xFF,0xFF,0xA0,0x2F,0x07,0x0B,0x2C,0x70,0xCF,0x07, 0,
+ 0, 0,0x0F,0xF4,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x50,0xFF,0xFF,0xFF,0xF4,0x0D, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x82,0xFF,0xFF,0xFF,0xB9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x97,0xFF,0xFF,0xFF,0x9B, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x97,0xFF,0xFF,0xFF,0x9A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x83,0xFF,0xFF,0xFF,0xB7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x52,0xFF,0xFF,0xFF,0xF2,0x0B, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x11,0xF6,0xFF,0xFF,0xFF,0x8A, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x8F,0xFF,0xFF,0xFF,0xFF,0x9B,0x2D,0x06,0x13,0x30,0x6B,0xCC,0x07, 0,
+ 0, 0, 0,0x0A,0xD2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0, 0, 0,0x13,0xBA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0, 0, 0, 0, 0,0x45,0xA0,0xDB,0xF3,0xF7,0xE0,0xC5,0x83,0x2E, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'd'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0,0x5D,0xC1,0xEF,0xF4,0xC6,0x55, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0,0x02,0xA5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x88,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0,0x72,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0x06,0xEE,0xFF,0xFF,0xFF,0xD0,0x2D,0x0A,0x62,0xFA,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0x4B,0xFF,0xFF,0xFF,0xFB,0x23, 0, 0, 0,0x83,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0x81,0xFF,0xFF,0xFF,0xBA, 0, 0, 0, 0,0x1D,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0xA3,0xFF,0xFF,0xFF,0x86, 0, 0, 0, 0, 0,0xE8,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0xB1,0xFF,0xFF,0xFF,0x71, 0, 0, 0, 0, 0,0xD2,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0xB2,0xFF,0xFF,0xFF,0x70, 0, 0, 0, 0, 0,0xD2,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0xA3,0xFF,0xFF,0xFF,0x86, 0, 0, 0, 0, 0,0xE8,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xBA, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0x4A,0xFF,0xFF,0xFF,0xFB,0x23, 0, 0, 0,0x83,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0x06,0xEE,0xFF,0xFF,0xFF,0xCF,0x2C,0x09,0x61,0xFA,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0,0x73,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF4,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0,0x02,0xAA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x87,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0,0x01,0x64,0xC9,0xF3,0xF2,0xC5,0x57, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'e'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x01,0x55,0xAC,0xE2,0xF8,0xF1,0xD5,0x94,0x2C, 0, 0, 0, 0,
+ 0, 0, 0,0x1A,0xC8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x83, 0, 0, 0,
+ 0, 0,0x10,0xDD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x83, 0, 0,
+ 0, 0,0x9F,0xFF,0xFF,0xFF,0xEC,0x53,0x0A,0x13,0x6B,0xF9,0xFF,0xFF,0xFD,0x30, 0,
+ 0,0x1B,0xFB,0xFF,0xFF,0xFF,0x52, 0, 0, 0, 0,0x83,0xFF,0xFF,0xFF,0xA0, 0,
+ 0,0x64,0xFF,0xFF,0xFF,0xDE, 0, 0, 0, 0, 0,0x1D,0xFF,0xFF,0xFF,0xEB, 0,
+ 0,0x96,0xFF,0xFF,0xFF,0xA9, 0, 0, 0, 0, 0,0x01,0xF7,0xFF,0xFF,0xFF,0x1F,
+ 0,0xAA,0xFF,0xFF,0xFF,0xFE,0xFC,0xFC,0xFD,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0x34,
+ 0,0xAB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x42,
+ 0,0x99,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x44,
+ 0,0x6B,0xFF,0xFF,0xFF,0x93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x24,0xFE,0xFF,0xFF,0xE2,0x0D, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xAC,0xFF,0xFF,0xFF,0xD2,0x56,0x19,0x04,0x0C,0x22,0x39,0x68,0xA9,0x8D, 0,
+ 0, 0,0x17,0xE2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9C, 0,
+ 0, 0, 0,0x1D,0xC5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9C, 0,
+ 0, 0, 0, 0, 0,0x46,0x9D,0xD6,0xEF,0xFB,0xEC,0xD8,0xC0,0x89,0x48,0x0C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'f'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x0D,0x7D,0xC7,0xEC,0xFA,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0,0x06,0xCF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0,0x58,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0,0x94,0xFF,0xFF,0xFF,0xC5,0x16, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xAA,0xFF,0xFF,0xFF,0x7E, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xB0,0xFF,0xFF,0xFF,0x78, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'g'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x36,0xAD,0xE9,0xF7,0xD9,0x86,0x0D,0xA0,0xFF,0xFF,0xFF,0x84, 0,
+ 0, 0, 0,0x60,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xD8,0xB2,0xFF,0xFF,0xFF,0x84, 0,
+ 0, 0,0x33,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x84, 0,
+ 0, 0,0xBC,0xFF,0xFF,0xFF,0xE6,0x40,0x09,0x4F,0xF2,0xFF,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x1C,0xFE,0xFF,0xFF,0xFF,0x4C, 0, 0, 0,0x6A,0xFF,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x59,0xFF,0xFF,0xFF,0xE3,0x02, 0, 0, 0,0x0D,0xF4,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x82,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0xC7,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x93,0xFF,0xFF,0xFF,0x94, 0, 0, 0, 0, 0,0xAD,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x96,0xFF,0xFF,0xFF,0x93, 0, 0, 0, 0, 0,0xAD,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x88,0xFF,0xFF,0xFF,0xAC, 0, 0, 0, 0, 0,0xC6,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x63,0xFF,0xFF,0xFF,0xE3,0x02, 0, 0, 0,0x0C,0xF4,0xFF,0xFF,0xFF,0x84, 0,
+ 0,0x28,0xFF,0xFF,0xFF,0xFF,0x4C, 0, 0, 0,0x68,0xFF,0xFF,0xFF,0xFF,0x84, 0,
+ 0, 0,0xCB,0xFF,0xFF,0xFF,0xE5,0x3F,0x08,0x4E,0xF1,0xFF,0xFF,0xFF,0xFF,0x84, 0,
+ 0, 0,0x41,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x84, 0,
+ 0, 0, 0,0x70,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xDD,0xB2,0xFF,0xFF,0xFF,0x84, 0,
+ 0, 0, 0, 0,0x3C,0xB1,0xEB,0xF9,0xDF,0x92,0x12,0xA4,0xFF,0xFF,0xFF,0x7D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xC2,0xFF,0xFF,0xFF,0x6B, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x1F,0xF6,0xFF,0xFF,0xFF,0x3F, 0,
+ 0, 0, 0,0xC7,0x7B,0x3E,0x22,0x0A,0x13,0x47,0xD3,0xFF,0xFF,0xFF,0xED,0x09, 0,
+ 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x76, 0, 0,
+ 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x93,0x01, 0, 0,
+ 0, 0, 0,0x28,0x7B,0xB9,0xD8,0xEF,0xFB,0xEE,0xCD,0x94,0x34, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'h'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90,0x0E,0x89,0xDC,0xF8,0xE9,0xA6,0x23, 0, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x97,0xD0,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x1F, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA1, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xFF,0xA6,0x15,0x1B,0xB5,0xFF,0xFF,0xFF,0xF1,0x01, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xF3,0x0C, 0, 0,0x2C,0xFF,0xFF,0xFF,0xFF,0x1A, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xB2, 0, 0, 0,0x04,0xFE,0xFF,0xFF,0xFF,0x29, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x98, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'i'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xD0,0xFF,0xFF,0xFF,0x58, 0, 0, 0, 0, 0,
+ 0, 0,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,
+ 0, 0,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,
+ 0, 0,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'j'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x50,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0,0x50,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0,0x50,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x1D,0xFF,0xFF,0xFF,0xFF,0x05, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x2D,0xFF,0xFF,0xFF,0xFA, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x61,0xFF,0xFF,0xFF,0xE0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x09,0x42,0xE3,0xFF,0xFF,0xFF,0xAE, 0, 0, 0, 0, 0,
+ 0, 0,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x53, 0, 0, 0, 0, 0,
+ 0, 0,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xAE, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF8,0xFF,0xFF,0xFF,0xFE,0xEE,0xC2,0x67,0x03, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'k'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0, 0, 0,0x0E,0xCF,0xFF,0xFF,0xFF,0xED,0x31,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0, 0,0x07,0xBF,0xFF,0xFF,0xFF,0xED,0x30, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0,0x03,0xAF,0xFF,0xFF,0xFF,0xEC,0x30, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0,0x9C,0xFF,0xFF,0xFF,0xEC,0x2F, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C,0x88,0xFF,0xFF,0xFF,0xEB,0x2E, 0, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0xE9,0xFF,0xFF,0xFF,0xEB,0x2D, 0, 0, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE6,0x0F, 0, 0, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x97, 0, 0, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0xFF,0xE4,0xEB,0xFF,0xFF,0xFE,0x3B, 0, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0xE2,0x22,0x66,0xFF,0xFF,0xFF,0xD5,0x06, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0,0x02,0xCE,0xFF,0xFF,0xFF,0x7D, 0, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0, 0,0x3D,0xFF,0xFF,0xFF,0xF8,0x26, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0, 0, 0,0xA8,0xFF,0xFF,0xFF,0xBF, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0, 0, 0,0x1D,0xF6,0xFF,0xFF,0xFF,0x63, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0, 0, 0, 0,0x7F,0xFF,0xFF,0xFF,0xEE,0x16,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x9C, 0, 0, 0, 0,0x09,0xE1,0xFF,0xFF,0xFF,0xA7,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'l'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x84,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x84,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x84,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x84,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x84,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x84,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x84,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x84,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x84,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x84,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x84,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x84,0xFF,0xFF,0xFF,0xA0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x82,0xFF,0xFF,0xFF,0xA1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x78,0xFF,0xFF,0xFF,0xAF, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5F,0xFF,0xFF,0xFF,0xE1,0x01, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x2C,0xFF,0xFF,0xFF,0xFF,0x95,0x1C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0xD2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7C, 0,
+ 0, 0, 0, 0, 0, 0,0x38,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7C, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x25,0x9A,0xDC,0xF7,0xFF,0xFF,0xFF,0xFF,0x7C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'm'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xD8,0xFF,0xFF,0x35,0x95,0xEC,0xEF,0x9D,0x0D,0x38,0xC6,0xF7,0xE9,0x96,0x0A, 0,
+ 0,0xD8,0xFF,0xFF,0xCC,0xFF,0xFF,0xFF,0xFF,0xB9,0xF1,0xFF,0xFF,0xFF,0xFF,0x93, 0,
+ 0,0xD8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x01,
+ 0,0xD8,0xFF,0xFF,0xE2,0x1B,0x5D,0xFF,0xFF,0xFF,0xD1,0x14,0x76,0xFF,0xFF,0xFF,0x24,
+ 0,0xD8,0xFF,0xFF,0xA2, 0,0x04,0xFC,0xFF,0xFF,0x83, 0,0x1F,0xFF,0xFF,0xFF,0x3F,
+ 0,0xD8,0xFF,0xFF,0x92, 0, 0,0xEE,0xFF,0xFF,0x72, 0,0x0E,0xFF,0xFF,0xFF,0x50,
+ 0,0xD8,0xFF,0xFF,0x90, 0, 0,0xEC,0xFF,0xFF,0x70, 0,0x0C,0xFF,0xFF,0xFF,0x57,
+ 0,0xD8,0xFF,0xFF,0x90, 0, 0,0xEC,0xFF,0xFF,0x70, 0,0x0C,0xFF,0xFF,0xFF,0x5B,
+ 0,0xD8,0xFF,0xFF,0x90, 0, 0,0xEC,0xFF,0xFF,0x70, 0,0x0C,0xFF,0xFF,0xFF,0x5C,
+ 0,0xD8,0xFF,0xFF,0x90, 0, 0,0xEC,0xFF,0xFF,0x70, 0,0x0C,0xFF,0xFF,0xFF,0x5C,
+ 0,0xD8,0xFF,0xFF,0x90, 0, 0,0xEC,0xFF,0xFF,0x70, 0,0x0C,0xFF,0xFF,0xFF,0x5C,
+ 0,0xD8,0xFF,0xFF,0x90, 0, 0,0xEC,0xFF,0xFF,0x70, 0,0x0C,0xFF,0xFF,0xFF,0x5C,
+ 0,0xD8,0xFF,0xFF,0x90, 0, 0,0xEC,0xFF,0xFF,0x70, 0,0x0C,0xFF,0xFF,0xFF,0x5C,
+ 0,0xD8,0xFF,0xFF,0x90, 0, 0,0xEC,0xFF,0xFF,0x70, 0,0x0C,0xFF,0xFF,0xFF,0x5C,
+ 0,0xD8,0xFF,0xFF,0x90, 0, 0,0xEC,0xFF,0xFF,0x70, 0,0x0C,0xFF,0xFF,0xFF,0x5C,
+ 0,0xD8,0xFF,0xFF,0x90, 0, 0,0xEC,0xFF,0xFF,0x70, 0,0x0C,0xFF,0xFF,0xFF,0x5C,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'n'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90,0x10,0x8C,0xDD,0xF8,0xE9,0xA6,0x23, 0, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x99,0xD5,0xFF,0xFF,0xFF,0xFF,0xFF,0xEB,0x1E, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xF4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA0, 0, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xFF,0xA8,0x15,0x1B,0xB5,0xFF,0xFF,0xFF,0xF0,0x01, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xF4,0x0E, 0, 0,0x2C,0xFF,0xFF,0xFF,0xFF,0x1A, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0xB3, 0, 0, 0,0x04,0xFF,0xFF,0xFF,0xFF,0x29, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x98, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0,0x90,0xFF,0xFF,0xFF,0x90, 0, 0, 0, 0,0xF4,0xFF,0xFF,0xFF,0x2C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'o'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x01,0x55,0xAE,0xE4,0xF8,0xEF,0xCD,0x85,0x18, 0, 0, 0, 0,
+ 0, 0, 0,0x16,0xC4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF4,0x5A, 0, 0, 0,
+ 0, 0,0x0A,0xD5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x55, 0, 0,
+ 0, 0,0x8E,0xFF,0xFF,0xFF,0xED,0x51,0x09,0x23,0xB0,0xFF,0xFF,0xFF,0xF0,0x12, 0,
+ 0,0x0F,0xF4,0xFF,0xFF,0xFF,0x4D, 0, 0, 0,0x06,0xD6,0xFF,0xFF,0xFF,0x7A, 0,
+ 0,0x4F,0xFF,0xFF,0xFF,0xDD, 0, 0, 0, 0, 0,0x6B,0xFF,0xFF,0xFF,0xC5, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xA4, 0, 0, 0, 0, 0,0x32,0xFF,0xFF,0xFF,0xF6, 0,
+ 0,0x93,0xFF,0xFF,0xFF,0x8D, 0, 0, 0, 0, 0,0x1A,0xFF,0xFF,0xFF,0xFF,0x0A,
+ 0,0x94,0xFF,0xFF,0xFF,0x8D, 0, 0, 0, 0, 0,0x1B,0xFF,0xFF,0xFF,0xFF,0x0A,
+ 0,0x80,0xFF,0xFF,0xFF,0xA4, 0, 0, 0, 0, 0,0x32,0xFF,0xFF,0xFF,0xF7, 0,
+ 0,0x4F,0xFF,0xFF,0xFF,0xDD, 0, 0, 0, 0, 0,0x6B,0xFF,0xFF,0xFF,0xC5, 0,
+ 0,0x0F,0xF4,0xFF,0xFF,0xFF,0x4B, 0, 0, 0,0x05,0xD5,0xFF,0xFF,0xFF,0x7A, 0,
+ 0, 0,0x8F,0xFF,0xFF,0xFF,0xEB,0x4F,0x08,0x22,0xAE,0xFF,0xFF,0xFF,0xF1,0x12, 0,
+ 0, 0,0x0B,0xD5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x55, 0, 0,
+ 0, 0, 0,0x16,0xC5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF5,0x5A, 0, 0, 0,
+ 0, 0, 0, 0,0x01,0x56,0xB0,0xE5,0xF9,0xF0,0xCE,0x86,0x19, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'p'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44,0x1D,0x9A,0xE3,0xF8,0xE2,0x9A,0x1D, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x6A,0xEB,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x33, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE1,0x09, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0xFF,0xB7,0x21,0x0E,0x7D,0xFF,0xFF,0xFF,0xFF,0x6B, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0xEA,0x0C, 0, 0, 0,0xAB,0xFF,0xFF,0xFF,0xC2, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x92, 0, 0, 0, 0,0x47,0xFF,0xFF,0xFF,0xF5,0x02,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x5E, 0, 0, 0, 0,0x13,0xFF,0xFF,0xFF,0xFF,0x1A,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x49, 0, 0, 0, 0, 0,0xFD,0xFF,0xFF,0xFF,0x29,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x48, 0, 0, 0, 0, 0,0xFD,0xFF,0xFF,0xFF,0x28,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x5E, 0, 0, 0, 0,0x13,0xFF,0xFF,0xFF,0xFF,0x1A,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x92, 0, 0, 0, 0,0x46,0xFF,0xFF,0xFF,0xF5,0x02,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0xEA,0x0C, 0, 0, 0,0xAB,0xFF,0xFF,0xFF,0xC2, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0xFF,0xB7,0x20,0x0D,0x7C,0xFF,0xFF,0xFF,0xFF,0x6B, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x08, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x6A,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xEE,0x31, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44,0x1C,0x9E,0xE7,0xF9,0xDF,0x95,0x1A, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'q'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x01,0x63,0xC8,0xF2,0xF1,0xC4,0x56, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0,0x02,0xA9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x87,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0,0x72,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF4,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0x06,0xED,0xFF,0xFF,0xFF,0xD0,0x2D,0x0A,0x62,0xFA,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0x4A,0xFF,0xFF,0xFF,0xFB,0x23, 0, 0, 0,0x83,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0x80,0xFF,0xFF,0xFF,0xBA, 0, 0, 0, 0,0x1D,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0xA3,0xFF,0xFF,0xFF,0x86, 0, 0, 0, 0, 0,0xE8,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0xB1,0xFF,0xFF,0xFF,0x71, 0, 0, 0, 0, 0,0xD2,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0xB2,0xFF,0xFF,0xFF,0x70, 0, 0, 0, 0, 0,0xD2,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0xA3,0xFF,0xFF,0xFF,0x86, 0, 0, 0, 0, 0,0xE8,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0x81,0xFF,0xFF,0xFF,0xBA, 0, 0, 0, 0,0x1C,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0x4B,0xFF,0xFF,0xFF,0xFB,0x23, 0, 0, 0,0x83,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0,0x07,0xEF,0xFF,0xFF,0xFF,0xCF,0x2C,0x09,0x61,0xFA,0xFF,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0,0x74,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0,0x02,0xA8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x87,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0,0x5E,0xC3,0xF0,0xF5,0xC8,0x58, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xCC,0xFF,0xFF,0xFF,0x54, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'r'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0x44,0x0B,0x79,0xCD,0xF0,0xF7,0xC9,0x60,0x05,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0x5B,0xD8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x4C,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x4C,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0xFF,0xF8,0x80,0x27,0x08,0x1B,0x6F,0xF2,0x4C,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0xFC,0x42, 0, 0, 0, 0, 0,0x2F,0x3E,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0xA8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0x66, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0x4E, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0x46, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0xE0,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 's'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x12,0x79,0xC3,0xEC,0xFB,0xEE,0xD6,0xB5,0x70,0x26, 0, 0, 0,
+ 0, 0, 0,0x3A,0xEB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0,
+ 0, 0,0x10,0xEA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x08, 0, 0,
+ 0, 0,0x63,0xFF,0xFF,0xFF,0xD0,0x3A,0x0C,0x09,0x23,0x40,0x85,0xD6,0x07, 0, 0,
+ 0, 0,0x88,0xFF,0xFF,0xFF,0x73, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x7F,0xFF,0xFF,0xFF,0xF3,0x7B,0x22, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3D,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE1,0xA2,0x5B,0x0A, 0, 0, 0, 0,
+ 0, 0, 0,0xA6,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xED,0x5B, 0, 0, 0,
+ 0, 0, 0,0x03,0x78,0xEC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x52, 0, 0,
+ 0, 0, 0, 0, 0,0x06,0x46,0x88,0xC5,0xF9,0xFF,0xFF,0xFF,0xFF,0xD3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x0C,0x6F,0xFE,0xFF,0xFF,0xFF,0x0C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0xDC,0xFF,0xFF,0xFF,0x14, 0,
+ 0, 0,0x4C,0xC7,0x83,0x44,0x27,0x10,0x05,0x1D,0x76,0xFE,0xFF,0xFF,0xF1,0x02, 0,
+ 0, 0,0x50,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x95, 0, 0,
+ 0, 0,0x50,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC1,0x0E, 0, 0,
+ 0, 0,0x03,0x33,0x72,0xAF,0xD1,0xE7,0xFA,0xF6,0xDE,0xAE,0x58,0x02, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 't'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x60,0xFF,0xFF,0xFF,0xC4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x60,0xFF,0xFF,0xFF,0xC4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x60,0xFF,0xFF,0xFF,0xC4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x60,0xFF,0xFF,0xFF,0xC4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x60,0xFF,0xFF,0xFF,0xC4, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x30, 0,
+ 0,0x6C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x30, 0,
+ 0,0x6C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x30, 0,
+ 0, 0, 0, 0, 0,0x60,0xFF,0xFF,0xFF,0xC4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x60,0xFF,0xFF,0xFF,0xC4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x60,0xFF,0xFF,0xFF,0xC4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x60,0xFF,0xFF,0xFF,0xC4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x60,0xFF,0xFF,0xFF,0xC4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x60,0xFF,0xFF,0xFF,0xC4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x60,0xFF,0xFF,0xFF,0xC4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x5F,0xFF,0xFF,0xFF,0xC4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x55,0xFF,0xFF,0xFF,0xD9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x37,0xFF,0xFF,0xFF,0xFF,0x6A,0x0F, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x07,0xED,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x30, 0,
+ 0, 0, 0, 0, 0, 0,0x6A,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x30, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x41,0xA4,0xD8,0xF3,0xFD,0xFF,0xFF,0xFF,0x30, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'u'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xBC,0xFF,0xFF,0xFF,0x6C, 0, 0, 0,0x20,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0xBC,0xFF,0xFF,0xFF,0x6C, 0, 0, 0,0x20,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0xBC,0xFF,0xFF,0xFF,0x6C, 0, 0, 0,0x20,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0xBC,0xFF,0xFF,0xFF,0x6C, 0, 0, 0,0x20,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0xBC,0xFF,0xFF,0xFF,0x6C, 0, 0, 0,0x20,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0xBC,0xFF,0xFF,0xFF,0x6C, 0, 0, 0,0x20,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0xBC,0xFF,0xFF,0xFF,0x6C, 0, 0, 0,0x20,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0xBC,0xFF,0xFF,0xFF,0x6C, 0, 0, 0,0x20,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0xBC,0xFF,0xFF,0xFF,0x6C, 0, 0, 0,0x20,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0xBC,0xFF,0xFF,0xFF,0x6C, 0, 0, 0,0x28,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0xB9,0xFF,0xFF,0xFF,0x7A, 0, 0, 0,0x43,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0xAC,0xFF,0xFF,0xFF,0xA3, 0, 0, 0,0x91,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0x83,0xFF,0xFF,0xFF,0xF5,0x4A,0x0E,0x59,0xF8,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0,0x32,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF6,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0, 0,0x9B,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0x75,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0, 0,0x02,0x72,0xD4,0xF8,0xEE,0xBA,0x44,0x20,0xFF,0xFF,0xFF,0xFF,0x08, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'v'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xB4,0xFF,0xFF,0xFF,0x7A, 0, 0, 0, 0, 0,0x0A,0xF8,0xFF,0xFF,0xFF,0x2B,
+ 0,0x64,0xFF,0xFF,0xFF,0xBF, 0, 0, 0, 0, 0,0x49,0xFF,0xFF,0xFF,0xDA, 0,
+ 0,0x16,0xFD,0xFF,0xFF,0xF9,0x0B, 0, 0, 0, 0,0x8F,0xFF,0xFF,0xFF,0x89, 0,
+ 0, 0,0xC3,0xFF,0xFF,0xFF,0x49, 0, 0, 0, 0,0xD5,0xFF,0xFF,0xFF,0x38, 0,
+ 0, 0,0x72,0xFF,0xFF,0xFF,0x8F, 0, 0, 0,0x1B,0xFF,0xFF,0xFF,0xE6,0x01, 0,
+ 0, 0,0x21,0xFF,0xFF,0xFF,0xD4, 0, 0, 0,0x61,0xFF,0xFF,0xFF,0x97, 0, 0,
+ 0, 0, 0,0xD1,0xFF,0xFF,0xFF,0x1A, 0, 0,0xA6,0xFF,0xFF,0xFF,0x46, 0, 0,
+ 0, 0, 0,0x81,0xFF,0xFF,0xFF,0x5E, 0,0x01,0xEA,0xFF,0xFF,0xF0,0x05, 0, 0,
+ 0, 0, 0,0x30,0xFF,0xFF,0xFF,0xA3, 0,0x32,0xFF,0xFF,0xFF,0xA5, 0, 0, 0,
+ 0, 0, 0, 0,0xDF,0xFF,0xFF,0xE7,0x01,0x78,0xFF,0xFF,0xFF,0x54, 0, 0, 0,
+ 0, 0, 0, 0,0x8F,0xFF,0xFF,0xFF,0x2E,0xBE,0xFF,0xFF,0xF7,0x0C, 0, 0, 0,
+ 0, 0, 0, 0,0x3F,0xFF,0xFF,0xFF,0x7E,0xF8,0xFF,0xFF,0xB2, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x03,0xEA,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0x62, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x9E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0x14, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x4D,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x08,0xF4,0xFF,0xFF,0xFF,0xFF,0x70, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'w'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0xE9,0xFF,0xFF,0x87, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x13,0xFF,0xFF,0xFF,
+0xBC,0xFF,0xFF,0xAF, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x3C,0xFF,0xFF,0xFF,
+0x8E,0xFF,0xFF,0xD6, 0, 0, 0, 0, 0, 0, 0, 0, 0,0x64,0xFF,0xFF,0xFA,
+0x60,0xFF,0xFF,0xFA,0x04, 0, 0, 0, 0, 0, 0, 0, 0,0x8C,0xFF,0xFF,0xD2,
+0x32,0xFF,0xFF,0xFF,0x26, 0,0x10,0xFE,0xFF,0xFF,0x81, 0, 0,0xB4,0xFF,0xFF,0xA4,
+0x07,0xFB,0xFF,0xFF,0x4D, 0,0x44,0xFF,0xFF,0xFF,0xB6, 0, 0,0xDC,0xFF,0xFF,0x76,
+ 0,0xD6,0xFF,0xFF,0x75, 0,0x79,0xFF,0xFF,0xFF,0xEB, 0,0x07,0xFC,0xFF,0xFF,0x48,
+ 0,0xA8,0xFF,0xFF,0x9D, 0,0xAE,0xFF,0xF4,0xFF,0xFF,0x1F,0x2C,0xFF,0xFF,0xFF,0x1A,
+ 0,0x7A,0xFF,0xFF,0xC4, 0,0xE3,0xFF,0x93,0xFE,0xFF,0x54,0x54,0xFF,0xFF,0xEC, 0,
+ 0,0x4C,0xFF,0xFF,0xEC,0x18,0xFF,0xFF,0x47,0xD6,0xFF,0x89,0x7C,0xFF,0xFF,0xBE, 0,
+ 0,0x1E,0xFF,0xFF,0xFF,0x62,0xFF,0xFE,0x10,0x9B,0xFF,0xBD,0xA4,0xFF,0xFF,0x90, 0,
+ 0, 0,0xEF,0xFF,0xFF,0xBF,0xFF,0xD4, 0,0x61,0xFF,0xF1,0xCD,0xFF,0xFF,0x62, 0,
+ 0, 0,0xC2,0xFF,0xFF,0xFE,0xFF,0x9A, 0,0x26,0xFF,0xFF,0xFE,0xFF,0xFF,0x34, 0,
+ 0, 0,0x94,0xFF,0xFF,0xFF,0xFF,0x60, 0, 0,0xEA,0xFF,0xFF,0xFF,0xFD,0x09, 0,
+ 0, 0,0x66,0xFF,0xFF,0xFF,0xFF,0x26, 0, 0,0xB0,0xFF,0xFF,0xFF,0xD8, 0, 0,
+ 0, 0,0x37,0xFF,0xFF,0xFF,0xEC, 0, 0, 0,0x75,0xFF,0xFF,0xFF,0xAA, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'x'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x66,0xFF,0xFF,0xFF,0xFF,0x5E, 0, 0, 0,0x07,0xDF,0xFF,0xFF,0xFF,0xD5,0x08,
+ 0, 0,0xB1,0xFF,0xFF,0xFF,0xE2,0x08, 0, 0,0x76,0xFF,0xFF,0xFF,0xFA,0x31, 0,
+ 0, 0,0x15,0xE8,0xFF,0xFF,0xFF,0x78, 0,0x14,0xF0,0xFF,0xFF,0xFF,0x78, 0, 0,
+ 0, 0, 0,0x4A,0xFF,0xFF,0xFF,0xF1,0x14,0x94,0xFF,0xFF,0xFF,0xC3,0x02, 0, 0,
+ 0, 0, 0, 0,0x95,0xFF,0xFF,0xFF,0xB1,0xFB,0xFF,0xFF,0xF2,0x21, 0, 0, 0,
+ 0, 0, 0, 0,0x09,0xD7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x60, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x32,0xFA,0xFF,0xFF,0xFF,0xFF,0xAE, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x8D,0xFF,0xFF,0xFF,0xFA,0x16, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x10,0xE2,0xFF,0xFF,0xFF,0xFF,0x76, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xA7,0xFF,0xFF,0xFF,0xFF,0xFF,0xF9,0x2E, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xE9,0xFF,0xFF,0xFF,0xD3,0x07, 0, 0, 0,
+ 0, 0, 0,0x1E,0xF0,0xFF,0xFF,0xFE,0x37,0xC3,0xFF,0xFF,0xFF,0x8D, 0, 0, 0,
+ 0, 0,0x02,0xC0,0xFF,0xFF,0xFF,0xA1, 0,0x32,0xFD,0xFF,0xFF,0xFE,0x41, 0, 0,
+ 0, 0,0x77,0xFF,0xFF,0xFF,0xF4,0x1A, 0, 0,0x9B,0xFF,0xFF,0xFF,0xE1,0x0F, 0,
+ 0,0x30,0xF9,0xFF,0xFF,0xFF,0x7B, 0, 0, 0,0x16,0xF0,0xFF,0xFF,0xFF,0xA4, 0,
+0x08,0xD5,0xFF,0xFF,0xFF,0xE0,0x08, 0, 0, 0, 0,0x72,0xFF,0xFF,0xFF,0xFF,0x56,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'y'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+0x0A,0xF0,0xFF,0xFF,0xFF,0x60, 0, 0, 0, 0, 0, 0,0xDE,0xFF,0xFF,0xFF,0x78,
+ 0,0x97,0xFF,0xFF,0xFF,0xB9, 0, 0, 0, 0, 0,0x34,0xFF,0xFF,0xFF,0xFD,0x1C,
+ 0,0x34,0xFF,0xFF,0xFF,0xFC,0x16, 0, 0, 0, 0,0x8A,0xFF,0xFF,0xFF,0xBB, 0,
+ 0, 0,0xD0,0xFF,0xFF,0xFF,0x6C, 0, 0, 0, 0,0xDE,0xFF,0xFF,0xFF,0x5C, 0,
+ 0, 0,0x6D,0xFF,0xFF,0xFF,0xC5, 0, 0, 0,0x35,0xFF,0xFF,0xFF,0xF3,0x0A, 0,
+ 0, 0,0x11,0xF7,0xFF,0xFF,0xFE,0x1F, 0, 0,0x8A,0xFF,0xFF,0xFF,0x9F, 0, 0,
+ 0, 0, 0,0xA6,0xFF,0xFF,0xFF,0x78, 0, 0,0xDE,0xFF,0xFF,0xFF,0x40, 0, 0,
+ 0, 0, 0,0x43,0xFF,0xFF,0xFF,0xD1, 0,0x35,0xFF,0xFF,0xFF,0xE0,0x01, 0, 0,
+ 0, 0, 0,0x01,0xDE,0xFF,0xFF,0xFF,0x2A,0x8B,0xFF,0xFF,0xFF,0x83, 0, 0, 0,
+ 0, 0, 0, 0,0x7C,0xFF,0xFF,0xFF,0x84,0xDF,0xFF,0xFF,0xFF,0x25, 0, 0, 0,
+ 0, 0, 0, 0,0x1C,0xFC,0xFF,0xFF,0xF2,0xFF,0xFF,0xFF,0xC6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0xB5,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x67, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x52,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,0x10, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x05,0xE9,0xFF,0xFF,0xFF,0xFF,0xAA, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x8B,0xFF,0xFF,0xFF,0xFF,0x4C, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x39,0xFF,0xFF,0xFF,0xE9,0x04, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x77,0xFF,0xFF,0xFF,0x8E, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x06,0xE0,0xFF,0xFF,0xFF,0x30, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x03,0x21,0xA3,0xFF,0xFF,0xFF,0xC6, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x34,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x44, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x34,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x8B, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x34,0xFF,0xFF,0xFF,0xF3,0xC9,0x56, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// 'z'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x5C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x50, 0,
+ 0, 0,0x5C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x50, 0,
+ 0, 0,0x5C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x50, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0x06,0xC0,0xFF,0xFF,0xFF,0xF3,0x26, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,0xA2,0xFF,0xFF,0xFF,0xFC,0x4A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x80,0xFF,0xFF,0xFF,0xFF,0x6B, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x5C,0xFF,0xFF,0xFF,0xFF,0x8E, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3E,0xF9,0xFF,0xFF,0xFF,0xB0,0x02, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x27,0xED,0xFF,0xFF,0xFF,0xCB,0x0A, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x14,0xDC,0xFF,0xFF,0xFF,0xE1,0x18, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x08,0xC5,0xFF,0xFF,0xFF,0xF1,0x2C, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x01,0xA9,0xFF,0xFF,0xFF,0xFB,0x46, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x7D,0xFF,0xFF,0xFF,0xFF,0x66, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x50, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x50, 0,
+ 0, 0,0xB4,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x50, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '{'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x31,0x9C,0xD3,0xF1,0xFC,0xFF,0xE8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x40,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xE8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE8, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x02,0xF6,0xFF,0xFF,0xFF,0x6D,0x15, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x14,0xFF,0xFF,0xFF,0xD8, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x1E,0xFF,0xFF,0xFF,0xB9, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x20,0xFF,0xFF,0xFF,0xB4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x20,0xFF,0xFF,0xFF,0xB4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x22,0xFF,0xFF,0xFF,0xB3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x36,0xFF,0xFF,0xFF,0xAD, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x77,0xFF,0xFF,0xFF,0x97, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x02,0x17,0x63,0xF3,0xFF,0xFF,0xFF,0x5A, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB6,0x04, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x80,0xFF,0xFF,0xFF,0xFF,0xF3,0x7E,0x01, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB3,0x03, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x02,0x18,0x66,0xF4,0xFF,0xFF,0xFF,0x56, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x79,0xFF,0xFF,0xFF,0x96, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x36,0xFF,0xFF,0xFF,0xAD, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x22,0xFF,0xFF,0xFF,0xB3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x20,0xFF,0xFF,0xFF,0xB4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x20,0xFF,0xFF,0xFF,0xB4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x1E,0xFF,0xFF,0xFF,0xBA, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x14,0xFF,0xFF,0xFF,0xD8, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x02,0xF5,0xFF,0xFF,0xFF,0x6D,0x14, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xBB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x40,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xE8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x32,0x9D,0xD5,0xF2,0xFC,0xFF,0xE8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '|'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0xE4,0xFF,0xFF,0x54, 0, 0, 0, 0, 0, 0,
+// '}'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x74,0xFF,0xFF,0xF6,0xE4,0xB9,0x66,0x03, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x74,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA8, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x74,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x28, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x08,0x35,0xD4,0xFF,0xFF,0xFF,0x64, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x65,0xFF,0xFF,0xFF,0x7F, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x46,0xFF,0xFF,0xFF,0x8A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x40,0xFF,0xFF,0xFF,0x8C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x40,0xFF,0xFF,0xFF,0x8C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x40,0xFF,0xFF,0xFF,0x8E, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3B,0xFF,0xFF,0xFF,0xA1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x24,0xFF,0xFF,0xFF,0xE0,0x04, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x01,0xE6,0xFF,0xFF,0xFF,0xAA,0x30,0x08, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x54,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,0x33,0xD0,0xFF,0xFF,0xFF,0xFF,0xF8, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,0x4F,0xF6,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x01,0xE4,0xFF,0xFF,0xFF,0xAD,0x32,0x09, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x23,0xFF,0xFF,0xFF,0xE1,0x04, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x3B,0xFF,0xFF,0xFF,0xA1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x40,0xFF,0xFF,0xFF,0x8E, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x40,0xFF,0xFF,0xFF,0x8C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x40,0xFF,0xFF,0xFF,0x8C, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x47,0xFF,0xFF,0xFF,0x8A, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,0x67,0xFF,0xFF,0xFF,0x7F, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x08,0x34,0xD5,0xFF,0xFF,0xFF,0x63, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x74,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x27, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x74,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xA8, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x74,0xFF,0xFF,0xF7,0xE5,0xBA,0x68,0x03, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// '~'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x1B,0x93,0xDF,0xF8,0xE1,0xAA,0x46, 0, 0, 0, 0, 0, 0,0x65,0x34,
+ 0,0x50,0xF2,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCC,0x5F,0x1D,0x09,0x3A,0xAD,0xFF,0x38,
+ 0,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,
+ 0,0xC0,0xE5,0x69,0x1C,0x08,0x28,0x6E,0xDA,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xB3,0x0C,
+ 0,0x7C,0x0F, 0, 0, 0, 0, 0,0x02,0x51,0xB7,0xEC,0xF3,0xC3,0x5B,0x01, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+// Small
+// ' '
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '!'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xB4,0xFF,0x20, 0, 0,
+ 0, 0, 0,0xB4,0xFF,0x20, 0, 0,
+ 0, 0, 0,0xB4,0xFF,0x20, 0, 0,
+ 0, 0, 0,0xB4,0xFF,0x20, 0, 0,
+ 0, 0, 0,0xB1,0xFF,0x1D, 0, 0,
+ 0, 0, 0,0x9B,0xFF,0x09, 0, 0,
+ 0, 0, 0,0x81,0xF3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xB4,0xFF,0x20, 0, 0,
+ 0, 0, 0,0xB4,0xFF,0x20, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '"'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x6C,0xFF,0x54, 0,0xEC,0xD4, 0,
+ 0,0x6C,0xFF,0x54, 0,0xEC,0xD4, 0,
+ 0,0x6C,0xFF,0x54, 0,0xEC,0xD4, 0,
+ 0,0x6C,0xFF,0x54, 0,0xEC,0xD4, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '#'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xCC,0xB8, 0,0xE4,0xA2,
+ 0, 0,0x08,0xFA,0x81,0x1A,0xFF,0x69,
+ 0, 0,0x39,0xFF,0x4B,0x51,0xFF,0x30,
+0x34,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0, 0,0xD5,0xAE,0x01,0xEB,0x97, 0,
+ 0,0x15,0xFE,0x6C,0x2C,0xFF,0x57, 0,
+0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x9C,
+ 0,0xB0,0xD4, 0,0xC4,0xBF, 0, 0,
+ 0,0xE6,0x9D,0x04,0xF5,0x87, 0, 0,
+0x1D,0xFF,0x67,0x31,0xFF,0x4F, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '$'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x38,0xC0, 0, 0, 0,
+ 0, 0, 0,0x38,0xC0, 0, 0, 0,
+ 0,0x18,0xAB,0xF0,0xFF,0xFF,0xD4, 0,
+ 0,0xAB,0xFD,0x66,0xC2,0x38,0x95, 0,
+ 0,0xD3,0xFD,0x55,0xC0, 0, 0, 0,
+ 0,0x81,0xFF,0xFB,0xE9,0x76,0x0E, 0,
+ 0, 0,0x56,0xBA,0xFF,0xFF,0xD7,0x09,
+ 0, 0, 0,0x38,0xC1,0xA5,0xFF,0x59,
+ 0,0x68, 0,0x38,0xC0,0x67,0xFF,0x6A,
+ 0,0xD4,0x95,0x4A,0xC3,0xAB,0xFB,0x29,
+ 0,0x2F,0xAC,0xEE,0xFE,0xD6,0x51, 0,
+ 0, 0, 0,0x38,0xC0, 0, 0, 0,
+ 0, 0, 0,0x38,0xC0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '%'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x20,0xC4,0xF4,0xAD,0x0B, 0, 0, 0,
+0xA9,0xAA,0x11,0xD3,0x79, 0, 0, 0,
+0xAA,0xA9,0x10,0xD2,0x79, 0, 0, 0,
+0x21,0xC6,0xF4,0xAF,0x0C,0x0A,0x6F,0x8F,
+ 0, 0, 0,0x0D,0x77,0x9D,0x37, 0,
+ 0,0x11,0x7D,0x99,0x2F, 0, 0, 0,
+0x2F,0x94,0x28, 0,0x47,0xDD,0xEE,0x7C,
+ 0, 0, 0, 0,0xE9,0x6A,0x2A,0xFB,
+ 0, 0, 0, 0,0xEA,0x68,0x28,0xFB,
+ 0, 0, 0, 0,0x49,0xDE,0xEF,0x80,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '&'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x02,0x89,0xE4,0xF6,0x9A,0x09, 0,
+ 0,0x59,0xFF,0x9A,0x0C,0x5D,0x45, 0,
+ 0,0x6E,0xFF,0x9F, 0, 0, 0, 0,
+ 0,0x1B,0xF7,0xF7,0x1F, 0, 0, 0,
+ 0,0x8A,0xFF,0xFF,0xB2, 0, 0, 0,
+0x5B,0xFF,0xA9,0xBF,0xFF,0x55,0x45,0xFF,
+0xAF,0xFF,0x2E,0x2B,0xFB,0xE7,0x65,0xFF,
+0xA6,0xFF,0x36, 0,0x8D,0xFF,0xF7,0xEF,
+0x47,0xFE,0xC1,0x1C,0x2D,0xFC,0xFF,0x85,
+ 0,0x51,0xCD,0xF6,0xF1,0xC4,0xF5,0xE5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '''
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xAC,0xFF,0x14, 0, 0,
+ 0, 0, 0,0xAC,0xFF,0x14, 0, 0,
+ 0, 0, 0,0xAC,0xFF,0x14, 0, 0,
+ 0, 0, 0,0xAC,0xFF,0x14, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '('
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,0x8D,0xF6,0x18, 0,
+ 0, 0, 0,0x2B,0xFC,0x92, 0, 0,
+ 0, 0, 0,0xA0,0xFF,0x2F, 0, 0,
+ 0, 0,0x06,0xF5,0xE1, 0, 0, 0,
+ 0, 0,0x39,0xFF,0xAD, 0, 0, 0,
+ 0, 0,0x55,0xFF,0x95, 0, 0, 0,
+ 0, 0,0x56,0xFF,0x95, 0, 0, 0,
+ 0, 0,0x3A,0xFF,0xAE, 0, 0, 0,
+ 0, 0,0x07,0xF7,0xE2, 0, 0, 0,
+ 0, 0, 0,0xA3,0xFF,0x30, 0, 0,
+ 0, 0, 0,0x2D,0xFC,0x93, 0, 0,
+ 0, 0, 0, 0,0x8D,0xF6,0x18, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// ')'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xA3,0xE9,0x12, 0, 0, 0,
+ 0, 0,0x25,0xFE,0x97, 0, 0, 0,
+ 0, 0, 0,0xC0,0xF8,0x17, 0, 0,
+ 0, 0, 0,0x72,0xFF,0x6B, 0, 0,
+ 0, 0, 0,0x3D,0xFF,0xA8, 0, 0,
+ 0, 0, 0,0x25,0xFF,0xC4, 0, 0,
+ 0, 0, 0,0x26,0xFF,0xC4, 0, 0,
+ 0, 0, 0,0x3E,0xFF,0xA8, 0, 0,
+ 0, 0, 0,0x73,0xFF,0x6B, 0, 0,
+ 0, 0, 0,0xC1,0xF8,0x17, 0, 0,
+ 0, 0,0x26,0xFE,0x98, 0, 0, 0,
+ 0, 0,0xA3,0xEA,0x12, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '*'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x64,0xC8, 0, 0, 0,
+0x08,0xC9,0x68,0x69,0xC8,0x35,0xB6,0x55,
+ 0,0x38,0xB6,0xF9,0xFA,0xE1,0x6B,0x07,
+ 0,0x38,0xB5,0xF8,0xF9,0xE1,0x6A,0x07,
+0x08,0xC9,0x67,0x69,0xC8,0x33,0xB6,0x55,
+ 0, 0, 0,0x64,0xC8, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '+'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x98,0xFF,0x08, 0, 0,
+ 0, 0, 0,0x98,0xFF,0x08, 0, 0,
+ 0, 0, 0,0x98,0xFF,0x08, 0, 0,
+0x8C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,
+0x8C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,
+ 0, 0, 0,0x98,0xFF,0x08, 0, 0,
+ 0, 0, 0,0x98,0xFF,0x08, 0, 0,
+ 0, 0, 0,0x98,0xFF,0x08, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// ','
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xD8,0xFF,0x4C, 0, 0,
+ 0, 0, 0,0xDC,0xFF,0x43, 0, 0,
+ 0, 0,0x18,0xFE,0xCD,0x02, 0, 0,
+ 0, 0,0x62,0xFF,0x3D, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '-'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xF0,0xFF,0xFF,0xFF,0x60, 0,
+ 0, 0,0xF0,0xFF,0xFF,0xFF,0x60, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '.'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF0,0xFF,0x58, 0, 0,
+ 0, 0, 0,0xF0,0xFF,0x58, 0, 0,
+ 0, 0, 0,0xF0,0xFF,0x58, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '/'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x1B,0xFA,0x6E,
+ 0, 0, 0, 0, 0,0x88,0xEF,0x0C,
+ 0, 0, 0, 0,0x0C,0xEF,0x88, 0,
+ 0, 0, 0, 0,0x6E,0xFA,0x1B, 0,
+ 0, 0, 0,0x02,0xDD,0xA3, 0, 0,
+ 0, 0, 0,0x53,0xFF,0x31, 0, 0,
+ 0, 0, 0,0xC6,0xBE, 0, 0, 0,
+ 0, 0,0x38,0xFF,0x4B, 0, 0, 0,
+ 0, 0,0xAB,0xD7,0x01, 0, 0, 0,
+ 0,0x20,0xFC,0x66, 0, 0, 0, 0,
+ 0,0x90,0xEA,0x08, 0, 0, 0, 0,
+0x0F,0xF3,0x81, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '0'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x01,0x81,0xE7,0xF7,0xBD,0x25, 0,
+ 0,0x6F,0xFF,0x80,0x26,0xF0,0xD9,0x04,
+ 0,0xD9,0xFF,0x10, 0,0xA3,0xFF,0x48,
+0x0D,0xFF,0xEE, 0, 0,0x80,0xFF,0x7C,
+0x22,0xFF,0xE2,0x6B,0xD3,0x74,0xFF,0x92,
+0x23,0xFF,0xE2,0x6D,0xD5,0x74,0xFF,0x91,
+0x0D,0xFF,0xEE, 0, 0,0x80,0xFF,0x7C,
+ 0,0xD9,0xFF,0x10, 0,0xA3,0xFF,0x49,
+ 0,0x6F,0xFF,0x80,0x26,0xF0,0xDB,0x05,
+ 0,0x01,0x82,0xE8,0xF8,0xBE,0x26, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '1'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x13,0x80,0xED,0xFF,0x80, 0, 0,
+ 0,0x7C,0x7F,0x86,0xFF,0x80, 0, 0,
+ 0, 0, 0,0x74,0xFF,0x80, 0, 0,
+ 0, 0, 0,0x74,0xFF,0x80, 0, 0,
+ 0, 0, 0,0x74,0xFF,0x80, 0, 0,
+ 0, 0, 0,0x74,0xFF,0x80, 0, 0,
+ 0, 0, 0,0x74,0xFF,0x80, 0, 0,
+ 0, 0, 0,0x74,0xFF,0x80, 0, 0,
+ 0, 0, 0,0x74,0xFF,0x80, 0, 0,
+ 0,0xB8,0xFF,0xFF,0xFF,0xFF,0xFF,0xC4,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '2'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x41,0xBA,0xF6,0xE6,0xA2,0x1A, 0,
+ 0,0xBD,0x41,0x08,0x49,0xFC,0xCF,0x02,
+ 0, 0, 0, 0, 0,0xD8,0xFF,0x29,
+ 0, 0, 0, 0,0x0C,0xF8,0xFF,0x27,
+ 0, 0, 0, 0,0x8A,0xFF,0xD9,0x02,
+ 0, 0, 0,0x4D,0xFE,0xFA,0x3D, 0,
+ 0, 0,0x2B,0xF2,0xFD,0x59, 0, 0,
+ 0,0x13,0xDD,0xFF,0x67, 0, 0, 0,
+0x05,0xC1,0xFF,0x72, 0, 0, 0, 0,
+0x37,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x44,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '3'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x30,0xAF,0xF4,0xED,0xBB,0x38, 0,
+ 0,0xA7,0x4D,0x09,0x32,0xF0,0xF2,0x12,
+ 0, 0, 0, 0, 0,0xB6,0xFF,0x3B,
+ 0, 0, 0,0x01,0x2F,0xEC,0xDF,0x0C,
+ 0, 0,0x54,0xFF,0xFF,0xD7,0x29, 0,
+ 0, 0, 0,0x01,0x33,0xE7,0xE9,0x18,
+ 0, 0, 0, 0, 0,0x85,0xFF,0x6E,
+ 0, 0, 0, 0, 0,0x7B,0xFF,0x6E,
+0x22,0xA6,0x37,0x0D,0x2B,0xDF,0xF5,0x25,
+0x01,0x57,0xC5,0xF2,0xEC,0xBC,0x3E, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '4'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x04,0xC8,0xFF,0xAC, 0,
+ 0, 0, 0,0x88,0xFF,0xFF,0xAC, 0,
+ 0, 0,0x44,0xFE,0xC0,0xFF,0xAC, 0,
+ 0,0x15,0xE7,0xD1,0x45,0xFF,0xAC, 0,
+0x01,0xB6,0xFB,0x31,0x40,0xFF,0xAC, 0,
+0x43,0xFF,0x81, 0,0x40,0xFF,0xAC, 0,
+0x4C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCC,
+ 0, 0, 0, 0,0x40,0xFF,0xAC, 0,
+ 0, 0, 0, 0,0x40,0xFF,0xAC, 0,
+ 0, 0, 0, 0,0x40,0xFF,0xAC, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '5'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xB0,0xFF,0xFF,0xFF,0xFF,0xDC, 0,
+ 0,0xB0,0xF4, 0, 0, 0, 0, 0,
+ 0,0xB0,0xF4, 0, 0, 0, 0, 0,
+ 0,0xB0,0xFE,0xF4,0xEC,0xAC,0x1C, 0,
+ 0,0x86,0x44,0x0E,0x5A,0xFC,0xD7,0x07,
+ 0, 0, 0, 0, 0,0xAA,0xFF,0x50,
+ 0, 0, 0, 0, 0,0x85,0xFF,0x73,
+ 0, 0, 0, 0, 0,0xA7,0xFF,0x57,
+0x03,0xAA,0x2D,0x0C,0x57,0xFA,0xDB,0x08,
+ 0,0x49,0xC2,0xF3,0xE1,0x9B,0x17, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '6'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x43,0xC2,0xF4,0xE1,0x65, 0,
+ 0,0x3E,0xFB,0x9E,0x18,0x1E,0x9C,0x0B,
+ 0,0xBB,0xF3,0x09, 0, 0, 0, 0,
+0x03,0xF7,0xEB,0xC6,0xF5,0xDF,0x6D, 0,
+0x15,0xFF,0xFF,0x90,0x13,0xC1,0xFF,0x40,
+0x17,0xFF,0xFF,0x26, 0,0x5C,0xFF,0x8E,
+0x06,0xFD,0xFF,0x11, 0,0x45,0xFF,0xA2,
+ 0,0xD3,0xFF,0x26, 0,0x5B,0xFF,0x83,
+ 0,0x6F,0xFF,0x90,0x12,0xC0,0xFB,0x26,
+ 0,0x01,0x7E,0xE3,0xF7,0xCE,0x48, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '7'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x14,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x60,
+ 0, 0, 0, 0,0x0B,0xF4,0xFF,0x4D,
+ 0, 0, 0, 0,0x5E,0xFF,0xE9,0x05,
+ 0, 0, 0, 0,0xBD,0xFF,0x88, 0,
+ 0, 0, 0,0x1D,0xFD,0xFE,0x23, 0,
+ 0, 0, 0,0x7A,0xFF,0xBA, 0, 0,
+ 0, 0, 0,0xD8,0xFF,0x53, 0, 0,
+ 0, 0,0x38,0xFF,0xE7,0x05, 0, 0,
+ 0, 0,0x96,0xFF,0x85, 0, 0, 0,
+ 0,0x06,0xED,0xFE,0x21, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '8'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x0D,0x99,0xE7,0xF4,0xC7,0x40, 0,
+ 0,0x9A,0xFF,0x4D,0x15,0xCD,0xF4,0x15,
+ 0,0xD1,0xF4, 0, 0,0x89,0xFF,0x40,
+ 0,0x8B,0xFF,0x4C,0x14,0xCE,0xEA,0x10,
+ 0,0x08,0xC3,0xFF,0xFF,0xF8,0x47, 0,
+ 0,0xA7,0xFC,0x46,0x15,0xC4,0xF2,0x22,
+0x0F,0xFF,0xC5, 0, 0,0x56,0xFF,0x7A,
+0x0B,0xFE,0xC5, 0, 0,0x57,0xFF,0x74,
+ 0,0xBB,0xFC,0x46,0x15,0xC6,0xFA,0x2B,
+ 0,0x18,0xA2,0xE7,0xF4,0xCA,0x4A, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '9'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x13,0xA4,0xEA,0xF3,0xB4,0x21, 0,
+ 0,0xB5,0xFB,0x3B,0x32,0xF7,0xD5,0x03,
+0x15,0xFF,0xC6, 0, 0,0xBA,0xFF,0x3E,
+0x33,0xFF,0xB1, 0, 0,0xA5,0xFF,0x6E,
+0x1F,0xFF,0xC6, 0, 0,0xBA,0xFF,0x82,
+0x01,0xCE,0xFB,0x3A,0x31,0xF7,0xFF,0x80,
+ 0,0x26,0xBF,0xF5,0xE7,0xC8,0xFF,0x66,
+ 0, 0, 0, 0, 0,0x8D,0xFF,0x27,
+ 0,0x73,0x3F,0x0C,0x4B,0xF2,0xA5, 0,
+ 0,0x23,0xBC,0xF7,0xDF,0x85,0x06, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// ':'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF0,0xFF,0x58, 0, 0,
+ 0, 0, 0,0xF0,0xFF,0x58, 0, 0,
+ 0, 0, 0,0xF0,0xFF,0x58, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF0,0xFF,0x58, 0, 0,
+ 0, 0, 0,0xF0,0xFF,0x58, 0, 0,
+ 0, 0, 0,0xF0,0xFF,0x58, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// ';'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF0,0xFF,0x58, 0, 0,
+ 0, 0, 0,0xF0,0xFF,0x58, 0, 0,
+ 0, 0, 0,0xF0,0xFF,0x58, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xF0,0xFF,0x58, 0, 0,
+ 0, 0, 0,0xF3,0xFF,0x4F, 0, 0,
+ 0, 0,0x21,0xFF,0xD7,0x04, 0, 0,
+ 0, 0,0x5B,0xFF,0x49, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '<'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x1F,0x7E,0xB2,
+ 0, 0,0x09,0x5B,0xBC,0xFE,0xFE,0xA6,
+0x21,0x99,0xF1,0xFF,0xCA,0x72,0x1B, 0,
+0x64,0xFF,0xDF,0x3F, 0, 0, 0, 0,
+0x23,0x9E,0xF3,0xFE,0xC4,0x6D,0x19, 0,
+ 0, 0,0x0B,0x5F,0xBF,0xFE,0xFD,0xA5,
+ 0, 0, 0, 0, 0,0x21,0x80,0xB3,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '='
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x64,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD4,
+0x64,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD4,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x64,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD4,
+0x64,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD4,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '>'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x5C,0xA9,0x48,0x02, 0, 0, 0, 0,
+0x46,0xED,0xFF,0xE4,0x86,0x26, 0, 0,
+ 0,0x05,0x4C,0xA4,0xF3,0xFF,0xC4,0x59,
+ 0, 0, 0, 0,0x10,0xA3,0xFF,0xD4,
+ 0,0x04,0x48,0x9F,0xEF,0xFF,0xC8,0x5C,
+0x46,0xEC,0xFF,0xE6,0x89,0x28, 0, 0,
+0x5C,0xAA,0x4A,0x03, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '?'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x0B,0x7F,0xD9,0xF6,0xD4,0x5A, 0,
+ 0,0x5B,0x79,0x1F,0x12,0xD2,0xFE,0x23,
+ 0, 0, 0, 0,0x06,0xDB,0xFF,0x29,
+ 0, 0, 0,0x04,0xAE,0xFF,0x86, 0,
+ 0, 0, 0,0x90,0xFF,0x83, 0, 0,
+ 0, 0, 0,0xE7,0xE9,0x01, 0, 0,
+ 0, 0, 0,0xFC,0xD4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0xFC,0xD4, 0, 0, 0,
+ 0, 0, 0,0xFC,0xD4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '@'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x65,0xD1,0xF7,0xDD,0x75,0x01,
+ 0,0x8B,0xE9,0x4B,0x09,0x3F,0xEF,0x69,
+0x36,0xFE,0x45, 0, 0, 0,0x8D,0xC9,
+0x9B,0xD2, 0,0x4F,0xDE,0xEF,0xCF,0xE9,
+0xD4,0x91,0x16,0xF4,0x80,0x12,0xC5,0xEC,
+0xEC,0x74,0x4E,0xFF,0x1A, 0,0x66,0xEC,
+0xEB,0x6F,0x4E,0xFF,0x19, 0,0x67,0xEC,
+0xCF,0x8E,0x15,0xF4,0x80,0x12,0xC5,0xEC,
+0x8E,0xD6, 0,0x4F,0xDE,0xF2,0xD2,0xEC,
+0x24,0xF8,0x5F, 0, 0, 0, 0, 0,
+ 0,0x61,0xF6,0x74,0x16,0x13,0x72,0x71,
+ 0, 0,0x3C,0xB3,0xED,0xF8,0xDD,0x78,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'A'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x28,0xFF,0xFF,0x96, 0, 0,
+ 0, 0,0x6E,0xFF,0xFE,0xDD, 0, 0,
+ 0, 0,0xB5,0xFE,0xB4,0xFF,0x23, 0,
+ 0,0x07,0xF5,0xD6,0x67,0xFF,0x6A, 0,
+ 0,0x43,0xFF,0x9B,0x2C,0xFF,0xB0, 0,
+ 0,0x8A,0xFF,0x61,0x01,0xEF,0xF1,0x04,
+ 0,0xD0,0xFF,0xFF,0xFF,0xFF,0xFF,0x3D,
+0x18,0xFE,0xC1, 0, 0,0x56,0xFF,0x83,
+0x5E,0xFF,0x8D, 0, 0,0x20,0xFF,0xCA,
+0xA5,0xFF,0x59, 0, 0, 0,0xEA,0xFD,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'B'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x24,0xFF,0xFF,0xFF,0xF6,0xD6,0x71, 0,
+0x24,0xFF,0xCC, 0,0x10,0xBD,0xFF,0x54,
+0x24,0xFF,0xCC, 0, 0,0x78,0xFF,0x84,
+0x24,0xFF,0xCC, 0,0x0E,0xB8,0xFE,0x45,
+0x24,0xFF,0xFF,0xFF,0xFF,0xF5,0x75, 0,
+0x24,0xFF,0xCC, 0,0x0E,0x9E,0xFF,0x6A,
+0x24,0xFF,0xCC, 0, 0,0x30,0xFF,0xD3,
+0x24,0xFF,0xCC, 0, 0,0x2C,0xFF,0xDC,
+0x24,0xFF,0xCC, 0,0x0C,0x93,0xFF,0x9A,
+0x24,0xFF,0xFF,0xFF,0xFC,0xE3,0x99,0x0D,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'C'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x22,0xA9,0xEC,0xEF,0xA0,0x0E,
+ 0,0x17,0xE8,0xF1,0x3F,0x0F,0x5A,0x53,
+ 0,0x8B,0xFF,0x89, 0, 0, 0, 0,
+ 0,0xD0,0xFF,0x44, 0, 0, 0, 0,
+ 0,0xED,0xFF,0x2E, 0, 0, 0, 0,
+ 0,0xED,0xFF,0x2D, 0, 0, 0, 0,
+ 0,0xD0,0xFF,0x44, 0, 0, 0, 0,
+ 0,0x8B,0xFF,0x89, 0, 0, 0, 0,
+ 0,0x17,0xE9,0xF3,0x4A,0x10,0x57,0x52,
+ 0, 0,0x23,0xAA,0xED,0xF0,0x9F,0x0E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'D'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x10,0xFF,0xFF,0xF9,0xDD,0x94,0x16, 0,
+0x10,0xFF,0xF4,0x07,0x51,0xF6,0xDB,0x0C,
+0x10,0xFF,0xF4, 0, 0,0x98,0xFF,0x6C,
+0x10,0xFF,0xF4, 0, 0,0x62,0xFF,0xAB,
+0x10,0xFF,0xF4, 0, 0,0x50,0xFF,0xC4,
+0x10,0xFF,0xF4, 0, 0,0x51,0xFF,0xC4,
+0x10,0xFF,0xF4, 0, 0,0x63,0xFF,0xAB,
+0x10,0xFF,0xF4, 0, 0,0x98,0xFF,0x6C,
+0x10,0xFF,0xF4,0x07,0x50,0xF6,0xDC,0x0C,
+0x10,0xFF,0xFF,0xF9,0xDE,0x95,0x17, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'E'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xD8,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,
+ 0,0xD8,0xFF,0x2C, 0, 0, 0, 0,
+ 0,0xD8,0xFF,0x2C, 0, 0, 0, 0,
+ 0,0xD8,0xFF,0x2C, 0, 0, 0, 0,
+ 0,0xD8,0xFF,0xFF,0xFF,0xFF,0xFF,0x18,
+ 0,0xD8,0xFF,0x2C, 0, 0, 0, 0,
+ 0,0xD8,0xFF,0x2C, 0, 0, 0, 0,
+ 0,0xD8,0xFF,0x2C, 0, 0, 0, 0,
+ 0,0xD8,0xFF,0x2C, 0, 0, 0, 0,
+ 0,0xD8,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'F'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0x9C,
+ 0,0xC0,0xFF,0x44, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0x44, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0x44, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0x38,
+ 0,0xC0,0xFF,0x44, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0x44, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0x44, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0x44, 0, 0, 0, 0,
+ 0,0xC0,0xFF,0x44, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'G'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x40,0xC0,0xF4,0xEF,0x8E,0x0A,
+ 0,0x41,0xFB,0xDA,0x2F,0x13,0x60,0x4F,
+ 0,0xC9,0xFF,0x43, 0, 0, 0, 0,
+0x10,0xFF,0xFD,0x06, 0, 0, 0, 0,
+0x2D,0xFF,0xEC, 0, 0, 0, 0, 0,
+0x2D,0xFF,0xF1, 0,0x6C,0xFF,0xFF,0xB8,
+0x10,0xFE,0xFF,0x09, 0,0x08,0xFF,0xB8,
+ 0,0xC8,0xFF,0x4B, 0,0x08,0xFF,0xB8,
+ 0,0x41,0xFB,0xCE,0x1F,0x20,0xFF,0xB8,
+ 0, 0,0x43,0xC4,0xF6,0xF3,0xD1,0x66,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'H'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x10,0xFF,0xF4, 0, 0,0x88,0xFF,0x80,
+0x10,0xFF,0xF4, 0, 0,0x88,0xFF,0x80,
+0x10,0xFF,0xF4, 0, 0,0x88,0xFF,0x80,
+0x10,0xFF,0xF4, 0, 0,0x88,0xFF,0x80,
+0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,
+0x10,0xFF,0xF4, 0, 0,0x88,0xFF,0x80,
+0x10,0xFF,0xF4, 0, 0,0x88,0xFF,0x80,
+0x10,0xFF,0xF4, 0, 0,0x88,0xFF,0x80,
+0x10,0xFF,0xF4, 0, 0,0x88,0xFF,0x80,
+0x10,0xFF,0xF4, 0, 0,0x88,0xFF,0x80,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'I'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xD4,0xFF,0xFF,0xFF,0xFF,0xFF,0x40,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0,0xD4,0xFF,0xFF,0xFF,0xFF,0xFF,0x40,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'J'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x98,0xFF,0xFF,0xFF,0xE4, 0,
+ 0, 0, 0, 0,0x20,0xFF,0xE4, 0,
+ 0, 0, 0, 0,0x20,0xFF,0xE4, 0,
+ 0, 0, 0, 0,0x20,0xFF,0xE4, 0,
+ 0, 0, 0, 0,0x20,0xFF,0xE4, 0,
+ 0, 0, 0, 0,0x20,0xFF,0xE4, 0,
+ 0, 0, 0, 0,0x20,0xFF,0xE4, 0,
+ 0, 0, 0, 0,0x25,0xFF,0xDD, 0,
+0x3B,0x8C,0x28,0x09,0x7E,0xFF,0xAD, 0,
+0x04,0x65,0xCE,0xF8,0xEF,0xB5,0x1D, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'K'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x34,0xFF,0xD0, 0, 0,0x6B,0xFF,0xCF,
+0x34,0xFF,0xD0, 0,0x3D,0xFA,0xE9,0x1E,
+0x34,0xFF,0xD0,0x1C,0xE8,0xF9,0x3C, 0,
+0x34,0xFF,0xD7,0xCA,0xFF,0x64, 0, 0,
+0x34,0xFF,0xFF,0xFF,0xFF,0x57, 0, 0,
+0x34,0xFF,0xFF,0xD4,0xFF,0xDD,0x06, 0,
+0x34,0xFF,0xE7,0x0F,0xBF,0xFF,0x71, 0,
+0x34,0xFF,0xD0, 0,0x37,0xFF,0xED,0x10,
+0x34,0xFF,0xD0, 0, 0,0xAD,0xFF,0x8B,
+0x34,0xFF,0xD0, 0, 0,0x28,0xFC,0xF8,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'L'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x78,0xFF,0x90, 0, 0, 0, 0,
+ 0,0x78,0xFF,0x90, 0, 0, 0, 0,
+ 0,0x78,0xFF,0x90, 0, 0, 0, 0,
+ 0,0x78,0xFF,0x90, 0, 0, 0, 0,
+ 0,0x78,0xFF,0x90, 0, 0, 0, 0,
+ 0,0x78,0xFF,0x90, 0, 0, 0, 0,
+ 0,0x78,0xFF,0x90, 0, 0, 0, 0,
+ 0,0x78,0xFF,0x90, 0, 0, 0, 0,
+ 0,0x78,0xFF,0x90, 0, 0, 0, 0,
+ 0,0x78,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'M'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x68,0xFF,0xFF,0x25, 0,0xBA,0xFF,0xD8,
+0x68,0xFF,0xFF,0x70,0x0B,0xF8,0xFF,0xD8,
+0x68,0xFF,0xD6,0xBC,0x4E,0xEF,0xE6,0xD8,
+0x68,0xFF,0x92,0xFA,0xA6,0xAE,0xE4,0xD8,
+0x68,0xFF,0x59,0xF4,0xFE,0x6B,0xE4,0xD8,
+0x68,0xFF,0x54,0xB6,0xFF,0x29,0xE4,0xD8,
+0x68,0xFF,0x54, 0, 0, 0,0xE4,0xD8,
+0x68,0xFF,0x54, 0, 0, 0,0xE4,0xD8,
+0x68,0xFF,0x54, 0, 0, 0,0xE4,0xD8,
+0x68,0xFF,0x54, 0, 0, 0,0xE4,0xD8,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'N'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x30,0xFF,0xFF,0x2D, 0,0x2C,0xFF,0x9C,
+0x30,0xFF,0xFF,0x92, 0,0x2C,0xFF,0x9C,
+0x30,0xFF,0xFC,0xEE,0x08,0x2C,0xFF,0x9C,
+0x30,0xFF,0xB6,0xFD,0x5A,0x2C,0xFF,0x9C,
+0x30,0xFF,0x98,0xB6,0xBE,0x2C,0xFF,0x9C,
+0x30,0xFF,0x98,0x51,0xFE,0x50,0xFF,0x9C,
+0x30,0xFF,0x98,0x04,0xE8,0xB3,0xFF,0x9C,
+0x30,0xFF,0x98, 0,0x88,0xFC,0xFF,0x9C,
+0x30,0xFF,0x98, 0,0x24,0xFE,0xFF,0x9C,
+0x30,0xFF,0x98, 0, 0,0xBE,0xFF,0x9C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'O'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x07,0x90,0xE9,0xF6,0xC2,0x31, 0,
+ 0,0x96,0xFF,0x6D,0x1F,0xE4,0xED,0x14,
+0x0F,0xF9,0xEE,0x01, 0,0x83,0xFF,0x74,
+0x42,0xFF,0xCB, 0, 0,0x5D,0xFF,0xAD,
+0x5A,0xFF,0xBE, 0, 0,0x4F,0xFF,0xC5,
+0x5A,0xFF,0xBE, 0, 0,0x4F,0xFF,0xC5,
+0x43,0xFF,0xCB, 0, 0,0x5D,0xFF,0xAE,
+0x0F,0xFA,0xEE,0x01, 0,0x83,0xFF,0x75,
+ 0,0x96,0xFF,0x6B,0x1F,0xE2,0xED,0x14,
+ 0,0x07,0x91,0xEB,0xF8,0xC3,0x32, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'P'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE4,0xFF,0xFF,0xF7,0xD8,0x81,0x02,
+ 0,0xE4,0xFF,0x20,0x15,0xB3,0xFF,0x78,
+ 0,0xE4,0xFF,0x20, 0,0x4D,0xFF,0xC2,
+ 0,0xE4,0xFF,0x20, 0,0x4E,0xFF,0xC1,
+ 0,0xE4,0xFF,0x20,0x14,0xB1,0xFF,0x78,
+ 0,0xE4,0xFF,0xFF,0xF8,0xD9,0x82,0x02,
+ 0,0xE4,0xFF,0x20, 0, 0, 0, 0,
+ 0,0xE4,0xFF,0x20, 0, 0, 0, 0,
+ 0,0xE4,0xFF,0x20, 0, 0, 0, 0,
+ 0,0xE4,0xFF,0x20, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'Q'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x07,0x90,0xE9,0xF6,0xC1,0x2E, 0,
+ 0,0x96,0xFF,0x6D,0x1F,0xE4,0xEA,0x11,
+0x0F,0xF9,0xEE,0x01, 0,0x83,0xFF,0x70,
+0x42,0xFF,0xCB, 0, 0,0x5D,0xFF,0xAA,
+0x5A,0xFF,0xBE, 0, 0,0x4F,0xFF,0xC3,
+0x5A,0xFF,0xBE, 0, 0,0x4F,0xFF,0xC4,
+0x43,0xFF,0xCB, 0, 0,0x5D,0xFF,0xB1,
+0x0F,0xFA,0xEE,0x01, 0,0x83,0xFF,0x7D,
+ 0,0x96,0xFF,0x6B,0x1F,0xE2,0xFA,0x22,
+ 0,0x07,0x91,0xEB,0xFF,0xFF,0x70, 0,
+ 0, 0, 0, 0,0x2C,0xF5,0xDF,0x1E,
+ 0, 0, 0, 0, 0,0x5E,0x95,0x03,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'R'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x18,0xFF,0xFF,0xFF,0xF5,0xCC,0x55, 0,
+0x18,0xFF,0xEC, 0,0x27,0xE7,0xFA,0x2A,
+0x18,0xFF,0xEC, 0, 0,0xA0,0xFF,0x6A,
+0x18,0xFF,0xEC, 0, 0,0xA1,0xFF,0x70,
+0x18,0xFF,0xEC, 0,0x26,0xE7,0xF6,0x23,
+0x18,0xFF,0xFF,0xFF,0xFF,0xEB,0x37, 0,
+0x18,0xFF,0xEC,0x05,0x99,0xFF,0xA2, 0,
+0x18,0xFF,0xEC, 0,0x0D,0xEE,0xFD,0x29,
+0x18,0xFF,0xEC, 0, 0,0x81,0xFF,0xA9,
+0x18,0xFF,0xEC, 0, 0,0x12,0xF3,0xFE,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'S'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x15,0x9E,0xE6,0xF0,0xBD,0x46, 0,
+ 0,0xBA,0xFA,0x3D,0x07,0x38,0xB7,0x03,
+0x0C,0xFE,0xEA,0x02, 0, 0, 0, 0,
+0x0C,0xFE,0xFF,0xB1,0x2E, 0, 0, 0,
+ 0,0x9B,0xFF,0xFF,0xFF,0xBB,0x31, 0,
+ 0,0x01,0x5F,0xD4,0xFF,0xFF,0xF5,0x26,
+ 0, 0, 0, 0,0x4F,0xEB,0xFF,0x82,
+ 0, 0, 0, 0, 0,0x82,0xFF,0x83,
+0x13,0xB8,0x48,0x14,0x17,0xC4,0xFD,0x3B,
+ 0,0x4C,0xBD,0xEE,0xF0,0xC9,0x53, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'T'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x64,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'U'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x48,0xFF,0xBC, 0, 0,0x50,0xFF,0xB4,
+0x48,0xFF,0xBC, 0, 0,0x50,0xFF,0xB4,
+0x48,0xFF,0xBC, 0, 0,0x50,0xFF,0xB4,
+0x48,0xFF,0xBC, 0, 0,0x50,0xFF,0xB4,
+0x48,0xFF,0xBC, 0, 0,0x50,0xFF,0xB4,
+0x48,0xFF,0xBC, 0, 0,0x50,0xFF,0xB4,
+0x47,0xFF,0xBC, 0, 0,0x50,0xFF,0xB2,
+0x2E,0xFF,0xC4, 0, 0,0x58,0xFF,0x99,
+0x06,0xDE,0xF9,0x3B,0x11,0xB9,0xFF,0x50,
+ 0,0x2D,0xB6,0xEA,0xFB,0xDC,0x77, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'V'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x7E,0xFF,0x87, 0, 0,0x18,0xFF,0xEB,
+0x40,0xFF,0xBE, 0, 0,0x4F,0xFF,0xAE,
+0x08,0xF9,0xF2,0x02, 0,0x86,0xFF,0x6F,
+ 0,0xC4,0xFF,0x2C, 0,0xBD,0xFF,0x31,
+ 0,0x86,0xFF,0x63,0x02,0xF1,0xF0,0x02,
+ 0,0x48,0xFF,0x9A,0x2B,0xFF,0xB4, 0,
+ 0,0x0D,0xFC,0xD1,0x62,0xFF,0x76, 0,
+ 0, 0,0xCC,0xFC,0xA5,0xFF,0x37, 0,
+ 0, 0,0x8E,0xFF,0xF8,0xF4,0x04, 0,
+ 0, 0,0x4F,0xFF,0xFF,0xBB, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'W'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xF0,0xD0, 0, 0, 0, 0,0x62,0xFF,
+0xD0,0xE9, 0, 0, 0, 0,0x76,0xFF,
+0xAF,0xFE,0x04, 0, 0, 0,0x8A,0xFF,
+0x8F,0xFF,0x1B,0xB9,0xFF,0x28,0x9E,0xFD,
+0x6F,0xFF,0x34,0xEA,0xFF,0x63,0xB1,0xE4,
+0x4E,0xFF,0x6A,0xFF,0xC9,0x9E,0xC5,0xC6,
+0x2E,0xFF,0xB5,0xE5,0x71,0xD9,0xD9,0xA8,
+0x0D,0xFF,0xF7,0xAC,0x35,0xFF,0xF7,0x8A,
+ 0,0xED,0xFF,0x74,0x04,0xF5,0xFF,0x6C,
+ 0,0xCC,0xFF,0x3C, 0,0xBE,0xFF,0x4E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'X'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x71,0xFF,0xA6, 0, 0,0x38,0xFE,0xD7,
+0x04,0xD5,0xFF,0x3C,0x01,0xCA,0xFF,0x46,
+ 0,0x42,0xFF,0xCE,0x64,0xFF,0xAF, 0,
+ 0, 0,0xAB,0xFF,0xFA,0xF7,0x21, 0,
+ 0, 0,0x1E,0xF6,0xFF,0x84, 0, 0,
+ 0, 0,0x2E,0xFC,0xFF,0x9A, 0, 0,
+ 0, 0,0xC1,0xFF,0xF1,0xFD,0x33, 0,
+ 0,0x58,0xFF,0xBC,0x4F,0xFF,0xC6,0x01,
+0x0A,0xE3,0xFB,0x2A, 0,0xB8,0xFF,0x5E,
+0x85,0xFF,0x8F, 0, 0,0x28,0xFA,0xE6,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'Y'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xAE,0xFF,0x7A, 0, 0,0x15,0xF5,0xFA,
+0x2B,0xFD,0xEC,0x0C, 0,0x8A,0xFF,0x97,
+ 0,0xA5,0xFF,0x78,0x14,0xF4,0xF7,0x1B,
+ 0,0x24,0xFB,0xEB,0x92,0xFF,0x8D, 0,
+ 0, 0,0x9B,0xFF,0xFF,0xF3,0x14, 0,
+ 0, 0,0x1D,0xF8,0xFF,0x82, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0,0xCC,0xFF,0x38, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'Z'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x10,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD8,
+ 0, 0, 0, 0,0x0D,0xE3,0xFF,0xD3,
+ 0, 0, 0, 0,0x94,0xFF,0xFF,0x5F,
+ 0, 0, 0,0x39,0xFD,0xFF,0xB7, 0,
+ 0, 0,0x05,0xD4,0xFF,0xF1,0x1D, 0,
+ 0, 0,0x7D,0xFF,0xFF,0x67, 0, 0,
+ 0,0x27,0xF8,0xFF,0xBE,0x01, 0, 0,
+0x01,0xC1,0xFF,0xF5,0x22, 0, 0, 0,
+0x34,0xFF,0xFF,0x6F, 0, 0, 0, 0,
+0x38,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '['
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x1C,0xFF,0xFF,0xFF,0x5C, 0,
+ 0, 0,0x1C,0xFF,0xB4, 0, 0, 0,
+ 0, 0,0x1C,0xFF,0xB4, 0, 0, 0,
+ 0, 0,0x1C,0xFF,0xB4, 0, 0, 0,
+ 0, 0,0x1C,0xFF,0xB4, 0, 0, 0,
+ 0, 0,0x1C,0xFF,0xB4, 0, 0, 0,
+ 0, 0,0x1C,0xFF,0xB4, 0, 0, 0,
+ 0, 0,0x1C,0xFF,0xB4, 0, 0, 0,
+ 0, 0,0x1C,0xFF,0xB4, 0, 0, 0,
+ 0, 0,0x1C,0xFF,0xB4, 0, 0, 0,
+ 0, 0,0x1C,0xFF,0xB4, 0, 0, 0,
+ 0, 0,0x1C,0xFF,0xFF,0xFF,0x5C, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '\'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x10,0xF3,0x80, 0, 0, 0, 0, 0,
+ 0,0x91,0xEA,0x08, 0, 0, 0, 0,
+ 0,0x21,0xFC,0x66, 0, 0, 0, 0,
+ 0, 0,0xAC,0xD7,0x01, 0, 0, 0,
+ 0, 0,0x3A,0xFF,0x4B, 0, 0, 0,
+ 0, 0, 0,0xC7,0xBE, 0, 0, 0,
+ 0, 0, 0,0x55,0xFF,0x31, 0, 0,
+ 0, 0, 0,0x03,0xDF,0xA3, 0, 0,
+ 0, 0, 0, 0,0x71,0xFA,0x1B, 0,
+ 0, 0, 0, 0,0x0D,0xF0,0x88, 0,
+ 0, 0, 0, 0, 0,0x8C,0xEF,0x0C,
+ 0, 0, 0, 0, 0,0x1D,0xFB,0x6E,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// ']'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0xEC,0xFF,0xFF,0x8C, 0, 0,
+ 0, 0, 0,0x48,0xFF,0x8C, 0, 0,
+ 0, 0, 0,0x48,0xFF,0x8C, 0, 0,
+ 0, 0, 0,0x48,0xFF,0x8C, 0, 0,
+ 0, 0, 0,0x48,0xFF,0x8C, 0, 0,
+ 0, 0, 0,0x48,0xFF,0x8C, 0, 0,
+ 0, 0, 0,0x48,0xFF,0x8C, 0, 0,
+ 0, 0, 0,0x48,0xFF,0x8C, 0, 0,
+ 0, 0, 0,0x48,0xFF,0x8C, 0, 0,
+ 0, 0, 0,0x48,0xFF,0x8C, 0, 0,
+ 0, 0, 0,0x48,0xFF,0x8C, 0, 0,
+ 0, 0,0xEC,0xFF,0xFF,0x8C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '^'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x17,0xE8,0xFF,0x6E, 0, 0,
+ 0,0x02,0xBC,0xFF,0xF9,0xF9,0x34, 0,
+ 0,0x7E,0xFF,0x8E,0x32,0xED,0xDD,0x0F,
+0x3F,0xFC,0x8C, 0, 0,0x30,0xEC,0xAB,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '_'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '`'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x3F,0xFA,0x9A, 0, 0, 0, 0,
+ 0, 0,0x62,0xFE,0x40, 0, 0, 0,
+ 0, 0, 0,0x8B,0xDB,0x09, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'a'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x1D,0xA0,0xE1,0xF9,0xDB,0x6F, 0,
+ 0,0x7C,0x65,0x21,0x10,0xBA,0xFF,0x3F,
+ 0, 0, 0, 0, 0,0x6F,0xFF,0x80,
+ 0,0x4F,0xC6,0xEE,0xFF,0xFF,0xFF,0x92,
+0x23,0xFB,0xF8,0x44,0x07,0x74,0xFF,0x94,
+0x50,0xFF,0xD1, 0, 0,0x99,0xFF,0x94,
+0x26,0xFD,0xF3,0x25,0x35,0xF0,0xFF,0x94,
+ 0,0x60,0xDC,0xF6,0xCE,0xAD,0xFF,0x94,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'b'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF8,0xFF,0x04, 0, 0, 0, 0,
+ 0,0xF8,0xFF,0x04, 0, 0, 0, 0,
+ 0,0xF8,0xFF,0x04, 0, 0, 0, 0,
+ 0,0xF8,0xFF,0x91,0xEA,0xED,0x80, 0,
+ 0,0xF8,0xFF,0xA2,0x16,0xC5,0xFF,0x48,
+ 0,0xF8,0xFF,0x30, 0,0x5C,0xFF,0xA2,
+ 0,0xF8,0xFF,0x0D, 0,0x3A,0xFF,0xC2,
+ 0,0xF8,0xFF,0x0D, 0,0x3A,0xFF,0xC1,
+ 0,0xF8,0xFF,0x30, 0,0x5C,0xFF,0xA2,
+ 0,0xF8,0xFF,0xA2,0x16,0xC5,0xFF,0x46,
+ 0,0xF8,0xFF,0x92,0xEB,0xF0,0x82, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'c'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x3C,0xC2,0xF6,0xE0,0x87,0x06,
+ 0,0x22,0xF7,0xE0,0x32,0x0D,0x72,0x3A,
+ 0,0x98,0xFF,0x67, 0, 0, 0, 0,
+ 0,0xC5,0xFF,0x39, 0, 0, 0, 0,
+ 0,0xC5,0xFF,0x38, 0, 0, 0, 0,
+ 0,0x98,0xFF,0x66, 0, 0, 0, 0,
+ 0,0x22,0xF7,0xDF,0x30,0x13,0x70,0x39,
+ 0, 0,0x3D,0xC3,0xF7,0xE2,0x82,0x05,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'd'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,0x98,0xFF,0x68,
+ 0, 0, 0, 0, 0,0x98,0xFF,0x68,
+ 0, 0, 0, 0, 0,0x98,0xFF,0x68,
+ 0,0x34,0xD1,0xF6,0xC4,0xBE,0xFF,0x68,
+0x01,0xDA,0xFD,0x44,0x40,0xFC,0xFF,0x68,
+0x37,0xFF,0xCA, 0, 0,0xC4,0xFF,0x68,
+0x56,0xFF,0xA9, 0, 0,0xA2,0xFF,0x68,
+0x57,0xFF,0xA8, 0, 0,0xA2,0xFF,0x68,
+0x37,0xFF,0xCA, 0, 0,0xC4,0xFF,0x68,
+0x01,0xDB,0xFD,0x44,0x40,0xFC,0xFF,0x68,
+ 0,0x36,0xD4,0xF6,0xC5,0xBD,0xFF,0x68,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'e'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x0B,0x94,0xE9,0xF4,0xCE,0x57, 0,
+ 0,0xA5,0xFE,0x50,0x0F,0xA7,0xFF,0x4D,
+0x21,0xFE,0xC9, 0, 0,0x39,0xFF,0xB4,
+0x4C,0xFF,0xFE,0xFC,0xFD,0xFF,0xFF,0xD7,
+0x57,0xFF,0xB8, 0, 0, 0, 0, 0,
+0x2B,0xFF,0xE2,0x02, 0, 0, 0, 0,
+ 0,0xB6,0xFF,0x83,0x10,0x1F,0x69,0x71,
+ 0,0x0B,0x8F,0xE3,0xF9,0xDA,0x8A,0x12,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'f'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x4E,0xD8,0xF8,0xFF,0x68,
+ 0, 0, 0,0xD8,0xFF,0x2E, 0, 0,
+ 0, 0, 0,0xF2,0xFF,0x0C, 0, 0,
+ 0,0xD0,0xFF,0xFF,0xFF,0xFF,0xFF,0x68,
+ 0, 0, 0,0xF4,0xFF,0x0C, 0, 0,
+ 0, 0, 0,0xF4,0xFF,0x0C, 0, 0,
+ 0, 0, 0,0xF4,0xFF,0x0C, 0, 0,
+ 0, 0, 0,0xF4,0xFF,0x0C, 0, 0,
+ 0, 0, 0,0xF4,0xFF,0x0C, 0, 0,
+ 0, 0, 0,0xF4,0xFF,0x0C, 0, 0,
+ 0, 0, 0,0xF4,0xFF,0x0C, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'g'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x1F,0xC1,0xF7,0xD3,0xBF,0xFF,0x80,
+ 0,0xBC,0xFF,0x54,0x38,0xF9,0xFF,0x80,
+0x1F,0xFF,0xD9, 0, 0,0xB4,0xFF,0x80,
+0x43,0xFF,0xB5, 0, 0,0x8E,0xFF,0x80,
+0x47,0xFF,0xB5, 0, 0,0x8F,0xFF,0x80,
+0x25,0xFF,0xD9, 0, 0,0xB4,0xFF,0x80,
+ 0,0xC5,0xFF,0x54,0x37,0xF8,0xFF,0x80,
+ 0,0x24,0xC5,0xF8,0xD6,0xBF,0xFF,0x7E,
+ 0, 0, 0, 0, 0,0x97,0xFF,0x63,
+ 0,0x6B,0x52,0x11,0x2B,0xE8,0xF8,0x22,
+ 0,0x19,0xA3,0xE9,0xF8,0xCF,0x53, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'h'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xD4,0xFF,0x2C, 0, 0, 0, 0,
+ 0,0xD4,0xFF,0x2C, 0, 0, 0, 0,
+ 0,0xD4,0xFF,0x2C, 0, 0, 0, 0,
+ 0,0xD4,0xFF,0xA4,0xE2,0xEF,0x89, 0,
+ 0,0xD4,0xFF,0x93,0x15,0xE1,0xFF,0x2E,
+ 0,0xD4,0xFF,0x39, 0,0xB1,0xFF,0x51,
+ 0,0xD4,0xFF,0x2C, 0,0xAC,0xFF,0x54,
+ 0,0xD4,0xFF,0x2C, 0,0xAC,0xFF,0x54,
+ 0,0xD4,0xFF,0x2C, 0,0xAC,0xFF,0x54,
+ 0,0xD4,0xFF,0x2C, 0,0xAC,0xFF,0x54,
+ 0,0xD4,0xFF,0x2C, 0,0xAC,0xFF,0x54,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'i'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x88,0xFF,0x78, 0, 0,
+ 0, 0, 0,0x88,0xFF,0x78, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x7C,0xFF,0xFF,0xFF,0x78, 0, 0,
+ 0, 0, 0,0x88,0xFF,0x78, 0, 0,
+ 0, 0, 0,0x88,0xFF,0x78, 0, 0,
+ 0, 0, 0,0x88,0xFF,0x78, 0, 0,
+ 0, 0, 0,0x88,0xFF,0x78, 0, 0,
+ 0, 0, 0,0x88,0xFF,0x78, 0, 0,
+ 0, 0, 0,0x88,0xFF,0x78, 0, 0,
+0x04,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF8,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'j'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x30,0xFF,0xD0, 0, 0,
+ 0, 0, 0,0x30,0xFF,0xD0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x38,0xFF,0xFF,0xFF,0xD0, 0, 0,
+ 0, 0, 0,0x30,0xFF,0xD0, 0, 0,
+ 0, 0, 0,0x30,0xFF,0xD0, 0, 0,
+ 0, 0, 0,0x30,0xFF,0xD0, 0, 0,
+ 0, 0, 0,0x30,0xFF,0xD0, 0, 0,
+ 0, 0, 0,0x30,0xFF,0xD0, 0, 0,
+ 0, 0, 0,0x30,0xFF,0xD0, 0, 0,
+ 0, 0, 0,0x30,0xFF,0xD0, 0, 0,
+ 0, 0, 0,0x39,0xFF,0xC1, 0, 0,
+ 0, 0,0x04,0x8A,0xFF,0x91, 0, 0,
+0x04,0xFF,0xFF,0xF3,0xB6,0x18, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'k'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xD0,0xFF,0x30, 0, 0, 0, 0, 0,
+0xD0,0xFF,0x30, 0, 0, 0, 0, 0,
+0xD0,0xFF,0x30, 0, 0, 0, 0, 0,
+0xD0,0xFF,0x30,0x0C,0xCD,0xFF,0x8B, 0,
+0xD0,0xFF,0x34,0xB7,0xFF,0x91, 0, 0,
+0xD0,0xFF,0xC5,0xFF,0x97, 0, 0, 0,
+0xD0,0xFF,0xFF,0xFF,0x70, 0, 0, 0,
+0xD0,0xFF,0xA4,0xEC,0xF2,0x1A, 0, 0,
+0xD0,0xFF,0x30,0x6D,0xFF,0xA9, 0, 0,
+0xD0,0xFF,0x30,0x05,0xD9,0xFF,0x45, 0,
+0xD0,0xFF,0x30, 0,0x4F,0xFF,0xDA,0x07,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'l'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x64,0xFF,0xFF,0xFF,0xA8, 0, 0, 0,
+ 0, 0,0x5C,0xFF,0xA8, 0, 0, 0,
+ 0, 0,0x5C,0xFF,0xA8, 0, 0, 0,
+ 0, 0,0x5C,0xFF,0xA8, 0, 0, 0,
+ 0, 0,0x5C,0xFF,0xA8, 0, 0, 0,
+ 0, 0,0x5C,0xFF,0xA8, 0, 0, 0,
+ 0, 0,0x5C,0xFF,0xA8, 0, 0, 0,
+ 0, 0,0x5C,0xFF,0xA8, 0, 0, 0,
+ 0, 0,0x4E,0xFF,0xB1, 0, 0, 0,
+ 0, 0,0x21,0xFD,0xE8,0x1B, 0, 0,
+ 0, 0, 0,0x6C,0xE2,0xFE,0xFF,0x7C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'm'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x70,0xFF,0xBA,0xF2,0xAC,0xDE,0xED,0x56,
+0x70,0xFF,0x57,0xB7,0xFF,0x32,0xDF,0xC4,
+0x70,0xFF,0x35,0x96,0xFF,0x09,0xC2,0xDD,
+0x70,0xFF,0x34,0x94,0xFF,0x08,0xC0,0xE3,
+0x70,0xFF,0x34,0x94,0xFF,0x08,0xC0,0xE4,
+0x70,0xFF,0x34,0x94,0xFF,0x08,0xC0,0xE4,
+0x70,0xFF,0x34,0x94,0xFF,0x08,0xC0,0xE4,
+0x70,0xFF,0x34,0x94,0xFF,0x08,0xC0,0xE4,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'n'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xD4,0xFF,0xA5,0xE2,0xEF,0x89, 0,
+ 0,0xD4,0xFF,0x97,0x15,0xE2,0xFF,0x2D,
+ 0,0xD4,0xFF,0x3A, 0,0xB1,0xFF,0x51,
+ 0,0xD4,0xFF,0x2C, 0,0xAC,0xFF,0x54,
+ 0,0xD4,0xFF,0x2C, 0,0xAC,0xFF,0x54,
+ 0,0xD4,0xFF,0x2C, 0,0xAC,0xFF,0x54,
+ 0,0xD4,0xFF,0x2C, 0,0xAC,0xFF,0x54,
+ 0,0xD4,0xFF,0x2C, 0,0xAC,0xFF,0x54,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'o'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x09,0x93,0xE9,0xF8,0xC4,0x36, 0,
+ 0,0x9C,0xFF,0x5E,0x1D,0xDA,0xF1,0x17,
+0x18,0xFD,0xDB, 0, 0,0x70,0xFF,0x84,
+0x42,0xFF,0xB6, 0, 0,0x4A,0xFF,0xB1,
+0x42,0xFF,0xB5, 0, 0,0x4B,0xFF,0xB0,
+0x19,0xFD,0xDB, 0, 0,0x6F,0xFF,0x84,
+ 0,0x9C,0xFF,0x5C,0x1C,0xD8,0xF1,0x17,
+ 0,0x09,0x93,0xEB,0xF8,0xC5,0x37, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'p'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xF8,0xFF,0x90,0xE7,0xEF,0x81, 0,
+ 0,0xF8,0xFF,0xA2,0x16,0xC5,0xFF,0x46,
+ 0,0xF8,0xFF,0x30, 0,0x5C,0xFF,0xA2,
+ 0,0xF8,0xFF,0x0D, 0,0x3A,0xFF,0xC2,
+ 0,0xF8,0xFF,0x0D, 0,0x3A,0xFF,0xC1,
+ 0,0xF8,0xFF,0x30, 0,0x5C,0xFF,0xA2,
+ 0,0xF8,0xFF,0xA2,0x16,0xC5,0xFF,0x48,
+ 0,0xF8,0xFF,0x91,0xEB,0xEE,0x81, 0,
+ 0,0xF8,0xFF,0x04, 0, 0, 0, 0,
+ 0,0xF8,0xFF,0x04, 0, 0, 0, 0,
+ 0,0xF8,0xFF,0x04, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'q'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x35,0xD3,0xF5,0xC1,0xBD,0xFF,0x68,
+0x01,0xDB,0xFD,0x44,0x40,0xFC,0xFF,0x68,
+0x37,0xFF,0xCA, 0, 0,0xC4,0xFF,0x68,
+0x56,0xFF,0xA9, 0, 0,0xA2,0xFF,0x68,
+0x57,0xFF,0xA8, 0, 0,0xA2,0xFF,0x68,
+0x37,0xFF,0xCA, 0, 0,0xC4,0xFF,0x68,
+0x01,0xDA,0xFD,0x44,0x40,0xFC,0xFF,0x68,
+ 0,0x34,0xD2,0xF7,0xC4,0xBE,0xFF,0x68,
+ 0, 0, 0, 0, 0,0x98,0xFF,0x68,
+ 0, 0, 0, 0, 0,0x98,0xFF,0x68,
+ 0, 0, 0, 0, 0,0x98,0xFF,0x68,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'r'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x04,0xFF,0xFF,0x97,0xE1,0xFD,0xE0,
+ 0,0x04,0xFF,0xFF,0xC5,0x1E,0x18,0x81,
+ 0,0x04,0xFF,0xFF,0x2A, 0, 0, 0,
+ 0,0x04,0xFF,0xFF,0x04, 0, 0, 0,
+ 0,0x04,0xFF,0xFF, 0, 0, 0, 0,
+ 0,0x04,0xFF,0xFF, 0, 0, 0, 0,
+ 0,0x04,0xFF,0xFF, 0, 0, 0, 0,
+ 0,0x04,0xFF,0xFF, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 's'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0x11,0xA1,0xE9,0xEF,0xB4,0x2E, 0,
+ 0,0x9C,0xFF,0x4B,0x0B,0x41,0x95, 0,
+ 0,0xC8,0xFF,0x79,0x08, 0, 0, 0,
+ 0,0x84,0xFF,0xFF,0xF3,0xAE,0x32, 0,
+ 0,0x01,0x61,0xBA,0xF9,0xFF,0xF2,0x13,
+ 0, 0, 0, 0,0x14,0xCD,0xFF,0x40,
+ 0,0x90,0x59,0x16,0x12,0xC6,0xFB,0x1D,
+ 0,0x20,0x9B,0xE1,0xF6,0xD2,0x56, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 't'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0,0x48,0xFF,0xB8, 0, 0, 0,
+ 0, 0,0x48,0xFF,0xB8, 0, 0, 0,
+0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x54,
+ 0, 0,0x48,0xFF,0xB8, 0, 0, 0,
+ 0, 0,0x48,0xFF,0xB8, 0, 0, 0,
+ 0, 0,0x48,0xFF,0xB8, 0, 0, 0,
+ 0, 0,0x48,0xFF,0xB8, 0, 0, 0,
+ 0, 0,0x45,0xFF,0xB8, 0, 0, 0,
+ 0, 0,0x27,0xFF,0xDF,0x11, 0, 0,
+ 0, 0, 0,0x89,0xE9,0xFE,0xFF,0x54,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'u'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xE8,0xFF,0x18, 0,0xC0,0xFF,0x40,
+ 0,0xE8,0xFF,0x18, 0,0xC0,0xFF,0x40,
+ 0,0xE8,0xFF,0x18, 0,0xC0,0xFF,0x40,
+ 0,0xE8,0xFF,0x18, 0,0xC0,0xFF,0x40,
+ 0,0xE8,0xFF,0x18, 0,0xC0,0xFF,0x40,
+ 0,0xE5,0xFF,0x1C, 0,0xCE,0xFF,0x40,
+ 0,0xC3,0xFF,0x5D,0x30,0xFB,0xFF,0x40,
+ 0,0x3B,0xD9,0xF4,0xC1,0xD7,0xFF,0x40,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'v'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x4E,0xFF,0xB5, 0, 0,0x46,0xFF,0xB8,
+0x09,0xF6,0xF3,0x05, 0,0x89,0xFF,0x6B,
+ 0,0xB2,0xFF,0x3B, 0,0xCC,0xFF,0x1E,
+ 0,0x64,0xFF,0x7E,0x11,0xFD,0xD0, 0,
+ 0,0x17,0xFE,0xC1,0x53,0xFF,0x82, 0,
+ 0, 0,0xC8,0xF9,0xA1,0xFF,0x35, 0,
+ 0, 0,0x7A,0xFF,0xFB,0xE6,0x01, 0,
+ 0, 0,0x2B,0xFF,0xFF,0x9A, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'w'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0xEA,0xBE, 0, 0, 0, 0,0x50,0xFF,
+0xBE,0xE5, 0, 0, 0, 0,0x76,0xFF,
+0x91,0xFF,0x0B,0xB2,0xFF,0x20,0x9D,0xF9,
+0x65,0xFF,0x31,0xE6,0xFD,0x53,0xC4,0xD1,
+0x38,0xFF,0x70,0xFE,0xB0,0x86,0xEA,0xA5,
+0x0C,0xFE,0xCB,0xD5,0x68,0xCA,0xFF,0x79,
+ 0,0xDF,0xFF,0x9C,0x30,0xFF,0xFF,0x4D,
+ 0,0xB2,0xFF,0x64,0x03,0xF4,0xFF,0x21,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'x'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x1D,0xF0,0xFF,0x35, 0,0xC7,0xFF,0x7D,
+ 0,0x60,0xFF,0xBD,0x50,0xFF,0xCC,0x04,
+ 0, 0,0xB2,0xFF,0xEB,0xF8,0x2B, 0,
+ 0, 0,0x18,0xF1,0xFF,0x7D, 0, 0,
+ 0, 0,0x42,0xFE,0xFF,0xB2, 0, 0,
+ 0,0x0D,0xE0,0xF9,0xC2,0xFF,0x5E, 0,
+ 0,0x9C,0xFF,0x8D,0x24,0xFA,0xEF,0x1A,
+0x49,0xFF,0xEE,0x11, 0,0x8F,0xFF,0xB5,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'y'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x69,0xFF,0xAE, 0, 0,0x3A,0xFF,0xDF,
+0x11,0xF8,0xF7,0x0D, 0,0x8C,0xFF,0x89,
+ 0,0xAB,0xFF,0x5B, 0,0xDE,0xFF,0x32,
+ 0,0x4C,0xFF,0xB2,0x31,0xFF,0xDB, 0,
+ 0,0x04,0xE9,0xF8,0x93,0xFF,0x84, 0,
+ 0, 0,0x8E,0xFF,0xFD,0xFF,0x2D, 0,
+ 0, 0,0x30,0xFF,0xFF,0xD6, 0, 0,
+ 0, 0, 0,0xD2,0xFF,0x7F, 0, 0,
+ 0, 0,0x01,0xE4,0xFF,0x29, 0, 0,
+ 0,0x01,0x5D,0xFF,0xC5, 0, 0, 0,
+0x20,0xFF,0xFC,0xC9,0x23, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// 'z'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0x64,
+ 0, 0, 0, 0,0x42,0xFC,0xFF,0x5F,
+ 0, 0, 0,0x1B,0xE9,0xFF,0xCD,0x08,
+ 0, 0,0x05,0xC5,0xFF,0xEE,0x21, 0,
+ 0, 0,0x90,0xFF,0xFE,0x4C, 0, 0,
+ 0,0x56,0xFF,0xFF,0x84, 0, 0, 0,
+ 0,0xDF,0xFF,0xBC,0x02, 0, 0, 0,
+ 0,0xE4,0xFF,0xFF,0xFF,0xFF,0xFF,0x64,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '{'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x26,0xCB,0xF7,0xFF,0x34,
+ 0, 0, 0,0x93,0xFF,0x6B,0x02, 0,
+ 0, 0, 0,0xAE,0xFF,0x30, 0, 0,
+ 0, 0, 0,0xB0,0xFF,0x2C, 0, 0,
+ 0, 0, 0,0xBD,0xFF,0x26, 0, 0,
+ 0,0x02,0x32,0xF4,0xF2,0x09, 0, 0,
+ 0,0xCC,0xFF,0xF6,0x58, 0, 0, 0,
+ 0,0x02,0x36,0xF6,0xEF,0x08, 0, 0,
+ 0, 0, 0,0xBE,0xFF,0x26, 0, 0,
+ 0, 0, 0,0xB0,0xFF,0x2C, 0, 0,
+ 0, 0, 0,0xAE,0xFF,0x30, 0, 0,
+ 0, 0, 0,0x93,0xFF,0x6A,0x02, 0,
+ 0, 0, 0,0x26,0xCC,0xF8,0xFF,0x34,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '|'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0,0x90,0xFC, 0, 0, 0,
+ 0, 0, 0,0x90,0xFC, 0, 0, 0,
+ 0, 0, 0,0x90,0xFC, 0, 0, 0,
+ 0, 0, 0,0x90,0xFC, 0, 0, 0,
+ 0, 0, 0,0x90,0xFC, 0, 0, 0,
+ 0, 0, 0,0x90,0xFC, 0, 0, 0,
+ 0, 0, 0,0x90,0xFC, 0, 0, 0,
+ 0, 0, 0,0x90,0xFC, 0, 0, 0,
+ 0, 0, 0,0x90,0xFC, 0, 0, 0,
+ 0, 0, 0,0x90,0xFC, 0, 0, 0,
+ 0, 0, 0,0x90,0xFC, 0, 0, 0,
+ 0, 0, 0,0x90,0xFC, 0, 0, 0,
+ 0, 0, 0,0x90,0xFC, 0, 0, 0,
+ 0, 0, 0,0x90,0xFC, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '}'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0,0xC4,0xFC,0xE5,0x6E, 0, 0, 0,
+ 0, 0,0x17,0xE9,0xF8,0x02, 0, 0,
+ 0, 0, 0,0xC1,0xFF,0x16, 0, 0,
+ 0, 0, 0,0xBC,0xFF,0x18, 0, 0,
+ 0, 0, 0,0xB7,0xFF,0x24, 0, 0,
+ 0, 0, 0,0x8E,0xFF,0x89,0x0A, 0,
+ 0, 0, 0,0x11,0xD1,0xFF,0xFF,0x38,
+ 0, 0, 0,0x8B,0xFF,0x8C,0x0B, 0,
+ 0, 0, 0,0xB6,0xFF,0x25, 0, 0,
+ 0, 0, 0,0xBC,0xFF,0x18, 0, 0,
+ 0, 0, 0,0xC1,0xFF,0x16, 0, 0,
+ 0, 0,0x17,0xE9,0xF8,0x02, 0, 0,
+ 0,0xC4,0xFD,0xE6,0x6F, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+// '~'
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+0x16,0xAC,0xF1,0xD8,0x72,0x14,0x28,0x8A,
+0x64,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xD4,
+0x51,0x53,0x0D,0x31,0x9D,0xF1,0xD7,0x4C,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+
+ // clang-format on
+};
+} // anonymous namespace
+
+const uint8_t *OverlayState::getFontData() const
+{
+ return kFontData;
+}
+#else
+const uint8_t *OverlayState::getFontData() const
+{
+ return nullptr;
+}
+#endif
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Overlay_font_autogen.h b/gfx/angle/checkout/src/libANGLE/Overlay_font_autogen.h
new file mode 100644
index 0000000000..333c0ee3c6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Overlay_font_autogen.h
@@ -0,0 +1,27 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_overlay_fonts.py using overlay/DejaVuSansMono-Bold.ttf.
+//
+// Copyright 2022 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Overlay_font_autogen.h:
+// Autogenerated overlay font data.
+
+#include "libANGLE/Overlay.h"
+
+namespace gl
+{
+namespace overlay
+{
+constexpr uint32_t kFontMipCount = 2;
+constexpr uint32_t kFontCharacters = 95;
+constexpr uint32_t kFontGlyphWidth = 17;
+constexpr uint32_t kFontGlyphHeight = 34;
+constexpr uint32_t kFontMipDataSize[kFontMipCount] = {54910, 12920};
+constexpr uint32_t kFontMipDataOffset[kFontMipCount] = {0, 54910};
+constexpr uint32_t kFontTotalDataSize = 67830;
+constexpr uint32_t kFontMipLarge = 0;
+constexpr uint32_t kFontMipSmall = 1;
+} // namespace overlay
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/PixelLocalStorage.cpp b/gfx/angle/checkout/src/libANGLE/PixelLocalStorage.cpp
new file mode 100644
index 0000000000..e5e560af5f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/PixelLocalStorage.cpp
@@ -0,0 +1,826 @@
+//
+// Copyright 2022 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// PixelLocalStorage.cpp: Defines the renderer-agnostic container classes
+// gl::PixelLocalStorage and gl::PixelLocalStoragePlane for
+// ANGLE_shader_pixel_local_storage.
+
+#include "libANGLE/PixelLocalStorage.h"
+
+#include <numeric>
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace gl
+{
+// RAII utilities for working with GL state.
+namespace
+{
+class ScopedBindTexture2D
+{
+ public:
+ ScopedBindTexture2D(Context *context, TextureID texture)
+ : mContext(context),
+ mSavedTexBinding2D(
+ mContext->getState().getSamplerTextureId(mContext->getState().getActiveSampler(),
+ TextureType::_2D))
+ {
+ mContext->bindTexture(TextureType::_2D, texture);
+ }
+
+ ~ScopedBindTexture2D() { mContext->bindTexture(TextureType::_2D, mSavedTexBinding2D); }
+
+ private:
+ Context *const mContext;
+ TextureID mSavedTexBinding2D;
+};
+
+class ScopedRestoreDrawFramebuffer
+{
+ public:
+ ScopedRestoreDrawFramebuffer(Context *context)
+ : mContext(context), mSavedFramebuffer(mContext->getState().getDrawFramebuffer())
+ {
+ ASSERT(mSavedFramebuffer);
+ }
+
+ ~ScopedRestoreDrawFramebuffer() { mContext->bindDrawFramebuffer(mSavedFramebuffer->id()); }
+
+ private:
+ Context *const mContext;
+ Framebuffer *const mSavedFramebuffer;
+};
+
+class ScopedDisableScissor
+{
+ public:
+ ScopedDisableScissor(Context *context)
+ : mContext(context), mScissorTestEnabled(mContext->getState().isScissorTestEnabled())
+ {
+ if (mScissorTestEnabled)
+ {
+ mContext->disable(GL_SCISSOR_TEST);
+ }
+ }
+
+ ~ScopedDisableScissor()
+ {
+ if (mScissorTestEnabled)
+ {
+ mContext->enable(GL_SCISSOR_TEST);
+ }
+ }
+
+ private:
+ Context *const mContext;
+ const GLint mScissorTestEnabled;
+};
+} // namespace
+
+PixelLocalStoragePlane::~PixelLocalStoragePlane()
+{
+ // Call deinitialize or onContextObjectsLost first!
+ ASSERT(mMemorylessTextureID.value == 0);
+ // Call deinitialize or onFramebufferDestroyed first!
+ ASSERT(mTextureRef == nullptr);
+}
+
+void PixelLocalStoragePlane::onContextObjectsLost()
+{
+ // We normally call deleteTexture on the memoryless plane texture ID, since we own it, but in
+ // this case we can let it go.
+ mMemorylessTextureID = TextureID();
+}
+
+void PixelLocalStoragePlane::onFramebufferDestroyed(const Context *context)
+{
+ if (mTextureRef != nullptr)
+ {
+ mTextureRef->release(context);
+ mTextureRef = nullptr;
+ }
+}
+
+void PixelLocalStoragePlane::deinitialize(Context *context)
+{
+ mInternalformat = GL_NONE;
+ mMemoryless = false;
+ if (mMemorylessTextureID.value != 0)
+ {
+ // The app could have technically deleted mMemorylessTextureID by guessing its value and
+ // calling glDeleteTextures, but it seems unnecessary to worry about that here. (Worst case
+ // we delete one of their textures.) This also isn't a problem in WebGL.
+ context->deleteTexture(mMemorylessTextureID);
+ mMemorylessTextureID = TextureID();
+ }
+ if (mTextureRef != nullptr)
+ {
+ mTextureRef->release(context);
+ mTextureRef = nullptr;
+ }
+}
+
+void PixelLocalStoragePlane::setMemoryless(Context *context, GLenum internalformat)
+{
+ deinitialize(context);
+ mInternalformat = internalformat;
+ mMemoryless = true;
+ mTextureImageIndex = ImageIndex::MakeFromType(TextureType::_2D, 0, 0);
+ // The backing texture will get allocated lazily, once we know what dimensions it should be.
+ ASSERT(mMemorylessTextureID.value == 0);
+ ASSERT(mTextureRef == nullptr);
+}
+
+void PixelLocalStoragePlane::setTextureBacked(Context *context, Texture *tex, int level, int layer)
+{
+ deinitialize(context);
+ ASSERT(tex->getImmutableFormat());
+ mInternalformat = tex->getState().getBaseLevelDesc().format.info->internalFormat;
+ mMemoryless = false;
+ mTextureImageIndex = ImageIndex::MakeFromType(tex->getType(), level, layer);
+ mTextureRef = tex;
+ mTextureRef->addRef();
+}
+
+bool PixelLocalStoragePlane::isTextureIDDeleted(const Context *context) const
+{
+ // We can tell if the texture has been deleted by looking up mTextureRef's ID on the Context. If
+ // they don't match, it's been deleted.
+ ASSERT(!isDeinitialized() || mTextureRef == nullptr);
+ return mTextureRef != nullptr && context->getTexture(mTextureRef->id()) != mTextureRef;
+}
+
+GLint PixelLocalStoragePlane::getIntegeri(const Context *context, GLenum target, GLuint index) const
+{
+ if (!isDeinitialized())
+ {
+ bool memoryless = isMemoryless() || isTextureIDDeleted(context);
+ switch (target)
+ {
+ case GL_PIXEL_LOCAL_FORMAT_ANGLE:
+ return mInternalformat;
+ case GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE:
+ return memoryless ? 0 : mTextureRef->id().value;
+ case GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE:
+ return memoryless ? 0 : mTextureImageIndex.getLevelIndex();
+ case GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE:
+ return memoryless ? 0 : mTextureImageIndex.getLayerIndex();
+ }
+ }
+ // Since GL_NONE == 0, PLS queries all return 0 when the plane is deinitialized.
+ static_assert(GL_NONE == 0, "Expecting GL_NONE to be zero.");
+ return 0;
+}
+
+bool PixelLocalStoragePlane::getTextureImageExtents(const Context *context, Extents *extents) const
+{
+ if (isDeinitialized() || isMemoryless() || isTextureIDDeleted(context))
+ {
+ return false;
+ }
+ ASSERT(mTextureRef != nullptr);
+ *extents =
+ mTextureRef->getExtents(mTextureImageIndex.getTarget(), mTextureImageIndex.getLevelIndex());
+ extents->depth = 0;
+ return true;
+}
+
+void PixelLocalStoragePlane::ensureBackingIfMemoryless(Context *context, Extents plsExtents)
+{
+ ASSERT(!isDeinitialized());
+ ASSERT(!isTextureIDDeleted(context)); // Convert to memoryless first in this case.
+ if (!isMemoryless())
+ {
+ ASSERT(mTextureRef != nullptr);
+ return;
+ }
+
+ // Internal textures backing memoryless planes are always 2D and not mipmapped.
+ ASSERT(mTextureImageIndex.getType() == TextureType::_2D);
+ ASSERT(mTextureImageIndex.getLevelIndex() == 0);
+ ASSERT(mTextureImageIndex.getLayerIndex() == 0);
+ const bool hasMemorylessTextureId = mMemorylessTextureID.value != 0;
+ const bool hasTextureRef = mTextureRef != nullptr;
+ ASSERT(hasMemorylessTextureId == hasTextureRef);
+
+ // Do we need to allocate a new backing texture?
+ if (mTextureRef == nullptr ||
+ static_cast<GLsizei>(mTextureRef->getWidth(TextureTarget::_2D, 0)) != plsExtents.width ||
+ static_cast<GLsizei>(mTextureRef->getHeight(TextureTarget::_2D, 0)) != plsExtents.height)
+ {
+ // Call setMemoryless() to release our current data.
+ setMemoryless(context, mInternalformat);
+ ASSERT(mTextureRef == nullptr);
+ ASSERT(mMemorylessTextureID.value == 0);
+
+ // Create a new texture that backs the memoryless plane.
+ context->genTextures(1, &mMemorylessTextureID);
+ {
+ ScopedBindTexture2D scopedBindTexture2D(context, mMemorylessTextureID);
+ context->bindTexture(TextureType::_2D, mMemorylessTextureID);
+ context->texStorage2D(TextureType::_2D, 1, mInternalformat, plsExtents.width,
+ plsExtents.height);
+ }
+
+ mTextureRef = context->getTexture(mMemorylessTextureID);
+ ASSERT(mTextureRef != nullptr);
+ ASSERT(mTextureRef->id() == mMemorylessTextureID);
+ mTextureRef->addRef();
+ }
+}
+
+void PixelLocalStoragePlane::attachToDrawFramebuffer(Context *context,
+ Extents plsExtents,
+ GLenum colorAttachment)
+{
+ ASSERT(!isDeinitialized());
+ ensureBackingIfMemoryless(context, plsExtents);
+ ASSERT(mTextureRef != nullptr);
+ if (mTextureImageIndex.usesTex3D()) // GL_TEXTURE_3D or GL_TEXTURE_2D_ARRAY.
+ {
+ context->framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, colorAttachment, mTextureRef->id(),
+ mTextureImageIndex.getLevelIndex(),
+ mTextureImageIndex.getLayerIndex());
+ }
+ else
+ {
+ context->framebufferTexture2D(GL_DRAW_FRAMEBUFFER, colorAttachment,
+ mTextureImageIndex.getTarget(), mTextureRef->id(),
+ mTextureImageIndex.getLevelIndex());
+ }
+}
+
+void PixelLocalStoragePlane::performLoadOperationClear(Context *context,
+ GLint drawBuffer,
+ GLenum loadop,
+ const void *data)
+{
+ // The GL scissor test must be disabled, since the intention is to clear the entire surface.
+ ASSERT(!context->getState().isScissorTestEnabled());
+ switch (mInternalformat)
+ {
+ case GL_RGBA8:
+ case GL_R32F:
+ {
+ GLfloat clearValue[4]{};
+ if (loadop == GL_CLEAR_ANGLE)
+ {
+ memcpy(clearValue, data, sizeof(clearValue));
+ }
+ context->clearBufferfv(GL_COLOR, drawBuffer, clearValue);
+ break;
+ }
+ case GL_RGBA8I:
+ {
+ GLint clearValue[4]{};
+ if (loadop == GL_CLEAR_ANGLE)
+ {
+ memcpy(clearValue, data, sizeof(clearValue));
+ }
+ context->clearBufferiv(GL_COLOR, drawBuffer, clearValue);
+ break;
+ }
+ case GL_RGBA8UI:
+ case GL_R32UI:
+ {
+ GLuint clearValue[4]{};
+ if (loadop == GL_CLEAR_ANGLE)
+ {
+ memcpy(clearValue, data, sizeof(clearValue));
+ }
+ context->clearBufferuiv(GL_COLOR, drawBuffer, clearValue);
+ break;
+ }
+ default:
+ // Invalid PLS internalformats should not have made it this far.
+ UNREACHABLE();
+ }
+}
+
+void PixelLocalStoragePlane::bindToImage(Context *context,
+ Extents plsExtents,
+ GLuint unit,
+ bool needsR32Packing)
+{
+ ASSERT(!isDeinitialized());
+ ensureBackingIfMemoryless(context, plsExtents);
+ ASSERT(mTextureRef != nullptr);
+ GLenum imageBindingFormat = mInternalformat;
+ if (needsR32Packing)
+ {
+ // D3D and ES require us to pack all PLS formats into r32f, r32i, or r32ui images.
+ switch (imageBindingFormat)
+ {
+ case GL_RGBA8:
+ case GL_RGBA8UI:
+ imageBindingFormat = GL_R32UI;
+ break;
+ case GL_RGBA8I:
+ imageBindingFormat = GL_R32I;
+ break;
+ }
+ }
+ if (mTextureRef->getType() != TextureType::_2D)
+ {
+ // TODO(anglebug.com/7279): Texture types other than GL_TEXTURE_2D will take a lot of
+ // consideration to support on all backends. Hold of on fully implementing them until the
+ // other backends are in place.
+ UNIMPLEMENTED();
+ }
+ context->bindImageTexture(unit, mTextureRef->id(), mTextureImageIndex.getLevelIndex(), GL_FALSE,
+ mTextureImageIndex.getLayerIndex(), GL_READ_WRITE,
+ imageBindingFormat);
+}
+
+PixelLocalStorage::PixelLocalStorage() {}
+PixelLocalStorage::~PixelLocalStorage() {}
+
+void PixelLocalStorage::onFramebufferDestroyed(const Context *context)
+{
+ if (context->getRefCount() == 0)
+ {
+ // If the Context's refcount is zero, we know it's in a teardown state and we can just let
+ // go of our GL objects -- they get cleaned up as part of context teardown. Otherwise, the
+ // Context should have called deleteContextObjects before reaching this point.
+ onContextObjectsLost();
+ for (PixelLocalStoragePlane &plane : mPlanes)
+ {
+ plane.onContextObjectsLost();
+ }
+ }
+ for (PixelLocalStoragePlane &plane : mPlanes)
+ {
+ plane.onFramebufferDestroyed(context);
+ }
+}
+
+void PixelLocalStorage::deleteContextObjects(Context *context)
+{
+ onDeleteContextObjects(context);
+ for (PixelLocalStoragePlane &plane : mPlanes)
+ {
+ plane.deinitialize(context);
+ }
+}
+
+void PixelLocalStorage::begin(Context *context,
+ GLsizei n,
+ const GLenum loadops[],
+ const void *cleardata)
+{
+ // Convert planes whose backing texture has been deleted to memoryless, and find the pixel local
+ // storage rendering dimensions.
+ Extents plsExtents;
+ bool hasPLSExtents = false;
+ for (int i = 0; i < n; ++i)
+ {
+ if (loadops[i] == GL_DISABLE_ANGLE)
+ {
+ continue;
+ }
+ PixelLocalStoragePlane &plane = mPlanes[i];
+ if (plane.isTextureIDDeleted(context))
+ {
+ // [ANGLE_shader_pixel_local_storage] Section 4.4.2.X "Configuring Pixel Local Storage
+ // on a Framebuffer": When a texture object is deleted, any pixel local storage plane to
+ // which it was bound is automatically converted to a memoryless plane of matching
+ // internalformat.
+ plane.setMemoryless(context, plane.getInternalformat());
+ }
+ if (!hasPLSExtents && plane.getTextureImageExtents(context, &plsExtents))
+ {
+ hasPLSExtents = true;
+ }
+ }
+ if (!hasPLSExtents)
+ {
+ // All PLS planes are memoryless. Use the rendering area of the framebuffer instead.
+ plsExtents =
+ context->getState().getDrawFramebuffer()->getState().getAttachmentExtentsIntersection();
+ ASSERT(plsExtents.depth == 0);
+ }
+
+ onBegin(context, n, loadops, reinterpret_cast<const char *>(cleardata), plsExtents);
+ mNumActivePLSPlanes = n;
+}
+
+void PixelLocalStorage::end(Context *context)
+{
+ onEnd(context, mNumActivePLSPlanes);
+ mNumActivePLSPlanes = 0;
+}
+
+void PixelLocalStorage::barrier(Context *context)
+{
+ ASSERT(!context->getExtensions().shaderPixelLocalStorageCoherentANGLE);
+ onBarrier(context);
+}
+
+namespace
+{
+// Implements pixel local storage with image load/store shader operations.
+class PixelLocalStorageImageLoadStore : public PixelLocalStorage
+{
+ public:
+ PixelLocalStorageImageLoadStore(bool needsR32Packing) : mNeedsR32Packing(needsR32Packing) {}
+
+ // Call deleteContextObjects or onContextObjectsLost first!
+ ~PixelLocalStorageImageLoadStore() override
+ {
+ ASSERT(mScratchFramebufferForClearing.value == 0);
+ }
+
+ void onContextObjectsLost() override
+ {
+ mScratchFramebufferForClearing = FramebufferID(); // Let go of GL objects.
+ }
+
+ void onDeleteContextObjects(Context *context) override
+ {
+ if (mScratchFramebufferForClearing.value != 0)
+ {
+ context->deleteFramebuffer(mScratchFramebufferForClearing);
+ mScratchFramebufferForClearing = FramebufferID();
+ }
+ }
+
+ void onBegin(Context *context,
+ GLsizei n,
+ const GLenum loadops[],
+ const char *cleardata,
+ Extents plsExtents) override
+ {
+ // Save the image bindings so we can restore them during onEnd().
+ const State &state = context->getState();
+ ASSERT(static_cast<size_t>(n) <= state.getImageUnits().size());
+ mSavedImageBindings.clear();
+ mSavedImageBindings.reserve(n);
+ for (int i = 0; i < n; ++i)
+ {
+ mSavedImageBindings.emplace_back(state.getImageUnit(i));
+ }
+
+ // Save the default framebuffer width/height so we can restore it during onEnd().
+ Framebuffer *framebuffer = state.getDrawFramebuffer();
+ mSavedFramebufferDefaultWidth = framebuffer->getDefaultWidth();
+ mSavedFramebufferDefaultHeight = framebuffer->getDefaultHeight();
+
+ // Specify the framebuffer width/height explicitly in case we end up rendering exclusively
+ // to shader images.
+ context->framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
+ plsExtents.width);
+ context->framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
+ plsExtents.height);
+
+ // Guard GL state and bind a scratch framebuffer in case we need to reallocate or clear any
+ // PLS planes.
+ const size_t maxDrawBuffers = context->getCaps().maxDrawBuffers;
+ ScopedRestoreDrawFramebuffer ScopedRestoreDrawFramebuffer(context);
+ if (mScratchFramebufferForClearing.value == 0)
+ {
+ context->genFramebuffers(1, &mScratchFramebufferForClearing);
+ context->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mScratchFramebufferForClearing);
+ // Turn on all draw buffers on the scratch framebuffer for clearing.
+ DrawBuffersVector<GLenum> drawBuffers(maxDrawBuffers);
+ std::iota(drawBuffers.begin(), drawBuffers.end(), GL_COLOR_ATTACHMENT0);
+ context->drawBuffers(static_cast<int>(drawBuffers.size()), drawBuffers.data());
+ }
+ else
+ {
+ context->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mScratchFramebufferForClearing);
+ }
+ ScopedDisableScissor scopedDisableScissor(context);
+
+ // Bind and clear the PLS planes.
+ size_t maxClearedAttachments = 0;
+ for (int i = 0; i < n;)
+ {
+ angle::FixedVector<int, IMPLEMENTATION_MAX_DRAW_BUFFERS> pendingClears;
+ for (; pendingClears.size() < maxDrawBuffers && i < n; ++i)
+ {
+ GLenum loadop = loadops[i];
+ if (loadop == GL_DISABLE_ANGLE)
+ {
+ continue;
+ }
+ PixelLocalStoragePlane &plane = getPlane(i);
+ ASSERT(!plane.isDeinitialized());
+ plane.bindToImage(context, plsExtents, i, mNeedsR32Packing);
+ if (loadop == GL_ZERO || loadop == GL_CLEAR_ANGLE)
+ {
+ plane.attachToDrawFramebuffer(
+ context, plsExtents,
+ GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(pendingClears.size()));
+ pendingClears.push_back(i); // Defer the clear for later.
+ }
+ }
+ // Clear in batches to be more efficient with GL state.
+ for (size_t drawBufferIdx = 0; drawBufferIdx < pendingClears.size(); ++drawBufferIdx)
+ {
+ int plsIdx = pendingClears[drawBufferIdx];
+ getPlane(plsIdx).performLoadOperationClear(
+ context, static_cast<GLint>(drawBufferIdx), loadops[plsIdx],
+ cleardata + plsIdx * 4 * 4);
+ }
+ maxClearedAttachments = std::max(maxClearedAttachments, pendingClears.size());
+ }
+
+ // Detach the cleared PLS textures from the scratch framebuffer.
+ for (size_t i = 0; i < maxClearedAttachments; ++i)
+ {
+ context->framebufferTexture2D(GL_DRAW_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(i),
+ TextureTarget::_2D, TextureID(), 0);
+ }
+
+ // Unlike other barriers, GL_SHADER_IMAGE_ACCESS_BARRIER_BIT also synchronizes all types of
+ // memory accesses that happened before the barrier:
+ //
+ // SHADER_IMAGE_ACCESS_BARRIER_BIT: Memory accesses using shader built-in image load and
+ // store functions issued after the barrier will reflect data written by shaders prior to
+ // the barrier. Additionally, image stores issued after the barrier will not execute until
+ // all memory accesses (e.g., loads, stores, texture fetches, vertex fetches) initiated
+ // prior to the barrier complete.
+ //
+ // So we don't any barriers other than GL_SHADER_IMAGE_ACCESS_BARRIER_BIT during begin().
+ context->memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
+ }
+
+ void onEnd(Context *context, GLsizei numActivePLSPlanes) override
+ {
+ // Restore the image bindings. Since glBindImageTexture and any commands that modify
+ // textures are banned while PLS is active, these will all still be alive and valid.
+ ASSERT(mSavedImageBindings.size() == static_cast<size_t>(numActivePLSPlanes));
+ for (GLuint unit = 0; unit < mSavedImageBindings.size(); ++unit)
+ {
+ ImageUnit &binding = mSavedImageBindings[unit];
+ context->bindImageTexture(unit, binding.texture.id(), binding.level, binding.layered,
+ binding.layer, binding.access, binding.format);
+
+ // BindingPointers have to be explicitly cleaned up.
+ binding.texture.set(context, nullptr);
+ }
+ mSavedImageBindings.clear();
+
+ // Restore the default framebuffer width/height.
+ context->framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
+ mSavedFramebufferDefaultWidth);
+ context->framebufferParameteri(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
+ mSavedFramebufferDefaultHeight);
+
+ // We need ALL_BARRIER_BITS during end() because GL_SHADER_IMAGE_ACCESS_BARRIER_BIT doesn't
+ // synchronize all types of memory accesses that can happen after the barrier.
+ context->memoryBarrier(GL_ALL_BARRIER_BITS);
+ }
+
+ void onBarrier(Context *context) override
+ {
+ context->memoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
+ }
+
+ private:
+ // D3D and ES require us to pack all PLS formats into r32f, r32i, or r32ui images.
+ const bool mNeedsR32Packing;
+ FramebufferID mScratchFramebufferForClearing{};
+
+ // Saved values to restore during onEnd().
+ GLint mSavedFramebufferDefaultWidth;
+ GLint mSavedFramebufferDefaultHeight;
+ std::vector<ImageUnit> mSavedImageBindings;
+};
+
+// Implements pixel local storage via framebuffer fetch.
+class PixelLocalStorageFramebufferFetch : public PixelLocalStorage
+{
+ public:
+ void onContextObjectsLost() override {}
+
+ void onDeleteContextObjects(Context *) override {}
+
+ void onBegin(Context *context,
+ GLsizei n,
+ const GLenum loadops[],
+ const char *cleardata,
+ Extents plsExtents) override
+ {
+ const State &state = context->getState();
+ const Caps &caps = context->getCaps();
+ Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
+ const DrawBuffersVector<GLenum> &appDrawBuffers = framebuffer->getDrawBufferStates();
+
+ // Remember the current draw buffer state so we can restore it during onEnd().
+ mSavedDrawBuffers.resize(appDrawBuffers.size());
+ std::copy(appDrawBuffers.begin(), appDrawBuffers.end(), mSavedDrawBuffers.begin());
+
+ // Set up new draw buffers for PLS.
+ int firstPLSDrawBuffer = caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes - n;
+ int numAppDrawBuffers =
+ std::min(static_cast<int>(appDrawBuffers.size()), firstPLSDrawBuffer);
+ DrawBuffersArray<GLenum> plsDrawBuffers;
+ std::copy(appDrawBuffers.begin(), appDrawBuffers.begin() + numAppDrawBuffers,
+ plsDrawBuffers.begin());
+ std::fill(plsDrawBuffers.begin() + numAppDrawBuffers,
+ plsDrawBuffers.begin() + firstPLSDrawBuffer, GL_NONE);
+
+ mBlendsToReEnable.reset();
+ mColorMasksToRestore.reset();
+ mInvalidateList.clear();
+ bool needsClear = false;
+
+ bool hasIndexedBlendAndColorMask = context->getExtensions().drawBuffersIndexedAny();
+ if (!hasIndexedBlendAndColorMask)
+ {
+ // We don't have indexed blend and color mask control. Disable them globally. (This also
+ // means the app can't have its own draw buffers while PLS is active.)
+ ASSERT(caps.maxColorAttachmentsWithActivePixelLocalStorage == 0);
+ if (state.isBlendEnabled())
+ {
+ context->disable(GL_BLEND);
+ mBlendsToReEnable.set(0);
+ }
+ std::array<bool, 4> &mask = mSavedColorMasks[0];
+ state.getBlendStateExt().getColorMaskIndexed(0, &mask[0], &mask[1], &mask[2], &mask[3]);
+ if (!(mask[0] && mask[1] && mask[2] && mask[3]))
+ {
+ context->colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ mColorMasksToRestore.set(0);
+ }
+ }
+
+ for (GLsizei i = 0; i < n; ++i)
+ {
+ GLuint drawBufferIdx = getDrawBufferIdx(caps, i);
+ GLenum loadop = loadops[i];
+ if (loadop == GL_DISABLE_ANGLE)
+ {
+ plsDrawBuffers[drawBufferIdx] = GL_NONE;
+ continue;
+ }
+
+ PixelLocalStoragePlane &plane = getPlane(i);
+ ASSERT(!plane.isDeinitialized());
+
+ // Attach our PLS texture to the framebuffer. Validation should have already ensured
+ // nothing else was attached at this point.
+ GLenum colorAttachment = GL_COLOR_ATTACHMENT0 + drawBufferIdx;
+ ASSERT(!framebuffer->getAttachment(context, colorAttachment));
+ plane.attachToDrawFramebuffer(context, plsExtents, colorAttachment);
+ plsDrawBuffers[drawBufferIdx] = colorAttachment;
+
+ if (hasIndexedBlendAndColorMask)
+ {
+ // Ensure blend and color mask are disabled for this draw buffer.
+ if (state.isBlendEnabledIndexed(drawBufferIdx))
+ {
+ context->disablei(GL_BLEND, drawBufferIdx);
+ mBlendsToReEnable.set(drawBufferIdx);
+ }
+ std::array<bool, 4> &mask = mSavedColorMasks[drawBufferIdx];
+ state.getBlendStateExt().getColorMaskIndexed(drawBufferIdx, &mask[0], &mask[1],
+ &mask[2], &mask[3]);
+ if (!(mask[0] && mask[1] && mask[2] && mask[3]))
+ {
+ context->colorMaski(drawBufferIdx, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ mColorMasksToRestore.set(drawBufferIdx);
+ }
+ }
+
+ if (plane.isMemoryless())
+ {
+ // Memoryless planes don't need to be preserved after glEndPixelLocalStorageANGLE().
+ mInvalidateList.push_back(colorAttachment);
+ }
+
+ needsClear = needsClear || (loadop != GL_KEEP);
+ }
+
+ // Turn on the PLS draw buffers.
+ context->drawBuffers(caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes,
+ plsDrawBuffers.data());
+
+ // Clear the non-KEEP PLS planes now that their draw buffers are turned on.
+ if (needsClear)
+ {
+ ScopedDisableScissor scopedDisableScissor(context);
+ for (GLsizei i = 0; i < n; ++i)
+ {
+ GLenum loadop = loadops[i];
+ if (loadop != GL_DISABLE_ANGLE && loadop != GL_KEEP)
+ {
+ GLuint drawBufferIdx = getDrawBufferIdx(caps, i);
+ getPlane(i).performLoadOperationClear(context, drawBufferIdx, loadop,
+ cleardata + i * 4 * 4);
+ }
+ }
+ }
+
+ if (!context->getExtensions().shaderPixelLocalStorageCoherentANGLE)
+ {
+ // Insert a barrier if we aren't coherent, since the textures may have been rendered to
+ // previously.
+ barrier(context);
+ }
+ }
+
+ void onEnd(Context *context, GLint numActivePLSPlanes) override
+ {
+
+ const Caps &caps = context->getCaps();
+
+ // Invalidate the memoryless PLS attachments.
+ if (!mInvalidateList.empty())
+ {
+ context->invalidateFramebuffer(GL_DRAW_FRAMEBUFFER,
+ static_cast<GLsizei>(mInvalidateList.size()),
+ mInvalidateList.data());
+ mInvalidateList.clear();
+ }
+
+ bool hasIndexedBlendAndColorMask = context->getExtensions().drawBuffersIndexedAny();
+ if (!hasIndexedBlendAndColorMask)
+ {
+ // Restore global blend and color mask. Validation should have ensured these didn't
+ // change while pixel local storage was active.
+ if (mBlendsToReEnable[0])
+ {
+ context->enable(GL_BLEND);
+ }
+ if (mColorMasksToRestore[0])
+ {
+ const std::array<bool, 4> &mask = mSavedColorMasks[0];
+ context->colorMask(mask[0], mask[1], mask[2], mask[3]);
+ }
+ }
+
+ for (GLsizei i = 0; i < numActivePLSPlanes; ++i)
+ {
+ // Reset color attachments where PLS was attached. Validation should have already
+ // ensured nothing was attached at these points when we activated pixel local storage,
+ // and that nothing got attached during.
+ GLuint drawBufferIdx = getDrawBufferIdx(caps, i);
+ GLenum colorAttachment = GL_COLOR_ATTACHMENT0 + drawBufferIdx;
+ context->framebufferTexture2D(GL_DRAW_FRAMEBUFFER, colorAttachment, TextureTarget::_2D,
+ TextureID(), 0);
+
+ if (hasIndexedBlendAndColorMask)
+ {
+ // Restore this draw buffer's blend and color mask. Validation should have ensured
+ // these did not change while pixel local storage was active.
+ if (mBlendsToReEnable[drawBufferIdx])
+ {
+ context->enablei(GL_BLEND, drawBufferIdx);
+ }
+ if (mColorMasksToRestore[drawBufferIdx])
+ {
+ const std::array<bool, 4> &mask = mSavedColorMasks[drawBufferIdx];
+ context->colorMaski(drawBufferIdx, mask[0], mask[1], mask[2], mask[3]);
+ }
+ }
+ }
+
+ // Restore the draw buffer state from before PLS was enabled.
+ context->drawBuffers(static_cast<GLsizei>(mSavedDrawBuffers.size()),
+ mSavedDrawBuffers.data());
+ mSavedDrawBuffers.clear();
+ }
+
+ void onBarrier(Context *context) override { context->framebufferFetchBarrier(); }
+
+ private:
+ GLuint getDrawBufferIdx(const Caps &caps, GLuint plsPlaneIdx)
+ {
+ // Bind the PLS attachments in reverse order from the rear. This way, the shader translator
+ // doesn't need to know how many planes are going to be active in order to figure out plane
+ // indices.
+ return caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes - plsPlaneIdx - 1;
+ }
+
+ DrawBuffersVector<GLenum> mSavedDrawBuffers;
+ DrawBufferMask mBlendsToReEnable;
+ DrawBufferMask mColorMasksToRestore;
+ DrawBuffersArray<std::array<bool, 4>> mSavedColorMasks;
+ DrawBuffersVector<GLenum> mInvalidateList;
+};
+} // namespace
+
+std::unique_ptr<PixelLocalStorage> PixelLocalStorage::Make(const Context *context)
+{
+ switch (context->getImplementation()->getNativePixelLocalStorageType())
+ {
+ case ShPixelLocalStorageType::ImageStoreR32PackedFormats:
+ return std::make_unique<PixelLocalStorageImageLoadStore>(true);
+ case ShPixelLocalStorageType::ImageStoreNativeFormats:
+ return std::make_unique<PixelLocalStorageImageLoadStore>(false);
+ case ShPixelLocalStorageType::FramebufferFetch:
+ return std::make_unique<PixelLocalStorageFramebufferFetch>();
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/PixelLocalStorage.h b/gfx/angle/checkout/src/libANGLE/PixelLocalStorage.h
new file mode 100644
index 0000000000..f60ab7443d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/PixelLocalStorage.h
@@ -0,0 +1,177 @@
+//
+// Copyright 2022 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// PixelLocalStorage.h: Defines the renderer-agnostic container classes
+// gl::PixelLocalStorage and gl::PixelLocalStoragePlane for
+// ANGLE_shader_pixel_local_storage.
+
+#ifndef LIBANGLE_PIXEL_LOCAL_STORAGE_H_
+#define LIBANGLE_PIXEL_LOCAL_STORAGE_H_
+
+#include "angle_gl.h"
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+
+class Context;
+class Texture;
+
+// Holds the configuration of an ANGLE_shader_pixel_local_storage plane.
+//
+// Unlike normal framebuffer attachments, pixel local storage planes don't take effect until the
+// application calls glBeginPixelLocalStorageANGLE, and the manner in which they take effect is
+// highly dependent on the backend implementation. A PixelLocalStoragePlane is just a plain data
+// description what to set up later once PLS is enabled.
+class PixelLocalStoragePlane : angle::NonCopyable
+{
+ public:
+ ~PixelLocalStoragePlane();
+
+ // Called when the context is lost or destroyed. Causes this class to clear its GL object
+ // handles.
+ void onContextObjectsLost();
+
+ // Called when the owning framebuffer is being destroyed. Causes this class to release its
+ // texture object reference.
+ void onFramebufferDestroyed(const Context *);
+
+ void deinitialize(Context *);
+ void setMemoryless(Context *, GLenum internalformat);
+ void setTextureBacked(Context *, Texture *, int level, int layer);
+
+ bool isDeinitialized() const { return mInternalformat == GL_NONE; }
+
+ // Returns true if the texture ID bound to this plane has been deleted.
+ //
+ // [ANGLE_shader_pixel_local_storage] Section 4.4.2.X "Configuring Pixel Local Storage
+ // on a Framebuffer": When a texture object is deleted, any pixel local storage plane to
+ // which it was bound is automatically converted to a memoryless plane of matching
+ // internalformat.
+ bool isTextureIDDeleted(const Context *) const;
+
+ bool isMemoryless() const
+ {
+ // isMemoryless() should be false if the plane is deinitialized.
+ ASSERT(!(isDeinitialized() && mMemoryless));
+ return mMemoryless;
+ }
+
+ GLenum getInternalformat() const { return mInternalformat; }
+
+ // Implements glGetIntegeri_v() for GL_PIXEL_LOCAL_FORMAT_ANGLE,
+ // GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE, GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE, and
+ // GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE
+ GLint getIntegeri(const Context *, GLenum target, GLuint index) const;
+
+ // If this plane is texture backed, stores the bound texture image's {width, height, 0} to
+ // Extents and returns true. Otherwise returns false, meaning the plane is either deinitialized
+ // or memoryless.
+ bool getTextureImageExtents(const Context *, Extents *extents) const;
+
+ // Attaches this plane to the specified color attachment point on the current draw framebuffer.
+ void attachToDrawFramebuffer(Context *, Extents plsExtents, GLenum colorAttachment);
+
+ // Clears the draw buffer at 0-based index 'drawbuffer' on the current framebuffer. Reads the
+ // clear value from 'data' if 'loadop' is GL_CLEAR_ANGLE, otherwise clears to zero.
+ //
+ // 'data' is interpereted as either 4 GLfloats, 4 GLints, or 4 GLuints, depending on
+ // mInternalFormat.
+ //
+ // The context must internally disable the scissor test before calling this method, since the
+ // intention is to clear the entire surface.
+ void performLoadOperationClear(Context *, GLint drawbuffer, GLenum loadop, const void *data);
+
+ // Binds this PLS plane to a texture image unit for image load/store shader operations.
+ void bindToImage(Context *, Extents plsExtents, GLuint unit, bool needsR32Packing);
+
+ private:
+ // Ensures we have an internal backing texture for memoryless planes. In GL, we need a backing
+ // texture even if the plane is memoryless; glInvalidateFramebuffer() will ideally prevent the
+ // driver from writing out data where possible.
+ void ensureBackingIfMemoryless(Context *, Extents plsSize);
+
+ GLenum mInternalformat = GL_NONE; // GL_NONE if this plane is in a deinitialized state.
+ bool mMemoryless = false;
+ TextureID mMemorylessTextureID{}; // We own memoryless backing textures and must delete them.
+ ImageIndex mTextureImageIndex;
+ Texture *mTextureRef = nullptr;
+};
+
+// Manages a collection of PixelLocalStoragePlanes and applies them to ANGLE's GL state.
+//
+// The main magic of ANGLE_shader_pixel_local_storage happens inside shaders, so we just emulate the
+// client API on top of ANGLE's OpenGL ES API for simplicity.
+class PixelLocalStorage
+{
+ public:
+ static std::unique_ptr<PixelLocalStorage> Make(const Context *);
+
+ PixelLocalStorage();
+ virtual ~PixelLocalStorage();
+
+ // Called when the owning framebuffer is being destroyed.
+ void onFramebufferDestroyed(const Context *);
+
+ // Deletes any GL objects that have been allocated for pixel local storage. These can't be
+ // cleaned up in the destructor because they require a non-const Context object.
+ void deleteContextObjects(Context *);
+
+ const PixelLocalStoragePlane &getPlane(GLint plane) const
+ {
+ ASSERT(0 <= plane && plane < IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES);
+ return mPlanes[plane];
+ }
+
+ PixelLocalStoragePlane &getPlane(GLint plane)
+ {
+ ASSERT(0 <= plane && plane < IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES);
+ return mPlanes[plane];
+ }
+
+ // ANGLE_shader_pixel_local_storage API.
+ void deinitialize(Context *context, GLint plane) { mPlanes[plane].deinitialize(context); }
+ void setMemoryless(Context *context, GLint plane, GLenum internalformat)
+ {
+ mPlanes[plane].setMemoryless(context, internalformat);
+ }
+ void setTextureBacked(Context *context, GLint plane, Texture *tex, int level, int layer)
+ {
+ mPlanes[plane].setTextureBacked(context, tex, level, layer);
+ }
+ void begin(Context *, GLsizei n, const GLenum loadops[], const void *cleardata);
+ void end(Context *);
+ void barrier(Context *);
+
+ protected:
+ // Called when the context is lost or destroyed. Causes the subclass to clear its GL object
+ // handles.
+ virtual void onContextObjectsLost() = 0;
+
+ // Called when the framebuffer is being destroyed. Causes the subclass to delete its frontend GL
+ // object handles.
+ virtual void onDeleteContextObjects(Context *) = 0;
+
+ // ANGLE_shader_pixel_local_storage API.
+ virtual void onBegin(Context *,
+ GLsizei n,
+ const GLenum loadops[],
+ const char *cleardata,
+ Extents plsSize) = 0;
+ virtual void onEnd(Context *, GLsizei numActivePLSPlanes) = 0;
+ virtual void onBarrier(Context *) = 0;
+
+ private:
+ std::array<PixelLocalStoragePlane, IMPLEMENTATION_MAX_PIXEL_LOCAL_STORAGE_PLANES> mPlanes;
+
+ // "n" from the last call to begin(), or 0 if pixel local storage is not active.
+ GLsizei mNumActivePLSPlanes = 0;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_PIXEL_LOCAL_STORAGE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Platform.cpp b/gfx/angle/checkout/src/libANGLE/Platform.cpp
new file mode 100644
index 0000000000..d798fd4e86
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Platform.cpp
@@ -0,0 +1,76 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Platform.cpp: Implementation methods for angle::Platform.
+
+#include <platform/PlatformMethods.h>
+
+#include <cstring>
+
+#include "common/debug.h"
+
+namespace
+{
+// TODO(jmadill): Make methods owned by egl::Display.
+angle::PlatformMethods &PlatformMethods()
+{
+ static angle::PlatformMethods platformMethods;
+ return platformMethods;
+}
+} // anonymous namespace
+
+angle::PlatformMethods *ANGLEPlatformCurrent()
+{
+ return &PlatformMethods();
+}
+
+bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display,
+ const char *const methodNames[],
+ unsigned int methodNameCount,
+ void *context,
+ void *platformMethods)
+{
+ angle::PlatformMethods **platformMethodsOut =
+ reinterpret_cast<angle::PlatformMethods **>(platformMethods);
+
+ // We allow for a lower input count of impl platform methods if the subset is correct.
+ if (methodNameCount > angle::g_NumPlatformMethods)
+ {
+ ERR() << "Invalid platform method count: " << methodNameCount << ", expected "
+ << angle::g_NumPlatformMethods << ".";
+ return false;
+ }
+
+ for (unsigned int nameIndex = 0; nameIndex < methodNameCount; ++nameIndex)
+ {
+ const char *expectedName = angle::g_PlatformMethodNames[nameIndex];
+ const char *actualName = methodNames[nameIndex];
+
+ // Skip deprecated methods. The names of these methods start with |placeholder|.
+ constexpr char kPlaceholder[] = "placeholder";
+ if (strncmp(expectedName, kPlaceholder, sizeof(kPlaceholder) - 1) == 0)
+ {
+ continue;
+ }
+ if (strcmp(expectedName, actualName) != 0)
+ {
+ ERR() << "Invalid platform method name: " << actualName << ", expected " << expectedName
+ << ".";
+ return false;
+ }
+ }
+
+ // TODO(jmadill): Store platform methods in display.
+ PlatformMethods().context = context;
+ *platformMethodsOut = &PlatformMethods();
+ return true;
+}
+
+void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDisplayType display)
+{
+ // TODO(jmadill): Store platform methods in display.
+ PlatformMethods() = angle::PlatformMethods();
+}
diff --git a/gfx/angle/checkout/src/libANGLE/Program.cpp b/gfx/angle/checkout/src/libANGLE/Program.cpp
new file mode 100644
index 0000000000..3191a43ff3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Program.cpp
@@ -0,0 +1,3810 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Program.cpp: Implements the gl::Program class. Implements GL program objects
+// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
+
+#include "libANGLE/Program.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "common/angle_version_info.h"
+#include "common/bitset_utils.h"
+#include "common/debug.h"
+#include "common/platform.h"
+#include "common/string_utils.h"
+#include "common/utilities.h"
+#include "compiler/translator/blocklayout.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/MemoryProgramCache.h"
+#include "libANGLE/ProgramLinkedResources.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/VaryingPacking.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/capture/FrameCapture.h"
+#include "libANGLE/features.h"
+#include "libANGLE/histogram_macros.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/ProgramImpl.h"
+#include "platform/FrontendFeatures_autogen.h"
+#include "platform/PlatformMethods.h"
+
+namespace gl
+{
+
+namespace
+{
+
+// This simplified cast function doesn't need to worry about advanced concepts like
+// depth range values, or casting to bool.
+template <typename DestT, typename SrcT>
+DestT UniformStateQueryCast(SrcT value);
+
+// From-Float-To-Integer Casts
+template <>
+GLint UniformStateQueryCast(GLfloat value)
+{
+ return clampCast<GLint>(roundf(value));
+}
+
+template <>
+GLuint UniformStateQueryCast(GLfloat value)
+{
+ return clampCast<GLuint>(roundf(value));
+}
+
+// From-Integer-to-Integer Casts
+template <>
+GLint UniformStateQueryCast(GLuint value)
+{
+ return clampCast<GLint>(value);
+}
+
+template <>
+GLuint UniformStateQueryCast(GLint value)
+{
+ return clampCast<GLuint>(value);
+}
+
+// From-Boolean-to-Anything Casts
+template <>
+GLfloat UniformStateQueryCast(GLboolean value)
+{
+ return (ConvertToBool(value) ? 1.0f : 0.0f);
+}
+
+template <>
+GLint UniformStateQueryCast(GLboolean value)
+{
+ return (ConvertToBool(value) ? 1 : 0);
+}
+
+template <>
+GLuint UniformStateQueryCast(GLboolean value)
+{
+ return (ConvertToBool(value) ? 1u : 0u);
+}
+
+// Default to static_cast
+template <typename DestT, typename SrcT>
+DestT UniformStateQueryCast(SrcT value)
+{
+ return static_cast<DestT>(value);
+}
+
+template <typename SrcT, typename DestT>
+void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int components)
+{
+ for (int comp = 0; comp < components; ++comp)
+ {
+ // We only work with strides of 4 bytes for uniform components. (GLfloat/GLint)
+ // Don't use SrcT stride directly since GLboolean has a stride of 1 byte.
+ size_t offset = comp * 4;
+ const SrcT *typedSrcPointer = reinterpret_cast<const SrcT *>(&srcPointer[offset]);
+ dataOut[comp] = UniformStateQueryCast<DestT>(*typedSrcPointer);
+ }
+}
+
+template <typename VarT>
+GLuint GetResourceIndexFromName(const std::vector<VarT> &list, const std::string &name)
+{
+ std::string nameAsArrayName = name + "[0]";
+ for (size_t index = 0; index < list.size(); index++)
+ {
+ const VarT &resource = list[index];
+ if (resource.name == name || (resource.isArray() && resource.name == nameAsArrayName))
+ {
+ return static_cast<GLuint>(index);
+ }
+ }
+
+ return GL_INVALID_INDEX;
+}
+
+GLint GetVariableLocation(const std::vector<sh::ShaderVariable> &list,
+ const std::vector<VariableLocation> &locationList,
+ const std::string &name)
+{
+ size_t nameLengthWithoutArrayIndex;
+ unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
+
+ for (size_t location = 0u; location < locationList.size(); ++location)
+ {
+ const VariableLocation &variableLocation = locationList[location];
+ if (!variableLocation.used())
+ {
+ continue;
+ }
+
+ const sh::ShaderVariable &variable = list[variableLocation.index];
+
+ // Array output variables may be bound out of order, so we need to ensure we only pick the
+ // first element if given the base name.
+ if ((variable.name == name) && (variableLocation.arrayIndex == 0))
+ {
+ return static_cast<GLint>(location);
+ }
+ if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
+ angle::BeginsWith(variable.name, name, nameLengthWithoutArrayIndex))
+ {
+ return static_cast<GLint>(location);
+ }
+ }
+
+ return -1;
+}
+
+GLint GetVariableLocation(const std::vector<LinkedUniform> &list,
+ const std::vector<VariableLocation> &locationList,
+ const std::string &name)
+{
+ size_t nameLengthWithoutArrayIndex;
+ unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
+
+ for (size_t location = 0u; location < locationList.size(); ++location)
+ {
+ const VariableLocation &variableLocation = locationList[location];
+ if (!variableLocation.used())
+ {
+ continue;
+ }
+
+ const LinkedUniform &variable = list[variableLocation.index];
+
+ // Array output variables may be bound out of order, so we need to ensure we only pick the
+ // first element if given the base name. Uniforms don't allow this behavior and some code
+ // seemingly depends on the opposite behavior, so only enable it for output variables.
+ if (angle::BeginsWith(variable.name, name) && (variableLocation.arrayIndex == 0))
+ {
+ if (name.length() == variable.name.length())
+ {
+ ASSERT(name == variable.name);
+ // GLES 3.1 November 2016 page 87.
+ // The string exactly matches the name of the active variable.
+ return static_cast<GLint>(location);
+ }
+ if (name.length() + 3u == variable.name.length() && variable.isArray())
+ {
+ ASSERT(name + "[0]" == variable.name);
+ // The string identifies the base name of an active array, where the string would
+ // exactly match the name of the variable if the suffix "[0]" were appended to the
+ // string.
+ return static_cast<GLint>(location);
+ }
+ }
+ if (variable.isArray() && variableLocation.arrayIndex == arrayIndex &&
+ nameLengthWithoutArrayIndex + 3u == variable.name.length() &&
+ angle::BeginsWith(variable.name, name, nameLengthWithoutArrayIndex))
+ {
+ ASSERT(name.substr(0u, nameLengthWithoutArrayIndex) + "[0]" == variable.name);
+ // The string identifies an active element of the array, where the string ends with the
+ // concatenation of the "[" character, an integer (with no "+" sign, extra leading
+ // zeroes, or whitespace) identifying an array element, and the "]" character, the
+ // integer is less than the number of active elements of the array variable, and where
+ // the string would exactly match the enumerated name of the array if the decimal
+ // integer were replaced with zero.
+ return static_cast<GLint>(location);
+ }
+ }
+
+ return -1;
+}
+
+void CopyStringToBuffer(GLchar *buffer,
+ const std::string &string,
+ GLsizei bufSize,
+ GLsizei *lengthOut)
+{
+ ASSERT(bufSize > 0);
+ size_t length = std::min<size_t>(bufSize - 1, string.length());
+ memcpy(buffer, string.c_str(), length);
+ buffer[length] = '\0';
+
+ if (lengthOut)
+ {
+ *lengthOut = static_cast<GLsizei>(length);
+ }
+}
+
+GLuint GetInterfaceBlockIndex(const std::vector<InterfaceBlock> &list, const std::string &name)
+{
+ std::vector<unsigned int> subscripts;
+ std::string baseName = ParseResourceName(name, &subscripts);
+
+ unsigned int numBlocks = static_cast<unsigned int>(list.size());
+ for (unsigned int blockIndex = 0; blockIndex < numBlocks; blockIndex++)
+ {
+ const auto &block = list[blockIndex];
+ if (block.name == baseName)
+ {
+ const bool arrayElementZero =
+ (subscripts.empty() && (!block.isArray || block.arrayElement == 0));
+ const bool arrayElementMatches =
+ (subscripts.size() == 1 && subscripts[0] == block.arrayElement);
+ if (arrayElementMatches || arrayElementZero)
+ {
+ return blockIndex;
+ }
+ }
+ }
+
+ return GL_INVALID_INDEX;
+}
+
+void GetInterfaceBlockName(const UniformBlockIndex index,
+ const std::vector<InterfaceBlock> &list,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name)
+{
+ ASSERT(index.value < list.size());
+
+ const auto &block = list[index.value];
+
+ if (bufSize > 0)
+ {
+ std::string blockName = block.name;
+
+ if (block.isArray)
+ {
+ blockName += ArrayString(block.arrayElement);
+ }
+ CopyStringToBuffer(name, blockName, bufSize, length);
+ }
+}
+
+void InitUniformBlockLinker(const Context *context,
+ const ProgramState &state,
+ UniformBlockLinker *blockLinker)
+{
+ for (ShaderType shaderType : AllShaderTypes())
+ {
+ Shader *shader = state.getAttachedShader(shaderType);
+ if (shader)
+ {
+ blockLinker->addShaderBlocks(shaderType, &shader->getUniformBlocks(context));
+ }
+ }
+}
+
+void InitShaderStorageBlockLinker(const Context *context,
+ const ProgramState &state,
+ ShaderStorageBlockLinker *blockLinker)
+{
+ for (ShaderType shaderType : AllShaderTypes())
+ {
+ Shader *shader = state.getAttachedShader(shaderType);
+ if (shader != nullptr)
+ {
+ blockLinker->addShaderBlocks(shaderType, &shader->getShaderStorageBlocks(context));
+ }
+ }
+}
+} // anonymous namespace
+
+const char *GetLinkMismatchErrorString(LinkMismatchError linkError)
+{
+ switch (linkError)
+ {
+ case LinkMismatchError::TYPE_MISMATCH:
+ return "Type";
+ case LinkMismatchError::ARRAYNESS_MISMATCH:
+ return "Array-ness";
+ case LinkMismatchError::ARRAY_SIZE_MISMATCH:
+ return "Array size";
+ case LinkMismatchError::PRECISION_MISMATCH:
+ return "Precision";
+ case LinkMismatchError::STRUCT_NAME_MISMATCH:
+ return "Structure name";
+ case LinkMismatchError::FIELD_NUMBER_MISMATCH:
+ return "Field number";
+ case LinkMismatchError::FIELD_NAME_MISMATCH:
+ return "Field name";
+
+ case LinkMismatchError::INTERPOLATION_TYPE_MISMATCH:
+ return "Interpolation type";
+ case LinkMismatchError::INVARIANCE_MISMATCH:
+ return "Invariance";
+
+ case LinkMismatchError::BINDING_MISMATCH:
+ return "Binding layout qualifier";
+ case LinkMismatchError::LOCATION_MISMATCH:
+ return "Location layout qualifier";
+ case LinkMismatchError::OFFSET_MISMATCH:
+ return "Offset layout qualifier";
+ case LinkMismatchError::INSTANCE_NAME_MISMATCH:
+ return "Instance name qualifier";
+ case LinkMismatchError::FORMAT_MISMATCH:
+ return "Format qualifier";
+
+ case LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH:
+ return "Layout qualifier";
+ case LinkMismatchError::MATRIX_PACKING_MISMATCH:
+ return "Matrix Packing";
+
+ case LinkMismatchError::FIELD_LOCATION_MISMATCH:
+ return "Field location";
+ case LinkMismatchError::FIELD_STRUCT_NAME_MISMATCH:
+ return "Field structure name";
+ default:
+ UNREACHABLE();
+ return "";
+ }
+}
+
+void UpdateInterfaceVariable(std::vector<sh::ShaderVariable> *block, const sh::ShaderVariable &var)
+{
+ if (!var.isStruct())
+ {
+ block->emplace_back(var);
+ block->back().resetEffectiveLocation();
+ }
+
+ for (const sh::ShaderVariable &field : var.fields)
+ {
+ ASSERT(!var.name.empty() || var.isShaderIOBlock);
+
+ // Shader I/O block naming is similar to UBOs and SSBOs:
+ //
+ // in Block
+ // {
+ // type field; // produces "field"
+ // };
+ //
+ // in Block2
+ // {
+ // type field; // produces "Block2.field"
+ // } block2;
+ //
+ const std::string &baseName = var.isShaderIOBlock ? var.structOrBlockName : var.name;
+ const std::string prefix = var.name.empty() ? "" : baseName + ".";
+
+ if (!field.isStruct())
+ {
+ sh::ShaderVariable fieldCopy = field;
+ fieldCopy.updateEffectiveLocation(var);
+ fieldCopy.name = prefix + field.name;
+ block->emplace_back(fieldCopy);
+ }
+
+ for (const sh::ShaderVariable &nested : field.fields)
+ {
+ sh::ShaderVariable nestedCopy = nested;
+ nestedCopy.updateEffectiveLocation(field);
+ nestedCopy.name = prefix + field.name + "." + nested.name;
+ block->emplace_back(nestedCopy);
+ }
+ }
+}
+
+void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var)
+{
+ stream->writeInt(var.binding);
+ stream->writeInt(var.dataSize);
+
+ for (ShaderType shaderType : AllShaderTypes())
+ {
+ stream->writeBool(var.isActive(shaderType));
+ }
+
+ stream->writeInt(var.memberIndexes.size());
+ for (unsigned int memberCounterIndex : var.memberIndexes)
+ {
+ stream->writeInt(memberCounterIndex);
+ }
+}
+
+void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *var)
+{
+ var->binding = stream->readInt<int>();
+ var->dataSize = stream->readInt<unsigned int>();
+
+ for (ShaderType shaderType : AllShaderTypes())
+ {
+ var->setActive(shaderType, stream->readBool());
+ }
+
+ size_t numMembers = stream->readInt<size_t>();
+ for (size_t blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++)
+ {
+ var->memberIndexes.push_back(stream->readInt<unsigned int>());
+ }
+}
+
+void WriteBufferVariable(BinaryOutputStream *stream, const BufferVariable &var)
+{
+ WriteShaderVar(stream, var);
+
+ stream->writeInt(var.bufferIndex);
+ WriteBlockMemberInfo(stream, var.blockInfo);
+ stream->writeInt(var.topLevelArraySize);
+
+ for (ShaderType shaderType : AllShaderTypes())
+ {
+ stream->writeBool(var.isActive(shaderType));
+ }
+}
+
+void LoadBufferVariable(BinaryInputStream *stream, BufferVariable *var)
+{
+ LoadShaderVar(stream, var);
+
+ var->bufferIndex = stream->readInt<int>();
+ LoadBlockMemberInfo(stream, &var->blockInfo);
+ var->topLevelArraySize = stream->readInt<int>();
+
+ for (ShaderType shaderType : AllShaderTypes())
+ {
+ var->setActive(shaderType, stream->readBool());
+ }
+}
+
+void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block)
+{
+ stream->writeString(block.name);
+ stream->writeString(block.mappedName);
+ stream->writeBool(block.isArray);
+ stream->writeInt(block.arrayElement);
+
+ WriteShaderVariableBuffer(stream, block);
+}
+
+void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block)
+{
+ block->name = stream->readString();
+ block->mappedName = stream->readString();
+ block->isArray = stream->readBool();
+ block->arrayElement = stream->readInt<unsigned int>();
+
+ LoadShaderVariableBuffer(stream, block);
+}
+
+void WriteShInterfaceBlock(BinaryOutputStream *stream, const sh::InterfaceBlock &block)
+{
+ stream->writeString(block.name);
+ stream->writeString(block.mappedName);
+ stream->writeString(block.instanceName);
+ stream->writeInt(block.arraySize);
+ stream->writeEnum(block.layout);
+ stream->writeBool(block.isRowMajorLayout);
+ stream->writeInt(block.binding);
+ stream->writeBool(block.staticUse);
+ stream->writeBool(block.active);
+ stream->writeEnum(block.blockType);
+
+ stream->writeInt<size_t>(block.fields.size());
+ for (const sh::ShaderVariable &shaderVariable : block.fields)
+ {
+ WriteShaderVar(stream, shaderVariable);
+ }
+}
+
+void LoadShInterfaceBlock(BinaryInputStream *stream, sh::InterfaceBlock *block)
+{
+ block->name = stream->readString();
+ block->mappedName = stream->readString();
+ block->instanceName = stream->readString();
+ block->arraySize = stream->readInt<unsigned int>();
+ block->layout = stream->readEnum<sh::BlockLayoutType>();
+ block->isRowMajorLayout = stream->readBool();
+ block->binding = stream->readInt<int>();
+ block->staticUse = stream->readBool();
+ block->active = stream->readBool();
+ block->blockType = stream->readEnum<sh::BlockType>();
+
+ block->fields.resize(stream->readInt<size_t>());
+ for (sh::ShaderVariable &variable : block->fields)
+ {
+ LoadShaderVar(stream, &variable);
+ }
+}
+
+// Saves the linking context for later use in resolveLink().
+struct Program::LinkingState
+{
+ std::shared_ptr<ProgramExecutable> linkedExecutable;
+ ProgramLinkedResources resources;
+ egl::BlobCache::Key programHash;
+ std::unique_ptr<rx::LinkEvent> linkEvent;
+ bool linkingFromBinary;
+};
+
+const char *const g_fakepath = "C:\\fakepath";
+
+// InfoLog implementation.
+InfoLog::InfoLog() : mLazyStream(nullptr) {}
+
+InfoLog::~InfoLog() {}
+
+size_t InfoLog::getLength() const
+{
+ if (!mLazyStream)
+ {
+ return 0;
+ }
+
+ const std::string &logString = mLazyStream->str();
+ return logString.empty() ? 0 : logString.length() + 1;
+}
+
+void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
+{
+ size_t index = 0;
+
+ if (bufSize > 0)
+ {
+ const std::string logString(str());
+
+ if (!logString.empty())
+ {
+ index = std::min(static_cast<size_t>(bufSize) - 1, logString.length());
+ memcpy(infoLog, logString.c_str(), index);
+ }
+
+ infoLog[index] = '\0';
+ }
+
+ if (length)
+ {
+ *length = static_cast<GLsizei>(index);
+ }
+}
+
+// append a sanitized message to the program info log.
+// The D3D compiler includes a fake file path in some of the warning or error
+// messages, so lets remove all occurrences of this fake file path from the log.
+void InfoLog::appendSanitized(const char *message)
+{
+ ensureInitialized();
+
+ std::string msg(message);
+
+ size_t found;
+ do
+ {
+ found = msg.find(g_fakepath);
+ if (found != std::string::npos)
+ {
+ msg.erase(found, strlen(g_fakepath));
+ }
+ } while (found != std::string::npos);
+
+ if (!msg.empty())
+ {
+ *mLazyStream << message << std::endl;
+ }
+}
+
+void InfoLog::reset()
+{
+ if (mLazyStream)
+ {
+ mLazyStream.reset(nullptr);
+ }
+}
+
+bool InfoLog::empty() const
+{
+ if (!mLazyStream)
+ {
+ return true;
+ }
+
+ return mLazyStream->rdbuf()->in_avail() == 0;
+}
+
+void LogLinkMismatch(InfoLog &infoLog,
+ const std::string &variableName,
+ const char *variableType,
+ LinkMismatchError linkError,
+ const std::string &mismatchedStructOrBlockFieldName,
+ ShaderType shaderType1,
+ ShaderType shaderType2)
+{
+ std::ostringstream stream;
+ stream << GetLinkMismatchErrorString(linkError) << "s of " << variableType << " '"
+ << variableName;
+
+ if (!mismatchedStructOrBlockFieldName.empty())
+ {
+ stream << "' member '" << variableName << "." << mismatchedStructOrBlockFieldName;
+ }
+
+ stream << "' differ between " << GetShaderTypeString(shaderType1) << " and "
+ << GetShaderTypeString(shaderType2) << " shaders.";
+
+ infoLog << stream.str();
+}
+
+bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock)
+{
+ // Only 'packed' blocks are allowed to be considered inactive.
+ return interfaceBlock.active || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED;
+}
+
+void WriteBlockMemberInfo(BinaryOutputStream *stream, const sh::BlockMemberInfo &var)
+{
+ stream->writeInt(var.arrayStride);
+ stream->writeBool(var.isRowMajorMatrix);
+ stream->writeInt(var.matrixStride);
+ stream->writeInt(var.offset);
+ stream->writeInt(var.topLevelArrayStride);
+}
+
+void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var)
+{
+ var->arrayStride = stream->readInt<int>();
+ var->isRowMajorMatrix = stream->readBool();
+ var->matrixStride = stream->readInt<int>();
+ var->offset = stream->readInt<int>();
+ var->topLevelArrayStride = stream->readInt<int>();
+}
+
+void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var)
+{
+ stream->writeInt(var.type);
+ stream->writeInt(var.precision);
+ stream->writeString(var.name);
+ stream->writeString(var.mappedName);
+ stream->writeIntVector(var.arraySizes);
+ stream->writeBool(var.staticUse);
+ stream->writeBool(var.active);
+ stream->writeInt<size_t>(var.fields.size());
+ for (const sh::ShaderVariable &shaderVariable : var.fields)
+ {
+ WriteShaderVar(stream, shaderVariable);
+ }
+ stream->writeString(var.structOrBlockName);
+ stream->writeString(var.mappedStructOrBlockName);
+ stream->writeBool(var.isRowMajorLayout);
+ stream->writeInt(var.location);
+ stream->writeBool(var.hasImplicitLocation);
+ stream->writeInt(var.binding);
+ stream->writeInt(var.imageUnitFormat);
+ stream->writeInt(var.offset);
+ stream->writeBool(var.rasterOrdered);
+ stream->writeBool(var.readonly);
+ stream->writeBool(var.writeonly);
+ stream->writeBool(var.isFragmentInOut);
+ stream->writeInt(var.index);
+ stream->writeBool(var.yuv);
+ stream->writeEnum(var.interpolation);
+ stream->writeBool(var.isInvariant);
+ stream->writeBool(var.isShaderIOBlock);
+ stream->writeBool(var.isPatch);
+ stream->writeBool(var.texelFetchStaticUse);
+ stream->writeInt(var.getFlattenedOffsetInParentArrays());
+}
+
+void LoadShaderVar(gl::BinaryInputStream *stream, sh::ShaderVariable *var)
+{
+ var->type = stream->readInt<GLenum>();
+ var->precision = stream->readInt<GLenum>();
+ stream->readString(&var->name);
+ stream->readString(&var->mappedName);
+ stream->readIntVector<unsigned int>(&var->arraySizes);
+ var->staticUse = stream->readBool();
+ var->active = stream->readBool();
+ size_t elementCount = stream->readInt<size_t>();
+ var->fields.resize(elementCount);
+ for (sh::ShaderVariable &variable : var->fields)
+ {
+ LoadShaderVar(stream, &variable);
+ }
+ stream->readString(&var->structOrBlockName);
+ stream->readString(&var->mappedStructOrBlockName);
+ var->isRowMajorLayout = stream->readBool();
+ var->location = stream->readInt<int>();
+ var->hasImplicitLocation = stream->readBool();
+ var->binding = stream->readInt<int>();
+ var->imageUnitFormat = stream->readInt<GLenum>();
+ var->offset = stream->readInt<int>();
+ var->rasterOrdered = stream->readBool();
+ var->readonly = stream->readBool();
+ var->writeonly = stream->readBool();
+ var->isFragmentInOut = stream->readBool();
+ var->index = stream->readInt<int>();
+ var->yuv = stream->readBool();
+ var->interpolation = stream->readEnum<sh::InterpolationType>();
+ var->isInvariant = stream->readBool();
+ var->isShaderIOBlock = stream->readBool();
+ var->isPatch = stream->readBool();
+ var->texelFetchStaticUse = stream->readBool();
+ var->setParentArrayIndex(stream->readInt<int>());
+}
+
+// VariableLocation implementation.
+VariableLocation::VariableLocation() : arrayIndex(0), index(kUnused), ignored(false) {}
+
+VariableLocation::VariableLocation(unsigned int arrayIndex, unsigned int index)
+ : arrayIndex(arrayIndex), index(index), ignored(false)
+{
+ ASSERT(arrayIndex != GL_INVALID_INDEX);
+}
+
+// SamplerBindings implementation.
+SamplerBinding::SamplerBinding(TextureType textureTypeIn,
+ GLenum samplerTypeIn,
+ SamplerFormat formatIn,
+ size_t elementCount)
+ : textureType(textureTypeIn),
+ samplerType(samplerTypeIn),
+ format(formatIn),
+ boundTextureUnits(elementCount, 0)
+{}
+
+SamplerBinding::SamplerBinding(const SamplerBinding &other) = default;
+
+SamplerBinding::~SamplerBinding() = default;
+
+// ProgramBindings implementation.
+ProgramBindings::ProgramBindings() {}
+
+ProgramBindings::~ProgramBindings() {}
+
+void ProgramBindings::bindLocation(GLuint index, const std::string &name)
+{
+ mBindings[name] = index;
+}
+
+int ProgramBindings::getBindingByName(const std::string &name) const
+{
+ auto iter = mBindings.find(name);
+ return (iter != mBindings.end()) ? iter->second : -1;
+}
+
+int ProgramBindings::getBinding(const sh::ShaderVariable &variable) const
+{
+ return getBindingByName(variable.name);
+}
+
+ProgramBindings::const_iterator ProgramBindings::begin() const
+{
+ return mBindings.begin();
+}
+
+ProgramBindings::const_iterator ProgramBindings::end() const
+{
+ return mBindings.end();
+}
+
+std::map<std::string, GLuint> ProgramBindings::getStableIterationMap() const
+{
+ return std::map<std::string, GLuint>(mBindings.begin(), mBindings.end());
+}
+
+// ProgramAliasedBindings implementation.
+ProgramAliasedBindings::ProgramAliasedBindings() {}
+
+ProgramAliasedBindings::~ProgramAliasedBindings() {}
+
+void ProgramAliasedBindings::bindLocation(GLuint index, const std::string &name)
+{
+ mBindings[name] = ProgramBinding(index);
+
+ // EXT_blend_func_extended spec: "If it specifies the base name of an array,
+ // it identifies the resources associated with the first element of the array."
+ //
+ // Normalize array bindings so that "name" and "name[0]" map to the same entry.
+ // If this binding is of the form "name[0]", then mark the "name" binding as
+ // aliased but do not update it yet in case "name" is not actually an array.
+ size_t nameLengthWithoutArrayIndex;
+ unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
+ if (arrayIndex == 0)
+ {
+ std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
+ auto iter = mBindings.find(baseName);
+ if (iter != mBindings.end())
+ {
+ iter->second.aliased = true;
+ }
+ }
+}
+
+int ProgramAliasedBindings::getBindingByName(const std::string &name) const
+{
+ auto iter = mBindings.find(name);
+ return (iter != mBindings.end()) ? iter->second.location : -1;
+}
+
+int ProgramAliasedBindings::getBindingByLocation(GLuint location) const
+{
+ for (const auto &iter : mBindings)
+ {
+ if (iter.second.location == location)
+ {
+ return iter.second.location;
+ }
+ }
+ return -1;
+}
+
+int ProgramAliasedBindings::getBinding(const sh::ShaderVariable &variable) const
+{
+ const std::string &name = variable.name;
+
+ // Check with the normalized array name if applicable.
+ if (variable.isArray())
+ {
+ size_t nameLengthWithoutArrayIndex;
+ unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
+ if (arrayIndex == 0)
+ {
+ std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
+ auto iter = mBindings.find(baseName);
+ // If "name" exists and is not aliased, that means it was modified more
+ // recently than its "name[0]" form and should be used instead of that.
+ if (iter != mBindings.end() && !iter->second.aliased)
+ {
+ return iter->second.location;
+ }
+ }
+ else if (arrayIndex == GL_INVALID_INDEX)
+ {
+ auto iter = mBindings.find(variable.name);
+ // If "name" exists and is not aliased, that means it was modified more
+ // recently than its "name[0]" form and should be used instead of that.
+ if (iter != mBindings.end() && !iter->second.aliased)
+ {
+ return iter->second.location;
+ }
+ // The base name was aliased, so use the name with the array notation.
+ return getBindingByName(name + "[0]");
+ }
+ }
+
+ return getBindingByName(name);
+}
+
+ProgramAliasedBindings::const_iterator ProgramAliasedBindings::begin() const
+{
+ return mBindings.begin();
+}
+
+ProgramAliasedBindings::const_iterator ProgramAliasedBindings::end() const
+{
+ return mBindings.end();
+}
+
+std::map<std::string, ProgramBinding> ProgramAliasedBindings::getStableIterationMap() const
+{
+ return std::map<std::string, ProgramBinding>(mBindings.begin(), mBindings.end());
+}
+
+// ImageBinding implementation.
+ImageBinding::ImageBinding(size_t count, TextureType textureTypeIn)
+ : textureType(textureTypeIn), boundImageUnits(count, 0)
+{}
+ImageBinding::ImageBinding(GLuint imageUnit, size_t count, TextureType textureTypeIn)
+ : textureType(textureTypeIn)
+{
+ for (size_t index = 0; index < count; ++index)
+ {
+ boundImageUnits.push_back(imageUnit + static_cast<GLuint>(index));
+ }
+}
+
+ImageBinding::ImageBinding(const ImageBinding &other) = default;
+
+ImageBinding::~ImageBinding() = default;
+
+// ProgramState implementation.
+ProgramState::ProgramState()
+ : mLabel(),
+ mAttachedShaders{},
+ mLocationsUsedForXfbExtension(0),
+ mBinaryRetrieveableHint(false),
+ mSeparable(false),
+ mNumViews(-1),
+ mDrawIDLocation(-1),
+ mBaseVertexLocation(-1),
+ mBaseInstanceLocation(-1),
+ mCachedBaseVertex(0),
+ mCachedBaseInstance(0),
+ mExecutable(new ProgramExecutable())
+{
+ mComputeShaderLocalSize.fill(1);
+}
+
+ProgramState::~ProgramState()
+{
+ ASSERT(!hasAttachedShader());
+}
+
+const std::string &ProgramState::getLabel()
+{
+ return mLabel;
+}
+
+Shader *ProgramState::getAttachedShader(ShaderType shaderType) const
+{
+ ASSERT(shaderType != ShaderType::InvalidEnum);
+ return mAttachedShaders[shaderType];
+}
+
+GLuint ProgramState::getUniformIndexFromName(const std::string &name) const
+{
+ return GetResourceIndexFromName(mExecutable->mUniforms, name);
+}
+
+GLuint ProgramState::getBufferVariableIndexFromName(const std::string &name) const
+{
+ return GetResourceIndexFromName(mBufferVariables, name);
+}
+
+GLuint ProgramState::getUniformIndexFromLocation(UniformLocation location) const
+{
+ ASSERT(location.value >= 0 && static_cast<size_t>(location.value) < mUniformLocations.size());
+ return mUniformLocations[location.value].index;
+}
+
+Optional<GLuint> ProgramState::getSamplerIndex(UniformLocation location) const
+{
+ GLuint index = getUniformIndexFromLocation(location);
+ if (!isSamplerUniformIndex(index))
+ {
+ return Optional<GLuint>::Invalid();
+ }
+
+ return getSamplerIndexFromUniformIndex(index);
+}
+
+bool ProgramState::isSamplerUniformIndex(GLuint index) const
+{
+ return mExecutable->mSamplerUniformRange.contains(index);
+}
+
+GLuint ProgramState::getSamplerIndexFromUniformIndex(GLuint uniformIndex) const
+{
+ ASSERT(isSamplerUniformIndex(uniformIndex));
+ return uniformIndex - mExecutable->mSamplerUniformRange.low();
+}
+
+GLuint ProgramState::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
+{
+ return mExecutable->getUniformIndexFromSamplerIndex(samplerIndex);
+}
+
+bool ProgramState::isImageUniformIndex(GLuint index) const
+{
+ return mExecutable->mImageUniformRange.contains(index);
+}
+
+GLuint ProgramState::getImageIndexFromUniformIndex(GLuint uniformIndex) const
+{
+ ASSERT(isImageUniformIndex(uniformIndex));
+ return uniformIndex - mExecutable->mImageUniformRange.low();
+}
+
+GLuint ProgramState::getAttributeLocation(const std::string &name) const
+{
+ for (const sh::ShaderVariable &attribute : mExecutable->mProgramInputs)
+ {
+ if (attribute.name == name)
+ {
+ return attribute.location;
+ }
+ }
+
+ return static_cast<GLuint>(-1);
+}
+
+bool ProgramState::hasAttachedShader() const
+{
+ for (const Shader *shader : mAttachedShaders)
+ {
+ if (shader)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+ShaderType ProgramState::getFirstAttachedShaderStageType() const
+{
+ const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
+ if (linkedStages.none())
+ {
+ return ShaderType::InvalidEnum;
+ }
+
+ return linkedStages.first();
+}
+
+ShaderType ProgramState::getLastAttachedShaderStageType() const
+{
+ const ShaderBitSet linkedStages = mExecutable->getLinkedShaderStages();
+ if (linkedStages.none())
+ {
+ return ShaderType::InvalidEnum;
+ }
+
+ return linkedStages.last();
+}
+
+ShaderType ProgramState::getAttachedTransformFeedbackStage() const
+{
+ if (mAttachedShaders[ShaderType::Geometry])
+ {
+ return ShaderType::Geometry;
+ }
+ if (mAttachedShaders[ShaderType::TessEvaluation])
+ {
+ return ShaderType::TessEvaluation;
+ }
+ return ShaderType::Vertex;
+}
+
+Program::Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle)
+ : mSerial(factory->generateSerial()),
+ mProgram(factory->createProgram(mState)),
+ mValidated(false),
+ mLinked(false),
+ mDeleteStatus(false),
+ mRefCount(0),
+ mResourceManager(manager),
+ mHandle(handle)
+{
+ ASSERT(mProgram);
+
+ unlink();
+}
+
+Program::~Program()
+{
+ ASSERT(!mProgram);
+}
+
+void Program::onDestroy(const Context *context)
+{
+ resolveLink(context);
+ for (ShaderType shaderType : AllShaderTypes())
+ {
+ if (mState.mAttachedShaders[shaderType])
+ {
+ mState.mAttachedShaders[shaderType]->release(context);
+ mState.mAttachedShaders[shaderType] = nullptr;
+ }
+ }
+
+ mProgram->destroy(context);
+
+ ASSERT(!mState.hasAttachedShader());
+ SafeDelete(mProgram);
+
+ delete this;
+}
+ShaderProgramID Program::id() const
+{
+ ASSERT(!mLinkingState);
+ return mHandle;
+}
+
+angle::Result Program::setLabel(const Context *context, const std::string &label)
+{
+ ASSERT(!mLinkingState);
+ mState.mLabel = label;
+
+ if (mProgram)
+ {
+ return mProgram->onLabelUpdate(context);
+ }
+ return angle::Result::Continue;
+}
+
+const std::string &Program::getLabel() const
+{
+ ASSERT(!mLinkingState);
+ return mState.mLabel;
+}
+
+void Program::attachShader(Shader *shader)
+{
+ ShaderType shaderType = shader->getType();
+ ASSERT(shaderType != ShaderType::InvalidEnum);
+
+ mState.mAttachedShaders[shaderType] = shader;
+ mState.mAttachedShaders[shaderType]->addRef();
+}
+
+void Program::detachShader(const Context *context, Shader *shader)
+{
+ resolveLink(context);
+ ShaderType shaderType = shader->getType();
+ ASSERT(shaderType != ShaderType::InvalidEnum);
+
+ ASSERT(mState.mAttachedShaders[shaderType] == shader);
+ shader->release(context);
+ mState.mAttachedShaders[shaderType] = nullptr;
+}
+
+int Program::getAttachedShadersCount() const
+{
+ ASSERT(!mLinkingState);
+ int numAttachedShaders = 0;
+ for (const Shader *shader : mState.mAttachedShaders)
+ {
+ if (shader)
+ {
+ ++numAttachedShaders;
+ }
+ }
+
+ return numAttachedShaders;
+}
+
+Shader *Program::getAttachedShader(ShaderType shaderType) const
+{
+ ASSERT(!mLinkingState);
+ return mState.getAttachedShader(shaderType);
+}
+
+void Program::bindAttributeLocation(GLuint index, const char *name)
+{
+ ASSERT(!mLinkingState);
+ mAttributeBindings.bindLocation(index, name);
+}
+
+void Program::bindUniformLocation(UniformLocation location, const char *name)
+{
+ ASSERT(!mLinkingState);
+ mState.mUniformLocationBindings.bindLocation(location.value, name);
+}
+
+void Program::bindFragmentOutputLocation(GLuint index, const char *name)
+{
+ mFragmentOutputLocations.bindLocation(index, name);
+}
+
+void Program::bindFragmentOutputIndex(GLuint index, const char *name)
+{
+ mFragmentOutputIndexes.bindLocation(index, name);
+}
+
+angle::Result Program::link(const Context *context)
+{
+ angle::Result result = linkImpl(context);
+
+ // Avoid having two ProgramExecutables if the link failed and the Program had successfully
+ // linked previously.
+ if (mLinkingState && mLinkingState->linkedExecutable)
+ {
+ mState.mExecutable = mLinkingState->linkedExecutable;
+ }
+
+ return result;
+}
+
+// The attached shaders are checked for linking errors by matching up their variables.
+// Uniform, input and output variables get collected.
+// The code gets compiled into binaries.
+angle::Result Program::linkImpl(const Context *context)
+{
+ ASSERT(!mLinkingState);
+ // Don't make any local variables pointing to anything within the ProgramExecutable, since
+ // unlink() could make a new ProgramExecutable making any references/pointers invalid.
+ auto *platform = ANGLEPlatformCurrent();
+ double startTime = platform->currentTime(platform);
+
+ // Unlink the program, but do not clear the validation-related caching yet, since we can still
+ // use the previously linked program if linking the shaders fails.
+ mLinked = false;
+
+ mState.mExecutable->resetInfoLog();
+
+ // Validate we have properly attached shaders before checking the cache.
+ if (!linkValidateShaders(context, mState.mExecutable->getInfoLog()))
+ {
+ return angle::Result::Continue;
+ }
+
+ egl::BlobCache::Key programHash = {0};
+ MemoryProgramCache *cache = context->getMemoryProgramCache();
+
+ // TODO: http://anglebug.com/4530: Enable program caching for separable programs
+ if (cache && !isSeparable())
+ {
+ std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
+ angle::Result cacheResult = cache->getProgram(context, this, &programHash);
+ ANGLE_TRY(cacheResult);
+
+ // Check explicitly for Continue, Incomplete means a cache miss
+ if (cacheResult == angle::Result::Continue)
+ {
+ std::scoped_lock lock(mHistogramMutex);
+ // Succeeded in loading the binaries in the front-end, back end may still be loading
+ // asynchronously
+ double delta = platform->currentTime(platform) - startTime;
+ int us = static_cast<int>(delta * 1000000.0);
+ ANGLE_HISTOGRAM_COUNTS("GPU.ANGLE.ProgramCache.ProgramCacheHitTimeUS", us);
+ return angle::Result::Continue;
+ }
+ }
+
+ // Cache load failed, fall through to normal linking.
+ unlink();
+ InfoLog &infoLog = mState.mExecutable->getInfoLog();
+
+ // Re-link shaders after the unlink call.
+ bool result = linkValidateShaders(context, infoLog);
+ ASSERT(result);
+
+ std::unique_ptr<LinkingState> linkingState(new LinkingState());
+ ProgramMergedVaryings mergedVaryings;
+ LinkingVariables linkingVariables(context, mState);
+ ProgramLinkedResources &resources = linkingState->resources;
+
+ resources.init(&mState.mExecutable->mUniformBlocks, &mState.mExecutable->mUniforms,
+ &mState.mExecutable->mShaderStorageBlocks, &mState.mBufferVariables,
+ &mState.mExecutable->mAtomicCounterBuffers);
+
+ // TODO: Fix incomplete linking. http://anglebug.com/6358
+ updateLinkedShaderStages();
+
+ InitUniformBlockLinker(context, mState, &resources.uniformBlockLinker);
+ InitShaderStorageBlockLinker(context, mState, &resources.shaderStorageBlockLinker);
+
+ if (mState.mAttachedShaders[ShaderType::Compute])
+ {
+ GLuint combinedImageUniforms = 0;
+ if (!linkUniforms(context, &resources.unusedUniforms, &combinedImageUniforms, infoLog))
+ {
+ return angle::Result::Continue;
+ }
+
+ GLuint combinedShaderStorageBlocks = 0u;
+ if (!LinkValidateProgramInterfaceBlocks(context,
+ mState.mExecutable->getLinkedShaderStages(),
+ resources, infoLog, &combinedShaderStorageBlocks))
+ {
+ return angle::Result::Continue;
+ }
+
+ // [OpenGL ES 3.1] Chapter 8.22 Page 203:
+ // A link error will be generated if the sum of the number of active image uniforms used in
+ // all shaders, the number of active shader storage blocks, and the number of active
+ // fragment shader outputs exceeds the implementation-dependent value of
+ // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
+ if (combinedImageUniforms + combinedShaderStorageBlocks >
+ static_cast<GLuint>(context->getCaps().maxCombinedShaderOutputResources))
+ {
+ infoLog
+ << "The sum of the number of active image uniforms, active shader storage blocks "
+ "and active fragment shader outputs exceeds "
+ "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
+ << context->getCaps().maxCombinedShaderOutputResources << ")";
+ return angle::Result::Continue;
+ }
+ }
+ else
+ {
+ if (!linkAttributes(context, infoLog))
+ {
+ return angle::Result::Continue;
+ }
+
+ if (!linkVaryings(context, infoLog))
+ {
+ return angle::Result::Continue;
+ }
+
+ GLuint combinedImageUniforms = 0;
+ if (!linkUniforms(context, &resources.unusedUniforms, &combinedImageUniforms, infoLog))
+ {
+ return angle::Result::Continue;
+ }
+
+ GLuint combinedShaderStorageBlocks = 0u;
+ if (!LinkValidateProgramInterfaceBlocks(context,
+ mState.mExecutable->getLinkedShaderStages(),
+ resources, infoLog, &combinedShaderStorageBlocks))
+ {
+ return angle::Result::Continue;
+ }
+
+ if (!LinkValidateProgramGlobalNames(infoLog, getExecutable(), linkingVariables))
+ {
+ return angle::Result::Continue;
+ }
+
+ gl::Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
+ if (vertexShader)
+ {
+ mState.mNumViews = vertexShader->getNumViews(context);
+ mState.mSpecConstUsageBits |= vertexShader->getSpecConstUsageBits();
+ }
+
+ gl::Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
+ if (fragmentShader)
+ {
+ if (!mState.mExecutable->linkValidateOutputVariables(
+ context->getCaps(), context->getExtensions(), context->getClientVersion(),
+ combinedImageUniforms, combinedShaderStorageBlocks,
+ fragmentShader->getActiveOutputVariables(context),
+ fragmentShader->getShaderVersion(context), mFragmentOutputLocations,
+ mFragmentOutputIndexes))
+ {
+ return angle::Result::Continue;
+ }
+
+ mState.mExecutable->mHasDiscard = fragmentShader->hasDiscard();
+ mState.mExecutable->mEnablesPerSampleShading =
+ fragmentShader->enablesPerSampleShading();
+ mState.mExecutable->mAdvancedBlendEquations =
+ fragmentShader->getAdvancedBlendEquations();
+ mState.mSpecConstUsageBits |= fragmentShader->getSpecConstUsageBits();
+ }
+
+ mergedVaryings = GetMergedVaryingsFromLinkingVariables(linkingVariables);
+ if (!mState.mExecutable->linkMergedVaryings(
+ context, mergedVaryings, mState.mTransformFeedbackVaryingNames, linkingVariables,
+ isSeparable(), &resources.varyingPacking))
+ {
+ return angle::Result::Continue;
+ }
+ }
+
+ mState.mExecutable->saveLinkedStateInfo(context, mState);
+
+ mLinkingState = std::move(linkingState);
+ mLinkingState->linkingFromBinary = false;
+ mLinkingState->programHash = programHash;
+ mLinkingState->linkEvent = mProgram->link(context, resources, infoLog, mergedVaryings);
+
+ // Must be after mProgram->link() to avoid misleading the linker about output variables.
+ mState.updateProgramInterfaceInputs(context);
+ mState.updateProgramInterfaceOutputs(context);
+
+ if (mState.mSeparable)
+ {
+ mLinkingState->linkedExecutable = mState.mExecutable;
+ }
+
+ return angle::Result::Continue;
+}
+
+bool Program::isLinking() const
+{
+ return (mLinkingState.get() && mLinkingState->linkEvent &&
+ mLinkingState->linkEvent->isLinking());
+}
+
+void Program::resolveLinkImpl(const Context *context)
+{
+ ASSERT(mLinkingState.get());
+
+ angle::Result result = mLinkingState->linkEvent->wait(context);
+
+ mLinked = result == angle::Result::Continue;
+ std::unique_ptr<LinkingState> linkingState = std::move(mLinkingState);
+ if (!mLinked)
+ {
+ mState.mExecutable->reset(false);
+ return;
+ }
+
+ if (linkingState->linkingFromBinary)
+ {
+ // All internal Program state is already loaded from the binary.
+ return;
+ }
+
+ initInterfaceBlockBindings();
+
+ // According to GLES 3.0/3.1 spec for LinkProgram and UseProgram,
+ // Only successfully linked program can replace the executables.
+ ASSERT(mLinked);
+
+ // Mark implementation-specific unreferenced uniforms as ignored.
+ std::vector<ImageBinding> *imageBindings = getExecutable().getImageBindings();
+ mProgram->markUnusedUniformLocations(&mState.mUniformLocations,
+ &mState.mExecutable->mSamplerBindings, imageBindings);
+
+ // Must be called after markUnusedUniformLocations.
+ postResolveLink(context);
+
+ // Save to the program cache.
+ std::lock_guard<std::mutex> cacheLock(context->getProgramCacheMutex());
+ MemoryProgramCache *cache = context->getMemoryProgramCache();
+ // TODO: http://anglebug.com/4530: Enable program caching for separable programs
+ if (cache && !isSeparable() &&
+ (mState.mExecutable->mLinkedTransformFeedbackVaryings.empty() ||
+ !context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled))
+ {
+ if (cache->putProgram(linkingState->programHash, context, this) == angle::Result::Stop)
+ {
+ // Don't fail linking if putting the program binary into the cache fails, the program is
+ // still usable.
+ ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
+ "Failed to save linked program to memory program cache.");
+ }
+ }
+}
+
+void Program::updateLinkedShaderStages()
+{
+ mState.mExecutable->resetLinkedShaderStages();
+
+ for (const Shader *shader : mState.mAttachedShaders)
+ {
+ if (shader)
+ {
+ mState.mExecutable->setLinkedShaderStages(shader->getType());
+ }
+ }
+}
+
+void ProgramState::updateActiveSamplers()
+{
+ mExecutable->mActiveSamplerRefCounts.fill(0);
+ mExecutable->updateActiveSamplers(*this);
+}
+
+void ProgramState::updateProgramInterfaceInputs(const Context *context)
+{
+ const ShaderType firstAttachedShaderType = getFirstAttachedShaderStageType();
+
+ if (firstAttachedShaderType == ShaderType::Vertex)
+ {
+ // Vertex attributes are already what we need, so nothing to do
+ return;
+ }
+
+ Shader *shader = getAttachedShader(firstAttachedShaderType);
+ ASSERT(shader);
+
+ // Copy over each input varying, since the Shader could go away
+ if (shader->getType() == ShaderType::Compute)
+ {
+ for (const sh::ShaderVariable &attribute : shader->getAllAttributes(context))
+ {
+ // Compute Shaders have the following built-in input variables.
+ //
+ // in uvec3 gl_NumWorkGroups;
+ // in uvec3 gl_WorkGroupID;
+ // in uvec3 gl_LocalInvocationID;
+ // in uvec3 gl_GlobalInvocationID;
+ // in uint gl_LocalInvocationIndex;
+ // They are all vecs or uints, so no special handling is required.
+ mExecutable->mProgramInputs.emplace_back(attribute);
+ }
+ }
+ else
+ {
+ for (const sh::ShaderVariable &varying : shader->getInputVaryings(context))
+ {
+ UpdateInterfaceVariable(&mExecutable->mProgramInputs, varying);
+ }
+ }
+}
+
+void ProgramState::updateProgramInterfaceOutputs(const Context *context)
+{
+ const ShaderType lastAttachedShaderType = getLastAttachedShaderStageType();
+
+ if (lastAttachedShaderType == ShaderType::Fragment)
+ {
+ // Fragment outputs are already what we need, so nothing to do
+ return;
+ }
+ if (lastAttachedShaderType == ShaderType::Compute)
+ {
+ // If the program only contains a Compute Shader, then there are no user-defined outputs.
+ return;
+ }
+
+ Shader *shader = getAttachedShader(lastAttachedShaderType);
+ ASSERT(shader);
+
+ // Copy over each output varying, since the Shader could go away
+ for (const sh::ShaderVariable &varying : shader->getOutputVaryings(context))
+ {
+ UpdateInterfaceVariable(&mExecutable->mOutputVariables, varying);
+ }
+}
+
+// Returns the program object to an unlinked state, before re-linking, or at destruction
+void Program::unlink()
+{
+ if (mLinkingState && mLinkingState->linkedExecutable)
+ {
+ // The new ProgramExecutable that we'll attempt to link with needs to start from a copy of
+ // the last successfully linked ProgramExecutable, so we don't lose any state information.
+ mState.mExecutable.reset(new ProgramExecutable(*mLinkingState->linkedExecutable));
+ }
+ mState.mExecutable->reset(true);
+
+ mState.mUniformLocations.clear();
+ mState.mBufferVariables.clear();
+ mState.mComputeShaderLocalSize.fill(1);
+ mState.mNumViews = -1;
+ mState.mDrawIDLocation = -1;
+ mState.mBaseVertexLocation = -1;
+ mState.mBaseInstanceLocation = -1;
+ mState.mCachedBaseVertex = 0;
+ mState.mCachedBaseInstance = 0;
+ mState.mSpecConstUsageBits.reset();
+
+ mValidated = false;
+
+ mLinked = false;
+}
+
+angle::Result Program::loadBinary(const Context *context,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length)
+{
+ ASSERT(!mLinkingState);
+ unlink();
+ InfoLog &infoLog = mState.mExecutable->getInfoLog();
+
+ if (!angle::GetANGLEHasBinaryLoading())
+ {
+ return angle::Result::Incomplete;
+ }
+
+ ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE);
+ if (binaryFormat != GL_PROGRAM_BINARY_ANGLE)
+ {
+ infoLog << "Invalid program binary format.";
+ return angle::Result::Incomplete;
+ }
+
+ BinaryInputStream stream(binary, length);
+ ANGLE_TRY(deserialize(context, stream, infoLog));
+ // Currently we require the full shader text to compute the program hash.
+ // We could also store the binary in the internal program cache.
+
+ for (size_t uniformBlockIndex = 0;
+ uniformBlockIndex < mState.mExecutable->getActiveUniformBlockCount(); ++uniformBlockIndex)
+ {
+ mDirtyBits.set(uniformBlockIndex);
+ }
+
+ // The rx::LinkEvent returned from ProgramImpl::load is a base class with multiple
+ // implementations. In some implementations, a background thread is used to compile the
+ // shaders. Any calls to the LinkEvent object, therefore, are racy and may interfere with
+ // the operation.
+
+ // We do not want to call LinkEvent::wait because that will cause the background thread
+ // to finish its task before returning, thus defeating the purpose of background compilation.
+ // We need to defer waiting on background compilation until the very last minute when we
+ // absolutely need the results, such as when the developer binds the program or queries
+ // for the completion status.
+
+ // If load returns nullptr, we know for sure that the binary is not compatible with the backend.
+ // The loaded binary could have been read from the on-disk shader cache and be corrupted or
+ // serialized with different revision and subsystem id than the currently loaded backend.
+ // Returning 'Incomplete' to the caller results in link happening using the original shader
+ // sources.
+ angle::Result result;
+ std::unique_ptr<LinkingState> linkingState;
+ std::unique_ptr<rx::LinkEvent> linkEvent = mProgram->load(context, &stream, infoLog);
+ if (linkEvent)
+ {
+ linkingState = std::make_unique<LinkingState>();
+ linkingState->linkingFromBinary = true;
+ linkingState->linkEvent = std::move(linkEvent);
+ result = angle::Result::Continue;
+ }
+ else
+ {
+ result = angle::Result::Incomplete;
+ }
+ mLinkingState = std::move(linkingState);
+
+ return result;
+}
+
+angle::Result Program::saveBinary(Context *context,
+ GLenum *binaryFormat,
+ void *binary,
+ GLsizei bufSize,
+ GLsizei *length) const
+{
+ ASSERT(!mLinkingState);
+ if (binaryFormat)
+ {
+ *binaryFormat = GL_PROGRAM_BINARY_ANGLE;
+ }
+
+ angle::MemoryBuffer memoryBuf;
+ ANGLE_TRY(serialize(context, &memoryBuf));
+
+ GLsizei streamLength = static_cast<GLsizei>(memoryBuf.size());
+ const uint8_t *streamState = memoryBuf.data();
+
+ if (streamLength > bufSize)
+ {
+ if (length)
+ {
+ *length = 0;
+ }
+
+ // TODO: This should be moved to the validation layer but computing the size of the binary
+ // before saving it causes the save to happen twice. It may be possible to write the binary
+ // to a separate buffer, validate sizes and then copy it.
+ ANGLE_CHECK(context, false, "Insufficient buffer size", GL_INVALID_OPERATION);
+ }
+
+ if (binary)
+ {
+ char *ptr = reinterpret_cast<char *>(binary);
+
+ memcpy(ptr, streamState, streamLength);
+ ptr += streamLength;
+
+ ASSERT(ptr - streamLength == binary);
+ }
+
+ if (length)
+ {
+ *length = streamLength;
+ }
+
+ return angle::Result::Continue;
+}
+
+GLint Program::getBinaryLength(Context *context) const
+{
+ ASSERT(!mLinkingState);
+ if (!mLinked)
+ {
+ return 0;
+ }
+
+ GLint length;
+ angle::Result result =
+ saveBinary(context, nullptr, nullptr, std::numeric_limits<GLint>::max(), &length);
+ if (result != angle::Result::Continue)
+ {
+ return 0;
+ }
+
+ return length;
+}
+
+void Program::setBinaryRetrievableHint(bool retrievable)
+{
+ ASSERT(!mLinkingState);
+ // TODO(jmadill) : replace with dirty bits
+ mProgram->setBinaryRetrievableHint(retrievable);
+ mState.mBinaryRetrieveableHint = retrievable;
+}
+
+bool Program::getBinaryRetrievableHint() const
+{
+ ASSERT(!mLinkingState);
+ return mState.mBinaryRetrieveableHint;
+}
+
+void Program::setSeparable(bool separable)
+{
+ ASSERT(!mLinkingState);
+ // TODO(yunchao) : replace with dirty bits
+ if (mState.mSeparable != separable)
+ {
+ mProgram->setSeparable(separable);
+ mState.mSeparable = separable;
+ }
+}
+
+bool Program::isSeparable() const
+{
+ ASSERT(!mLinkingState);
+ return mState.mSeparable;
+}
+
+void Program::deleteSelf(const Context *context)
+{
+ ASSERT(mRefCount == 0 && mDeleteStatus);
+ mResourceManager->deleteProgram(context, mHandle);
+}
+
+unsigned int Program::getRefCount() const
+{
+ return mRefCount;
+}
+
+void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const
+{
+ ASSERT(!mLinkingState);
+ int total = 0;
+
+ for (const Shader *shader : mState.mAttachedShaders)
+ {
+ if (shader && (total < maxCount))
+ {
+ shaders[total] = shader->getHandle();
+ ++total;
+ }
+ }
+
+ if (count)
+ {
+ *count = total;
+ }
+}
+
+GLuint Program::getAttributeLocation(const std::string &name) const
+{
+ ASSERT(!mLinkingState);
+ return mState.getAttributeLocation(name);
+}
+
+void Program::getActiveAttribute(GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name) const
+{
+ ASSERT(!mLinkingState);
+ if (!mLinked)
+ {
+ if (bufsize > 0)
+ {
+ name[0] = '\0';
+ }
+
+ if (length)
+ {
+ *length = 0;
+ }
+
+ *type = GL_NONE;
+ *size = 1;
+ return;
+ }
+
+ ASSERT(index < mState.mExecutable->getProgramInputs().size());
+ const sh::ShaderVariable &attrib = mState.mExecutable->getProgramInputs()[index];
+
+ if (bufsize > 0)
+ {
+ CopyStringToBuffer(name, attrib.name, bufsize, length);
+ }
+
+ // Always a single 'type' instance
+ *size = 1;
+ *type = attrib.type;
+}
+
+GLint Program::getActiveAttributeCount() const
+{
+ ASSERT(!mLinkingState);
+ if (!mLinked)
+ {
+ return 0;
+ }
+
+ return static_cast<GLint>(mState.mExecutable->getProgramInputs().size());
+}
+
+GLint Program::getActiveAttributeMaxLength() const
+{
+ ASSERT(!mLinkingState);
+ if (!mLinked)
+ {
+ return 0;
+ }
+
+ size_t maxLength = 0;
+
+ for (const sh::ShaderVariable &attrib : mState.mExecutable->getProgramInputs())
+ {
+ maxLength = std::max(attrib.name.length() + 1, maxLength);
+ }
+
+ return static_cast<GLint>(maxLength);
+}
+
+const std::vector<sh::ShaderVariable> &Program::getAttributes() const
+{
+ ASSERT(!mLinkingState);
+ return mState.mExecutable->getProgramInputs();
+}
+
+const sh::WorkGroupSize &Program::getComputeShaderLocalSize() const
+{
+ ASSERT(!mLinkingState);
+ return mState.mComputeShaderLocalSize;
+}
+
+PrimitiveMode Program::getGeometryShaderInputPrimitiveType() const
+{
+ ASSERT(!mLinkingState && mState.mExecutable);
+ return mState.mExecutable->getGeometryShaderInputPrimitiveType();
+}
+PrimitiveMode Program::getGeometryShaderOutputPrimitiveType() const
+{
+ ASSERT(!mLinkingState && mState.mExecutable);
+ return mState.mExecutable->getGeometryShaderOutputPrimitiveType();
+}
+GLint Program::getGeometryShaderInvocations() const
+{
+ ASSERT(!mLinkingState && mState.mExecutable);
+ return mState.mExecutable->getGeometryShaderInvocations();
+}
+GLint Program::getGeometryShaderMaxVertices() const
+{
+ ASSERT(!mLinkingState && mState.mExecutable);
+ return mState.mExecutable->getGeometryShaderMaxVertices();
+}
+
+GLint Program::getTessControlShaderVertices() const
+{
+ ASSERT(!mLinkingState && mState.mExecutable);
+ return mState.mExecutable->mTessControlShaderVertices;
+}
+
+GLenum Program::getTessGenMode() const
+{
+ ASSERT(!mLinkingState && mState.mExecutable);
+ return mState.mExecutable->mTessGenMode;
+}
+
+GLenum Program::getTessGenPointMode() const
+{
+ ASSERT(!mLinkingState && mState.mExecutable);
+ return mState.mExecutable->mTessGenPointMode;
+}
+
+GLenum Program::getTessGenSpacing() const
+{
+ ASSERT(!mLinkingState && mState.mExecutable);
+ return mState.mExecutable->mTessGenSpacing;
+}
+
+GLenum Program::getTessGenVertexOrder() const
+{
+ ASSERT(!mLinkingState && mState.mExecutable);
+ return mState.mExecutable->mTessGenVertexOrder;
+}
+
+const sh::ShaderVariable &Program::getInputResource(size_t index) const
+{
+ ASSERT(!mLinkingState);
+ ASSERT(index < mState.mExecutable->getProgramInputs().size());
+ return mState.mExecutable->getProgramInputs()[index];
+}
+
+GLuint Program::getInputResourceIndex(const GLchar *name) const
+{
+ ASSERT(!mLinkingState);
+ const std::string nameString = StripLastArrayIndex(name);
+
+ for (size_t index = 0; index < mState.mExecutable->getProgramInputs().size(); index++)
+ {
+ sh::ShaderVariable resource = getInputResource(index);
+ if (resource.name == nameString)
+ {
+ return static_cast<GLuint>(index);
+ }
+ }
+
+ return GL_INVALID_INDEX;
+}
+
+GLuint Program::getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const
+{
+ if (resource.isArray())
+ {
+ return std::max(max, clampCast<GLint>((resource.name + "[0]").size()));
+ }
+ else
+ {
+ return std::max(max, clampCast<GLint>((resource.name).size()));
+ }
+}
+
+GLuint Program::getInputResourceMaxNameSize() const
+{
+ GLint max = 0;
+
+ for (const sh::ShaderVariable &resource : mState.mExecutable->getProgramInputs())
+ {
+ max = getResourceMaxNameSize(resource, max);
+ }
+
+ return max;
+}
+
+GLuint Program::getOutputResourceMaxNameSize() const
+{
+ GLint max = 0;
+
+ for (const sh::ShaderVariable &resource : mState.mExecutable->getOutputVariables())
+ {
+ max = getResourceMaxNameSize(resource, max);
+ }
+
+ return max;
+}
+
+GLuint Program::getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const
+{
+ if (variable.isBuiltIn())
+ {
+ return GL_INVALID_INDEX;
+ }
+
+ GLint location = variable.location;
+ if (variable.isArray())
+ {
+ size_t nameLengthWithoutArrayIndexOut;
+ size_t arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndexOut);
+ // The 'name' string may not contain the array notation "[0]"
+ if (arrayIndex != GL_INVALID_INDEX)
+ {
+ location += arrayIndex;
+ }
+ }
+
+ return location;
+}
+
+GLuint Program::getInputResourceLocation(const GLchar *name) const
+{
+ const GLuint index = getInputResourceIndex(name);
+ if (index == GL_INVALID_INDEX)
+ {
+ return index;
+ }
+
+ const sh::ShaderVariable &variable = getInputResource(index);
+
+ return getResourceLocation(name, variable);
+}
+
+GLuint Program::getOutputResourceLocation(const GLchar *name) const
+{
+ const GLuint index = getOutputResourceIndex(name);
+ if (index == GL_INVALID_INDEX)
+ {
+ return index;
+ }
+
+ const sh::ShaderVariable &variable = getOutputResource(index);
+
+ return getResourceLocation(name, variable);
+}
+
+GLuint Program::getOutputResourceIndex(const GLchar *name) const
+{
+ ASSERT(!mLinkingState);
+ const std::string nameString = StripLastArrayIndex(name);
+
+ for (size_t index = 0; index < mState.mExecutable->getOutputVariables().size(); index++)
+ {
+ sh::ShaderVariable resource = getOutputResource(index);
+ if (resource.name == nameString)
+ {
+ return static_cast<GLuint>(index);
+ }
+ }
+
+ return GL_INVALID_INDEX;
+}
+
+size_t Program::getOutputResourceCount() const
+{
+ ASSERT(!mLinkingState);
+ return (mLinked ? mState.mExecutable->getOutputVariables().size() : 0);
+}
+
+void Program::getResourceName(const std::string name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *dest) const
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (!mLinked)
+ {
+ if (bufSize > 0)
+ {
+ dest[0] = '\0';
+ }
+ return;
+ }
+
+ if (bufSize > 0)
+ {
+ CopyStringToBuffer(dest, name, bufSize, length);
+ }
+}
+
+void Program::getInputResourceName(GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name) const
+{
+ ASSERT(!mLinkingState);
+ getResourceName(getInputResourceName(index), bufSize, length, name);
+}
+
+void Program::getOutputResourceName(GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name) const
+{
+ ASSERT(!mLinkingState);
+ getResourceName(getOutputResourceName(index), bufSize, length, name);
+}
+
+void Program::getUniformResourceName(GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name) const
+{
+ ASSERT(!mLinkingState);
+ ASSERT(index < mState.mExecutable->getUniforms().size());
+ getResourceName(mState.mExecutable->getUniforms()[index].name, bufSize, length, name);
+}
+
+void Program::getBufferVariableResourceName(GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name) const
+{
+ ASSERT(!mLinkingState);
+ ASSERT(index < mState.mBufferVariables.size());
+ getResourceName(mState.mBufferVariables[index].name, bufSize, length, name);
+}
+
+const std::string Program::getResourceName(const sh::ShaderVariable &resource) const
+{
+ std::string resourceName = resource.name;
+
+ if (resource.isArray())
+ {
+ resourceName += "[0]";
+ }
+
+ return resourceName;
+}
+
+const std::string Program::getInputResourceName(GLuint index) const
+{
+ ASSERT(!mLinkingState);
+ const sh::ShaderVariable &resource = getInputResource(index);
+
+ return getResourceName(resource);
+}
+
+const std::string Program::getOutputResourceName(GLuint index) const
+{
+ ASSERT(!mLinkingState);
+ const sh::ShaderVariable &resource = getOutputResource(index);
+
+ return getResourceName(resource);
+}
+
+const sh::ShaderVariable &Program::getOutputResource(size_t index) const
+{
+ ASSERT(!mLinkingState);
+ ASSERT(index < mState.mExecutable->getOutputVariables().size());
+ return mState.mExecutable->getOutputVariables()[index];
+}
+
+const ProgramBindings &Program::getAttributeBindings() const
+{
+ ASSERT(!mLinkingState);
+ return mAttributeBindings;
+}
+const ProgramAliasedBindings &Program::getUniformLocationBindings() const
+{
+ ASSERT(!mLinkingState);
+ return mState.mUniformLocationBindings;
+}
+
+const gl::ProgramAliasedBindings &Program::getFragmentOutputLocations() const
+{
+ ASSERT(!mLinkingState);
+ return mFragmentOutputLocations;
+}
+
+const gl::ProgramAliasedBindings &Program::getFragmentOutputIndexes() const
+{
+ ASSERT(!mLinkingState);
+ return mFragmentOutputIndexes;
+}
+
+const std::vector<GLsizei> &Program::getTransformFeedbackStrides() const
+{
+ ASSERT(!mLinkingState);
+ return mState.mExecutable->getTransformFeedbackStrides();
+}
+
+GLint Program::getFragDataLocation(const std::string &name) const
+{
+ ASSERT(!mLinkingState);
+ GLint primaryLocation = GetVariableLocation(mState.mExecutable->getOutputVariables(),
+ mState.mExecutable->getOutputLocations(), name);
+ if (primaryLocation != -1)
+ {
+ return primaryLocation;
+ }
+ return GetVariableLocation(mState.mExecutable->getOutputVariables(),
+ mState.mExecutable->getSecondaryOutputLocations(), name);
+}
+
+GLint Program::getFragDataIndex(const std::string &name) const
+{
+ ASSERT(!mLinkingState);
+ if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
+ mState.mExecutable->getOutputLocations(), name) != -1)
+ {
+ return 0;
+ }
+ if (GetVariableLocation(mState.mExecutable->getOutputVariables(),
+ mState.mExecutable->getSecondaryOutputLocations(), name) != -1)
+ {
+ return 1;
+ }
+ return -1;
+}
+
+void Program::getActiveUniform(GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name) const
+{
+ ASSERT(!mLinkingState);
+ if (mLinked)
+ {
+ // index must be smaller than getActiveUniformCount()
+ ASSERT(index < mState.mExecutable->getUniforms().size());
+ const LinkedUniform &uniform = mState.mExecutable->getUniforms()[index];
+
+ if (bufsize > 0)
+ {
+ std::string string = uniform.name;
+ CopyStringToBuffer(name, string, bufsize, length);
+ }
+
+ *size = clampCast<GLint>(uniform.getBasicTypeElementCount());
+ *type = uniform.type;
+ }
+ else
+ {
+ if (bufsize > 0)
+ {
+ name[0] = '\0';
+ }
+
+ if (length)
+ {
+ *length = 0;
+ }
+
+ *size = 0;
+ *type = GL_NONE;
+ }
+}
+
+GLint Program::getActiveUniformCount() const
+{
+ ASSERT(!mLinkingState);
+ if (mLinked)
+ {
+ return static_cast<GLint>(mState.mExecutable->getUniforms().size());
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+size_t Program::getActiveBufferVariableCount() const
+{
+ ASSERT(!mLinkingState);
+ return mLinked ? mState.mBufferVariables.size() : 0;
+}
+
+GLint Program::getActiveUniformMaxLength() const
+{
+ ASSERT(!mLinkingState);
+ size_t maxLength = 0;
+
+ if (mLinked)
+ {
+ for (const LinkedUniform &uniform : mState.mExecutable->getUniforms())
+ {
+ if (!uniform.name.empty())
+ {
+ size_t length = uniform.name.length() + 1u;
+ if (uniform.isArray())
+ {
+ length += 3; // Counting in "[0]".
+ }
+ maxLength = std::max(length, maxLength);
+ }
+ }
+ }
+
+ return static_cast<GLint>(maxLength);
+}
+
+bool Program::isValidUniformLocation(UniformLocation location) const
+{
+ ASSERT(!mLinkingState);
+ ASSERT(angle::IsValueInRangeForNumericType<GLint>(mState.mUniformLocations.size()));
+ return (location.value >= 0 &&
+ static_cast<size_t>(location.value) < mState.mUniformLocations.size() &&
+ mState.mUniformLocations[static_cast<size_t>(location.value)].used());
+}
+
+const LinkedUniform &Program::getUniformByLocation(UniformLocation location) const
+{
+ ASSERT(!mLinkingState);
+ ASSERT(location.value >= 0 &&
+ static_cast<size_t>(location.value) < mState.mUniformLocations.size());
+ return mState.mExecutable->getUniforms()[mState.getUniformIndexFromLocation(location)];
+}
+
+const VariableLocation &Program::getUniformLocation(UniformLocation location) const
+{
+ ASSERT(!mLinkingState);
+ ASSERT(location.value >= 0 &&
+ static_cast<size_t>(location.value) < mState.mUniformLocations.size());
+ return mState.mUniformLocations[location.value];
+}
+
+const BufferVariable &Program::getBufferVariableByIndex(GLuint index) const
+{
+ ASSERT(!mLinkingState);
+ ASSERT(index < static_cast<size_t>(mState.mBufferVariables.size()));
+ return mState.mBufferVariables[index];
+}
+
+UniformLocation Program::getUniformLocation(const std::string &name) const
+{
+ ASSERT(!mLinkingState);
+ return {GetVariableLocation(mState.mExecutable->getUniforms(), mState.mUniformLocations, name)};
+}
+
+GLuint Program::getUniformIndex(const std::string &name) const
+{
+ ASSERT(!mLinkingState);
+ return mState.getUniformIndexFromName(name);
+}
+
+bool Program::shouldIgnoreUniform(UniformLocation location) const
+{
+ if (location.value == -1)
+ {
+ return true;
+ }
+
+ if (mState.mUniformLocations[static_cast<size_t>(location.value)].ignored)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+template <typename UniformT,
+ GLint UniformSize,
+ void (rx::ProgramImpl::*SetUniformFunc)(GLint, GLsizei, const UniformT *)>
+void Program::setUniformGeneric(UniformLocation location, GLsizei count, const UniformT *v)
+{
+ ASSERT(!mLinkingState);
+ if (shouldIgnoreUniform(location))
+ {
+ return;
+ }
+
+ const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
+ GLsizei clampedCount = clampUniformCount(locationInfo, count, UniformSize, v);
+ (mProgram->*SetUniformFunc)(location.value, clampedCount, v);
+ onStateChange(angle::SubjectMessage::ProgramUniformUpdated);
+}
+
+void Program::setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v)
+{
+ setUniformGeneric<GLfloat, 1, &rx::ProgramImpl::setUniform1fv>(location, count, v);
+}
+
+void Program::setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v)
+{
+ setUniformGeneric<GLfloat, 2, &rx::ProgramImpl::setUniform2fv>(location, count, v);
+}
+
+void Program::setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v)
+{
+ setUniformGeneric<GLfloat, 3, &rx::ProgramImpl::setUniform3fv>(location, count, v);
+}
+
+void Program::setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v)
+{
+ setUniformGeneric<GLfloat, 4, &rx::ProgramImpl::setUniform4fv>(location, count, v);
+}
+
+void Program::setUniform1iv(Context *context,
+ UniformLocation location,
+ GLsizei count,
+ const GLint *v)
+{
+ ASSERT(!mLinkingState);
+ if (shouldIgnoreUniform(location))
+ {
+ return;
+ }
+
+ const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
+ GLsizei clampedCount = clampUniformCount(locationInfo, count, 1, v);
+
+ mProgram->setUniform1iv(location.value, clampedCount, v);
+
+ if (mState.isSamplerUniformIndex(locationInfo.index))
+ {
+ updateSamplerUniform(context, locationInfo, clampedCount, v);
+ }
+ else
+ {
+ onStateChange(angle::SubjectMessage::ProgramUniformUpdated);
+ }
+}
+
+void Program::setUniform2iv(UniformLocation location, GLsizei count, const GLint *v)
+{
+ setUniformGeneric<GLint, 2, &rx::ProgramImpl::setUniform2iv>(location, count, v);
+}
+
+void Program::setUniform3iv(UniformLocation location, GLsizei count, const GLint *v)
+{
+ setUniformGeneric<GLint, 3, &rx::ProgramImpl::setUniform3iv>(location, count, v);
+}
+
+void Program::setUniform4iv(UniformLocation location, GLsizei count, const GLint *v)
+{
+ setUniformGeneric<GLint, 4, &rx::ProgramImpl::setUniform4iv>(location, count, v);
+}
+
+void Program::setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v)
+{
+ setUniformGeneric<GLuint, 1, &rx::ProgramImpl::setUniform1uiv>(location, count, v);
+}
+
+void Program::setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v)
+{
+ setUniformGeneric<GLuint, 2, &rx::ProgramImpl::setUniform2uiv>(location, count, v);
+}
+
+void Program::setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v)
+{
+ setUniformGeneric<GLuint, 3, &rx::ProgramImpl::setUniform3uiv>(location, count, v);
+}
+
+void Program::setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v)
+{
+ setUniformGeneric<GLuint, 4, &rx::ProgramImpl::setUniform4uiv>(location, count, v);
+}
+
+template <
+ typename UniformT,
+ GLint MatrixC,
+ GLint MatrixR,
+ void (rx::ProgramImpl::*SetUniformMatrixFunc)(GLint, GLsizei, GLboolean, const UniformT *)>
+void Program::setUniformMatrixGeneric(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const UniformT *v)
+{
+ ASSERT(!mLinkingState);
+ if (shouldIgnoreUniform(location))
+ {
+ return;
+ }
+
+ GLsizei clampedCount = clampMatrixUniformCount<MatrixC, MatrixR>(location, count, transpose, v);
+ (mProgram->*SetUniformMatrixFunc)(location.value, clampedCount, transpose, v);
+ onStateChange(angle::SubjectMessage::ProgramUniformUpdated);
+}
+
+void Program::setUniformMatrix2fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *v)
+{
+ setUniformMatrixGeneric<GLfloat, 2, 2, &rx::ProgramImpl::setUniformMatrix2fv>(location, count,
+ transpose, v);
+}
+
+void Program::setUniformMatrix3fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *v)
+{
+ setUniformMatrixGeneric<GLfloat, 3, 3, &rx::ProgramImpl::setUniformMatrix3fv>(location, count,
+ transpose, v);
+}
+
+void Program::setUniformMatrix4fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *v)
+{
+ setUniformMatrixGeneric<GLfloat, 4, 4, &rx::ProgramImpl::setUniformMatrix4fv>(location, count,
+ transpose, v);
+}
+
+void Program::setUniformMatrix2x3fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *v)
+{
+ setUniformMatrixGeneric<GLfloat, 2, 3, &rx::ProgramImpl::setUniformMatrix2x3fv>(location, count,
+ transpose, v);
+}
+
+void Program::setUniformMatrix2x4fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *v)
+{
+ setUniformMatrixGeneric<GLfloat, 2, 4, &rx::ProgramImpl::setUniformMatrix2x4fv>(location, count,
+ transpose, v);
+}
+
+void Program::setUniformMatrix3x2fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *v)
+{
+ setUniformMatrixGeneric<GLfloat, 3, 2, &rx::ProgramImpl::setUniformMatrix3x2fv>(location, count,
+ transpose, v);
+}
+
+void Program::setUniformMatrix3x4fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *v)
+{
+ setUniformMatrixGeneric<GLfloat, 3, 4, &rx::ProgramImpl::setUniformMatrix3x4fv>(location, count,
+ transpose, v);
+}
+
+void Program::setUniformMatrix4x2fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *v)
+{
+ setUniformMatrixGeneric<GLfloat, 4, 2, &rx::ProgramImpl::setUniformMatrix4x2fv>(location, count,
+ transpose, v);
+}
+
+void Program::setUniformMatrix4x3fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *v)
+{
+ setUniformMatrixGeneric<GLfloat, 4, 3, &rx::ProgramImpl::setUniformMatrix4x3fv>(location, count,
+ transpose, v);
+}
+
+GLuint Program::getSamplerUniformBinding(const VariableLocation &uniformLocation) const
+{
+ ASSERT(!mLinkingState);
+ GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(uniformLocation.index);
+ const std::vector<GLuint> &boundTextureUnits =
+ mState.mExecutable->mSamplerBindings[samplerIndex].boundTextureUnits;
+ return (uniformLocation.arrayIndex < boundTextureUnits.size())
+ ? boundTextureUnits[uniformLocation.arrayIndex]
+ : 0;
+}
+
+GLuint Program::getImageUniformBinding(const VariableLocation &uniformLocation) const
+{
+ ASSERT(!mLinkingState);
+ GLuint imageIndex = mState.getImageIndexFromUniformIndex(uniformLocation.index);
+
+ const std::vector<ImageBinding> &imageBindings = getExecutable().getImageBindings();
+ const std::vector<GLuint> &boundImageUnits = imageBindings[imageIndex].boundImageUnits;
+ return boundImageUnits[uniformLocation.arrayIndex];
+}
+
+void Program::getUniformfv(const Context *context, UniformLocation location, GLfloat *v) const
+{
+ ASSERT(!mLinkingState);
+ const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
+ const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index];
+
+ if (uniform.isSampler())
+ {
+ *v = static_cast<GLfloat>(getSamplerUniformBinding(uniformLocation));
+ return;
+ }
+ else if (uniform.isImage())
+ {
+ *v = static_cast<GLfloat>(getImageUniformBinding(uniformLocation));
+ return;
+ }
+
+ const GLenum nativeType = gl::VariableComponentType(uniform.type);
+ if (nativeType == GL_FLOAT)
+ {
+ mProgram->getUniformfv(context, location.value, v);
+ }
+ else
+ {
+ getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
+ }
+}
+
+void Program::getUniformiv(const Context *context, UniformLocation location, GLint *v) const
+{
+ ASSERT(!mLinkingState);
+ const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
+ const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index];
+
+ if (uniform.isSampler())
+ {
+ *v = static_cast<GLint>(getSamplerUniformBinding(uniformLocation));
+ return;
+ }
+ else if (uniform.isImage())
+ {
+ *v = static_cast<GLint>(getImageUniformBinding(uniformLocation));
+ return;
+ }
+
+ const GLenum nativeType = gl::VariableComponentType(uniform.type);
+ if (nativeType == GL_INT || nativeType == GL_BOOL)
+ {
+ mProgram->getUniformiv(context, location.value, v);
+ }
+ else
+ {
+ getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
+ }
+}
+
+void Program::getUniformuiv(const Context *context, UniformLocation location, GLuint *v) const
+{
+ ASSERT(!mLinkingState);
+ const VariableLocation &uniformLocation = mState.getUniformLocations()[location.value];
+ const LinkedUniform &uniform = mState.getUniforms()[uniformLocation.index];
+
+ if (uniform.isSampler())
+ {
+ *v = getSamplerUniformBinding(uniformLocation);
+ return;
+ }
+ else if (uniform.isImage())
+ {
+ *v = getImageUniformBinding(uniformLocation);
+ return;
+ }
+
+ const GLenum nativeType = VariableComponentType(uniform.type);
+ if (nativeType == GL_UNSIGNED_INT)
+ {
+ mProgram->getUniformuiv(context, location.value, v);
+ }
+ else
+ {
+ getUniformInternal(context, v, location, nativeType, VariableComponentCount(uniform.type));
+ }
+}
+
+void Program::flagForDeletion()
+{
+ ASSERT(!mLinkingState);
+ mDeleteStatus = true;
+}
+
+bool Program::isFlaggedForDeletion() const
+{
+ ASSERT(!mLinkingState);
+ return mDeleteStatus;
+}
+
+void Program::validate(const Caps &caps)
+{
+ ASSERT(!mLinkingState);
+ mState.mExecutable->resetInfoLog();
+ InfoLog &infoLog = mState.mExecutable->getInfoLog();
+
+ if (mLinked)
+ {
+ mValidated = ConvertToBool(mProgram->validate(caps, &infoLog));
+ }
+ else
+ {
+ infoLog << "Program has not been successfully linked.";
+ }
+}
+
+bool Program::isValidated() const
+{
+ ASSERT(!mLinkingState);
+ return mValidated;
+}
+
+void Program::getActiveUniformBlockName(const Context *context,
+ const UniformBlockIndex blockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *blockName) const
+{
+ ASSERT(!mLinkingState);
+ GetInterfaceBlockName(blockIndex, mState.mExecutable->getUniformBlocks(), bufSize, length,
+ blockName);
+}
+
+void Program::getActiveShaderStorageBlockName(const GLuint blockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *blockName) const
+{
+ ASSERT(!mLinkingState);
+ GetInterfaceBlockName({blockIndex}, mState.mExecutable->getShaderStorageBlocks(), bufSize,
+ length, blockName);
+}
+
+template <typename T>
+GLint Program::getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const
+{
+ int maxLength = 0;
+
+ if (mLinked)
+ {
+ for (const T &resource : resources)
+ {
+ if (!resource.name.empty())
+ {
+ int length = static_cast<int>(resource.nameWithArrayIndex().length());
+ maxLength = std::max(length + 1, maxLength);
+ }
+ }
+ }
+
+ return maxLength;
+}
+
+GLint Program::getActiveUniformBlockMaxNameLength() const
+{
+ ASSERT(!mLinkingState);
+ return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getUniformBlocks());
+}
+
+GLint Program::getActiveShaderStorageBlockMaxNameLength() const
+{
+ ASSERT(!mLinkingState);
+ return getActiveInterfaceBlockMaxNameLength(mState.mExecutable->getShaderStorageBlocks());
+}
+
+GLuint Program::getUniformBlockIndex(const std::string &name) const
+{
+ ASSERT(!mLinkingState);
+ return GetInterfaceBlockIndex(mState.mExecutable->getUniformBlocks(), name);
+}
+
+GLuint Program::getShaderStorageBlockIndex(const std::string &name) const
+{
+ ASSERT(!mLinkingState);
+ return GetInterfaceBlockIndex(mState.mExecutable->getShaderStorageBlocks(), name);
+}
+
+const InterfaceBlock &Program::getUniformBlockByIndex(GLuint index) const
+{
+ ASSERT(!mLinkingState);
+ ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveUniformBlockCount()));
+ return mState.mExecutable->getUniformBlocks()[index];
+}
+
+const InterfaceBlock &Program::getShaderStorageBlockByIndex(GLuint index) const
+{
+ ASSERT(!mLinkingState);
+ ASSERT(index < static_cast<GLuint>(mState.mExecutable->getActiveShaderStorageBlockCount()));
+ return mState.mExecutable->getShaderStorageBlocks()[index];
+}
+
+void Program::bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding)
+{
+ ASSERT(!mLinkingState);
+ mState.mExecutable->mUniformBlocks[uniformBlockIndex.value].binding = uniformBlockBinding;
+ mState.mExecutable->mActiveUniformBlockBindings.set(uniformBlockIndex.value,
+ uniformBlockBinding != 0);
+ mDirtyBits.set(DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + uniformBlockIndex.value);
+}
+
+GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
+{
+ ASSERT(!mLinkingState);
+ return mState.getUniformBlockBinding(uniformBlockIndex);
+}
+
+GLuint Program::getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const
+{
+ ASSERT(!mLinkingState);
+ return mState.getShaderStorageBlockBinding(shaderStorageBlockIndex);
+}
+
+void Program::setTransformFeedbackVaryings(GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode)
+{
+ ASSERT(!mLinkingState);
+ mState.mTransformFeedbackVaryingNames.resize(count);
+ for (GLsizei i = 0; i < count; i++)
+ {
+ mState.mTransformFeedbackVaryingNames[i] = varyings[i];
+ }
+
+ mState.mExecutable->mTransformFeedbackBufferMode = bufferMode;
+}
+
+void Program::getTransformFeedbackVarying(GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name) const
+{
+ ASSERT(!mLinkingState);
+ if (mLinked)
+ {
+ ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
+ const auto &var = mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
+ std::string varName = var.nameWithArrayIndex();
+ GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varName.length()));
+ if (length)
+ {
+ *length = lastNameIdx;
+ }
+ if (size)
+ {
+ *size = var.size();
+ }
+ if (type)
+ {
+ *type = var.type;
+ }
+ if (name)
+ {
+ memcpy(name, varName.c_str(), lastNameIdx);
+ name[lastNameIdx] = '\0';
+ }
+ }
+}
+
+GLsizei Program::getTransformFeedbackVaryingCount() const
+{
+ ASSERT(!mLinkingState);
+ if (mLinked)
+ {
+ return static_cast<GLsizei>(mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+GLsizei Program::getTransformFeedbackVaryingMaxLength() const
+{
+ ASSERT(!mLinkingState);
+ if (mLinked)
+ {
+ GLsizei maxSize = 0;
+ for (const auto &var : mState.mExecutable->mLinkedTransformFeedbackVaryings)
+ {
+ maxSize =
+ std::max(maxSize, static_cast<GLsizei>(var.nameWithArrayIndex().length() + 1));
+ }
+
+ return maxSize;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+GLenum Program::getTransformFeedbackBufferMode() const
+{
+ ASSERT(!mLinkingState);
+ return mState.mExecutable->getTransformFeedbackBufferMode();
+}
+
+bool Program::linkValidateShaders(const Context *context, InfoLog &infoLog)
+{
+ const ShaderMap<Shader *> &shaders = mState.mAttachedShaders;
+
+ bool isComputeShaderAttached = shaders[ShaderType::Compute] != nullptr;
+ bool isGraphicsShaderAttached = shaders[ShaderType::Vertex] ||
+ shaders[ShaderType::TessControl] ||
+ shaders[ShaderType::TessEvaluation] ||
+ shaders[ShaderType::Geometry] || shaders[ShaderType::Fragment];
+ // Check whether we both have a compute and non-compute shaders attached.
+ // If there are of both types attached, then linking should fail.
+ // OpenGL ES 3.10, 7.3 Program Objects, under LinkProgram
+ if (isComputeShaderAttached && isGraphicsShaderAttached)
+ {
+ infoLog << "Both compute and graphics shaders are attached to the same program.";
+ return false;
+ }
+
+ Optional<int> version;
+ for (ShaderType shaderType : kAllGraphicsShaderTypes)
+ {
+ Shader *shader = shaders[shaderType];
+ ASSERT(!shader || shader->getType() == shaderType);
+ if (!shader)
+ {
+ continue;
+ }
+
+ if (!shader->isCompiled(context))
+ {
+ infoLog << ShaderTypeToString(shaderType) << " shader is not compiled.";
+ return false;
+ }
+
+ if (!version.valid())
+ {
+ version = shader->getShaderVersion(context);
+ }
+ else if (version != shader->getShaderVersion(context))
+ {
+ infoLog << ShaderTypeToString(shaderType)
+ << " shader version does not match other shader versions.";
+ return false;
+ }
+ }
+
+ if (isComputeShaderAttached)
+ {
+ ASSERT(shaders[ShaderType::Compute]->getType() == ShaderType::Compute);
+
+ mState.mComputeShaderLocalSize = shaders[ShaderType::Compute]->getWorkGroupSize(context);
+
+ // GLSL ES 3.10, 4.4.1.1 Compute Shader Inputs
+ // If the work group size is not specified, a link time error should occur.
+ if (!mState.mComputeShaderLocalSize.isDeclared())
+ {
+ infoLog << "Work group size is not specified.";
+ return false;
+ }
+ }
+ else
+ {
+ if (!isGraphicsShaderAttached)
+ {
+ infoLog << "No compiled shaders.";
+ return false;
+ }
+
+ bool hasVertex = shaders[ShaderType::Vertex] != nullptr;
+ bool hasFragment = shaders[ShaderType::Fragment] != nullptr;
+ if (!isSeparable() && (!hasVertex || !hasFragment))
+ {
+ infoLog
+ << "The program must contain objects to form both a vertex and fragment shader.";
+ return false;
+ }
+
+ bool hasTessControl = shaders[ShaderType::TessControl] != nullptr;
+ bool hasTessEvaluation = shaders[ShaderType::TessEvaluation] != nullptr;
+ if (!isSeparable() && (hasTessControl != hasTessEvaluation))
+ {
+ infoLog << "Tessellation control and evaluation shaders must be specified together.";
+ return false;
+ }
+
+ Shader *geometryShader = shaders[ShaderType::Geometry];
+ if (shaders[ShaderType::Geometry])
+ {
+ // [GL_EXT_geometry_shader] Chapter 7
+ // Linking can fail for a variety of reasons as specified in the OpenGL ES Shading
+ // Language Specification, as well as any of the following reasons:
+ // * One or more of the shader objects attached to <program> are not compiled
+ // successfully.
+ // * The shaders do not use the same shader language version.
+ // * <program> contains objects to form a geometry shader, and
+ // - <program> is not separable and contains no objects to form a vertex shader; or
+ // - the input primitive type, output primitive type, or maximum output vertex count
+ // is not specified in the compiled geometry shader object.
+ ASSERT(geometryShader->getType() == ShaderType::Geometry);
+
+ Optional<PrimitiveMode> inputPrimitive =
+ geometryShader->getGeometryShaderInputPrimitiveType(context);
+ if (!inputPrimitive.valid())
+ {
+ infoLog << "Input primitive type is not specified in the geometry shader.";
+ return false;
+ }
+
+ Optional<PrimitiveMode> outputPrimitive =
+ geometryShader->getGeometryShaderOutputPrimitiveType(context);
+ if (!outputPrimitive.valid())
+ {
+ infoLog << "Output primitive type is not specified in the geometry shader.";
+ return false;
+ }
+
+ Optional<GLint> maxVertices = geometryShader->getGeometryShaderMaxVertices(context);
+ if (!maxVertices.valid())
+ {
+ infoLog << "'max_vertices' is not specified in the geometry shader.";
+ return false;
+ }
+
+ mState.mExecutable->mGeometryShaderInputPrimitiveType = inputPrimitive.value();
+ mState.mExecutable->mGeometryShaderOutputPrimitiveType = outputPrimitive.value();
+ mState.mExecutable->mGeometryShaderMaxVertices = maxVertices.value();
+ mState.mExecutable->mGeometryShaderInvocations =
+ geometryShader->getGeometryShaderInvocations(context);
+ }
+
+ Shader *tessControlShader = shaders[ShaderType::TessControl];
+ if (tessControlShader)
+ {
+ int tcsShaderVertices = tessControlShader->getTessControlShaderVertices(context);
+ if (tcsShaderVertices == 0)
+ {
+ // In tessellation control shader, output vertices should be specified at least
+ // once.
+ // > GLSL ES Version 3.20.6 spec:
+ // > 4.4.2. Output Layout Qualifiers
+ // > Tessellation Control Outputs
+ // > ...
+ // > There must be at least one layout qualifier specifying an output patch vertex
+ // > count in any program containing a tessellation control shader.
+ infoLog << "In Tessellation Control Shader, at least one layout qualifier "
+ "specifying an output patch vertex count must exist.";
+ return false;
+ }
+
+ mState.mExecutable->mTessControlShaderVertices = tcsShaderVertices;
+ }
+
+ Shader *tessEvaluationShader = shaders[ShaderType::TessEvaluation];
+ if (tessEvaluationShader)
+ {
+ GLenum tesPrimitiveMode = tessEvaluationShader->getTessGenMode(context);
+ if (tesPrimitiveMode == 0)
+ {
+ // In tessellation evaluation shader, a primitive mode should be specified at least
+ // once.
+ // > GLSL ES Version 3.20.6 spec:
+ // > 4.4.1. Input Layout Qualifiers
+ // > Tessellation Evaluation Inputs
+ // > ...
+ // > The tessellation evaluation shader object in a program must declare a primitive
+ // > mode in its input layout. Declaring vertex spacing, ordering, or point mode
+ // > identifiers is optional.
+ infoLog << "The Tessellation Evaluation Shader object in a program must declare a "
+ "primitive mode in its input layout.";
+ return false;
+ }
+
+ mState.mExecutable->mTessGenMode = tesPrimitiveMode;
+ mState.mExecutable->mTessGenSpacing = tessEvaluationShader->getTessGenSpacing(context);
+ mState.mExecutable->mTessGenVertexOrder =
+ tessEvaluationShader->getTessGenVertexOrder(context);
+ mState.mExecutable->mTessGenPointMode =
+ tessEvaluationShader->getTessGenPointMode(context);
+ }
+ }
+
+ return true;
+}
+
+GLuint Program::getTransformFeedbackVaryingResourceIndex(const GLchar *name) const
+{
+ ASSERT(!mLinkingState);
+ for (GLuint tfIndex = 0; tfIndex < mState.mExecutable->mLinkedTransformFeedbackVaryings.size();
+ ++tfIndex)
+ {
+ const auto &tf = mState.mExecutable->mLinkedTransformFeedbackVaryings[tfIndex];
+ if (tf.nameWithArrayIndex() == name)
+ {
+ return tfIndex;
+ }
+ }
+ return GL_INVALID_INDEX;
+}
+
+const TransformFeedbackVarying &Program::getTransformFeedbackVaryingResource(GLuint index) const
+{
+ ASSERT(!mLinkingState);
+ ASSERT(index < mState.mExecutable->mLinkedTransformFeedbackVaryings.size());
+ return mState.mExecutable->mLinkedTransformFeedbackVaryings[index];
+}
+
+bool Program::hasDrawIDUniform() const
+{
+ ASSERT(!mLinkingState);
+ return mState.mDrawIDLocation >= 0;
+}
+
+void Program::setDrawIDUniform(GLint drawid)
+{
+ ASSERT(!mLinkingState);
+ ASSERT(mState.mDrawIDLocation >= 0);
+ mProgram->setUniform1iv(mState.mDrawIDLocation, 1, &drawid);
+}
+
+bool Program::hasBaseVertexUniform() const
+{
+ ASSERT(!mLinkingState);
+ return mState.mBaseVertexLocation >= 0;
+}
+
+void Program::setBaseVertexUniform(GLint baseVertex)
+{
+ ASSERT(!mLinkingState);
+ ASSERT(mState.mBaseVertexLocation >= 0);
+ if (baseVertex == mState.mCachedBaseVertex)
+ {
+ return;
+ }
+ mState.mCachedBaseVertex = baseVertex;
+ mProgram->setUniform1iv(mState.mBaseVertexLocation, 1, &baseVertex);
+}
+
+bool Program::hasBaseInstanceUniform() const
+{
+ ASSERT(!mLinkingState);
+ return mState.mBaseInstanceLocation >= 0;
+}
+
+void Program::setBaseInstanceUniform(GLuint baseInstance)
+{
+ ASSERT(!mLinkingState);
+ ASSERT(mState.mBaseInstanceLocation >= 0);
+ if (baseInstance == mState.mCachedBaseInstance)
+ {
+ return;
+ }
+ mState.mCachedBaseInstance = baseInstance;
+ GLint baseInstanceInt = baseInstance;
+ mProgram->setUniform1iv(mState.mBaseInstanceLocation, 1, &baseInstanceInt);
+}
+
+bool Program::linkVaryings(const Context *context, InfoLog &infoLog) const
+{
+ ShaderType previousShaderType = ShaderType::InvalidEnum;
+ for (ShaderType shaderType : kAllGraphicsShaderTypes)
+ {
+ Shader *currentShader = mState.mAttachedShaders[shaderType];
+ if (!currentShader)
+ {
+ continue;
+ }
+
+ if (previousShaderType != ShaderType::InvalidEnum)
+ {
+ Shader *previousShader = mState.mAttachedShaders[previousShaderType];
+ const std::vector<sh::ShaderVariable> &outputVaryings =
+ previousShader->getOutputVaryings(context);
+
+ if (!LinkValidateShaderInterfaceMatching(
+ outputVaryings, currentShader->getInputVaryings(context), previousShaderType,
+ currentShader->getType(), previousShader->getShaderVersion(context),
+ currentShader->getShaderVersion(context), isSeparable(), infoLog))
+ {
+ return false;
+ }
+ }
+ previousShaderType = currentShader->getType();
+ }
+
+ // TODO: http://anglebug.com/3571 and http://anglebug.com/3572
+ // Need to move logic of validating builtin varyings inside the for-loop above.
+ // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
+ // can be redeclared in Geometry or Tessellation shaders as well.
+ Shader *vertexShader = mState.mAttachedShaders[ShaderType::Vertex];
+ Shader *fragmentShader = mState.mAttachedShaders[ShaderType::Fragment];
+ if (vertexShader && fragmentShader &&
+ !LinkValidateBuiltInVaryings(vertexShader->getOutputVaryings(context),
+ fragmentShader->getInputVaryings(context),
+ vertexShader->getType(), fragmentShader->getType(),
+ vertexShader->getShaderVersion(context),
+ fragmentShader->getShaderVersion(context), infoLog))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool Program::linkUniforms(const Context *context,
+ std::vector<UnusedUniform> *unusedUniformsOutOrNull,
+ GLuint *combinedImageUniformsOut,
+ InfoLog &infoLog)
+{
+ // Initialize executable shader map.
+ ShaderMap<std::vector<sh::ShaderVariable>> shaderUniforms;
+ for (Shader *shader : mState.mAttachedShaders)
+ {
+ if (shader)
+ {
+ shaderUniforms[shader->getType()] = shader->getUniforms(context);
+ }
+ }
+
+ if (!mState.mExecutable->linkUniforms(context, shaderUniforms, infoLog,
+ mState.mUniformLocationBindings, combinedImageUniformsOut,
+ unusedUniformsOutOrNull, &mState.mUniformLocations))
+ {
+ return false;
+ }
+
+ if (context->getClientVersion() >= Version(3, 1))
+ {
+ GLint locationSize = static_cast<GLint>(mState.getUniformLocations().size());
+
+ if (locationSize > context->getCaps().maxUniformLocations)
+ {
+ infoLog << "Exceeded maximum uniform location size";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Assigns locations to all attributes (except built-ins) from the bindings and program locations.
+bool Program::linkAttributes(const Context *context, InfoLog &infoLog)
+{
+ const Caps &caps = context->getCaps();
+ const Limitations &limitations = context->getLimitations();
+ bool webglCompatibility = context->isWebGL();
+ int shaderVersion = -1;
+ unsigned int usedLocations = 0;
+
+ Shader *vertexShader = mState.getAttachedShader(gl::ShaderType::Vertex);
+
+ if (!vertexShader)
+ {
+ // No vertex shader, so no attributes, so nothing to do
+ return true;
+ }
+
+ shaderVersion = vertexShader->getShaderVersion(context);
+ if (shaderVersion >= 300)
+ {
+ // In GLSL ES 3.00.6, aliasing checks should be done with all declared attributes -
+ // see GLSL ES 3.00.6 section 12.46. Inactive attributes will be pruned after
+ // aliasing checks.
+ mState.mExecutable->mProgramInputs = vertexShader->getAllAttributes(context);
+ }
+ else
+ {
+ // In GLSL ES 1.00.17 we only do aliasing checks for active attributes.
+ mState.mExecutable->mProgramInputs = vertexShader->getActiveAttributes(context);
+ }
+
+ GLuint maxAttribs = static_cast<GLuint>(caps.maxVertexAttributes);
+ std::vector<sh::ShaderVariable *> usedAttribMap(maxAttribs, nullptr);
+
+ // Assign locations to attributes that have a binding location and check for attribute aliasing.
+ for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
+ {
+ // GLSL ES 3.10 January 2016 section 4.3.4: Vertex shader inputs can't be arrays or
+ // structures, so we don't need to worry about adjusting their names or generating entries
+ // for each member/element (unlike uniforms for example).
+ ASSERT(!attribute.isArray() && !attribute.isStruct());
+
+ int bindingLocation = mAttributeBindings.getBinding(attribute);
+ if (attribute.location == -1 && bindingLocation != -1)
+ {
+ attribute.location = bindingLocation;
+ }
+
+ if (attribute.location != -1)
+ {
+ // Location is set by glBindAttribLocation or by location layout qualifier
+ const int regs = VariableRegisterCount(attribute.type);
+
+ if (static_cast<GLuint>(regs + attribute.location) > maxAttribs)
+ {
+ infoLog << "Attribute (" << attribute.name << ") at location " << attribute.location
+ << " is too big to fit";
+
+ return false;
+ }
+
+ for (int reg = 0; reg < regs; reg++)
+ {
+ const int regLocation = attribute.location + reg;
+ sh::ShaderVariable *linkedAttribute = usedAttribMap[regLocation];
+
+ // In GLSL ES 3.00.6 and in WebGL, attribute aliasing produces a link error.
+ // In non-WebGL GLSL ES 1.00.17, attribute aliasing is allowed with some
+ // restrictions - see GLSL ES 1.00.17 section 2.10.4, but ANGLE currently has a bug.
+ // In D3D 9 and 11, aliasing is not supported, so check a limitation.
+ if (linkedAttribute)
+ {
+ if (shaderVersion >= 300 || webglCompatibility ||
+ limitations.noVertexAttributeAliasing)
+ {
+ infoLog << "Attribute '" << attribute.name << "' aliases attribute '"
+ << linkedAttribute->name << "' at location " << regLocation;
+ return false;
+ }
+ }
+ else
+ {
+ usedAttribMap[regLocation] = &attribute;
+ }
+
+ usedLocations |= 1 << regLocation;
+ }
+ }
+ }
+
+ // Assign locations to attributes that don't have a binding location.
+ for (sh::ShaderVariable &attribute : mState.mExecutable->mProgramInputs)
+ {
+ // Not set by glBindAttribLocation or by location layout qualifier
+ if (attribute.location == -1)
+ {
+ int regs = VariableRegisterCount(attribute.type);
+ int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs);
+
+ if (availableIndex == -1 || static_cast<GLuint>(availableIndex + regs) > maxAttribs)
+ {
+ infoLog << "Too many attributes (" << attribute.name << ")";
+ return false;
+ }
+
+ attribute.location = availableIndex;
+ }
+ }
+
+ ASSERT(mState.mExecutable->mAttributesTypeMask.none());
+ ASSERT(mState.mExecutable->mAttributesMask.none());
+
+ // Prune inactive attributes. This step is only needed on shaderVersion >= 300 since on earlier
+ // shader versions we're only processing active attributes to begin with.
+ if (shaderVersion >= 300)
+ {
+ for (auto attributeIter = mState.mExecutable->getProgramInputs().begin();
+ attributeIter != mState.mExecutable->getProgramInputs().end();)
+ {
+ if (attributeIter->active)
+ {
+ ++attributeIter;
+ }
+ else
+ {
+ attributeIter = mState.mExecutable->mProgramInputs.erase(attributeIter);
+ }
+ }
+ }
+
+ for (const sh::ShaderVariable &attribute : mState.mExecutable->getProgramInputs())
+ {
+ ASSERT(attribute.active);
+ ASSERT(attribute.location != -1);
+ unsigned int regs = static_cast<unsigned int>(VariableRegisterCount(attribute.type));
+
+ unsigned int location = static_cast<unsigned int>(attribute.location);
+ for (unsigned int r = 0; r < regs; r++)
+ {
+ // Built-in active program inputs don't have a bound attribute.
+ if (!attribute.isBuiltIn())
+ {
+ mState.mExecutable->mActiveAttribLocationsMask.set(location);
+ mState.mExecutable->mMaxActiveAttribLocation =
+ std::max(mState.mExecutable->mMaxActiveAttribLocation, location + 1);
+
+ ComponentType componentType =
+ GLenumToComponentType(VariableComponentType(attribute.type));
+
+ SetComponentTypeMask(componentType, location,
+ &mState.mExecutable->mAttributesTypeMask);
+ mState.mExecutable->mAttributesMask.set(location);
+
+ location++;
+ }
+ }
+ }
+
+ return true;
+}
+
+void Program::setUniformValuesFromBindingQualifiers()
+{
+ for (unsigned int samplerIndex : mState.mExecutable->getSamplerUniformRange())
+ {
+ const auto &samplerUniform = mState.mExecutable->getUniforms()[samplerIndex];
+ if (samplerUniform.binding != -1)
+ {
+ UniformLocation location = getUniformLocation(samplerUniform.name);
+ ASSERT(location.value != -1);
+ std::vector<GLint> boundTextureUnits;
+ for (unsigned int elementIndex = 0;
+ elementIndex < samplerUniform.getBasicTypeElementCount(); ++elementIndex)
+ {
+ boundTextureUnits.push_back(samplerUniform.binding + elementIndex);
+ }
+
+ // Here we pass nullptr to avoid a large chain of calls that need a non-const Context.
+ // We know it's safe not to notify the Context because this is only called after link.
+ setUniform1iv(nullptr, location, static_cast<GLsizei>(boundTextureUnits.size()),
+ boundTextureUnits.data());
+ }
+ }
+}
+
+void Program::initInterfaceBlockBindings()
+{
+ // Set initial bindings from shader.
+ for (unsigned int blockIndex = 0; blockIndex < mState.mExecutable->getActiveUniformBlockCount();
+ blockIndex++)
+ {
+ InterfaceBlock &uniformBlock = mState.mExecutable->mUniformBlocks[blockIndex];
+ bindUniformBlock({blockIndex}, uniformBlock.binding);
+ }
+}
+
+void Program::updateSamplerUniform(Context *context,
+ const VariableLocation &locationInfo,
+ GLsizei clampedCount,
+ const GLint *v)
+{
+ ASSERT(mState.isSamplerUniformIndex(locationInfo.index));
+ GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationInfo.index);
+ SamplerBinding &samplerBinding = mState.mExecutable->mSamplerBindings[samplerIndex];
+ std::vector<GLuint> &boundTextureUnits = samplerBinding.boundTextureUnits;
+
+ if (locationInfo.arrayIndex >= boundTextureUnits.size())
+ {
+ return;
+ }
+ GLsizei safeUniformCount = std::min(
+ clampedCount, static_cast<GLsizei>(boundTextureUnits.size() - locationInfo.arrayIndex));
+
+ // Update the sampler uniforms.
+ for (GLsizei arrayIndex = 0; arrayIndex < safeUniformCount; ++arrayIndex)
+ {
+ GLint oldTextureUnit = boundTextureUnits[arrayIndex + locationInfo.arrayIndex];
+ GLint newTextureUnit = v[arrayIndex];
+
+ if (oldTextureUnit == newTextureUnit)
+ {
+ continue;
+ }
+
+ // Update sampler's bound textureUnit
+ boundTextureUnits[arrayIndex + locationInfo.arrayIndex] = newTextureUnit;
+
+ // Update the reference counts.
+ uint32_t &oldRefCount = mState.mExecutable->mActiveSamplerRefCounts[oldTextureUnit];
+ uint32_t &newRefCount = mState.mExecutable->mActiveSamplerRefCounts[newTextureUnit];
+ ASSERT(oldRefCount > 0);
+ ASSERT(newRefCount < std::numeric_limits<uint32_t>::max());
+ oldRefCount--;
+ newRefCount++;
+
+ // Check for binding type change.
+ TextureType newSamplerType = mState.mExecutable->mActiveSamplerTypes[newTextureUnit];
+ TextureType oldSamplerType = mState.mExecutable->mActiveSamplerTypes[oldTextureUnit];
+ SamplerFormat newSamplerFormat = mState.mExecutable->mActiveSamplerFormats[newTextureUnit];
+ SamplerFormat oldSamplerFormat = mState.mExecutable->mActiveSamplerFormats[oldTextureUnit];
+ bool newSamplerYUV = mState.mExecutable->mActiveSamplerYUV.test(newTextureUnit);
+
+ if (newRefCount == 1)
+ {
+ mState.mExecutable->setActive(newTextureUnit, samplerBinding,
+ mState.mExecutable->getUniforms()[locationInfo.index]);
+ }
+ else
+ {
+ if (newSamplerType != samplerBinding.textureType ||
+ newSamplerYUV != IsSamplerYUVType(samplerBinding.samplerType))
+ {
+ mState.mExecutable->hasSamplerTypeConflict(newTextureUnit);
+ }
+
+ if (newSamplerFormat != samplerBinding.format)
+ {
+ mState.mExecutable->hasSamplerFormatConflict(newTextureUnit);
+ }
+ }
+
+ // Unset previously active sampler.
+ if (oldRefCount == 0)
+ {
+ mState.mExecutable->setInactive(oldTextureUnit);
+ }
+ else
+ {
+ if (oldSamplerType == TextureType::InvalidEnum ||
+ oldSamplerFormat == SamplerFormat::InvalidEnum)
+ {
+ // Previous conflict. Check if this new change fixed the conflict.
+ mState.setSamplerUniformTextureTypeAndFormat(oldTextureUnit);
+ }
+ }
+
+ // Update the observing PPO's executable, if any.
+ // Do this before any of the Context work, since that uses the current ProgramExecutable,
+ // which will be the PPO's if this Program is bound to it, rather than this Program's.
+ if (isSeparable())
+ {
+ onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
+ }
+
+ // Notify context.
+ if (context)
+ {
+ context->onSamplerUniformChange(newTextureUnit);
+ context->onSamplerUniformChange(oldTextureUnit);
+ }
+ }
+
+ // Invalidate the validation cache.
+ getExecutable().resetCachedValidateSamplersResult();
+ // Inform any PPOs this Program may be bound to.
+ onStateChange(angle::SubjectMessage::SamplerUniformsUpdated);
+}
+
+void ProgramState::setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex)
+{
+ mExecutable->setSamplerUniformTextureTypeAndFormat(textureUnitIndex,
+ mExecutable->mSamplerBindings);
+}
+
+template <typename T>
+GLsizei Program::clampUniformCount(const VariableLocation &locationInfo,
+ GLsizei count,
+ int vectorSize,
+ const T *v)
+{
+ if (count == 1)
+ return 1;
+
+ const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
+
+ // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
+ // element index used, as reported by GetActiveUniform, will be ignored by the GL."
+ unsigned int remainingElements =
+ linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
+ GLsizei maxElementCount =
+ static_cast<GLsizei>(remainingElements * linkedUniform.getElementComponents());
+
+ if (count * vectorSize > maxElementCount)
+ {
+ return maxElementCount / vectorSize;
+ }
+
+ return count;
+}
+
+template <size_t cols, size_t rows, typename T>
+GLsizei Program::clampMatrixUniformCount(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const T *v)
+{
+ const VariableLocation &locationInfo = mState.mUniformLocations[location.value];
+
+ if (!transpose)
+ {
+ return clampUniformCount(locationInfo, count, cols * rows, v);
+ }
+
+ const LinkedUniform &linkedUniform = mState.mExecutable->getUniforms()[locationInfo.index];
+
+ // OpenGL ES 3.0.4 spec pg 67: "Values for any array element that exceeds the highest array
+ // element index used, as reported by GetActiveUniform, will be ignored by the GL."
+ unsigned int remainingElements =
+ linkedUniform.getBasicTypeElementCount() - locationInfo.arrayIndex;
+ return std::min(count, static_cast<GLsizei>(remainingElements));
+}
+
+// Driver differences mean that doing the uniform value cast ourselves gives consistent results.
+// EG: on NVIDIA drivers, it was observed that getUniformi for MAX_INT+1 returned MIN_INT.
+template <typename DestT>
+void Program::getUniformInternal(const Context *context,
+ DestT *dataOut,
+ UniformLocation location,
+ GLenum nativeType,
+ int components) const
+{
+ switch (nativeType)
+ {
+ case GL_BOOL:
+ {
+ GLint tempValue[16] = {0};
+ mProgram->getUniformiv(context, location.value, tempValue);
+ UniformStateQueryCastLoop<GLboolean>(
+ dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
+ break;
+ }
+ case GL_INT:
+ {
+ GLint tempValue[16] = {0};
+ mProgram->getUniformiv(context, location.value, tempValue);
+ UniformStateQueryCastLoop<GLint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
+ components);
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ {
+ GLuint tempValue[16] = {0};
+ mProgram->getUniformuiv(context, location.value, tempValue);
+ UniformStateQueryCastLoop<GLuint>(dataOut, reinterpret_cast<const uint8_t *>(tempValue),
+ components);
+ break;
+ }
+ case GL_FLOAT:
+ {
+ GLfloat tempValue[16] = {0};
+ mProgram->getUniformfv(context, location.value, tempValue);
+ UniformStateQueryCastLoop<GLfloat>(
+ dataOut, reinterpret_cast<const uint8_t *>(tempValue), components);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+angle::Result Program::syncState(const Context *context)
+{
+ if (mDirtyBits.any())
+ {
+ ASSERT(!mLinkingState);
+ ANGLE_TRY(mProgram->syncState(context, mDirtyBits));
+ mDirtyBits.reset();
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Program::serialize(const Context *context, angle::MemoryBuffer *binaryOut) const
+{
+ BinaryOutputStream stream;
+
+ stream.writeBytes(reinterpret_cast<const unsigned char *>(angle::GetANGLECommitHash()),
+ angle::GetANGLECommitHashSize());
+
+ // nullptr context is supported when computing binary length.
+ if (context)
+ {
+ stream.writeInt(context->getClientVersion().major);
+ stream.writeInt(context->getClientVersion().minor);
+ }
+ else
+ {
+ stream.writeInt(2);
+ stream.writeInt(0);
+ }
+
+ // Must be before mExecutable->save(), since it uses the value.
+ stream.writeBool(mState.mSeparable);
+
+ mState.mExecutable->save(mState.mSeparable, &stream);
+
+ const auto &computeLocalSize = mState.getComputeShaderLocalSize();
+
+ stream.writeInt(computeLocalSize[0]);
+ stream.writeInt(computeLocalSize[1]);
+ stream.writeInt(computeLocalSize[2]);
+
+ stream.writeInt(mState.mNumViews);
+ stream.writeInt(mState.mSpecConstUsageBits.bits());
+
+ stream.writeInt(mState.getUniformLocations().size());
+ for (const auto &variable : mState.getUniformLocations())
+ {
+ stream.writeInt(variable.arrayIndex);
+ stream.writeIntOrNegOne(variable.index);
+ stream.writeBool(variable.ignored);
+ }
+
+ stream.writeInt(mState.getBufferVariables().size());
+ for (const BufferVariable &bufferVariable : mState.getBufferVariables())
+ {
+ WriteBufferVariable(&stream, bufferVariable);
+ }
+
+ // Warn the app layer if saving a binary with unsupported transform feedback.
+ if (!mState.getLinkedTransformFeedbackVaryings().empty() &&
+ context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
+ {
+ ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
+ "Saving program binary with transform feedback, which is not supported "
+ "on this driver.");
+ }
+
+ if (context->getShareGroup()->getFrameCaptureShared()->enabled())
+ {
+ // Serialize the source for each stage for re-use during capture
+ for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
+ {
+ gl::Shader *shader = getAttachedShader(shaderType);
+ if (shader)
+ {
+ stream.writeString(shader->getSourceString());
+ }
+ else
+ {
+ // If we don't have an attached shader, which would occur if this program was
+ // created via glProgramBinary, pull from our cached copy
+ const angle::ProgramSources &cachedLinkedSources =
+ context->getShareGroup()->getFrameCaptureShared()->getProgramSources(id());
+ const std::string &cachedSourceString = cachedLinkedSources[shaderType];
+ ASSERT(!cachedSourceString.empty());
+ stream.writeString(cachedSourceString.c_str());
+ }
+ }
+ }
+
+ mProgram->save(context, &stream);
+
+ ASSERT(binaryOut);
+ if (!binaryOut->resize(stream.length()))
+ {
+ std::stringstream sstream;
+ sstream << "Failed to allocate enough memory to serialize a program. (" << stream.length()
+ << " bytes )";
+ ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
+ sstream.str().c_str());
+ return angle::Result::Incomplete;
+ }
+ memcpy(binaryOut->data(), stream.data(), stream.length());
+ return angle::Result::Continue;
+}
+
+angle::Result Program::deserialize(const Context *context,
+ BinaryInputStream &stream,
+ InfoLog &infoLog)
+{
+ std::vector<uint8_t> commitString(angle::GetANGLECommitHashSize(), 0);
+ stream.readBytes(commitString.data(), commitString.size());
+ if (memcmp(commitString.data(), angle::GetANGLECommitHash(), commitString.size()) != 0)
+ {
+ infoLog << "Invalid program binary version.";
+ return angle::Result::Stop;
+ }
+
+ int majorVersion = stream.readInt<int>();
+ int minorVersion = stream.readInt<int>();
+ if (majorVersion != context->getClientMajorVersion() ||
+ minorVersion != context->getClientMinorVersion())
+ {
+ infoLog << "Cannot load program binaries across different ES context versions.";
+ return angle::Result::Stop;
+ }
+
+ // Must be before mExecutable->load(), since it uses the value.
+ mState.mSeparable = stream.readBool();
+
+ mState.mExecutable->load(mState.mSeparable, &stream);
+
+ mState.mComputeShaderLocalSize[0] = stream.readInt<int>();
+ mState.mComputeShaderLocalSize[1] = stream.readInt<int>();
+ mState.mComputeShaderLocalSize[2] = stream.readInt<int>();
+
+ mState.mNumViews = stream.readInt<int>();
+
+ static_assert(sizeof(mState.mSpecConstUsageBits.bits()) == sizeof(uint32_t));
+ mState.mSpecConstUsageBits = rx::SpecConstUsageBits(stream.readInt<uint32_t>());
+
+ const size_t uniformIndexCount = stream.readInt<size_t>();
+ ASSERT(mState.mUniformLocations.empty());
+ for (size_t uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; ++uniformIndexIndex)
+ {
+ VariableLocation variable;
+ stream.readInt(&variable.arrayIndex);
+ stream.readInt(&variable.index);
+ stream.readBool(&variable.ignored);
+
+ mState.mUniformLocations.push_back(variable);
+ }
+
+ size_t bufferVariableCount = stream.readInt<size_t>();
+ ASSERT(mState.mBufferVariables.empty());
+ for (size_t bufferVarIndex = 0; bufferVarIndex < bufferVariableCount; ++bufferVarIndex)
+ {
+ BufferVariable bufferVariable;
+ LoadBufferVariable(&stream, &bufferVariable);
+ mState.mBufferVariables.push_back(bufferVariable);
+ }
+
+ static_assert(static_cast<unsigned long>(ShaderType::EnumCount) <= sizeof(unsigned long) * 8,
+ "Too many shader types");
+
+ // Reject programs that use transform feedback varyings if the hardware cannot support them.
+ if (mState.mExecutable->getLinkedTransformFeedbackVaryings().size() > 0 &&
+ context->getFrontendFeatures().disableProgramCachingForTransformFeedback.enabled)
+ {
+ infoLog << "Current driver does not support transform feedback in binary programs.";
+ return angle::Result::Stop;
+ }
+
+ if (!mState.mAttachedShaders[ShaderType::Compute])
+ {
+ mState.mExecutable->updateTransformFeedbackStrides();
+ }
+
+ postResolveLink(context);
+ mState.mExecutable->updateCanDrawWith();
+
+ if (context->getShareGroup()->getFrameCaptureShared()->enabled())
+ {
+ // Extract the source for each stage from the program binary
+ angle::ProgramSources sources;
+
+ for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
+ {
+ std::string shaderSource = stream.readString();
+ ASSERT(shaderSource.length() > 0);
+ sources[shaderType] = std::move(shaderSource);
+ }
+
+ // Store it for use during mid-execution capture
+ context->getShareGroup()->getFrameCaptureShared()->setProgramSources(id(),
+ std::move(sources));
+ }
+
+ return angle::Result::Continue;
+}
+
+void Program::postResolveLink(const gl::Context *context)
+{
+ mState.updateActiveSamplers();
+ mState.mExecutable->mActiveImageShaderBits.fill({});
+ mState.mExecutable->updateActiveImages(getExecutable());
+
+ setUniformValuesFromBindingQualifiers();
+
+ if (context->getExtensions().multiDrawANGLE)
+ {
+ mState.mDrawIDLocation = getUniformLocation("gl_DrawID").value;
+ }
+
+ if (context->getExtensions().baseVertexBaseInstanceShaderBuiltinANGLE)
+ {
+ mState.mBaseVertexLocation = getUniformLocation("gl_BaseVertex").value;
+ mState.mBaseInstanceLocation = getUniformLocation("gl_BaseInstance").value;
+ }
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Program.h b/gfx/angle/checkout/src/libANGLE/Program.h
new file mode 100644
index 0000000000..0b7b62480b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Program.h
@@ -0,0 +1,897 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Program.h: Defines the gl::Program class. Implements GL program objects
+// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
+
+#ifndef LIBANGLE_PROGRAM_H_
+#define LIBANGLE_PROGRAM_H_
+
+#include <GLES2/gl2.h>
+#include <GLSLANG/ShaderVars.h>
+
+#include <array>
+#include <map>
+#include <set>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "common/Optional.h"
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "common/utilities.h"
+
+#include "libANGLE/Constants.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/InfoLog.h"
+#include "libANGLE/ProgramExecutable.h"
+#include "libANGLE/ProgramLinkedResources.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+class GLImplFactory;
+class ProgramImpl;
+struct TranslatedAttribute;
+} // namespace rx
+
+namespace gl
+{
+class Buffer;
+class BinaryInputStream;
+class BinaryOutputStream;
+struct Caps;
+class Context;
+struct Extensions;
+class Framebuffer;
+class ProgramExecutable;
+class Shader;
+class ShaderProgramManager;
+class State;
+struct UnusedUniform;
+struct Version;
+
+extern const char *const g_fakepath;
+
+enum class LinkMismatchError
+{
+ // Shared
+ NO_MISMATCH,
+ TYPE_MISMATCH,
+ ARRAYNESS_MISMATCH,
+ ARRAY_SIZE_MISMATCH,
+ PRECISION_MISMATCH,
+ STRUCT_NAME_MISMATCH,
+ FIELD_NUMBER_MISMATCH,
+ FIELD_NAME_MISMATCH,
+
+ // Varying specific
+ INTERPOLATION_TYPE_MISMATCH,
+ INVARIANCE_MISMATCH,
+
+ // Uniform specific
+ BINDING_MISMATCH,
+ LOCATION_MISMATCH,
+ OFFSET_MISMATCH,
+ INSTANCE_NAME_MISMATCH,
+ FORMAT_MISMATCH,
+
+ // Interface block specific
+ LAYOUT_QUALIFIER_MISMATCH,
+ MATRIX_PACKING_MISMATCH,
+
+ // I/O block specific
+ FIELD_LOCATION_MISMATCH,
+ FIELD_STRUCT_NAME_MISMATCH,
+};
+
+void LogLinkMismatch(InfoLog &infoLog,
+ const std::string &variableName,
+ const char *variableType,
+ LinkMismatchError linkError,
+ const std::string &mismatchedStructOrBlockFieldName,
+ ShaderType shaderType1,
+ ShaderType shaderType2);
+
+bool IsActiveInterfaceBlock(const sh::InterfaceBlock &interfaceBlock);
+
+void WriteBlockMemberInfo(BinaryOutputStream *stream, const sh::BlockMemberInfo &var);
+void LoadBlockMemberInfo(BinaryInputStream *stream, sh::BlockMemberInfo *var);
+
+void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var);
+void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var);
+
+void WriteInterfaceBlock(BinaryOutputStream *stream, const InterfaceBlock &block);
+void LoadInterfaceBlock(BinaryInputStream *stream, InterfaceBlock *block);
+
+void WriteShInterfaceBlock(BinaryOutputStream *stream, const sh::InterfaceBlock &block);
+void LoadShInterfaceBlock(BinaryInputStream *stream, sh::InterfaceBlock *block);
+
+void WriteShaderVariableBuffer(BinaryOutputStream *stream, const ShaderVariableBuffer &var);
+void LoadShaderVariableBuffer(BinaryInputStream *stream, ShaderVariableBuffer *var);
+
+// Struct used for correlating uniforms/elements of uniform arrays to handles
+struct VariableLocation
+{
+ static constexpr unsigned int kUnused = GL_INVALID_INDEX;
+
+ VariableLocation();
+ VariableLocation(unsigned int arrayIndex, unsigned int index);
+
+ // If used is false, it means this location is only used to fill an empty space in an array,
+ // and there is no corresponding uniform variable for this location. It can also mean the
+ // uniform was optimized out by the implementation.
+ bool used() const { return (index != kUnused); }
+ void markUnused() { index = kUnused; }
+ void markIgnored() { ignored = true; }
+
+ bool operator==(const VariableLocation &other) const
+ {
+ return arrayIndex == other.arrayIndex && index == other.index;
+ }
+
+ // "arrayIndex" stores the index of the innermost GLSL array. It's zero for non-arrays.
+ unsigned int arrayIndex;
+ // "index" is an index of the variable. The variable contains the indices for other than the
+ // innermost GLSL arrays.
+ unsigned int index;
+
+ // If this location was bound to an unreferenced uniform. Setting data on this uniform is a
+ // no-op.
+ bool ignored;
+};
+
+// Information about a variable binding.
+// Currently used by CHROMIUM_path_rendering
+struct BindingInfo
+{
+ // The type of binding, for example GL_FLOAT_VEC3.
+ // This can be GL_NONE if the variable is optimized away.
+ GLenum type;
+
+ // This is the name of the variable in
+ // the translated shader program. Note that
+ // this can be empty in the case where the
+ // variable has been optimized away.
+ std::string name;
+
+ // True if the binding is valid, otherwise false.
+ bool valid;
+};
+
+struct ProgramBinding
+{
+ ProgramBinding() : location(GL_INVALID_INDEX), aliased(false) {}
+ ProgramBinding(GLuint index) : location(index), aliased(false) {}
+
+ GLuint location;
+ // Whether another binding was set that may potentially alias this.
+ bool aliased;
+};
+
+class ProgramBindings final : angle::NonCopyable
+{
+ public:
+ ProgramBindings();
+ ~ProgramBindings();
+
+ void bindLocation(GLuint index, const std::string &name);
+ int getBindingByName(const std::string &name) const;
+ int getBinding(const sh::ShaderVariable &variable) const;
+
+ using const_iterator = angle::HashMap<std::string, GLuint>::const_iterator;
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ std::map<std::string, GLuint> getStableIterationMap() const;
+
+ private:
+ angle::HashMap<std::string, GLuint> mBindings;
+};
+
+// Uniforms and Fragment Outputs require special treatment due to array notation (e.g., "[0]")
+class ProgramAliasedBindings final : angle::NonCopyable
+{
+ public:
+ ProgramAliasedBindings();
+ ~ProgramAliasedBindings();
+
+ void bindLocation(GLuint index, const std::string &name);
+ int getBindingByName(const std::string &name) const;
+ int getBindingByLocation(GLuint location) const;
+ int getBinding(const sh::ShaderVariable &variable) const;
+
+ using const_iterator = angle::HashMap<std::string, ProgramBinding>::const_iterator;
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ std::map<std::string, ProgramBinding> getStableIterationMap() const;
+
+ private:
+ angle::HashMap<std::string, ProgramBinding> mBindings;
+};
+
+class ProgramState final : angle::NonCopyable
+{
+ public:
+ ProgramState();
+ ~ProgramState();
+
+ const std::string &getLabel();
+
+ Shader *getAttachedShader(ShaderType shaderType) const;
+ const gl::ShaderMap<Shader *> &getAttachedShaders() const { return mAttachedShaders; }
+ const std::vector<std::string> &getTransformFeedbackVaryingNames() const
+ {
+ return mTransformFeedbackVaryingNames;
+ }
+ GLint getTransformFeedbackBufferMode() const
+ {
+ return mExecutable->getTransformFeedbackBufferMode();
+ }
+ GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
+ {
+ return mExecutable->getUniformBlockBinding(uniformBlockIndex);
+ }
+ GLuint getShaderStorageBlockBinding(GLuint blockIndex) const
+ {
+ return mExecutable->getShaderStorageBlockBinding(blockIndex);
+ }
+ const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const
+ {
+ return mExecutable->getActiveUniformBlockBindings();
+ }
+ const std::vector<sh::ShaderVariable> &getProgramInputs() const
+ {
+ return mExecutable->getProgramInputs();
+ }
+ const std::vector<sh::ShaderVariable> &getOutputVariables() const
+ {
+ return mExecutable->getOutputVariables();
+ }
+ const std::vector<VariableLocation> &getOutputLocations() const
+ {
+ return mExecutable->getOutputLocations();
+ }
+ const std::vector<VariableLocation> &getSecondaryOutputLocations() const
+ {
+ return mExecutable->getSecondaryOutputLocations();
+ }
+ const std::vector<LinkedUniform> &getUniforms() const { return mExecutable->getUniforms(); }
+ const std::vector<VariableLocation> &getUniformLocations() const { return mUniformLocations; }
+ const std::vector<InterfaceBlock> &getUniformBlocks() const
+ {
+ return mExecutable->getUniformBlocks();
+ }
+ const std::vector<InterfaceBlock> &getShaderStorageBlocks() const
+ {
+ return mExecutable->getShaderStorageBlocks();
+ }
+ const std::vector<BufferVariable> &getBufferVariables() const { return mBufferVariables; }
+ const std::vector<SamplerBinding> &getSamplerBindings() const
+ {
+ return mExecutable->getSamplerBindings();
+ }
+ const std::vector<ImageBinding> &getImageBindings() const
+ {
+ return getExecutable().getImageBindings();
+ }
+ const sh::WorkGroupSize &getComputeShaderLocalSize() const { return mComputeShaderLocalSize; }
+ const RangeUI &getDefaultUniformRange() const { return mExecutable->getDefaultUniformRange(); }
+ const RangeUI &getSamplerUniformRange() const { return mExecutable->getSamplerUniformRange(); }
+ const RangeUI &getImageUniformRange() const { return mExecutable->getImageUniformRange(); }
+ const RangeUI &getAtomicCounterUniformRange() const
+ {
+ return mExecutable->getAtomicCounterUniformRange();
+ }
+ const RangeUI &getFragmentInoutRange() const { return mExecutable->getFragmentInoutRange(); }
+
+ const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
+ {
+ return mExecutable->getLinkedTransformFeedbackVaryings();
+ }
+ const std::vector<GLsizei> &getTransformFeedbackStrides() const
+ {
+ return mExecutable->getTransformFeedbackStrides();
+ }
+ const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
+ {
+ return mExecutable->getAtomicCounterBuffers();
+ }
+
+ GLuint getUniformIndexFromName(const std::string &name) const;
+ GLuint getUniformIndexFromLocation(UniformLocation location) const;
+ Optional<GLuint> getSamplerIndex(UniformLocation location) const;
+ bool isSamplerUniformIndex(GLuint index) const;
+ GLuint getSamplerIndexFromUniformIndex(GLuint uniformIndex) const;
+ GLuint getUniformIndexFromSamplerIndex(GLuint samplerIndex) const;
+ bool isImageUniformIndex(GLuint index) const;
+ GLuint getImageIndexFromUniformIndex(GLuint uniformIndex) const;
+ GLuint getAttributeLocation(const std::string &name) const;
+
+ GLuint getBufferVariableIndexFromName(const std::string &name) const;
+
+ int getNumViews() const { return mNumViews; }
+ bool usesMultiview() const { return mNumViews != -1; }
+
+ bool hasAttachedShader() const;
+
+ ShaderType getFirstAttachedShaderStageType() const;
+ ShaderType getLastAttachedShaderStageType() const;
+
+ const ProgramAliasedBindings &getUniformLocationBindings() const
+ {
+ return mUniformLocationBindings;
+ }
+
+ const ProgramExecutable &getExecutable() const
+ {
+ ASSERT(mExecutable);
+ return *mExecutable;
+ }
+ ProgramExecutable &getExecutable()
+ {
+ ASSERT(mExecutable);
+ return *mExecutable;
+ }
+
+ bool hasImages() const { return !getImageBindings().empty(); }
+ rx::SpecConstUsageBits getSpecConstUsageBits() const { return mSpecConstUsageBits; }
+
+ // A Program can only either be graphics or compute, but never both, so it
+ // can answer isCompute() based on which shaders it has.
+ bool isCompute() const { return mExecutable->hasLinkedShaderStage(ShaderType::Compute); }
+
+ const std::string &getLabel() const { return mLabel; }
+
+ uint32_t getLocationsUsedForXfbExtension() const { return mLocationsUsedForXfbExtension; }
+
+ bool hasBinaryRetrieveableHint() const { return mBinaryRetrieveableHint; }
+
+ bool isSeparable() const { return mSeparable; }
+
+ int getDrawIDLocation() const { return mDrawIDLocation; }
+
+ int getBaseVertexLocation() const { return mBaseVertexLocation; }
+
+ int getBaseInstanceLocation() const { return mBaseInstanceLocation; }
+
+ ShaderType getAttachedTransformFeedbackStage() const;
+
+ private:
+ friend class MemoryProgramCache;
+ friend class Program;
+
+ void updateActiveSamplers();
+ void updateProgramInterfaceInputs(const Context *context);
+ void updateProgramInterfaceOutputs(const Context *context);
+
+ // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'.
+ void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex);
+
+ std::string mLabel;
+
+ sh::WorkGroupSize mComputeShaderLocalSize;
+
+ ShaderMap<Shader *> mAttachedShaders;
+
+ uint32_t mLocationsUsedForXfbExtension;
+ std::vector<std::string> mTransformFeedbackVaryingNames;
+
+ std::vector<VariableLocation> mUniformLocations;
+ std::vector<BufferVariable> mBufferVariables;
+
+ bool mBinaryRetrieveableHint;
+ bool mSeparable;
+ rx::SpecConstUsageBits mSpecConstUsageBits;
+
+ // ANGLE_multiview.
+ int mNumViews;
+
+ // GL_ANGLE_multi_draw
+ int mDrawIDLocation;
+
+ // GL_ANGLE_base_vertex_base_instance_shader_builtin
+ int mBaseVertexLocation;
+ int mBaseInstanceLocation;
+ // Cached value of base vertex and base instance
+ // need to reset them to zero if using non base vertex or base instance draw calls.
+ GLint mCachedBaseVertex;
+ GLuint mCachedBaseInstance;
+
+ // Note that this has nothing to do with binding layout qualifiers that can be set for some
+ // uniforms in GLES3.1+. It is used to pre-set the location of uniforms.
+ ProgramAliasedBindings mUniformLocationBindings;
+
+ std::shared_ptr<ProgramExecutable> mExecutable;
+};
+
+struct ProgramVaryingRef
+{
+ const sh::ShaderVariable *get(ShaderType stage) const
+ {
+ ASSERT(stage == frontShaderStage || stage == backShaderStage);
+ const sh::ShaderVariable *ref = stage == frontShaderStage ? frontShader : backShader;
+ ASSERT(ref);
+ return ref;
+ }
+
+ const sh::ShaderVariable *frontShader = nullptr;
+ const sh::ShaderVariable *backShader = nullptr;
+ ShaderType frontShaderStage = ShaderType::InvalidEnum;
+ ShaderType backShaderStage = ShaderType::InvalidEnum;
+};
+
+using ProgramMergedVaryings = std::vector<ProgramVaryingRef>;
+
+class Program final : public LabeledObject, public angle::Subject
+{
+ public:
+ Program(rx::GLImplFactory *factory, ShaderProgramManager *manager, ShaderProgramID handle);
+ void onDestroy(const Context *context);
+
+ ShaderProgramID id() const;
+
+ angle::Result setLabel(const Context *context, const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ ANGLE_INLINE rx::ProgramImpl *getImplementation() const
+ {
+ ASSERT(!mLinkingState);
+ return mProgram;
+ }
+
+ void attachShader(Shader *shader);
+ void detachShader(const Context *context, Shader *shader);
+ int getAttachedShadersCount() const;
+
+ Shader *getAttachedShader(ShaderType shaderType) const;
+
+ void bindAttributeLocation(GLuint index, const char *name);
+ void bindUniformLocation(UniformLocation location, const char *name);
+
+ // EXT_blend_func_extended
+ void bindFragmentOutputLocation(GLuint index, const char *name);
+ void bindFragmentOutputIndex(GLuint index, const char *name);
+
+ // KHR_parallel_shader_compile
+ // Try to link the program asynchronously. As a result, background threads may be launched to
+ // execute the linking tasks concurrently.
+ angle::Result link(const Context *context);
+
+ // Peek whether there is any running linking tasks.
+ bool isLinking() const;
+ bool hasLinkingState() const { return mLinkingState != nullptr; }
+
+ bool isLinked() const
+ {
+ ASSERT(!mLinkingState);
+ return mLinked;
+ }
+
+ angle::Result loadBinary(const Context *context,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length);
+ angle::Result saveBinary(Context *context,
+ GLenum *binaryFormat,
+ void *binary,
+ GLsizei bufSize,
+ GLsizei *length) const;
+ GLint getBinaryLength(Context *context) const;
+ void setBinaryRetrievableHint(bool retrievable);
+ bool getBinaryRetrievableHint() const;
+
+ void setSeparable(bool separable);
+ bool isSeparable() const;
+
+ void getAttachedShaders(GLsizei maxCount, GLsizei *count, ShaderProgramID *shaders) const;
+
+ GLuint getAttributeLocation(const std::string &name) const;
+
+ void getActiveAttribute(GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name) const;
+ GLint getActiveAttributeCount() const;
+ GLint getActiveAttributeMaxLength() const;
+ const std::vector<sh::ShaderVariable> &getAttributes() const;
+
+ GLint getFragDataLocation(const std::string &name) const;
+ size_t getOutputResourceCount() const;
+
+ // EXT_blend_func_extended
+ GLint getFragDataIndex(const std::string &name) const;
+
+ void getActiveUniform(GLuint index,
+ GLsizei bufsize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name) const;
+ GLint getActiveUniformCount() const;
+ size_t getActiveBufferVariableCount() const;
+ GLint getActiveUniformMaxLength() const;
+ bool isValidUniformLocation(UniformLocation location) const;
+ const LinkedUniform &getUniformByLocation(UniformLocation location) const;
+ const VariableLocation &getUniformLocation(UniformLocation location) const;
+
+ const std::vector<VariableLocation> &getUniformLocations() const
+ {
+ ASSERT(!mLinkingState);
+ return mState.mUniformLocations;
+ }
+
+ const LinkedUniform &getUniformByIndex(GLuint index) const
+ {
+ ASSERT(!mLinkingState);
+ return mState.mExecutable->getUniformByIndex(index);
+ }
+
+ const BufferVariable &getBufferVariableByIndex(GLuint index) const;
+
+ enum SetUniformResult
+ {
+ SamplerChanged,
+ NoSamplerChange,
+ };
+
+ UniformLocation getUniformLocation(const std::string &name) const;
+ GLuint getUniformIndex(const std::string &name) const;
+ void setUniform1fv(UniformLocation location, GLsizei count, const GLfloat *v);
+ void setUniform2fv(UniformLocation location, GLsizei count, const GLfloat *v);
+ void setUniform3fv(UniformLocation location, GLsizei count, const GLfloat *v);
+ void setUniform4fv(UniformLocation location, GLsizei count, const GLfloat *v);
+ void setUniform1iv(Context *context, UniformLocation location, GLsizei count, const GLint *v);
+ void setUniform2iv(UniformLocation location, GLsizei count, const GLint *v);
+ void setUniform3iv(UniformLocation location, GLsizei count, const GLint *v);
+ void setUniform4iv(UniformLocation location, GLsizei count, const GLint *v);
+ void setUniform1uiv(UniformLocation location, GLsizei count, const GLuint *v);
+ void setUniform2uiv(UniformLocation location, GLsizei count, const GLuint *v);
+ void setUniform3uiv(UniformLocation location, GLsizei count, const GLuint *v);
+ void setUniform4uiv(UniformLocation location, GLsizei count, const GLuint *v);
+ void setUniformMatrix2fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix3fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix4fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix2x3fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix3x2fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix2x4fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix4x2fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix3x4fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+ void setUniformMatrix4x3fv(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+ void getUniformfv(const Context *context, UniformLocation location, GLfloat *params) const;
+ void getUniformiv(const Context *context, UniformLocation location, GLint *params) const;
+ void getUniformuiv(const Context *context, UniformLocation location, GLuint *params) const;
+
+ void getActiveUniformBlockName(const Context *context,
+ const UniformBlockIndex blockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *blockName) const;
+ void getActiveShaderStorageBlockName(const GLuint blockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *blockName) const;
+
+ ANGLE_INLINE GLuint getActiveUniformBlockCount() const
+ {
+ ASSERT(!mLinkingState);
+ return static_cast<GLuint>(mState.mExecutable->getActiveUniformBlockCount());
+ }
+
+ ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const
+ {
+ ASSERT(!mLinkingState);
+ return static_cast<GLuint>(mState.mExecutable->getActiveAtomicCounterBufferCount());
+ }
+
+ ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const
+ {
+ ASSERT(!mLinkingState);
+ return static_cast<GLuint>(mState.mExecutable->getActiveShaderStorageBlockCount());
+ }
+
+ GLint getActiveUniformBlockMaxNameLength() const;
+ GLint getActiveShaderStorageBlockMaxNameLength() const;
+
+ const std::vector<LinkedUniform> &getUniforms() const { return mState.getUniforms(); }
+ GLuint getUniformBlockIndex(const std::string &name) const;
+ GLuint getShaderStorageBlockIndex(const std::string &name) const;
+
+ void bindUniformBlock(UniformBlockIndex uniformBlockIndex, GLuint uniformBlockBinding);
+ GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
+ GLuint getShaderStorageBlockBinding(GLuint shaderStorageBlockIndex) const;
+
+ const InterfaceBlock &getUniformBlockByIndex(GLuint index) const;
+ const InterfaceBlock &getShaderStorageBlockByIndex(GLuint index) const;
+
+ void setTransformFeedbackVaryings(GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode);
+ void getTransformFeedbackVarying(GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name) const;
+ GLsizei getTransformFeedbackVaryingCount() const;
+ GLsizei getTransformFeedbackVaryingMaxLength() const;
+ GLenum getTransformFeedbackBufferMode() const;
+ GLuint getTransformFeedbackVaryingResourceIndex(const GLchar *name) const;
+ const TransformFeedbackVarying &getTransformFeedbackVaryingResource(GLuint index) const;
+
+ bool hasDrawIDUniform() const;
+ void setDrawIDUniform(GLint drawid);
+
+ bool hasBaseVertexUniform() const;
+ void setBaseVertexUniform(GLint baseVertex);
+ bool hasBaseInstanceUniform() const;
+ void setBaseInstanceUniform(GLuint baseInstance);
+
+ ANGLE_INLINE void addRef()
+ {
+ ASSERT(!mLinkingState);
+ mRefCount++;
+ }
+
+ ANGLE_INLINE void release(const Context *context)
+ {
+ ASSERT(!mLinkingState);
+ mRefCount--;
+
+ if (mRefCount == 0 && mDeleteStatus)
+ {
+ deleteSelf(context);
+ }
+ }
+
+ unsigned int getRefCount() const;
+ bool isInUse() const { return getRefCount() != 0; }
+ void flagForDeletion();
+ bool isFlaggedForDeletion() const;
+
+ void validate(const Caps &caps);
+ bool isValidated() const;
+
+ const std::vector<ImageBinding> &getImageBindings() const
+ {
+ ASSERT(!mLinkingState);
+ return getExecutable().getImageBindings();
+ }
+ const sh::WorkGroupSize &getComputeShaderLocalSize() const;
+ PrimitiveMode getGeometryShaderInputPrimitiveType() const;
+ PrimitiveMode getGeometryShaderOutputPrimitiveType() const;
+ GLint getGeometryShaderInvocations() const;
+ GLint getGeometryShaderMaxVertices() const;
+
+ GLint getTessControlShaderVertices() const;
+ GLenum getTessGenMode() const;
+ GLenum getTessGenPointMode() const;
+ GLenum getTessGenSpacing() const;
+ GLenum getTessGenVertexOrder() const;
+
+ const ProgramState &getState() const
+ {
+ ASSERT(!mLinkingState);
+ return mState;
+ }
+
+ GLuint getInputResourceIndex(const GLchar *name) const;
+ GLuint getOutputResourceIndex(const GLchar *name) const;
+ void getInputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
+ void getOutputResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
+ void getUniformResourceName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const;
+ void getBufferVariableResourceName(GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name) const;
+ const sh::ShaderVariable &getInputResource(size_t index) const;
+ GLuint getResourceMaxNameSize(const sh::ShaderVariable &resource, GLint max) const;
+ GLuint getInputResourceMaxNameSize() const;
+ GLuint getOutputResourceMaxNameSize() const;
+ GLuint getResourceLocation(const GLchar *name, const sh::ShaderVariable &variable) const;
+ GLuint getInputResourceLocation(const GLchar *name) const;
+ GLuint getOutputResourceLocation(const GLchar *name) const;
+ const std::string getResourceName(const sh::ShaderVariable &resource) const;
+ const std::string getInputResourceName(GLuint index) const;
+ const std::string getOutputResourceName(GLuint index) const;
+ const sh::ShaderVariable &getOutputResource(size_t index) const;
+
+ const ProgramBindings &getAttributeBindings() const;
+ const ProgramAliasedBindings &getUniformLocationBindings() const;
+ const ProgramAliasedBindings &getFragmentOutputLocations() const;
+ const ProgramAliasedBindings &getFragmentOutputIndexes() const;
+
+ int getNumViews() const
+ {
+ ASSERT(!mLinkingState);
+ return mState.getNumViews();
+ }
+
+ bool usesMultiview() const { return mState.usesMultiview(); }
+
+ const std::vector<GLsizei> &getTransformFeedbackStrides() const;
+
+ // Program dirty bits.
+ enum DirtyBitType
+ {
+ DIRTY_BIT_UNIFORM_BLOCK_BINDING_0,
+ DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX =
+ DIRTY_BIT_UNIFORM_BLOCK_BINDING_0 + IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS,
+
+ DIRTY_BIT_COUNT = DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX,
+ };
+
+ using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>;
+
+ angle::Result syncState(const Context *context);
+
+ // Try to resolve linking. Inlined to make sure its overhead is as low as possible.
+ void resolveLink(const Context *context)
+ {
+ if (mLinkingState)
+ {
+ resolveLinkImpl(context);
+ }
+ }
+
+ ANGLE_INLINE bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+
+ // Writes a program's binary to the output memory buffer.
+ angle::Result serialize(const Context *context, angle::MemoryBuffer *binaryOut) const;
+
+ rx::Serial serial() const { return mSerial; }
+
+ const ProgramExecutable &getExecutable() const { return mState.getExecutable(); }
+ ProgramExecutable &getExecutable() { return mState.getExecutable(); }
+
+ private:
+ struct LinkingState;
+
+ ~Program() override;
+
+ // Loads program state according to the specified binary blob.
+ angle::Result deserialize(const Context *context, BinaryInputStream &stream, InfoLog &infoLog);
+
+ void unlink();
+ void deleteSelf(const Context *context);
+
+ angle::Result linkImpl(const Context *context);
+
+ bool linkValidateShaders(const Context *context, InfoLog &infoLog);
+ bool linkAttributes(const Context *context, InfoLog &infoLog);
+ bool linkVaryings(const Context *context, InfoLog &infoLog) const;
+
+ bool linkUniforms(const Context *context,
+ std::vector<UnusedUniform> *unusedUniformsOutOrNull,
+ GLuint *combinedImageUniformsOut,
+ InfoLog &infoLog);
+
+ void updateLinkedShaderStages();
+
+ void setUniformValuesFromBindingQualifiers();
+ bool shouldIgnoreUniform(UniformLocation location) const;
+
+ void initInterfaceBlockBindings();
+
+ // Both these function update the cached uniform values and return a modified "count"
+ // so that the uniform update doesn't overflow the uniform.
+ template <typename T>
+ GLsizei clampUniformCount(const VariableLocation &locationInfo,
+ GLsizei count,
+ int vectorSize,
+ const T *v);
+ template <size_t cols, size_t rows, typename T>
+ GLsizei clampMatrixUniformCount(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const T *v);
+
+ void updateSamplerUniform(Context *context,
+ const VariableLocation &locationInfo,
+ GLsizei clampedCount,
+ const GLint *v);
+
+ template <typename DestT>
+ void getUniformInternal(const Context *context,
+ DestT *dataOut,
+ UniformLocation location,
+ GLenum nativeType,
+ int components) const;
+
+ void getResourceName(const std::string name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *dest) const;
+
+ template <typename T>
+ GLint getActiveInterfaceBlockMaxNameLength(const std::vector<T> &resources) const;
+
+ GLuint getSamplerUniformBinding(const VariableLocation &uniformLocation) const;
+ GLuint getImageUniformBinding(const VariableLocation &uniformLocation) const;
+
+ // Block until linking is finished and resolve it.
+ void resolveLinkImpl(const gl::Context *context);
+
+ void postResolveLink(const gl::Context *context);
+
+ template <typename UniformT,
+ GLint UniformSize,
+ void (rx::ProgramImpl::*SetUniformFunc)(GLint, GLsizei, const UniformT *)>
+ void setUniformGeneric(UniformLocation location, GLsizei count, const UniformT *v);
+
+ template <
+ typename UniformT,
+ GLint MatrixC,
+ GLint MatrixR,
+ void (rx::ProgramImpl::*SetUniformMatrixFunc)(GLint, GLsizei, GLboolean, const UniformT *)>
+ void setUniformMatrixGeneric(UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const UniformT *v);
+
+ rx::Serial mSerial;
+ ProgramState mState;
+ rx::ProgramImpl *mProgram;
+
+ bool mValidated;
+
+ ProgramBindings mAttributeBindings;
+
+ // EXT_blend_func_extended
+ ProgramAliasedBindings mFragmentOutputLocations;
+ ProgramAliasedBindings mFragmentOutputIndexes;
+
+ bool mLinked;
+ std::unique_ptr<LinkingState> mLinkingState;
+ bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use
+
+ unsigned int mRefCount;
+
+ ShaderProgramManager *mResourceManager;
+ const ShaderProgramID mHandle;
+
+ DirtyBits mDirtyBits;
+
+ std::mutex mHistogramMutex;
+};
+} // namespace gl
+
+#endif // LIBANGLE_PROGRAM_H_
diff --git a/gfx/angle/checkout/src/libANGLE/ProgramExecutable.cpp b/gfx/angle/checkout/src/libANGLE/ProgramExecutable.cpp
new file mode 100644
index 0000000000..6005519347
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/ProgramExecutable.cpp
@@ -0,0 +1,1785 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ProgramExecutable.cpp: Collects the interfaces common to both Programs and
+// ProgramPipelines in order to execute/draw with either.
+
+#include "libANGLE/ProgramExecutable.h"
+
+#include "common/string_utils.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Shader.h"
+
+namespace gl
+{
+namespace
+{
+bool IncludeSameArrayElement(const std::set<std::string> &nameSet, const std::string &name)
+{
+ std::vector<unsigned int> subscripts;
+ std::string baseName = ParseResourceName(name, &subscripts);
+ for (const std::string &nameInSet : nameSet)
+ {
+ std::vector<unsigned int> arrayIndices;
+ std::string arrayName = ParseResourceName(nameInSet, &arrayIndices);
+ if (baseName == arrayName &&
+ (subscripts.empty() || arrayIndices.empty() || subscripts == arrayIndices))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+// Find the matching varying or field by name.
+const sh::ShaderVariable *FindOutputVaryingOrField(const ProgramMergedVaryings &varyings,
+ ShaderType stage,
+ const std::string &name)
+{
+ const sh::ShaderVariable *var = nullptr;
+ for (const ProgramVaryingRef &ref : varyings)
+ {
+ if (ref.frontShaderStage != stage)
+ {
+ continue;
+ }
+
+ const sh::ShaderVariable *varying = ref.get(stage);
+ if (varying->name == name)
+ {
+ var = varying;
+ break;
+ }
+ GLuint fieldIndex = 0;
+ var = varying->findField(name, &fieldIndex);
+ if (var != nullptr)
+ {
+ break;
+ }
+ }
+ return var;
+}
+
+bool FindUsedOutputLocation(std::vector<VariableLocation> &outputLocations,
+ unsigned int baseLocation,
+ unsigned int elementCount,
+ const std::vector<VariableLocation> &reservedLocations,
+ unsigned int variableIndex)
+{
+ if (baseLocation + elementCount > outputLocations.size())
+ {
+ elementCount = baseLocation < outputLocations.size()
+ ? static_cast<unsigned int>(outputLocations.size() - baseLocation)
+ : 0;
+ }
+ for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
+ {
+ const unsigned int location = baseLocation + elementIndex;
+ if (outputLocations[location].used())
+ {
+ VariableLocation locationInfo(elementIndex, variableIndex);
+ if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
+ reservedLocations.end())
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void AssignOutputLocations(std::vector<VariableLocation> &outputLocations,
+ unsigned int baseLocation,
+ unsigned int elementCount,
+ const std::vector<VariableLocation> &reservedLocations,
+ unsigned int variableIndex,
+ sh::ShaderVariable &outputVariable)
+{
+ if (baseLocation + elementCount > outputLocations.size())
+ {
+ outputLocations.resize(baseLocation + elementCount);
+ }
+ for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
+ {
+ VariableLocation locationInfo(elementIndex, variableIndex);
+ if (std::find(reservedLocations.begin(), reservedLocations.end(), locationInfo) ==
+ reservedLocations.end())
+ {
+ outputVariable.location = baseLocation;
+ const unsigned int location = baseLocation + elementIndex;
+ outputLocations[location] = locationInfo;
+ }
+ }
+}
+
+int GetOutputLocationForLink(const ProgramAliasedBindings &fragmentOutputLocations,
+ const sh::ShaderVariable &outputVariable)
+{
+ if (outputVariable.location != -1)
+ {
+ return outputVariable.location;
+ }
+ int apiLocation = fragmentOutputLocations.getBinding(outputVariable);
+ if (apiLocation != -1)
+ {
+ return apiLocation;
+ }
+ return -1;
+}
+
+bool IsOutputSecondaryForLink(const ProgramAliasedBindings &fragmentOutputIndexes,
+ const sh::ShaderVariable &outputVariable)
+{
+ if (outputVariable.index != -1)
+ {
+ ASSERT(outputVariable.index == 0 || outputVariable.index == 1);
+ return (outputVariable.index == 1);
+ }
+ int apiIndex = fragmentOutputIndexes.getBinding(outputVariable);
+ if (apiIndex != -1)
+ {
+ // Index layout qualifier from the shader takes precedence, so the index from the API is
+ // checked only if the index was not set in the shader. This is not specified in the EXT
+ // spec, but is specified in desktop OpenGL specs.
+ return (apiIndex == 1);
+ }
+ // EXT_blend_func_extended: Outputs get index 0 by default.
+ return false;
+}
+
+RangeUI AddUniforms(const ShaderMap<Program *> &programs,
+ ShaderBitSet activeShaders,
+ std::vector<LinkedUniform> &outputUniforms,
+ const std::function<RangeUI(const ProgramState &)> &getRange)
+{
+ unsigned int startRange = static_cast<unsigned int>(outputUniforms.size());
+ for (ShaderType shaderType : activeShaders)
+ {
+ const ProgramState &programState = programs[shaderType]->getState();
+ const std::vector<LinkedUniform> &programUniforms = programState.getUniforms();
+ const RangeUI uniformRange = getRange(programState);
+
+ outputUniforms.insert(outputUniforms.end(), programUniforms.begin() + uniformRange.low(),
+ programUniforms.begin() + uniformRange.high());
+ }
+ return RangeUI(startRange, static_cast<unsigned int>(outputUniforms.size()));
+}
+
+template <typename BlockT>
+void AppendActiveBlocks(ShaderType shaderType,
+ const std::vector<BlockT> &blocksIn,
+ std::vector<BlockT> &blocksOut)
+{
+ for (const BlockT &block : blocksIn)
+ {
+ if (block.isActive(shaderType))
+ {
+ blocksOut.push_back(block);
+ }
+ }
+}
+} // anonymous namespace
+
+ProgramExecutable::ProgramExecutable()
+ : mMaxActiveAttribLocation(0),
+ mAttributesTypeMask(0),
+ mAttributesMask(0),
+ mActiveSamplerRefCounts{},
+ mCanDrawWith(false),
+ mYUVOutput(false),
+ mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS),
+ mDefaultUniformRange(0, 0),
+ mSamplerUniformRange(0, 0),
+ mImageUniformRange(0, 0),
+ mAtomicCounterUniformRange(0, 0),
+ mFragmentInoutRange(0, 0),
+ mHasDiscard(false),
+ mEnablesPerSampleShading(false),
+ // [GL_EXT_geometry_shader] Table 20.22
+ mGeometryShaderInputPrimitiveType(PrimitiveMode::Triangles),
+ mGeometryShaderOutputPrimitiveType(PrimitiveMode::TriangleStrip),
+ mGeometryShaderInvocations(1),
+ mGeometryShaderMaxVertices(0),
+ mTessControlShaderVertices(0),
+ mTessGenMode(GL_NONE),
+ mTessGenSpacing(GL_NONE),
+ mTessGenVertexOrder(GL_NONE),
+ mTessGenPointMode(GL_NONE)
+{
+ reset(true);
+}
+
+ProgramExecutable::ProgramExecutable(const ProgramExecutable &other)
+ : mLinkedShaderStages(other.mLinkedShaderStages),
+ mActiveAttribLocationsMask(other.mActiveAttribLocationsMask),
+ mMaxActiveAttribLocation(other.mMaxActiveAttribLocation),
+ mAttributesTypeMask(other.mAttributesTypeMask),
+ mAttributesMask(other.mAttributesMask),
+ mActiveSamplersMask(other.mActiveSamplersMask),
+ mActiveSamplerRefCounts(other.mActiveSamplerRefCounts),
+ mActiveSamplerTypes(other.mActiveSamplerTypes),
+ mActiveSamplerYUV(other.mActiveSamplerYUV),
+ mActiveSamplerFormats(other.mActiveSamplerFormats),
+ mActiveSamplerShaderBits(other.mActiveSamplerShaderBits),
+ mActiveImagesMask(other.mActiveImagesMask),
+ mActiveImageShaderBits(other.mActiveImageShaderBits),
+ mCanDrawWith(other.mCanDrawWith),
+ mOutputVariables(other.mOutputVariables),
+ mOutputLocations(other.mOutputLocations),
+ mSecondaryOutputLocations(other.mSecondaryOutputLocations),
+ mYUVOutput(other.mYUVOutput),
+ mProgramInputs(other.mProgramInputs),
+ mLinkedTransformFeedbackVaryings(other.mLinkedTransformFeedbackVaryings),
+ mTransformFeedbackStrides(other.mTransformFeedbackStrides),
+ mTransformFeedbackBufferMode(other.mTransformFeedbackBufferMode),
+ mUniforms(other.mUniforms),
+ mDefaultUniformRange(other.mDefaultUniformRange),
+ mSamplerUniformRange(other.mSamplerUniformRange),
+ mImageUniformRange(other.mImageUniformRange),
+ mAtomicCounterUniformRange(other.mAtomicCounterUniformRange),
+ mUniformBlocks(other.mUniformBlocks),
+ mActiveUniformBlockBindings(other.mActiveUniformBlockBindings),
+ mAtomicCounterBuffers(other.mAtomicCounterBuffers),
+ mShaderStorageBlocks(other.mShaderStorageBlocks),
+ mFragmentInoutRange(other.mFragmentInoutRange),
+ mHasDiscard(other.mHasDiscard),
+ mEnablesPerSampleShading(other.mEnablesPerSampleShading),
+ mAdvancedBlendEquations(other.mAdvancedBlendEquations)
+{
+ reset(true);
+}
+
+ProgramExecutable::~ProgramExecutable() = default;
+
+void ProgramExecutable::reset(bool clearInfoLog)
+{
+ if (clearInfoLog)
+ {
+ resetInfoLog();
+ }
+ mActiveAttribLocationsMask.reset();
+ mAttributesTypeMask.reset();
+ mAttributesMask.reset();
+ mMaxActiveAttribLocation = 0;
+
+ mActiveSamplersMask.reset();
+ mActiveSamplerRefCounts = {};
+ mActiveSamplerTypes.fill(TextureType::InvalidEnum);
+ mActiveSamplerYUV.reset();
+ mActiveSamplerFormats.fill(SamplerFormat::InvalidEnum);
+
+ mActiveImagesMask.reset();
+
+ mProgramInputs.clear();
+ mLinkedTransformFeedbackVaryings.clear();
+ mTransformFeedbackStrides.clear();
+ mUniforms.clear();
+ mUniformBlocks.clear();
+ mActiveUniformBlockBindings.reset();
+ mShaderStorageBlocks.clear();
+ mAtomicCounterBuffers.clear();
+ mOutputVariables.clear();
+ mOutputLocations.clear();
+ mActiveOutputVariablesMask.reset();
+ mSecondaryOutputLocations.clear();
+ mYUVOutput = false;
+ mSamplerBindings.clear();
+ mImageBindings.clear();
+
+ mDefaultUniformRange = RangeUI(0, 0);
+ mSamplerUniformRange = RangeUI(0, 0);
+ mImageUniformRange = RangeUI(0, 0);
+ mAtomicCounterUniformRange = RangeUI(0, 0);
+
+ mFragmentInoutRange = RangeUI(0, 0);
+ mHasDiscard = false;
+ mEnablesPerSampleShading = false;
+ mAdvancedBlendEquations.reset();
+
+ mGeometryShaderInputPrimitiveType = PrimitiveMode::Triangles;
+ mGeometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
+ mGeometryShaderInvocations = 1;
+ mGeometryShaderMaxVertices = 0;
+
+ mTessControlShaderVertices = 0;
+ mTessGenMode = GL_NONE;
+ mTessGenSpacing = GL_NONE;
+ mTessGenVertexOrder = GL_NONE;
+ mTessGenPointMode = GL_NONE;
+
+ mOutputVariableTypes.clear();
+ mDrawBufferTypeMask.reset();
+}
+
+void ProgramExecutable::load(bool isSeparable, gl::BinaryInputStream *stream)
+{
+ static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
+ "Too many vertex attribs for mask: All bits of mAttributesTypeMask types and "
+ "mask fit into 32 bits each");
+ mAttributesTypeMask = gl::ComponentTypeMask(stream->readInt<uint32_t>());
+ mAttributesMask = gl::AttributesMask(stream->readInt<uint32_t>());
+ mActiveAttribLocationsMask = gl::AttributesMask(stream->readInt<uint32_t>());
+ mMaxActiveAttribLocation = stream->readInt<unsigned int>();
+
+ unsigned int fragmentInoutRangeLow = stream->readInt<uint32_t>();
+ unsigned int fragmentInoutRangeHigh = stream->readInt<uint32_t>();
+ mFragmentInoutRange = RangeUI(fragmentInoutRangeLow, fragmentInoutRangeHigh);
+
+ mHasDiscard = stream->readBool();
+ mEnablesPerSampleShading = stream->readBool();
+
+ static_assert(sizeof(mAdvancedBlendEquations.bits()) == sizeof(uint32_t));
+ mAdvancedBlendEquations = BlendEquationBitSet(stream->readInt<uint32_t>());
+
+ mLinkedShaderStages = ShaderBitSet(stream->readInt<uint8_t>());
+
+ mGeometryShaderInputPrimitiveType = stream->readEnum<PrimitiveMode>();
+ mGeometryShaderOutputPrimitiveType = stream->readEnum<PrimitiveMode>();
+ mGeometryShaderInvocations = stream->readInt<int>();
+ mGeometryShaderMaxVertices = stream->readInt<int>();
+
+ mTessControlShaderVertices = stream->readInt<int>();
+ mTessGenMode = stream->readInt<GLenum>();
+ mTessGenSpacing = stream->readInt<GLenum>();
+ mTessGenVertexOrder = stream->readInt<GLenum>();
+ mTessGenPointMode = stream->readInt<GLenum>();
+
+ size_t attribCount = stream->readInt<size_t>();
+ ASSERT(getProgramInputs().empty());
+ for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex)
+ {
+ sh::ShaderVariable attrib;
+ LoadShaderVar(stream, &attrib);
+ attrib.location = stream->readInt<int>();
+ mProgramInputs.push_back(attrib);
+ }
+
+ size_t uniformCount = stream->readInt<size_t>();
+ ASSERT(getUniforms().empty());
+ for (size_t uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex)
+ {
+ LinkedUniform uniform;
+ LoadShaderVar(stream, &uniform);
+
+ uniform.bufferIndex = stream->readInt<int>();
+ LoadBlockMemberInfo(stream, &uniform.blockInfo);
+
+ stream->readIntVector<unsigned int>(&uniform.outerArraySizes);
+ uniform.outerArrayOffset = stream->readInt<unsigned int>();
+
+ uniform.typeInfo = &GetUniformTypeInfo(uniform.type);
+
+ // Active shader info
+ for (ShaderType shaderType : gl::AllShaderTypes())
+ {
+ uniform.setActive(shaderType, stream->readBool());
+ }
+
+ mUniforms.push_back(uniform);
+ }
+
+ size_t uniformBlockCount = stream->readInt<size_t>();
+ ASSERT(getUniformBlocks().empty());
+ for (size_t uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex)
+ {
+ InterfaceBlock uniformBlock;
+ LoadInterfaceBlock(stream, &uniformBlock);
+ mUniformBlocks.push_back(uniformBlock);
+
+ mActiveUniformBlockBindings.set(uniformBlockIndex, uniformBlock.binding != 0);
+ }
+
+ size_t shaderStorageBlockCount = stream->readInt<size_t>();
+ ASSERT(getShaderStorageBlocks().empty());
+ for (size_t shaderStorageBlockIndex = 0; shaderStorageBlockIndex < shaderStorageBlockCount;
+ ++shaderStorageBlockIndex)
+ {
+ InterfaceBlock shaderStorageBlock;
+ LoadInterfaceBlock(stream, &shaderStorageBlock);
+ mShaderStorageBlocks.push_back(shaderStorageBlock);
+ }
+
+ size_t atomicCounterBufferCount = stream->readInt<size_t>();
+ ASSERT(getAtomicCounterBuffers().empty());
+ for (size_t bufferIndex = 0; bufferIndex < atomicCounterBufferCount; ++bufferIndex)
+ {
+ AtomicCounterBuffer atomicCounterBuffer;
+ LoadShaderVariableBuffer(stream, &atomicCounterBuffer);
+
+ mAtomicCounterBuffers.push_back(atomicCounterBuffer);
+ }
+
+ size_t transformFeedbackVaryingCount = stream->readInt<size_t>();
+ ASSERT(mLinkedTransformFeedbackVaryings.empty());
+ for (size_t transformFeedbackVaryingIndex = 0;
+ transformFeedbackVaryingIndex < transformFeedbackVaryingCount;
+ ++transformFeedbackVaryingIndex)
+ {
+ sh::ShaderVariable varying;
+ stream->readIntVector<unsigned int>(&varying.arraySizes);
+ stream->readInt(&varying.type);
+ stream->readString(&varying.name);
+
+ GLuint arrayIndex = stream->readInt<GLuint>();
+
+ mLinkedTransformFeedbackVaryings.emplace_back(varying, arrayIndex);
+ }
+
+ mTransformFeedbackBufferMode = stream->readInt<GLint>();
+
+ size_t outputCount = stream->readInt<size_t>();
+ ASSERT(getOutputVariables().empty());
+ for (size_t outputIndex = 0; outputIndex < outputCount; ++outputIndex)
+ {
+ sh::ShaderVariable output;
+ LoadShaderVar(stream, &output);
+ output.location = stream->readInt<int>();
+ output.index = stream->readInt<int>();
+ mOutputVariables.push_back(output);
+ }
+
+ size_t outputVarCount = stream->readInt<size_t>();
+ ASSERT(getOutputLocations().empty());
+ for (size_t outputIndex = 0; outputIndex < outputVarCount; ++outputIndex)
+ {
+ VariableLocation locationData;
+ stream->readInt(&locationData.arrayIndex);
+ stream->readInt(&locationData.index);
+ stream->readBool(&locationData.ignored);
+ mOutputLocations.push_back(locationData);
+ }
+
+ mActiveOutputVariablesMask =
+ gl::DrawBufferMask(stream->readInt<gl::DrawBufferMask::value_type>());
+
+ size_t outputTypeCount = stream->readInt<size_t>();
+ for (size_t outputIndex = 0; outputIndex < outputTypeCount; ++outputIndex)
+ {
+ mOutputVariableTypes.push_back(stream->readInt<GLenum>());
+ }
+
+ static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
+ "All bits of mDrawBufferTypeMask and mActiveOutputVariables types and mask fit "
+ "into 32 bits each");
+ mDrawBufferTypeMask = gl::ComponentTypeMask(stream->readInt<uint32_t>());
+
+ stream->readBool(&mYUVOutput);
+
+ size_t secondaryOutputVarCount = stream->readInt<size_t>();
+ ASSERT(getSecondaryOutputLocations().empty());
+ for (size_t outputIndex = 0; outputIndex < secondaryOutputVarCount; ++outputIndex)
+ {
+ VariableLocation locationData;
+ stream->readInt(&locationData.arrayIndex);
+ stream->readInt(&locationData.index);
+ stream->readBool(&locationData.ignored);
+ mSecondaryOutputLocations.push_back(locationData);
+ }
+
+ unsigned int defaultUniformRangeLow = stream->readInt<unsigned int>();
+ unsigned int defaultUniformRangeHigh = stream->readInt<unsigned int>();
+ mDefaultUniformRange = RangeUI(defaultUniformRangeLow, defaultUniformRangeHigh);
+
+ unsigned int samplerRangeLow = stream->readInt<unsigned int>();
+ unsigned int samplerRangeHigh = stream->readInt<unsigned int>();
+ mSamplerUniformRange = RangeUI(samplerRangeLow, samplerRangeHigh);
+
+ size_t samplerCount = stream->readInt<size_t>();
+ for (size_t samplerIndex = 0; samplerIndex < samplerCount; ++samplerIndex)
+ {
+ TextureType textureType = stream->readEnum<TextureType>();
+ GLenum samplerType = stream->readInt<GLenum>();
+ SamplerFormat format = stream->readEnum<SamplerFormat>();
+ size_t bindingCount = stream->readInt<size_t>();
+ mSamplerBindings.emplace_back(textureType, samplerType, format, bindingCount);
+ }
+
+ unsigned int imageRangeLow = stream->readInt<unsigned int>();
+ unsigned int imageRangeHigh = stream->readInt<unsigned int>();
+ mImageUniformRange = RangeUI(imageRangeLow, imageRangeHigh);
+
+ size_t imageBindingCount = stream->readInt<size_t>();
+ for (size_t imageIndex = 0; imageIndex < imageBindingCount; ++imageIndex)
+ {
+ size_t elementCount = stream->readInt<size_t>();
+ TextureType textureType = static_cast<TextureType>(stream->readInt<unsigned int>());
+ ImageBinding imageBinding(elementCount, textureType);
+ for (size_t elementIndex = 0; elementIndex < elementCount; ++elementIndex)
+ {
+ imageBinding.boundImageUnits[elementIndex] = stream->readInt<unsigned int>();
+ }
+ mImageBindings.emplace_back(imageBinding);
+ }
+
+ unsigned int atomicCounterRangeLow = stream->readInt<unsigned int>();
+ unsigned int atomicCounterRangeHigh = stream->readInt<unsigned int>();
+ mAtomicCounterUniformRange = RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
+
+ // These values are currently only used by PPOs, so only load them when the program is marked
+ // separable to save memory.
+ if (isSeparable)
+ {
+ for (ShaderType shaderType : mLinkedShaderStages)
+ {
+ mLinkedOutputVaryings[shaderType].resize(stream->readInt<size_t>());
+ for (sh::ShaderVariable &variable : mLinkedOutputVaryings[shaderType])
+ {
+ LoadShaderVar(stream, &variable);
+ }
+ mLinkedInputVaryings[shaderType].resize(stream->readInt<size_t>());
+ for (sh::ShaderVariable &variable : mLinkedInputVaryings[shaderType])
+ {
+ LoadShaderVar(stream, &variable);
+ }
+ mLinkedUniforms[shaderType].resize(stream->readInt<size_t>());
+ for (sh::ShaderVariable &variable : mLinkedUniforms[shaderType])
+ {
+ LoadShaderVar(stream, &variable);
+ }
+ mLinkedUniformBlocks[shaderType].resize(stream->readInt<size_t>());
+ for (sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType])
+ {
+ LoadShInterfaceBlock(stream, &shaderStorageBlock);
+ }
+ mLinkedShaderVersions[shaderType] = stream->readInt<int>();
+ }
+ }
+}
+
+void ProgramExecutable::save(bool isSeparable, gl::BinaryOutputStream *stream) const
+{
+ static_assert(MAX_VERTEX_ATTRIBS * 2 <= sizeof(uint32_t) * 8,
+ "All bits of mAttributesTypeMask types and mask fit into 32 bits each");
+ stream->writeInt(static_cast<uint32_t>(mAttributesTypeMask.to_ulong()));
+ stream->writeInt(static_cast<uint32_t>(mAttributesMask.to_ulong()));
+ stream->writeInt(static_cast<uint32_t>(mActiveAttribLocationsMask.to_ulong()));
+ stream->writeInt(mMaxActiveAttribLocation);
+
+ stream->writeInt(mFragmentInoutRange.low());
+ stream->writeInt(mFragmentInoutRange.high());
+
+ stream->writeBool(mHasDiscard);
+ stream->writeBool(mEnablesPerSampleShading);
+ stream->writeInt(mAdvancedBlendEquations.bits());
+
+ stream->writeInt(mLinkedShaderStages.bits());
+
+ ASSERT(mGeometryShaderInvocations >= 1 && mGeometryShaderMaxVertices >= 0);
+ stream->writeEnum(mGeometryShaderInputPrimitiveType);
+ stream->writeEnum(mGeometryShaderOutputPrimitiveType);
+ stream->writeInt(mGeometryShaderInvocations);
+ stream->writeInt(mGeometryShaderMaxVertices);
+
+ stream->writeInt(mTessControlShaderVertices);
+ stream->writeInt(mTessGenMode);
+ stream->writeInt(mTessGenSpacing);
+ stream->writeInt(mTessGenVertexOrder);
+ stream->writeInt(mTessGenPointMode);
+
+ stream->writeInt(getProgramInputs().size());
+ for (const sh::ShaderVariable &attrib : getProgramInputs())
+ {
+ WriteShaderVar(stream, attrib);
+ stream->writeInt(attrib.location);
+ }
+
+ stream->writeInt(getUniforms().size());
+ for (const LinkedUniform &uniform : getUniforms())
+ {
+ WriteShaderVar(stream, uniform);
+
+ stream->writeInt(uniform.bufferIndex);
+ WriteBlockMemberInfo(stream, uniform.blockInfo);
+
+ stream->writeIntVector(uniform.outerArraySizes);
+ stream->writeInt(uniform.outerArrayOffset);
+
+ // Active shader info
+ for (ShaderType shaderType : gl::AllShaderTypes())
+ {
+ stream->writeBool(uniform.isActive(shaderType));
+ }
+ }
+
+ stream->writeInt(getUniformBlocks().size());
+ for (const InterfaceBlock &uniformBlock : getUniformBlocks())
+ {
+ WriteInterfaceBlock(stream, uniformBlock);
+ }
+
+ stream->writeInt(getShaderStorageBlocks().size());
+ for (const InterfaceBlock &shaderStorageBlock : getShaderStorageBlocks())
+ {
+ WriteInterfaceBlock(stream, shaderStorageBlock);
+ }
+
+ stream->writeInt(mAtomicCounterBuffers.size());
+ for (const AtomicCounterBuffer &atomicCounterBuffer : getAtomicCounterBuffers())
+ {
+ WriteShaderVariableBuffer(stream, atomicCounterBuffer);
+ }
+
+ stream->writeInt(getLinkedTransformFeedbackVaryings().size());
+ for (const auto &var : getLinkedTransformFeedbackVaryings())
+ {
+ stream->writeIntVector(var.arraySizes);
+ stream->writeInt(var.type);
+ stream->writeString(var.name);
+
+ stream->writeIntOrNegOne(var.arrayIndex);
+ }
+
+ stream->writeInt(getTransformFeedbackBufferMode());
+
+ stream->writeInt(getOutputVariables().size());
+ for (const sh::ShaderVariable &output : getOutputVariables())
+ {
+ WriteShaderVar(stream, output);
+ stream->writeInt(output.location);
+ stream->writeInt(output.index);
+ }
+
+ stream->writeInt(getOutputLocations().size());
+ for (const auto &outputVar : getOutputLocations())
+ {
+ stream->writeInt(outputVar.arrayIndex);
+ stream->writeIntOrNegOne(outputVar.index);
+ stream->writeBool(outputVar.ignored);
+ }
+
+ stream->writeInt(static_cast<int>(mActiveOutputVariablesMask.to_ulong()));
+
+ stream->writeInt(mOutputVariableTypes.size());
+ for (const auto &outputVariableType : mOutputVariableTypes)
+ {
+ stream->writeInt(outputVariableType);
+ }
+
+ static_assert(
+ IMPLEMENTATION_MAX_DRAW_BUFFERS * 2 <= 8 * sizeof(uint32_t),
+ "All bits of mDrawBufferTypeMask and mActiveOutputVariables can be contained in 32 bits");
+ stream->writeInt(static_cast<int>(mDrawBufferTypeMask.to_ulong()));
+
+ stream->writeBool(mYUVOutput);
+
+ stream->writeInt(getSecondaryOutputLocations().size());
+ for (const auto &outputVar : getSecondaryOutputLocations())
+ {
+ stream->writeInt(outputVar.arrayIndex);
+ stream->writeIntOrNegOne(outputVar.index);
+ stream->writeBool(outputVar.ignored);
+ }
+
+ stream->writeInt(getDefaultUniformRange().low());
+ stream->writeInt(getDefaultUniformRange().high());
+
+ stream->writeInt(getSamplerUniformRange().low());
+ stream->writeInt(getSamplerUniformRange().high());
+
+ stream->writeInt(getSamplerBindings().size());
+ for (const auto &samplerBinding : getSamplerBindings())
+ {
+ stream->writeEnum(samplerBinding.textureType);
+ stream->writeInt(samplerBinding.samplerType);
+ stream->writeEnum(samplerBinding.format);
+ stream->writeInt(samplerBinding.boundTextureUnits.size());
+ }
+
+ stream->writeInt(getImageUniformRange().low());
+ stream->writeInt(getImageUniformRange().high());
+
+ stream->writeInt(getImageBindings().size());
+ for (const auto &imageBinding : getImageBindings())
+ {
+ stream->writeInt(imageBinding.boundImageUnits.size());
+ stream->writeInt(static_cast<unsigned int>(imageBinding.textureType));
+ for (size_t i = 0; i < imageBinding.boundImageUnits.size(); ++i)
+ {
+ stream->writeInt(imageBinding.boundImageUnits[i]);
+ }
+ }
+
+ stream->writeInt(getAtomicCounterUniformRange().low());
+ stream->writeInt(getAtomicCounterUniformRange().high());
+
+ // These values are currently only used by PPOs, so only save them when the program is marked
+ // separable to save memory.
+ if (isSeparable)
+ {
+ for (ShaderType shaderType : mLinkedShaderStages)
+ {
+ stream->writeInt(mLinkedOutputVaryings[shaderType].size());
+ for (const sh::ShaderVariable &shaderVariable : mLinkedOutputVaryings[shaderType])
+ {
+ WriteShaderVar(stream, shaderVariable);
+ }
+ stream->writeInt(mLinkedInputVaryings[shaderType].size());
+ for (const sh::ShaderVariable &shaderVariable : mLinkedInputVaryings[shaderType])
+ {
+ WriteShaderVar(stream, shaderVariable);
+ }
+ stream->writeInt(mLinkedUniforms[shaderType].size());
+ for (const sh::ShaderVariable &shaderVariable : mLinkedUniforms[shaderType])
+ {
+ WriteShaderVar(stream, shaderVariable);
+ }
+ stream->writeInt(mLinkedUniformBlocks[shaderType].size());
+ for (const sh::InterfaceBlock &shaderStorageBlock : mLinkedUniformBlocks[shaderType])
+ {
+ WriteShInterfaceBlock(stream, shaderStorageBlock);
+ }
+ stream->writeInt(mLinkedShaderVersions[shaderType]);
+ }
+ }
+}
+
+int ProgramExecutable::getInfoLogLength() const
+{
+ return static_cast<int>(mInfoLog.getLength());
+}
+
+void ProgramExecutable::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
+{
+ return mInfoLog.getLog(bufSize, length, infoLog);
+}
+
+std::string ProgramExecutable::getInfoLogString() const
+{
+ return mInfoLog.str();
+}
+
+bool ProgramExecutable::isAttribLocationActive(size_t attribLocation) const
+{
+ ASSERT(attribLocation < mActiveAttribLocationsMask.size());
+ return mActiveAttribLocationsMask[attribLocation];
+}
+
+AttributesMask ProgramExecutable::getAttributesMask() const
+{
+ return mAttributesMask;
+}
+
+bool ProgramExecutable::hasDefaultUniforms() const
+{
+ return !getDefaultUniformRange().empty();
+}
+
+bool ProgramExecutable::hasTextures() const
+{
+ return !getSamplerBindings().empty();
+}
+
+bool ProgramExecutable::hasUniformBuffers() const
+{
+ return !mUniformBlocks.empty();
+}
+
+bool ProgramExecutable::hasStorageBuffers() const
+{
+ return !mShaderStorageBlocks.empty();
+}
+
+bool ProgramExecutable::hasAtomicCounterBuffers() const
+{
+ return !mAtomicCounterBuffers.empty();
+}
+
+bool ProgramExecutable::hasImages() const
+{
+ return !mImageBindings.empty();
+}
+
+bool ProgramExecutable::usesFramebufferFetch() const
+{
+ return (mFragmentInoutRange.length() > 0);
+}
+
+GLuint ProgramExecutable::getUniformIndexFromImageIndex(GLuint imageIndex) const
+{
+ ASSERT(imageIndex < mImageUniformRange.length());
+ return imageIndex + mImageUniformRange.low();
+}
+
+GLuint ProgramExecutable::getUniformIndexFromSamplerIndex(GLuint samplerIndex) const
+{
+ ASSERT(samplerIndex < mSamplerUniformRange.length());
+ return samplerIndex + mSamplerUniformRange.low();
+}
+
+void ProgramExecutable::setActive(size_t textureUnit,
+ const SamplerBinding &samplerBinding,
+ const gl::LinkedUniform &samplerUniform)
+{
+ mActiveSamplersMask.set(textureUnit);
+ mActiveSamplerTypes[textureUnit] = samplerBinding.textureType;
+ mActiveSamplerYUV[textureUnit] = IsSamplerYUVType(samplerBinding.samplerType);
+ mActiveSamplerFormats[textureUnit] = samplerBinding.format;
+ mActiveSamplerShaderBits[textureUnit] = samplerUniform.activeShaders();
+}
+
+void ProgramExecutable::setInactive(size_t textureUnit)
+{
+ mActiveSamplersMask.reset(textureUnit);
+ mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
+ mActiveSamplerYUV.reset(textureUnit);
+ mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
+ mActiveSamplerShaderBits[textureUnit].reset();
+}
+
+void ProgramExecutable::hasSamplerTypeConflict(size_t textureUnit)
+{
+ // Conflicts are marked with InvalidEnum
+ mActiveSamplerYUV.reset(textureUnit);
+ mActiveSamplerTypes[textureUnit] = TextureType::InvalidEnum;
+}
+
+void ProgramExecutable::hasSamplerFormatConflict(size_t textureUnit)
+{
+ // Conflicts are marked with InvalidEnum
+ mActiveSamplerFormats[textureUnit] = SamplerFormat::InvalidEnum;
+}
+
+void ProgramExecutable::updateActiveSamplers(const ProgramState &programState)
+{
+ const std::vector<SamplerBinding> &samplerBindings = programState.getSamplerBindings();
+
+ for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
+ {
+ const SamplerBinding &samplerBinding = samplerBindings[samplerIndex];
+
+ for (GLint textureUnit : samplerBinding.boundTextureUnits)
+ {
+ if (++mActiveSamplerRefCounts[textureUnit] == 1)
+ {
+ uint32_t uniformIndex = programState.getUniformIndexFromSamplerIndex(samplerIndex);
+ setActive(textureUnit, samplerBinding, programState.getUniforms()[uniformIndex]);
+ }
+ else
+ {
+ if (mActiveSamplerTypes[textureUnit] != samplerBinding.textureType ||
+ mActiveSamplerYUV.test(textureUnit) !=
+ IsSamplerYUVType(samplerBinding.samplerType))
+ {
+ hasSamplerTypeConflict(textureUnit);
+ }
+
+ if (mActiveSamplerFormats[textureUnit] != samplerBinding.format)
+ {
+ hasSamplerFormatConflict(textureUnit);
+ }
+ }
+ mActiveSamplersMask.set(textureUnit);
+ }
+ }
+
+ // Invalidate the validation cache.
+ resetCachedValidateSamplersResult();
+}
+
+void ProgramExecutable::updateActiveImages(const ProgramExecutable &executable)
+{
+ const std::vector<ImageBinding> &imageBindings = executable.getImageBindings();
+ for (uint32_t imageIndex = 0; imageIndex < imageBindings.size(); ++imageIndex)
+ {
+ const gl::ImageBinding &imageBinding = imageBindings.at(imageIndex);
+
+ uint32_t uniformIndex = executable.getUniformIndexFromImageIndex(imageIndex);
+ const gl::LinkedUniform &imageUniform = executable.getUniforms()[uniformIndex];
+ const ShaderBitSet shaderBits = imageUniform.activeShaders();
+ for (GLint imageUnit : imageBinding.boundImageUnits)
+ {
+ mActiveImagesMask.set(imageUnit);
+ mActiveImageShaderBits[imageUnit] |= shaderBits;
+ }
+ }
+}
+
+void ProgramExecutable::setSamplerUniformTextureTypeAndFormat(
+ size_t textureUnitIndex,
+ std::vector<SamplerBinding> &samplerBindings)
+{
+ bool foundBinding = false;
+ TextureType foundType = TextureType::InvalidEnum;
+ bool foundYUV = false;
+ SamplerFormat foundFormat = SamplerFormat::InvalidEnum;
+
+ for (uint32_t samplerIndex = 0; samplerIndex < samplerBindings.size(); ++samplerIndex)
+ {
+ const SamplerBinding &binding = samplerBindings[samplerIndex];
+
+ // A conflict exists if samplers of different types are sourced by the same texture unit.
+ // We need to check all bound textures to detect this error case.
+ for (GLuint textureUnit : binding.boundTextureUnits)
+ {
+ if (textureUnit != textureUnitIndex)
+ {
+ continue;
+ }
+
+ if (!foundBinding)
+ {
+ foundBinding = true;
+ foundType = binding.textureType;
+ foundYUV = IsSamplerYUVType(binding.samplerType);
+ foundFormat = binding.format;
+ uint32_t uniformIndex = getUniformIndexFromSamplerIndex(samplerIndex);
+ setActive(textureUnit, binding, mUniforms[uniformIndex]);
+ }
+ else
+ {
+ if (foundType != binding.textureType ||
+ foundYUV != IsSamplerYUVType(binding.samplerType))
+ {
+ hasSamplerTypeConflict(textureUnit);
+ }
+
+ if (foundFormat != binding.format)
+ {
+ hasSamplerFormatConflict(textureUnit);
+ }
+ }
+ }
+ }
+}
+
+void ProgramExecutable::updateCanDrawWith()
+{
+ mCanDrawWith = hasLinkedShaderStage(ShaderType::Vertex);
+}
+
+void ProgramExecutable::saveLinkedStateInfo(const Context *context, const ProgramState &state)
+{
+ for (ShaderType shaderType : getLinkedShaderStages())
+ {
+ Shader *shader = state.getAttachedShader(shaderType);
+ ASSERT(shader);
+ mLinkedOutputVaryings[shaderType] = shader->getOutputVaryings(context);
+ mLinkedInputVaryings[shaderType] = shader->getInputVaryings(context);
+ mLinkedShaderVersions[shaderType] = shader->getShaderVersion(context);
+ mLinkedUniforms[shaderType] = shader->getUniforms(context);
+ mLinkedUniformBlocks[shaderType] = shader->getUniformBlocks(context);
+ }
+}
+
+bool ProgramExecutable::isYUVOutput() const
+{
+ return mYUVOutput;
+}
+
+ShaderType ProgramExecutable::getLinkedTransformFeedbackStage() const
+{
+ return GetLastPreFragmentStage(mLinkedShaderStages);
+}
+
+bool ProgramExecutable::linkMergedVaryings(
+ const Context *context,
+ const ProgramMergedVaryings &mergedVaryings,
+ const std::vector<std::string> &transformFeedbackVaryingNames,
+ const LinkingVariables &linkingVariables,
+ bool isSeparable,
+ ProgramVaryingPacking *varyingPacking)
+{
+ ShaderType tfStage = GetLastPreFragmentStage(linkingVariables.isShaderStageUsedBitset);
+
+ if (!linkValidateTransformFeedback(context, mergedVaryings, tfStage,
+ transformFeedbackVaryingNames))
+ {
+ return false;
+ }
+
+ // Map the varyings to the register file
+ // In WebGL, we use a slightly different handling for packing variables.
+ gl::PackMode packMode = PackMode::ANGLE_RELAXED;
+ if (context->getLimitations().noFlexibleVaryingPacking)
+ {
+ // D3D9 pack mode is strictly more strict than WebGL, so takes priority.
+ packMode = PackMode::ANGLE_NON_CONFORMANT_D3D9;
+ }
+ else if (context->isWebGL())
+ {
+ packMode = PackMode::WEBGL_STRICT;
+ }
+
+ // Build active shader stage map.
+ ShaderBitSet activeShadersMask;
+ for (ShaderType shaderType : kAllGraphicsShaderTypes)
+ {
+ // - Check for attached shaders to handle the case of a Program linking the currently
+ // attached shaders.
+ // - Check for linked shaders to handle the case of a PPO linking separable programs before
+ // drawing.
+ if (linkingVariables.isShaderStageUsedBitset[shaderType] ||
+ getLinkedShaderStages().test(shaderType))
+ {
+ activeShadersMask[shaderType] = true;
+ }
+ }
+
+ if (!varyingPacking->collectAndPackUserVaryings(mInfoLog, context->getCaps(), packMode,
+ activeShadersMask, mergedVaryings,
+ transformFeedbackVaryingNames, isSeparable))
+ {
+ return false;
+ }
+
+ gatherTransformFeedbackVaryings(mergedVaryings, tfStage, transformFeedbackVaryingNames);
+ updateTransformFeedbackStrides();
+
+ return true;
+}
+
+bool ProgramExecutable::linkValidateTransformFeedback(
+ const Context *context,
+ const ProgramMergedVaryings &varyings,
+ ShaderType stage,
+ const std::vector<std::string> &transformFeedbackVaryingNames)
+{
+ const Version &version = context->getClientVersion();
+
+ // Validate the tf names regardless of the actual program varyings.
+ std::set<std::string> uniqueNames;
+ for (const std::string &tfVaryingName : transformFeedbackVaryingNames)
+ {
+ if (version < Version(3, 1) && tfVaryingName.find('[') != std::string::npos)
+ {
+ mInfoLog << "Capture of array elements is undefined and not supported.";
+ return false;
+ }
+ if (version >= Version(3, 1))
+ {
+ if (IncludeSameArrayElement(uniqueNames, tfVaryingName))
+ {
+ mInfoLog << "Two transform feedback varyings include the same array element ("
+ << tfVaryingName << ").";
+ return false;
+ }
+ }
+ else
+ {
+ if (uniqueNames.count(tfVaryingName) > 0)
+ {
+ mInfoLog << "Two transform feedback varyings specify the same output variable ("
+ << tfVaryingName << ").";
+ return false;
+ }
+ }
+ uniqueNames.insert(tfVaryingName);
+ }
+
+ // From OpneGLES spec. 11.1.2.1: A program will fail to link if:
+ // the count specified by TransformFeedbackVaryings is non-zero, but the
+ // program object has no vertex, tessellation evaluation, or geometry shader
+ if (transformFeedbackVaryingNames.size() > 0 &&
+ !gl::ShaderTypeSupportsTransformFeedback(getLinkedTransformFeedbackStage()))
+ {
+ mInfoLog << "Linked transform feedback stage " << getLinkedTransformFeedbackStage()
+ << " does not support transform feedback varying.";
+ return false;
+ }
+
+ // Validate against program varyings.
+ size_t totalComponents = 0;
+ for (const std::string &tfVaryingName : transformFeedbackVaryingNames)
+ {
+ std::vector<unsigned int> subscripts;
+ std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
+
+ const sh::ShaderVariable *var = FindOutputVaryingOrField(varyings, stage, baseName);
+ if (var == nullptr)
+ {
+ mInfoLog << "Transform feedback varying " << tfVaryingName
+ << " does not exist in the vertex shader.";
+ return false;
+ }
+
+ // Validate the matching variable.
+ if (var->isStruct())
+ {
+ mInfoLog << "Struct cannot be captured directly (" << baseName << ").";
+ return false;
+ }
+
+ size_t elementCount = 0;
+ size_t componentCount = 0;
+
+ if (var->isArray())
+ {
+ if (version < Version(3, 1))
+ {
+ mInfoLog << "Capture of arrays is undefined and not supported.";
+ return false;
+ }
+
+ // GLSL ES 3.10 section 4.3.6: A vertex output can't be an array of arrays.
+ ASSERT(!var->isArrayOfArrays());
+
+ if (!subscripts.empty() && subscripts[0] >= var->getOutermostArraySize())
+ {
+ mInfoLog << "Cannot capture outbound array element '" << tfVaryingName << "'.";
+ return false;
+ }
+ elementCount = (subscripts.empty() ? var->getOutermostArraySize() : 1);
+ }
+ else
+ {
+ if (!subscripts.empty())
+ {
+ mInfoLog << "Varying '" << baseName
+ << "' is not an array to be captured by element.";
+ return false;
+ }
+ elementCount = 1;
+ }
+
+ const Caps &caps = context->getCaps();
+
+ // TODO(jmadill): Investigate implementation limits on D3D11
+ componentCount = VariableComponentCount(var->type) * elementCount;
+ if (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
+ componentCount > static_cast<GLuint>(caps.maxTransformFeedbackSeparateComponents))
+ {
+ mInfoLog << "Transform feedback varying " << tfVaryingName << " components ("
+ << componentCount << ") exceed the maximum separate components ("
+ << caps.maxTransformFeedbackSeparateComponents << ").";
+ return false;
+ }
+
+ totalComponents += componentCount;
+ if (mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
+ totalComponents > static_cast<GLuint>(caps.maxTransformFeedbackInterleavedComponents))
+ {
+ mInfoLog << "Transform feedback varying total components (" << totalComponents
+ << ") exceed the maximum interleaved components ("
+ << caps.maxTransformFeedbackInterleavedComponents << ").";
+ return false;
+ }
+ }
+ return true;
+}
+
+void ProgramExecutable::gatherTransformFeedbackVaryings(
+ const ProgramMergedVaryings &varyings,
+ ShaderType stage,
+ const std::vector<std::string> &transformFeedbackVaryingNames)
+{
+ // Gather the linked varyings that are used for transform feedback, they should all exist.
+ mLinkedTransformFeedbackVaryings.clear();
+ for (const std::string &tfVaryingName : transformFeedbackVaryingNames)
+ {
+ std::vector<unsigned int> subscripts;
+ std::string baseName = ParseResourceName(tfVaryingName, &subscripts);
+ size_t subscript = GL_INVALID_INDEX;
+ if (!subscripts.empty())
+ {
+ subscript = subscripts.back();
+ }
+ for (const ProgramVaryingRef &ref : varyings)
+ {
+ if (ref.frontShaderStage != stage)
+ {
+ continue;
+ }
+
+ const sh::ShaderVariable *varying = ref.get(stage);
+ if (baseName == varying->name)
+ {
+ mLinkedTransformFeedbackVaryings.emplace_back(*varying,
+ static_cast<GLuint>(subscript));
+ break;
+ }
+ else if (varying->isStruct())
+ {
+ GLuint fieldIndex = 0;
+ const auto *field = varying->findField(tfVaryingName, &fieldIndex);
+ if (field != nullptr)
+ {
+ mLinkedTransformFeedbackVaryings.emplace_back(*field, *varying);
+ break;
+ }
+ }
+ }
+ }
+}
+
+void ProgramExecutable::updateTransformFeedbackStrides()
+{
+ if (mLinkedTransformFeedbackVaryings.empty())
+ {
+ return;
+ }
+
+ if (mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS)
+ {
+ mTransformFeedbackStrides.resize(1);
+ size_t totalSize = 0;
+ for (const TransformFeedbackVarying &varying : mLinkedTransformFeedbackVaryings)
+ {
+ totalSize += varying.size() * VariableExternalSize(varying.type);
+ }
+ mTransformFeedbackStrides[0] = static_cast<GLsizei>(totalSize);
+ }
+ else
+ {
+ mTransformFeedbackStrides.resize(mLinkedTransformFeedbackVaryings.size());
+ for (size_t i = 0; i < mLinkedTransformFeedbackVaryings.size(); i++)
+ {
+ TransformFeedbackVarying &varying = mLinkedTransformFeedbackVaryings[i];
+ mTransformFeedbackStrides[i] =
+ static_cast<GLsizei>(varying.size() * VariableExternalSize(varying.type));
+ }
+ }
+}
+
+bool ProgramExecutable::validateSamplersImpl(InfoLog *infoLog, const Caps &caps) const
+{
+ // if any two active samplers in a program are of different types, but refer to the same
+ // texture image unit, and this is the current program, then ValidateProgram will fail, and
+ // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
+ for (size_t textureUnit : mActiveSamplersMask)
+ {
+ if (mActiveSamplerTypes[textureUnit] == TextureType::InvalidEnum)
+ {
+ if (infoLog)
+ {
+ (*infoLog) << "Samplers of conflicting types refer to the same texture "
+ "image unit ("
+ << textureUnit << ").";
+ }
+
+ mCachedValidateSamplersResult = false;
+ return false;
+ }
+
+ if (mActiveSamplerFormats[textureUnit] == SamplerFormat::InvalidEnum)
+ {
+ if (infoLog)
+ {
+ (*infoLog) << "Samplers of conflicting formats refer to the same texture "
+ "image unit ("
+ << textureUnit << ").";
+ }
+
+ mCachedValidateSamplersResult = false;
+ return false;
+ }
+ }
+
+ mCachedValidateSamplersResult = true;
+ return true;
+}
+
+bool ProgramExecutable::linkValidateOutputVariables(
+ const Caps &caps,
+ const Extensions &extensions,
+ const Version &version,
+ GLuint combinedImageUniformsCount,
+ GLuint combinedShaderStorageBlocksCount,
+ const std::vector<sh::ShaderVariable> &outputVariables,
+ int fragmentShaderVersion,
+ const ProgramAliasedBindings &fragmentOutputLocations,
+ const ProgramAliasedBindings &fragmentOutputIndices)
+{
+ ASSERT(mOutputVariableTypes.empty());
+ ASSERT(mActiveOutputVariablesMask.none());
+ ASSERT(mDrawBufferTypeMask.none());
+ ASSERT(!mYUVOutput);
+
+ // Gather output variable types
+ for (const sh::ShaderVariable &outputVariable : outputVariables)
+ {
+ if (outputVariable.isBuiltIn() && outputVariable.name != "gl_FragColor" &&
+ outputVariable.name != "gl_FragData")
+ {
+ continue;
+ }
+
+ unsigned int baseLocation =
+ (outputVariable.location == -1 ? 0u
+ : static_cast<unsigned int>(outputVariable.location));
+
+ // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
+ // structures, so we may use getBasicTypeElementCount().
+ unsigned int elementCount = outputVariable.getBasicTypeElementCount();
+ for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++)
+ {
+ const unsigned int location = baseLocation + elementIndex;
+ if (location >= mOutputVariableTypes.size())
+ {
+ mOutputVariableTypes.resize(location + 1, GL_NONE);
+ }
+ ASSERT(location < mActiveOutputVariablesMask.size());
+ mActiveOutputVariablesMask.set(location);
+ mOutputVariableTypes[location] = VariableComponentType(outputVariable.type);
+ ComponentType componentType = GLenumToComponentType(mOutputVariableTypes[location]);
+ SetComponentTypeMask(componentType, location, &mDrawBufferTypeMask);
+ }
+
+ if (outputVariable.yuv)
+ {
+ ASSERT(outputVariables.size() == 1);
+ mYUVOutput = true;
+ }
+ }
+
+ if (version >= ES_3_1)
+ {
+ // [OpenGL ES 3.1] Chapter 8.22 Page 203:
+ // A link error will be generated if the sum of the number of active image uniforms used in
+ // all shaders, the number of active shader storage blocks, and the number of active
+ // fragment shader outputs exceeds the implementation-dependent value of
+ // MAX_COMBINED_SHADER_OUTPUT_RESOURCES.
+ if (combinedImageUniformsCount + combinedShaderStorageBlocksCount +
+ mActiveOutputVariablesMask.count() >
+ static_cast<GLuint>(caps.maxCombinedShaderOutputResources))
+ {
+ mInfoLog
+ << "The sum of the number of active image uniforms, active shader storage blocks "
+ "and active fragment shader outputs exceeds "
+ "MAX_COMBINED_SHADER_OUTPUT_RESOURCES ("
+ << caps.maxCombinedShaderOutputResources << ")";
+ return false;
+ }
+ }
+
+ mOutputVariables = outputVariables;
+
+ if (fragmentShaderVersion == 100)
+ {
+ return true;
+ }
+
+ // EXT_blend_func_extended doesn't specify anything related to binding specific elements of an
+ // output array in explicit terms.
+ //
+ // Assuming fragData is an output array, you can defend the position that:
+ // P1) you must support binding "fragData" because it's specified
+ // P2) you must support querying "fragData[x]" because it's specified
+ // P3) you must support binding "fragData[0]" because it's a frequently used pattern
+ //
+ // Then you can make the leap of faith:
+ // P4) you must support binding "fragData[x]" because you support "fragData[0]"
+ // P5) you must support binding "fragData[x]" because you support querying "fragData[x]"
+ //
+ // The spec brings in the "world of arrays" when it mentions binding the arrays and the
+ // automatic binding. Thus it must be interpreted that the thing is not undefined, rather you
+ // must infer the only possible interpretation (?). Note again: this need of interpretation
+ // might be completely off of what GL spec logic is.
+ //
+ // The other complexity is that unless you implement this feature, it's hard to understand what
+ // should happen when the client invokes the feature. You cannot add an additional error as it
+ // is not specified. One can ignore it, but obviously it creates the discrepancies...
+
+ std::vector<VariableLocation> reservedLocations;
+
+ // Process any output API bindings for arrays that don't alias to the first element.
+ for (const auto &bindingPair : fragmentOutputLocations)
+ {
+ const std::string &name = bindingPair.first;
+ const ProgramBinding &binding = bindingPair.second;
+
+ size_t nameLengthWithoutArrayIndex;
+ unsigned int arrayIndex = ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
+ if (arrayIndex == 0 || arrayIndex == GL_INVALID_INDEX)
+ {
+ continue;
+ }
+ for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
+ outputVariableIndex++)
+ {
+ const sh::ShaderVariable &outputVariable = mOutputVariables[outputVariableIndex];
+ // Check that the binding corresponds to an output array and its array index fits.
+ if (outputVariable.isBuiltIn() || !outputVariable.isArray() ||
+ !angle::BeginsWith(outputVariable.name, name, nameLengthWithoutArrayIndex) ||
+ arrayIndex >= outputVariable.getOutermostArraySize())
+ {
+ continue;
+ }
+
+ // Get the API index that corresponds to this exact binding.
+ // This index may differ from the index used for the array's base.
+ std::vector<VariableLocation> &outputLocations =
+ fragmentOutputIndices.getBindingByName(name) == 1 ? mSecondaryOutputLocations
+ : mOutputLocations;
+ unsigned int location = binding.location;
+ VariableLocation locationInfo(arrayIndex, outputVariableIndex);
+ if (location >= outputLocations.size())
+ {
+ outputLocations.resize(location + 1);
+ }
+ if (outputLocations[location].used())
+ {
+ mInfoLog << "Location of variable " << outputVariable.name
+ << " conflicts with another variable.";
+ return false;
+ }
+ outputLocations[location] = locationInfo;
+
+ // Note the array binding location so that it can be skipped later.
+ reservedLocations.push_back(locationInfo);
+ }
+ }
+
+ // Reserve locations for output variables whose location is fixed in the shader or through the
+ // API. Otherwise, the remaining unallocated outputs will be processed later.
+ for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
+ outputVariableIndex++)
+ {
+ const sh::ShaderVariable &outputVariable = mOutputVariables[outputVariableIndex];
+
+ // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
+ if (outputVariable.isBuiltIn())
+ continue;
+
+ int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable);
+ if (fixedLocation == -1)
+ {
+ // Here we're only reserving locations for variables whose location is fixed.
+ continue;
+ }
+ unsigned int baseLocation = static_cast<unsigned int>(fixedLocation);
+
+ std::vector<VariableLocation> &outputLocations =
+ IsOutputSecondaryForLink(fragmentOutputIndices, outputVariable)
+ ? mSecondaryOutputLocations
+ : mOutputLocations;
+
+ // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
+ // structures, so we may use getBasicTypeElementCount().
+ unsigned int elementCount = outputVariable.getBasicTypeElementCount();
+ if (FindUsedOutputLocation(outputLocations, baseLocation, elementCount, reservedLocations,
+ outputVariableIndex))
+ {
+ mInfoLog << "Location of variable " << outputVariable.name
+ << " conflicts with another variable.";
+ return false;
+ }
+ AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
+ outputVariableIndex, mOutputVariables[outputVariableIndex]);
+ }
+
+ // Here we assign locations for the output variables that don't yet have them. Note that we're
+ // not necessarily able to fit the variables optimally, since then we might have to try
+ // different arrangements of output arrays. Now we just assign the locations in the order that
+ // we got the output variables. The spec isn't clear on what kind of algorithm is required for
+ // finding locations for the output variables, so this should be acceptable at least for now.
+ GLuint maxLocation = static_cast<GLuint>(caps.maxDrawBuffers);
+ if (!mSecondaryOutputLocations.empty())
+ {
+ // EXT_blend_func_extended: Program outputs will be validated against
+ // MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT if there's even one output with index one.
+ maxLocation = caps.maxDualSourceDrawBuffers;
+ }
+
+ for (unsigned int outputVariableIndex = 0; outputVariableIndex < mOutputVariables.size();
+ outputVariableIndex++)
+ {
+ const sh::ShaderVariable &outputVariable = mOutputVariables[outputVariableIndex];
+
+ // Don't store outputs for gl_FragDepth, gl_FragColor, etc.
+ if (outputVariable.isBuiltIn())
+ continue;
+
+ int fixedLocation = GetOutputLocationForLink(fragmentOutputLocations, outputVariable);
+ std::vector<VariableLocation> &outputLocations =
+ IsOutputSecondaryForLink(fragmentOutputIndices, outputVariable)
+ ? mSecondaryOutputLocations
+ : mOutputLocations;
+ unsigned int baseLocation = 0;
+ unsigned int elementCount = outputVariable.getBasicTypeElementCount();
+ if (fixedLocation != -1)
+ {
+ // Secondary inputs might have caused the max location to drop below what has already
+ // been explicitly assigned locations. Check for any fixed locations above the max
+ // that should cause linking to fail.
+ baseLocation = static_cast<unsigned int>(fixedLocation);
+ }
+ else
+ {
+ // No fixed location, so try to fit the output in unassigned locations.
+ // Try baseLocations starting from 0 one at a time and see if the variable fits.
+ while (FindUsedOutputLocation(outputLocations, baseLocation, elementCount,
+ reservedLocations, outputVariableIndex))
+ {
+ baseLocation++;
+ }
+ AssignOutputLocations(outputLocations, baseLocation, elementCount, reservedLocations,
+ outputVariableIndex, mOutputVariables[outputVariableIndex]);
+ }
+
+ // Check for any elements assigned above the max location that are actually used.
+ if (baseLocation + elementCount > maxLocation &&
+ (baseLocation >= maxLocation ||
+ FindUsedOutputLocation(outputLocations, maxLocation,
+ baseLocation + elementCount - maxLocation, reservedLocations,
+ outputVariableIndex)))
+ {
+ // EXT_blend_func_extended: Linking can fail:
+ // "if the explicit binding assignments do not leave enough space for the linker to
+ // automatically assign a location for a varying out array, which requires multiple
+ // contiguous locations."
+ mInfoLog << "Could not fit output variable into available locations: "
+ << outputVariable.name;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ProgramExecutable::linkUniforms(
+ const Context *context,
+ const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms,
+ InfoLog &infoLog,
+ const ProgramAliasedBindings &uniformLocationBindings,
+ GLuint *combinedImageUniformsCountOut,
+ std::vector<UnusedUniform> *unusedUniformsOutOrNull,
+ std::vector<VariableLocation> *uniformLocationsOutOrNull)
+{
+ UniformLinker linker(mLinkedShaderStages, shaderUniforms);
+ if (!linker.link(context->getCaps(), infoLog, uniformLocationBindings))
+ {
+ return false;
+ }
+
+ linker.getResults(&mUniforms, unusedUniformsOutOrNull, uniformLocationsOutOrNull);
+
+ linkSamplerAndImageBindings(combinedImageUniformsCountOut);
+
+ if (!linkAtomicCounterBuffers(context, infoLog))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void ProgramExecutable::linkSamplerAndImageBindings(GLuint *combinedImageUniforms)
+{
+ ASSERT(combinedImageUniforms);
+
+ // Iterate over mExecutable->mUniforms from the back, and find the range of subpass inputs,
+ // atomic counters, images and samplers in that order.
+ auto highIter = mUniforms.rbegin();
+ auto lowIter = highIter;
+
+ unsigned int high = static_cast<unsigned int>(mUniforms.size());
+ unsigned int low = high;
+
+ // Note that uniform block uniforms are not yet appended to this list.
+ ASSERT(mUniforms.empty() || highIter->isAtomicCounter() || highIter->isImage() ||
+ highIter->isSampler() || highIter->isInDefaultBlock() || highIter->isFragmentInOut);
+
+ for (; lowIter != mUniforms.rend() && lowIter->isFragmentInOut; ++lowIter)
+ {
+ --low;
+ }
+
+ mFragmentInoutRange = RangeUI(low, high);
+
+ highIter = lowIter;
+ high = low;
+
+ for (; lowIter != mUniforms.rend() && lowIter->isAtomicCounter(); ++lowIter)
+ {
+ --low;
+ }
+
+ mAtomicCounterUniformRange = RangeUI(low, high);
+
+ highIter = lowIter;
+ high = low;
+
+ for (; lowIter != mUniforms.rend() && lowIter->isImage(); ++lowIter)
+ {
+ --low;
+ }
+
+ mImageUniformRange = RangeUI(low, high);
+ *combinedImageUniforms = 0u;
+ // If uniform is a image type, insert it into the mImageBindings array.
+ for (unsigned int imageIndex : mImageUniformRange)
+ {
+ // ES3.1 (section 7.6.1) and GLSL ES3.1 (section 4.4.5), Uniform*i{v} commands
+ // cannot load values into a uniform defined as an image. if declare without a
+ // binding qualifier, any uniform image variable (include all elements of
+ // unbound image array) should be bound to unit zero.
+ auto &imageUniform = mUniforms[imageIndex];
+ TextureType textureType = ImageTypeToTextureType(imageUniform.type);
+ const GLuint arraySize = imageUniform.isArray() ? imageUniform.arraySizes[0] : 1u;
+
+ if (imageUniform.binding == -1)
+ {
+ mImageBindings.emplace_back(
+ ImageBinding(imageUniform.getBasicTypeElementCount(), textureType));
+ }
+ else
+ {
+ // The arrays of arrays are flattened to arrays, it needs to record the array offset for
+ // the correct binding image unit.
+ mImageBindings.emplace_back(
+ ImageBinding(imageUniform.binding + imageUniform.parentArrayIndex() * arraySize,
+ imageUniform.getBasicTypeElementCount(), textureType));
+ }
+
+ *combinedImageUniforms += imageUniform.activeShaderCount() * arraySize;
+ }
+
+ highIter = lowIter;
+ high = low;
+
+ for (; lowIter != mUniforms.rend() && lowIter->isSampler(); ++lowIter)
+ {
+ --low;
+ }
+
+ mSamplerUniformRange = RangeUI(low, high);
+
+ // If uniform is a sampler type, insert it into the mSamplerBindings array.
+ for (unsigned int samplerIndex : mSamplerUniformRange)
+ {
+ const auto &samplerUniform = mUniforms[samplerIndex];
+ TextureType textureType = SamplerTypeToTextureType(samplerUniform.type);
+ GLenum samplerType = samplerUniform.typeInfo->type;
+ unsigned int elementCount = samplerUniform.getBasicTypeElementCount();
+ SamplerFormat format = samplerUniform.typeInfo->samplerFormat;
+ mSamplerBindings.emplace_back(textureType, samplerType, format, elementCount);
+ }
+
+ // Whatever is left constitutes the default uniforms.
+ mDefaultUniformRange = RangeUI(0, low);
+}
+
+bool ProgramExecutable::linkAtomicCounterBuffers(const Context *context, InfoLog &infoLog)
+{
+ for (unsigned int index : mAtomicCounterUniformRange)
+ {
+ auto &uniform = mUniforms[index];
+ uniform.blockInfo.offset = uniform.offset;
+ uniform.blockInfo.arrayStride = (uniform.isArray() ? 4 : 0);
+ uniform.blockInfo.matrixStride = 0;
+ uniform.blockInfo.isRowMajorMatrix = false;
+
+ bool found = false;
+ for (unsigned int bufferIndex = 0; bufferIndex < getActiveAtomicCounterBufferCount();
+ ++bufferIndex)
+ {
+ auto &buffer = mAtomicCounterBuffers[bufferIndex];
+ if (buffer.binding == uniform.binding)
+ {
+ buffer.memberIndexes.push_back(index);
+ uniform.bufferIndex = bufferIndex;
+ found = true;
+ buffer.unionReferencesWith(uniform);
+ break;
+ }
+ }
+ if (!found)
+ {
+ AtomicCounterBuffer atomicCounterBuffer;
+ atomicCounterBuffer.binding = uniform.binding;
+ atomicCounterBuffer.memberIndexes.push_back(index);
+ atomicCounterBuffer.unionReferencesWith(uniform);
+ mAtomicCounterBuffers.push_back(atomicCounterBuffer);
+ uniform.bufferIndex = static_cast<int>(getActiveAtomicCounterBufferCount() - 1);
+ }
+ }
+
+ // Count each atomic counter buffer to validate against
+ // per-stage and combined gl_Max*AtomicCounterBuffers.
+ GLint combinedShaderACBCount = 0;
+ gl::ShaderMap<GLint> perShaderACBCount = {};
+ for (unsigned int bufferIndex = 0; bufferIndex < getActiveAtomicCounterBufferCount();
+ ++bufferIndex)
+ {
+ AtomicCounterBuffer &acb = mAtomicCounterBuffers[bufferIndex];
+ const ShaderBitSet shaderStages = acb.activeShaders();
+ for (gl::ShaderType shaderType : shaderStages)
+ {
+ ++perShaderACBCount[shaderType];
+ }
+ ++combinedShaderACBCount;
+ }
+ const Caps &caps = context->getCaps();
+ if (combinedShaderACBCount > caps.maxCombinedAtomicCounterBuffers)
+ {
+ infoLog << " combined AtomicCounterBuffers count exceeds limit";
+ return false;
+ }
+ for (gl::ShaderType stage : gl::AllShaderTypes())
+ {
+ if (perShaderACBCount[stage] > caps.maxShaderAtomicCounterBuffers[stage])
+ {
+ infoLog << GetShaderTypeString(stage)
+ << " shader AtomicCounterBuffers count exceeds limit";
+ return false;
+ }
+ }
+ return true;
+}
+
+void ProgramExecutable::copyInputsFromProgram(const ProgramState &programState)
+{
+ mProgramInputs = programState.getProgramInputs();
+}
+
+void ProgramExecutable::copyShaderBuffersFromProgram(const ProgramState &programState,
+ ShaderType shaderType)
+{
+ AppendActiveBlocks(shaderType, programState.getUniformBlocks(), mUniformBlocks);
+ AppendActiveBlocks(shaderType, programState.getShaderStorageBlocks(), mShaderStorageBlocks);
+ AppendActiveBlocks(shaderType, programState.getAtomicCounterBuffers(), mAtomicCounterBuffers);
+}
+
+void ProgramExecutable::clearSamplerBindings()
+{
+ mSamplerBindings.clear();
+}
+
+void ProgramExecutable::copySamplerBindingsFromProgram(const ProgramState &programState)
+{
+ const std::vector<SamplerBinding> &bindings = programState.getSamplerBindings();
+ mSamplerBindings.insert(mSamplerBindings.end(), bindings.begin(), bindings.end());
+}
+
+void ProgramExecutable::copyImageBindingsFromProgram(const ProgramState &programState)
+{
+ const std::vector<ImageBinding> &bindings = programState.getImageBindings();
+ mImageBindings.insert(mImageBindings.end(), bindings.begin(), bindings.end());
+}
+
+void ProgramExecutable::copyOutputsFromProgram(const ProgramState &programState)
+{
+ mOutputVariables = programState.getOutputVariables();
+ mOutputLocations = programState.getOutputLocations();
+ mSecondaryOutputLocations = programState.getSecondaryOutputLocations();
+}
+
+void ProgramExecutable::copyUniformsFromProgramMap(const ShaderMap<Program *> &programs)
+{
+ // Merge default uniforms.
+ auto getDefaultRange = [](const ProgramState &state) { return state.getDefaultUniformRange(); };
+ mDefaultUniformRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getDefaultRange);
+
+ // Merge sampler uniforms.
+ auto getSamplerRange = [](const ProgramState &state) { return state.getSamplerUniformRange(); };
+ mSamplerUniformRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getSamplerRange);
+
+ // Merge image uniforms.
+ auto getImageRange = [](const ProgramState &state) { return state.getImageUniformRange(); };
+ mImageUniformRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getImageRange);
+
+ // Merge atomic counter uniforms.
+ auto getAtomicRange = [](const ProgramState &state) {
+ return state.getAtomicCounterUniformRange();
+ };
+ mAtomicCounterUniformRange =
+ AddUniforms(programs, mLinkedShaderStages, mUniforms, getAtomicRange);
+
+ // Merge fragment in/out uniforms.
+ auto getInoutRange = [](const ProgramState &state) { return state.getFragmentInoutRange(); };
+ mFragmentInoutRange = AddUniforms(programs, mLinkedShaderStages, mUniforms, getInoutRange);
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/ProgramExecutable.h b/gfx/angle/checkout/src/libANGLE/ProgramExecutable.h
new file mode 100644
index 0000000000..4344ef4b5a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/ProgramExecutable.h
@@ -0,0 +1,517 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ProgramExecutable.h: Collects the information and interfaces common to both Programs and
+// ProgramPipelines in order to execute/draw with either.
+
+#ifndef LIBANGLE_PROGRAMEXECUTABLE_H_
+#define LIBANGLE_PROGRAMEXECUTABLE_H_
+
+#include "BinaryStream.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/InfoLog.h"
+#include "libANGLE/ProgramLinkedResources.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/VaryingPacking.h"
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+
+// This small structure encapsulates binding sampler uniforms to active GL textures.
+struct SamplerBinding
+{
+ SamplerBinding(TextureType textureTypeIn,
+ GLenum samplerTypeIn,
+ SamplerFormat formatIn,
+ size_t elementCount);
+ SamplerBinding(const SamplerBinding &other);
+ ~SamplerBinding();
+
+ // Necessary for retrieving active textures from the GL state.
+ TextureType textureType;
+
+ GLenum samplerType;
+
+ SamplerFormat format;
+
+ // List of all textures bound to this sampler, of type textureType.
+ // Cropped by the amount of unused elements reported by the driver.
+ std::vector<GLuint> boundTextureUnits;
+};
+
+struct ImageBinding
+{
+ ImageBinding(size_t count, TextureType textureTypeIn);
+ ImageBinding(GLuint imageUnit, size_t count, TextureType textureTypeIn);
+ ImageBinding(const ImageBinding &other);
+ ~ImageBinding();
+
+ // Necessary for distinguishing between textures with images and texture buffers.
+ TextureType textureType;
+
+ // List of all textures bound.
+ // Cropped by the amount of unused elements reported by the driver.
+ std::vector<GLuint> boundImageUnits;
+};
+
+// A varying with transform feedback enabled. If it's an array, either the whole array or one of its
+// elements specified by 'arrayIndex' can set to be enabled.
+struct TransformFeedbackVarying : public sh::ShaderVariable
+{
+ TransformFeedbackVarying(const sh::ShaderVariable &varyingIn, GLuint arrayIndexIn)
+ : sh::ShaderVariable(varyingIn), arrayIndex(arrayIndexIn)
+ {
+ ASSERT(!isArrayOfArrays());
+ }
+
+ TransformFeedbackVarying(const sh::ShaderVariable &field, const sh::ShaderVariable &parent)
+ : arrayIndex(GL_INVALID_INDEX)
+ {
+ sh::ShaderVariable *thisVar = this;
+ *thisVar = field;
+ interpolation = parent.interpolation;
+ isInvariant = parent.isInvariant;
+ ASSERT(parent.isShaderIOBlock || !parent.name.empty());
+ if (!parent.name.empty())
+ {
+ name = parent.name + "." + name;
+ mappedName = parent.mappedName + "." + mappedName;
+ }
+ structOrBlockName = parent.structOrBlockName;
+ mappedStructOrBlockName = parent.mappedStructOrBlockName;
+ }
+
+ std::string nameWithArrayIndex() const
+ {
+ std::stringstream fullNameStr;
+ fullNameStr << name;
+ if (arrayIndex != GL_INVALID_INDEX)
+ {
+ fullNameStr << "[" << arrayIndex << "]";
+ }
+ return fullNameStr.str();
+ }
+ GLsizei size() const
+ {
+ return (isArray() && arrayIndex == GL_INVALID_INDEX ? getOutermostArraySize() : 1);
+ }
+
+ GLuint arrayIndex;
+};
+
+class ProgramState;
+class ProgramPipelineState;
+
+class ProgramExecutable final : public angle::Subject
+{
+ public:
+ ProgramExecutable();
+ ProgramExecutable(const ProgramExecutable &other);
+ ~ProgramExecutable() override;
+
+ void reset(bool clearInfoLog);
+
+ void save(bool isSeparable, gl::BinaryOutputStream *stream) const;
+ void load(bool isSeparable, gl::BinaryInputStream *stream);
+
+ int getInfoLogLength() const;
+ InfoLog &getInfoLog() { return mInfoLog; }
+ void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const;
+ std::string getInfoLogString() const;
+ void resetInfoLog() { mInfoLog.reset(); }
+
+ void resetLinkedShaderStages() { mLinkedShaderStages.reset(); }
+ const ShaderBitSet &getLinkedShaderStages() const { return mLinkedShaderStages; }
+ void setLinkedShaderStages(ShaderType shaderType)
+ {
+ mLinkedShaderStages.set(shaderType);
+ updateCanDrawWith();
+ }
+ bool hasLinkedShaderStage(ShaderType shaderType) const
+ {
+ ASSERT(shaderType != ShaderType::InvalidEnum);
+ return mLinkedShaderStages[shaderType];
+ }
+ size_t getLinkedShaderStageCount() const { return mLinkedShaderStages.count(); }
+ bool hasLinkedGraphicsShader() const
+ {
+ return mLinkedShaderStages.any() &&
+ mLinkedShaderStages != gl::ShaderBitSet{gl::ShaderType::Compute};
+ }
+ bool hasLinkedTessellationShader() const
+ {
+ return mLinkedShaderStages[ShaderType::TessEvaluation];
+ }
+
+ ShaderType getLinkedTransformFeedbackStage() const;
+
+ const AttributesMask &getActiveAttribLocationsMask() const
+ {
+ return mActiveAttribLocationsMask;
+ }
+ bool isAttribLocationActive(size_t attribLocation) const;
+ const AttributesMask &getNonBuiltinAttribLocationsMask() const { return mAttributesMask; }
+ unsigned int getMaxActiveAttribLocation() const { return mMaxActiveAttribLocation; }
+ const ComponentTypeMask &getAttributesTypeMask() const { return mAttributesTypeMask; }
+ AttributesMask getAttributesMask() const;
+
+ const ActiveTextureMask &getActiveSamplersMask() const { return mActiveSamplersMask; }
+ void setActiveTextureMask(ActiveTextureMask mask) { mActiveSamplersMask = mask; }
+ SamplerFormat getSamplerFormatForTextureUnitIndex(size_t textureUnitIndex) const
+ {
+ return mActiveSamplerFormats[textureUnitIndex];
+ }
+ const ShaderBitSet getSamplerShaderBitsForTextureUnitIndex(size_t textureUnitIndex) const
+ {
+ return mActiveSamplerShaderBits[textureUnitIndex];
+ }
+ const ActiveTextureMask &getActiveImagesMask() const { return mActiveImagesMask; }
+ void setActiveImagesMask(ActiveTextureMask mask) { mActiveImagesMask = mask; }
+ const ActiveTextureArray<ShaderBitSet> &getActiveImageShaderBits() const
+ {
+ return mActiveImageShaderBits;
+ }
+
+ const ActiveTextureMask &getActiveYUVSamplers() const { return mActiveSamplerYUV; }
+
+ const ActiveTextureArray<TextureType> &getActiveSamplerTypes() const
+ {
+ return mActiveSamplerTypes;
+ }
+
+ void setActive(size_t textureUnit,
+ const SamplerBinding &samplerBinding,
+ const gl::LinkedUniform &samplerUniform);
+ void setInactive(size_t textureUnit);
+ void hasSamplerTypeConflict(size_t textureUnit);
+ void hasSamplerFormatConflict(size_t textureUnit);
+
+ void updateActiveSamplers(const ProgramState &programState);
+
+ bool hasDefaultUniforms() const;
+ bool hasTextures() const;
+ bool hasUniformBuffers() const;
+ bool hasStorageBuffers() const;
+ bool hasAtomicCounterBuffers() const;
+ bool hasImages() const;
+ bool hasTransformFeedbackOutput() const
+ {
+ return !getLinkedTransformFeedbackVaryings().empty();
+ }
+ bool usesFramebufferFetch() const;
+
+ // Count the number of uniform and storage buffer declarations, counting arrays as one.
+ size_t getTransformFeedbackBufferCount() const { return mTransformFeedbackStrides.size(); }
+
+ void updateCanDrawWith();
+ bool hasVertexShader() const { return mCanDrawWith; }
+
+ const std::vector<sh::ShaderVariable> &getProgramInputs() const { return mProgramInputs; }
+ const std::vector<sh::ShaderVariable> &getOutputVariables() const { return mOutputVariables; }
+ const std::vector<VariableLocation> &getOutputLocations() const { return mOutputLocations; }
+ const std::vector<VariableLocation> &getSecondaryOutputLocations() const
+ {
+ return mSecondaryOutputLocations;
+ }
+ const std::vector<LinkedUniform> &getUniforms() const { return mUniforms; }
+ const std::vector<InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; }
+ const UniformBlockBindingMask &getActiveUniformBlockBindings() const
+ {
+ return mActiveUniformBlockBindings;
+ }
+ const std::vector<SamplerBinding> &getSamplerBindings() const { return mSamplerBindings; }
+ const std::vector<ImageBinding> &getImageBindings() const { return mImageBindings; }
+ std::vector<ImageBinding> *getImageBindings() { return &mImageBindings; }
+ const RangeUI &getDefaultUniformRange() const { return mDefaultUniformRange; }
+ const RangeUI &getSamplerUniformRange() const { return mSamplerUniformRange; }
+ const RangeUI &getImageUniformRange() const { return mImageUniformRange; }
+ const RangeUI &getAtomicCounterUniformRange() const { return mAtomicCounterUniformRange; }
+ const RangeUI &getFragmentInoutRange() const { return mFragmentInoutRange; }
+ bool hasDiscard() const { return mHasDiscard; }
+ bool enablesPerSampleShading() const { return mEnablesPerSampleShading; }
+ BlendEquationBitSet getAdvancedBlendEquations() const { return mAdvancedBlendEquations; }
+ const std::vector<TransformFeedbackVarying> &getLinkedTransformFeedbackVaryings() const
+ {
+ return mLinkedTransformFeedbackVaryings;
+ }
+ GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
+ GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const
+ {
+ ASSERT(uniformBlockIndex < mUniformBlocks.size());
+ return mUniformBlocks[uniformBlockIndex].binding;
+ }
+ GLuint getShaderStorageBlockBinding(GLuint blockIndex) const
+ {
+ ASSERT(blockIndex < mShaderStorageBlocks.size());
+ return mShaderStorageBlocks[blockIndex].binding;
+ }
+ const std::vector<GLsizei> &getTransformFeedbackStrides() const
+ {
+ return mTransformFeedbackStrides;
+ }
+ const std::vector<AtomicCounterBuffer> &getAtomicCounterBuffers() const
+ {
+ return mAtomicCounterBuffers;
+ }
+ const std::vector<InterfaceBlock> &getShaderStorageBlocks() const
+ {
+ return mShaderStorageBlocks;
+ }
+ const LinkedUniform &getUniformByIndex(GLuint index) const
+ {
+ ASSERT(index < static_cast<size_t>(mUniforms.size()));
+ return mUniforms[index];
+ }
+
+ ANGLE_INLINE GLuint getActiveUniformBlockCount() const
+ {
+ return static_cast<GLuint>(mUniformBlocks.size());
+ }
+
+ ANGLE_INLINE GLuint getActiveAtomicCounterBufferCount() const
+ {
+ return static_cast<GLuint>(mAtomicCounterBuffers.size());
+ }
+
+ ANGLE_INLINE GLuint getActiveShaderStorageBlockCount() const
+ {
+ size_t shaderStorageBlocksSize = mShaderStorageBlocks.size();
+ return static_cast<GLuint>(shaderStorageBlocksSize);
+ }
+
+ GLuint getUniformIndexFromImageIndex(GLuint imageIndex) const;
+
+ GLuint getUniformIndexFromSamplerIndex(GLuint samplerIndex) const;
+
+ void saveLinkedStateInfo(const Context *context, const ProgramState &state);
+ const std::vector<sh::ShaderVariable> &getLinkedOutputVaryings(ShaderType shaderType) const
+ {
+ return mLinkedOutputVaryings[shaderType];
+ }
+ const std::vector<sh::ShaderVariable> &getLinkedInputVaryings(ShaderType shaderType) const
+ {
+ return mLinkedInputVaryings[shaderType];
+ }
+
+ const std::vector<sh::ShaderVariable> &getLinkedUniforms(ShaderType shaderType) const
+ {
+ return mLinkedUniforms[shaderType];
+ }
+
+ const std::vector<sh::InterfaceBlock> &getLinkedUniformBlocks(ShaderType shaderType) const
+ {
+ return mLinkedUniformBlocks[shaderType];
+ }
+
+ int getLinkedShaderVersion(ShaderType shaderType) const
+ {
+ return mLinkedShaderVersions[shaderType];
+ }
+
+ bool isYUVOutput() const;
+
+ PrimitiveMode getGeometryShaderInputPrimitiveType() const
+ {
+ return mGeometryShaderInputPrimitiveType;
+ }
+
+ PrimitiveMode getGeometryShaderOutputPrimitiveType() const
+ {
+ return mGeometryShaderOutputPrimitiveType;
+ }
+
+ int getGeometryShaderInvocations() const { return mGeometryShaderInvocations; }
+
+ int getGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; }
+
+ GLenum getTessGenMode() const { return mTessGenMode; }
+
+ void resetCachedValidateSamplersResult() { mCachedValidateSamplersResult.reset(); }
+ bool validateSamplers(InfoLog *infoLog, const Caps &caps) const
+ {
+ // Use the cache if:
+ // - we aren't using an info log (which gives the full error).
+ // - The sample mapping hasn't changed and we've already validated.
+ if (infoLog == nullptr && mCachedValidateSamplersResult.valid())
+ {
+ return mCachedValidateSamplersResult.value();
+ }
+
+ return validateSamplersImpl(infoLog, caps);
+ }
+
+ ComponentTypeMask getFragmentOutputsTypeMask() const { return mDrawBufferTypeMask; }
+ DrawBufferMask getActiveOutputVariablesMask() const { return mActiveOutputVariablesMask; }
+
+ bool linkUniforms(const Context *context,
+ const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms,
+ InfoLog &infoLog,
+ const ProgramAliasedBindings &uniformLocationBindings,
+ GLuint *combinedImageUniformsCount,
+ std::vector<UnusedUniform> *unusedUniforms,
+ std::vector<VariableLocation> *uniformLocationsOutOrNull);
+
+ void copyInputsFromProgram(const ProgramState &programState);
+ void copyShaderBuffersFromProgram(const ProgramState &programState, ShaderType shaderType);
+ void clearSamplerBindings();
+ void copySamplerBindingsFromProgram(const ProgramState &programState);
+ void copyImageBindingsFromProgram(const ProgramState &programState);
+ void copyOutputsFromProgram(const ProgramState &programState);
+ void copyUniformsFromProgramMap(const ShaderMap<Program *> &programs);
+
+ private:
+ friend class Program;
+ friend class ProgramPipeline;
+ friend class ProgramState;
+
+ void updateActiveImages(const ProgramExecutable &executable);
+
+ // Scans the sampler bindings for type conflicts with sampler 'textureUnitIndex'.
+ void setSamplerUniformTextureTypeAndFormat(size_t textureUnitIndex,
+ std::vector<SamplerBinding> &samplerBindings);
+
+ bool linkMergedVaryings(const Context *context,
+ const ProgramMergedVaryings &mergedVaryings,
+ const std::vector<std::string> &transformFeedbackVaryingNames,
+ const LinkingVariables &linkingVariables,
+ bool isSeparable,
+ ProgramVaryingPacking *varyingPacking);
+
+ bool linkValidateTransformFeedback(
+ const Context *context,
+ const ProgramMergedVaryings &varyings,
+ ShaderType stage,
+ const std::vector<std::string> &transformFeedbackVaryingNames);
+
+ void gatherTransformFeedbackVaryings(
+ const ProgramMergedVaryings &varyings,
+ ShaderType stage,
+ const std::vector<std::string> &transformFeedbackVaryingNames);
+
+ void updateTransformFeedbackStrides();
+
+ bool validateSamplersImpl(InfoLog *infoLog, const Caps &caps) const;
+
+ bool linkValidateOutputVariables(const Caps &caps,
+ const Extensions &extensions,
+ const Version &version,
+ GLuint combinedImageUniformsCount,
+ GLuint combinedShaderStorageBlocksCount,
+ const std::vector<sh::ShaderVariable> &outputVariables,
+ int fragmentShaderVersion,
+ const ProgramAliasedBindings &fragmentOutputLocations,
+ const ProgramAliasedBindings &fragmentOutputIndices);
+
+ void linkSamplerAndImageBindings(GLuint *combinedImageUniformsCount);
+ bool linkAtomicCounterBuffers(const Context *context, InfoLog &infoLog);
+
+ InfoLog mInfoLog;
+
+ ShaderBitSet mLinkedShaderStages;
+
+ angle::BitSet<MAX_VERTEX_ATTRIBS> mActiveAttribLocationsMask;
+ unsigned int mMaxActiveAttribLocation;
+ ComponentTypeMask mAttributesTypeMask;
+ // mAttributesMask is identical to mActiveAttribLocationsMask with built-in attributes removed.
+ AttributesMask mAttributesMask;
+
+ // Cached mask of active samplers and sampler types.
+ ActiveTextureMask mActiveSamplersMask;
+ ActiveTextureArray<uint32_t> mActiveSamplerRefCounts;
+ ActiveTextureArray<TextureType> mActiveSamplerTypes;
+ ActiveTextureMask mActiveSamplerYUV;
+ ActiveTextureArray<SamplerFormat> mActiveSamplerFormats;
+ ActiveTextureArray<ShaderBitSet> mActiveSamplerShaderBits;
+
+ // Cached mask of active images.
+ ActiveTextureMask mActiveImagesMask;
+ ActiveTextureArray<ShaderBitSet> mActiveImageShaderBits;
+
+ bool mCanDrawWith;
+
+ // Names and mapped names of output variables that are arrays include [0] in the end, similarly
+ // to uniforms.
+ std::vector<sh::ShaderVariable> mOutputVariables;
+ std::vector<VariableLocation> mOutputLocations;
+ DrawBufferMask mActiveOutputVariablesMask;
+ // EXT_blend_func_extended secondary outputs (ones with index 1)
+ std::vector<VariableLocation> mSecondaryOutputLocations;
+ bool mYUVOutput;
+ // Vertex attributes, Fragment input varyings, etc.
+ std::vector<sh::ShaderVariable> mProgramInputs;
+ std::vector<TransformFeedbackVarying> mLinkedTransformFeedbackVaryings;
+ // The size of the data written to each transform feedback buffer per vertex.
+ std::vector<GLsizei> mTransformFeedbackStrides;
+ GLenum mTransformFeedbackBufferMode;
+ // Uniforms are sorted in order:
+ // 1. Non-opaque uniforms
+ // 2. Sampler uniforms
+ // 3. Image uniforms
+ // 4. Atomic counter uniforms
+ // 5. Subpass Input uniforms (Only for Vulkan)
+ // 6. Uniform block uniforms
+ // This makes opaque uniform validation easier, since we don't need a separate list.
+ // For generating the entries and naming them we follow the spec: GLES 3.1 November 2016 section
+ // 7.3.1.1 Naming Active Resources. There's a separate entry for each struct member and each
+ // inner array of an array of arrays. Names and mapped names of uniforms that are arrays include
+ // [0] in the end. This makes implementation of queries simpler.
+ std::vector<LinkedUniform> mUniforms;
+ RangeUI mDefaultUniformRange;
+ RangeUI mSamplerUniformRange;
+ RangeUI mImageUniformRange;
+ RangeUI mAtomicCounterUniformRange;
+ std::vector<InterfaceBlock> mUniformBlocks;
+
+ // For faster iteration on the blocks currently being bound.
+ UniformBlockBindingMask mActiveUniformBlockBindings;
+
+ std::vector<AtomicCounterBuffer> mAtomicCounterBuffers;
+ std::vector<InterfaceBlock> mShaderStorageBlocks;
+
+ RangeUI mFragmentInoutRange;
+ bool mHasDiscard;
+ bool mEnablesPerSampleShading;
+
+ // KHR_blend_equation_advanced supported equation list
+ BlendEquationBitSet mAdvancedBlendEquations;
+
+ // An array of the samplers that are used by the program
+ std::vector<SamplerBinding> mSamplerBindings;
+
+ // An array of the images that are used by the program
+ std::vector<ImageBinding> mImageBindings;
+
+ ShaderMap<std::vector<sh::ShaderVariable>> mLinkedOutputVaryings;
+ ShaderMap<std::vector<sh::ShaderVariable>> mLinkedInputVaryings;
+ ShaderMap<std::vector<sh::ShaderVariable>> mLinkedUniforms;
+ ShaderMap<std::vector<sh::InterfaceBlock>> mLinkedUniformBlocks;
+
+ ShaderMap<int> mLinkedShaderVersions;
+
+ // GL_EXT_geometry_shader.
+ PrimitiveMode mGeometryShaderInputPrimitiveType;
+ PrimitiveMode mGeometryShaderOutputPrimitiveType;
+ int mGeometryShaderInvocations;
+ int mGeometryShaderMaxVertices;
+
+ // GL_EXT_tessellation_shader
+ int mTessControlShaderVertices;
+ GLenum mTessGenMode;
+ GLenum mTessGenSpacing;
+ GLenum mTessGenVertexOrder;
+ GLenum mTessGenPointMode;
+
+ // Fragment output variable base types: FLOAT, INT, or UINT. Ordered by location.
+ std::vector<GLenum> mOutputVariableTypes;
+ ComponentTypeMask mDrawBufferTypeMask;
+
+ // Cache for sampler validation
+ mutable Optional<bool> mCachedValidateSamplersResult;
+};
+} // namespace gl
+
+#endif // LIBANGLE_PROGRAMEXECUTABLE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/ProgramLinkedResources.cpp b/gfx/angle/checkout/src/libANGLE/ProgramLinkedResources.cpp
new file mode 100644
index 0000000000..11000fdabc
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/ProgramLinkedResources.cpp
@@ -0,0 +1,2377 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramLinkedResources.cpp: implements link-time checks for default block uniforms, and generates
+// uniform locations. Populates data structures related to uniforms so that they can be stored in
+// program state.
+
+#include "libANGLE/ProgramLinkedResources.h"
+
+#include "common/string_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/features.h"
+
+namespace gl
+{
+namespace
+{
+LinkedUniform *FindUniform(std::vector<LinkedUniform> &list, const std::string &name)
+{
+ for (LinkedUniform &uniform : list)
+ {
+ if (uniform.name == name)
+ return &uniform;
+ }
+
+ return nullptr;
+}
+
+template <typename VarT>
+void SetActive(std::vector<VarT> *list, const std::string &name, ShaderType shaderType, bool active)
+{
+ for (auto &variable : *list)
+ {
+ if (variable.name == name)
+ {
+ variable.setActive(shaderType, active);
+ return;
+ }
+ }
+}
+
+// GLSL ES Spec 3.00.3, section 4.3.5.
+LinkMismatchError LinkValidateUniforms(const sh::ShaderVariable &uniform1,
+ const sh::ShaderVariable &uniform2,
+ std::string *mismatchedStructFieldName)
+{
+#if ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION == ANGLE_ENABLED
+ const bool validatePrecisionFeature = true;
+#else
+ const bool validatePrecisionFeature = false;
+#endif
+
+ // Validate precision match of uniforms iff they are statically used
+ bool validatePrecision = uniform1.staticUse && uniform2.staticUse && validatePrecisionFeature;
+ LinkMismatchError linkError = LinkValidateProgramVariables(
+ uniform1, uniform2, validatePrecision, false, false, mismatchedStructFieldName);
+ if (linkError != LinkMismatchError::NO_MISMATCH)
+ {
+ return linkError;
+ }
+
+ // GLSL ES Spec 3.10.4, section 4.4.5.
+ if (uniform1.binding != -1 && uniform2.binding != -1 && uniform1.binding != uniform2.binding)
+ {
+ return LinkMismatchError::BINDING_MISMATCH;
+ }
+
+ // GLSL ES Spec 3.10.4, section 9.2.1.
+ if (uniform1.location != -1 && uniform2.location != -1 &&
+ uniform1.location != uniform2.location)
+ {
+ return LinkMismatchError::LOCATION_MISMATCH;
+ }
+ if (uniform1.offset != uniform2.offset)
+ {
+ return LinkMismatchError::OFFSET_MISMATCH;
+ }
+
+ return LinkMismatchError::NO_MISMATCH;
+}
+
+GLuint GetMaximumShaderUniformVectors(ShaderType shaderType, const Caps &caps)
+{
+ switch (shaderType)
+ {
+ case ShaderType::Vertex:
+ return static_cast<GLuint>(caps.maxVertexUniformVectors);
+ case ShaderType::Fragment:
+ return static_cast<GLuint>(caps.maxFragmentUniformVectors);
+
+ case ShaderType::Compute:
+ case ShaderType::Geometry:
+ case ShaderType::TessControl:
+ case ShaderType::TessEvaluation:
+ return static_cast<GLuint>(caps.maxShaderUniformComponents[shaderType]) / 4;
+
+ default:
+ UNREACHABLE();
+ return 0u;
+ }
+}
+
+enum class UniformType : uint8_t
+{
+ Variable = 0,
+ Sampler = 1,
+ Image = 2,
+ AtomicCounter = 3,
+
+ InvalidEnum = 4,
+ EnumCount = 4,
+};
+
+const char *GetUniformResourceNameString(UniformType uniformType)
+{
+ switch (uniformType)
+ {
+ case UniformType::Variable:
+ return "uniform";
+ case UniformType::Sampler:
+ return "texture image unit";
+ case UniformType::Image:
+ return "image uniform";
+ case UniformType::AtomicCounter:
+ return "atomic counter";
+ default:
+ UNREACHABLE();
+ return "";
+ }
+}
+
+std::string GetUniformResourceLimitName(ShaderType shaderType, UniformType uniformType)
+{
+ // Special case: MAX_TEXTURE_IMAGE_UNITS (no "MAX_FRAGMENT_TEXTURE_IMAGE_UNITS")
+ if (shaderType == ShaderType::Fragment && uniformType == UniformType::Sampler)
+ {
+ return "MAX_TEXTURE_IMAGE_UNITS";
+ }
+
+ std::ostringstream ostream;
+ ostream << "MAX_" << GetShaderTypeString(shaderType) << "_";
+
+ switch (uniformType)
+ {
+ case UniformType::Variable:
+ // For vertex and fragment shaders, ES 2.0 only defines MAX_VERTEX_UNIFORM_VECTORS and
+ // MAX_FRAGMENT_UNIFORM_VECTORS ([OpenGL ES 2.0] Table 6.20).
+ if (shaderType == ShaderType::Vertex || shaderType == ShaderType::Fragment)
+ {
+ ostream << "UNIFORM_VECTORS";
+ break;
+ }
+ // For compute and geometry shaders, there are no definitions on
+ // "MAX_COMPUTE_UNIFORM_VECTORS" or "MAX_GEOMETRY_UNIFORM_VECTORS_EXT"
+ // ([OpenGL ES 3.1] Table 20.45, [EXT_geometry_shader] Table 20.43gs).
+ else
+ {
+ ostream << "UNIFORM_COMPONENTS";
+ }
+ break;
+ case UniformType::Sampler:
+ ostream << "TEXTURE_IMAGE_UNITS";
+ break;
+ case UniformType::Image:
+ ostream << "IMAGE_UNIFORMS";
+ break;
+ case UniformType::AtomicCounter:
+ ostream << "ATOMIC_COUNTERS";
+ break;
+ default:
+ UNREACHABLE();
+ return "";
+ }
+
+ if (shaderType == ShaderType::Geometry)
+ {
+ ostream << "_EXT";
+ }
+
+ return ostream.str();
+}
+
+void LogUniformsExceedLimit(ShaderType shaderType,
+ UniformType uniformType,
+ GLuint limit,
+ InfoLog &infoLog)
+{
+ infoLog << GetShaderTypeString(shaderType) << " shader "
+ << GetUniformResourceNameString(uniformType) << "s count exceeds "
+ << GetUniformResourceLimitName(shaderType, uniformType) << "(" << limit << ")";
+}
+
+// The purpose of this visitor is to capture the uniforms in a uniform block. Each new uniform is
+// added to "uniformsOut".
+class UniformBlockEncodingVisitor : public sh::VariableNameVisitor
+{
+ public:
+ UniformBlockEncodingVisitor(const GetBlockMemberInfoFunc &getMemberInfo,
+ const std::string &namePrefix,
+ const std::string &mappedNamePrefix,
+ std::vector<LinkedUniform> *uniformsOut,
+ ShaderType shaderType,
+ int blockIndex)
+ : sh::VariableNameVisitor(namePrefix, mappedNamePrefix),
+ mGetMemberInfo(getMemberInfo),
+ mUniformsOut(uniformsOut),
+ mShaderType(shaderType),
+ mBlockIndex(blockIndex)
+ {}
+
+ void visitNamedVariable(const sh::ShaderVariable &variable,
+ bool isRowMajor,
+ const std::string &name,
+ const std::string &mappedName,
+ const std::vector<unsigned int> &arraySizes) override
+ {
+ // If getBlockMemberInfo returns false, the variable is optimized out.
+ sh::BlockMemberInfo variableInfo;
+ if (!mGetMemberInfo(name, mappedName, &variableInfo))
+ return;
+
+ std::string nameWithArrayIndex = name;
+ std::string mappedNameWithArrayIndex = mappedName;
+
+ if (variable.isArray())
+ {
+ nameWithArrayIndex += "[0]";
+ mappedNameWithArrayIndex += "[0]";
+ }
+
+ if (mBlockIndex == -1)
+ {
+ SetActive(mUniformsOut, nameWithArrayIndex, mShaderType, variable.active);
+ return;
+ }
+
+ LinkedUniform newUniform(variable.type, variable.precision, nameWithArrayIndex,
+ variable.arraySizes, -1, -1, -1, mBlockIndex, variableInfo);
+ newUniform.mappedName = mappedNameWithArrayIndex;
+ newUniform.setActive(mShaderType, variable.active);
+
+ // Since block uniforms have no location, we don't need to store them in the uniform
+ // locations list.
+ mUniformsOut->push_back(newUniform);
+ }
+
+ private:
+ const GetBlockMemberInfoFunc &mGetMemberInfo;
+ std::vector<LinkedUniform> *mUniformsOut;
+ const ShaderType mShaderType;
+ const int mBlockIndex;
+};
+
+// The purpose of this visitor is to capture the buffer variables in a shader storage block. Each
+// new buffer variable is stored in "bufferVariablesOut".
+class ShaderStorageBlockVisitor : public sh::BlockEncoderVisitor
+{
+ public:
+ ShaderStorageBlockVisitor(const GetBlockMemberInfoFunc &getMemberInfo,
+ const std::string &namePrefix,
+ const std::string &mappedNamePrefix,
+ std::vector<BufferVariable> *bufferVariablesOut,
+ ShaderType shaderType,
+ int blockIndex)
+ : sh::BlockEncoderVisitor(namePrefix, mappedNamePrefix, &mStubEncoder),
+ mGetMemberInfo(getMemberInfo),
+ mBufferVariablesOut(bufferVariablesOut),
+ mShaderType(shaderType),
+ mBlockIndex(blockIndex)
+ {}
+
+ void visitNamedVariable(const sh::ShaderVariable &variable,
+ bool isRowMajor,
+ const std::string &name,
+ const std::string &mappedName,
+ const std::vector<unsigned int> &arraySizes) override
+ {
+ if (mSkipEnabled)
+ return;
+
+ // If getBlockMemberInfo returns false, the variable is optimized out.
+ sh::BlockMemberInfo variableInfo;
+ if (!mGetMemberInfo(name, mappedName, &variableInfo))
+ return;
+
+ std::string nameWithArrayIndex = name;
+ std::string mappedNameWithArrayIndex = mappedName;
+
+ if (variable.isArray())
+ {
+ nameWithArrayIndex += "[0]";
+ mappedNameWithArrayIndex += "[0]";
+ }
+
+ if (mBlockIndex == -1)
+ {
+ SetActive(mBufferVariablesOut, nameWithArrayIndex, mShaderType, variable.active);
+ return;
+ }
+
+ BufferVariable newBufferVariable(variable.type, variable.precision, nameWithArrayIndex,
+ variable.arraySizes, mBlockIndex, variableInfo);
+ newBufferVariable.mappedName = mappedNameWithArrayIndex;
+ newBufferVariable.setActive(mShaderType, variable.active);
+
+ newBufferVariable.topLevelArraySize = mTopLevelArraySize;
+
+ mBufferVariablesOut->push_back(newBufferVariable);
+ }
+
+ private:
+ const GetBlockMemberInfoFunc &mGetMemberInfo;
+ std::vector<BufferVariable> *mBufferVariablesOut;
+ const ShaderType mShaderType;
+ const int mBlockIndex;
+ sh::StubBlockEncoder mStubEncoder;
+};
+
+struct ShaderUniformCount
+{
+ unsigned int vectorCount = 0;
+ unsigned int samplerCount = 0;
+ unsigned int imageCount = 0;
+ unsigned int atomicCounterCount = 0;
+ unsigned int fragmentInOutCount = 0;
+};
+
+ShaderUniformCount &operator+=(ShaderUniformCount &lhs, const ShaderUniformCount &rhs)
+{
+ lhs.vectorCount += rhs.vectorCount;
+ lhs.samplerCount += rhs.samplerCount;
+ lhs.imageCount += rhs.imageCount;
+ lhs.atomicCounterCount += rhs.atomicCounterCount;
+ lhs.fragmentInOutCount += rhs.fragmentInOutCount;
+ return lhs;
+}
+
+// The purpose of this visitor is to flatten struct and array uniforms into a list of singleton
+// uniforms. They are stored in separate lists by uniform type so they can be sorted in order.
+// Counts for each uniform category are stored and can be queried with "getCounts".
+class FlattenUniformVisitor : public sh::VariableNameVisitor
+{
+ public:
+ FlattenUniformVisitor(ShaderType shaderType,
+ const sh::ShaderVariable &uniform,
+ std::vector<LinkedUniform> *uniforms,
+ std::vector<LinkedUniform> *samplerUniforms,
+ std::vector<LinkedUniform> *imageUniforms,
+ std::vector<LinkedUniform> *atomicCounterUniforms,
+ std::vector<LinkedUniform> *inputAttachmentUniforms,
+ std::vector<UnusedUniform> *unusedUniforms)
+ : sh::VariableNameVisitor("", ""),
+ mShaderType(shaderType),
+ mMarkActive(uniform.active),
+ mMarkStaticUse(uniform.staticUse),
+ mBinding(uniform.binding),
+ mOffset(uniform.offset),
+ mLocation(uniform.location),
+ mUniforms(uniforms),
+ mSamplerUniforms(samplerUniforms),
+ mImageUniforms(imageUniforms),
+ mAtomicCounterUniforms(atomicCounterUniforms),
+ mInputAttachmentUniforms(inputAttachmentUniforms),
+ mUnusedUniforms(unusedUniforms)
+ {}
+
+ void visitNamedOpaqueObject(const sh::ShaderVariable &variable,
+ const std::string &name,
+ const std::string &mappedName,
+ const std::vector<unsigned int> &arraySizes) override
+ {
+ visitNamedVariable(variable, false, name, mappedName, arraySizes);
+ }
+
+ void visitNamedVariable(const sh::ShaderVariable &variable,
+ bool isRowMajor,
+ const std::string &name,
+ const std::string &mappedName,
+ const std::vector<unsigned int> &arraySizes) override
+ {
+ bool isSampler = IsSamplerType(variable.type);
+ bool isImage = IsImageType(variable.type);
+ bool isAtomicCounter = IsAtomicCounterType(variable.type);
+ bool isFragmentInOut = variable.isFragmentInOut;
+ std::vector<LinkedUniform> *uniformList = mUniforms;
+ if (isSampler)
+ {
+ uniformList = mSamplerUniforms;
+ }
+ else if (isImage)
+ {
+ uniformList = mImageUniforms;
+ }
+ else if (isAtomicCounter)
+ {
+ uniformList = mAtomicCounterUniforms;
+ }
+ else if (isFragmentInOut)
+ {
+ uniformList = mInputAttachmentUniforms;
+ }
+
+ std::string fullNameWithArrayIndex(name);
+ std::string fullMappedNameWithArrayIndex(mappedName);
+
+ if (variable.isArray())
+ {
+ // We're following the GLES 3.1 November 2016 spec section 7.3.1.1 Naming Active
+ // Resources and including [0] at the end of array variable names.
+ fullNameWithArrayIndex += "[0]";
+ fullMappedNameWithArrayIndex += "[0]";
+ }
+
+ LinkedUniform *existingUniform = FindUniform(*uniformList, fullNameWithArrayIndex);
+ if (existingUniform)
+ {
+ if (getBinding() != -1)
+ {
+ existingUniform->binding = getBinding();
+ }
+ if (getOffset() != -1)
+ {
+ existingUniform->offset = getOffset();
+ }
+ if (mLocation != -1)
+ {
+ existingUniform->location = mLocation;
+ }
+ if (mMarkActive)
+ {
+ existingUniform->active = true;
+ existingUniform->setActive(mShaderType, true);
+ }
+ if (mMarkStaticUse)
+ {
+ existingUniform->staticUse = true;
+ }
+ }
+ else
+ {
+ LinkedUniform linkedUniform(variable.type, variable.precision, fullNameWithArrayIndex,
+ variable.arraySizes, getBinding(), getOffset(), mLocation,
+ -1, sh::kDefaultBlockMemberInfo);
+ linkedUniform.mappedName = fullMappedNameWithArrayIndex;
+ linkedUniform.active = mMarkActive;
+ linkedUniform.staticUse = mMarkStaticUse;
+ linkedUniform.outerArraySizes = arraySizes;
+ linkedUniform.texelFetchStaticUse = variable.texelFetchStaticUse;
+ linkedUniform.imageUnitFormat = variable.imageUnitFormat;
+ linkedUniform.isFragmentInOut = variable.isFragmentInOut;
+ if (variable.hasParentArrayIndex())
+ {
+ linkedUniform.setParentArrayIndex(variable.parentArrayIndex());
+ }
+
+ std::vector<unsigned int> arrayDims = arraySizes;
+ ASSERT(variable.arraySizes.size() == 1 || variable.arraySizes.size() == 0);
+ arrayDims.push_back(variable.arraySizes.empty() ? 1 : variable.arraySizes[0]);
+
+ size_t numDimensions = arraySizes.size();
+ uint32_t arrayStride = 1;
+ for (size_t dimension = numDimensions; dimension > 0;)
+ {
+ --dimension;
+ arrayStride *= arrayDims[dimension + 1];
+ linkedUniform.outerArrayOffset += arrayStride * mArrayElementStack[dimension];
+ }
+
+ if (mMarkActive)
+ {
+ linkedUniform.setActive(mShaderType, true);
+ }
+ else
+ {
+ mUnusedUniforms->emplace_back(
+ linkedUniform.name, linkedUniform.isSampler(), linkedUniform.isImage(),
+ linkedUniform.isAtomicCounter(), linkedUniform.isFragmentInOut);
+ }
+
+ uniformList->push_back(linkedUniform);
+ }
+
+ unsigned int elementCount = variable.getBasicTypeElementCount();
+
+ // Samplers and images aren't "real" uniforms, so they don't count towards register usage.
+ // Likewise, don't count "real" uniforms towards opaque count.
+
+ if (!IsOpaqueType(variable.type) && !isFragmentInOut)
+ {
+ mUniformCount.vectorCount += VariableRegisterCount(variable.type) * elementCount;
+ }
+
+ mUniformCount.samplerCount += (isSampler ? elementCount : 0);
+ mUniformCount.imageCount += (isImage ? elementCount : 0);
+ mUniformCount.atomicCounterCount += (isAtomicCounter ? elementCount : 0);
+ mUniformCount.fragmentInOutCount += (isFragmentInOut ? elementCount : 0);
+
+ if (mLocation != -1)
+ {
+ mLocation += elementCount;
+ }
+ }
+
+ void enterStructAccess(const sh::ShaderVariable &structVar, bool isRowMajor) override
+ {
+ mStructStackSize++;
+ sh::VariableNameVisitor::enterStructAccess(structVar, isRowMajor);
+ }
+
+ void exitStructAccess(const sh::ShaderVariable &structVar, bool isRowMajor) override
+ {
+ mStructStackSize--;
+ sh::VariableNameVisitor::exitStructAccess(structVar, isRowMajor);
+ }
+
+ void enterArrayElement(const sh::ShaderVariable &arrayVar, unsigned int arrayElement) override
+ {
+ mArrayElementStack.push_back(arrayElement);
+ sh::VariableNameVisitor::enterArrayElement(arrayVar, arrayElement);
+ }
+
+ void exitArrayElement(const sh::ShaderVariable &arrayVar, unsigned int arrayElement) override
+ {
+ mArrayElementStack.pop_back();
+ sh::VariableNameVisitor::exitArrayElement(arrayVar, arrayElement);
+ }
+
+ ShaderUniformCount getCounts() const { return mUniformCount; }
+
+ private:
+ int getBinding() const { return mStructStackSize == 0 ? mBinding : -1; }
+ int getOffset() const { return mStructStackSize == 0 ? mOffset : -1; }
+
+ ShaderType mShaderType;
+
+ // Active and StaticUse are given separately because they are tracked at struct granularity.
+ bool mMarkActive;
+ bool mMarkStaticUse;
+ int mBinding;
+ int mOffset;
+ int mLocation;
+ std::vector<LinkedUniform> *mUniforms;
+ std::vector<LinkedUniform> *mSamplerUniforms;
+ std::vector<LinkedUniform> *mImageUniforms;
+ std::vector<LinkedUniform> *mAtomicCounterUniforms;
+ std::vector<LinkedUniform> *mInputAttachmentUniforms;
+ std::vector<UnusedUniform> *mUnusedUniforms;
+ std::vector<unsigned int> mArrayElementStack;
+ ShaderUniformCount mUniformCount;
+ unsigned int mStructStackSize = 0;
+};
+
+class InterfaceBlockInfo final : angle::NonCopyable
+{
+ public:
+ InterfaceBlockInfo(CustomBlockLayoutEncoderFactory *customEncoderFactory)
+ : mCustomEncoderFactory(customEncoderFactory)
+ {}
+
+ void getShaderBlockInfo(const std::vector<sh::InterfaceBlock> &interfaceBlocks);
+
+ bool getBlockSize(const std::string &name, const std::string &mappedName, size_t *sizeOut);
+ bool getBlockMemberInfo(const std::string &name,
+ const std::string &mappedName,
+ sh::BlockMemberInfo *infoOut);
+
+ private:
+ size_t getBlockInfo(const sh::InterfaceBlock &interfaceBlock);
+
+ std::map<std::string, size_t> mBlockSizes;
+ sh::BlockLayoutMap mBlockLayout;
+ // Based on the interface block layout, the std140 or std430 encoders are used. On some
+ // platforms (currently only D3D), there could be another non-standard encoder used.
+ CustomBlockLayoutEncoderFactory *mCustomEncoderFactory;
+};
+
+void InterfaceBlockInfo::getShaderBlockInfo(const std::vector<sh::InterfaceBlock> &interfaceBlocks)
+{
+ for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks)
+ {
+ if (!IsActiveInterfaceBlock(interfaceBlock))
+ continue;
+
+ if (mBlockSizes.count(interfaceBlock.name) > 0)
+ continue;
+
+ size_t dataSize = getBlockInfo(interfaceBlock);
+ mBlockSizes[interfaceBlock.name] = dataSize;
+ }
+}
+
+size_t InterfaceBlockInfo::getBlockInfo(const sh::InterfaceBlock &interfaceBlock)
+{
+ ASSERT(IsActiveInterfaceBlock(interfaceBlock));
+
+ // define member uniforms
+ sh::Std140BlockEncoder std140Encoder;
+ sh::Std430BlockEncoder std430Encoder;
+ sh::BlockLayoutEncoder *customEncoder = nullptr;
+ sh::BlockLayoutEncoder *encoder = nullptr;
+
+ if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD140)
+ {
+ encoder = &std140Encoder;
+ }
+ else if (interfaceBlock.layout == sh::BLOCKLAYOUT_STD430)
+ {
+ encoder = &std430Encoder;
+ }
+ else if (mCustomEncoderFactory)
+ {
+ encoder = customEncoder = mCustomEncoderFactory->makeEncoder();
+ }
+ else
+ {
+ UNREACHABLE();
+ return 0;
+ }
+
+ sh::GetInterfaceBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder,
+ &mBlockLayout);
+
+ size_t offset = encoder->getCurrentOffset();
+
+ SafeDelete(customEncoder);
+
+ return offset;
+}
+
+bool InterfaceBlockInfo::getBlockSize(const std::string &name,
+ const std::string &mappedName,
+ size_t *sizeOut)
+{
+ size_t nameLengthWithoutArrayIndex;
+ ParseArrayIndex(name, &nameLengthWithoutArrayIndex);
+ std::string baseName = name.substr(0u, nameLengthWithoutArrayIndex);
+ auto sizeIter = mBlockSizes.find(baseName);
+ if (sizeIter == mBlockSizes.end())
+ {
+ *sizeOut = 0;
+ return false;
+ }
+
+ *sizeOut = sizeIter->second;
+ return true;
+}
+
+bool InterfaceBlockInfo::getBlockMemberInfo(const std::string &name,
+ const std::string &mappedName,
+ sh::BlockMemberInfo *infoOut)
+{
+ auto infoIter = mBlockLayout.find(name);
+ if (infoIter == mBlockLayout.end())
+ {
+ *infoOut = sh::kDefaultBlockMemberInfo;
+ return false;
+ }
+
+ *infoOut = infoIter->second;
+ return true;
+}
+
+void GetFilteredVaryings(const std::vector<sh::ShaderVariable> &varyings,
+ std::vector<const sh::ShaderVariable *> *filteredVaryingsOut)
+{
+ for (const sh::ShaderVariable &varying : varyings)
+ {
+ // Built-in varyings obey special rules
+ if (varying.isBuiltIn())
+ {
+ continue;
+ }
+
+ filteredVaryingsOut->push_back(&varying);
+ }
+}
+
+LinkMismatchError LinkValidateVaryings(const sh::ShaderVariable &outputVarying,
+ const sh::ShaderVariable &inputVarying,
+ int shaderVersion,
+ ShaderType frontShaderType,
+ ShaderType backShaderType,
+ bool isSeparable,
+ std::string *mismatchedStructFieldName)
+{
+ // [ES 3.2 spec] 7.4.1 Shader Interface Matching:
+ // Tessellation control shader per-vertex output variables and blocks and tessellation control,
+ // tessellation evaluation, and geometry shader per-vertex input variables and blocks are
+ // required to be declared as arrays, with each element representing input or output values for
+ // a single vertex of a multi-vertex primitive. For the purposes of interface matching, such
+ // variables and blocks are treated as though they were not declared as arrays.
+ bool treatOutputAsNonArray =
+ (frontShaderType == ShaderType::TessControl && !outputVarying.isPatch);
+ bool treatInputAsNonArray =
+ ((backShaderType == ShaderType::TessControl ||
+ backShaderType == ShaderType::TessEvaluation || backShaderType == ShaderType::Geometry) &&
+ !inputVarying.isPatch);
+
+ // Skip the validation on the array sizes between a vertex output varying and a geometry input
+ // varying as it has been done before.
+ bool validatePrecision = isSeparable && (shaderVersion > 100);
+ LinkMismatchError linkError = LinkValidateProgramVariables(
+ outputVarying, inputVarying, validatePrecision, treatOutputAsNonArray, treatInputAsNonArray,
+ mismatchedStructFieldName);
+ if (linkError != LinkMismatchError::NO_MISMATCH)
+ {
+ return linkError;
+ }
+
+ // Explicit locations must match if the names match.
+ if (outputVarying.isSameNameAtLinkTime(inputVarying) &&
+ outputVarying.location != inputVarying.location)
+ {
+ return LinkMismatchError::LOCATION_MISMATCH;
+ }
+
+ if (!sh::InterpolationTypesMatch(outputVarying.interpolation, inputVarying.interpolation))
+ {
+ return LinkMismatchError::INTERPOLATION_TYPE_MISMATCH;
+ }
+
+ if (shaderVersion == 100 && outputVarying.isInvariant != inputVarying.isInvariant)
+ {
+ return LinkMismatchError::INVARIANCE_MISMATCH;
+ }
+
+ return LinkMismatchError::NO_MISMATCH;
+}
+
+bool DoShaderVariablesMatch(int frontShaderVersion,
+ ShaderType frontShaderType,
+ ShaderType backShaderType,
+ const sh::ShaderVariable &input,
+ const sh::ShaderVariable &output,
+ bool isSeparable,
+ gl::InfoLog &infoLog)
+{
+ bool namesMatch = input.isSameNameAtLinkTime(output);
+ bool locationsMatch = input.location != -1 && input.location == output.location;
+
+ // An output block is considered to match an input block in the subsequent
+ // shader if the two blocks have the same block name, and the members of the
+ // block match exactly in name, type, qualification, and declaration order.
+ //
+ // - For the purposes of shader interface matching, the gl_PointSize
+ // member of the intrinsically declared gl_PerVertex shader interface
+ // block is ignored.
+ // - Output blocks that do not match in name, but have a location and match
+ // in every other way listed above may be considered to match by some
+ // implementations, but not all - so this behaviour should not be relied
+ // upon.
+
+ // An output variable is considered to match an input variable in the subsequent
+ // shader if:
+ //
+ // - the two variables match in name, type, and qualification; or
+ // - the two variables are declared with the same location qualifier and
+ // match in type and qualification.
+
+ if (namesMatch || locationsMatch)
+ {
+ std::string mismatchedStructFieldName;
+ LinkMismatchError linkError =
+ LinkValidateVaryings(output, input, frontShaderVersion, frontShaderType, backShaderType,
+ isSeparable, &mismatchedStructFieldName);
+ if (linkError != LinkMismatchError::NO_MISMATCH)
+ {
+ LogLinkMismatch(infoLog, input.name, "varying", linkError, mismatchedStructFieldName,
+ frontShaderType, backShaderType);
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+const char *GetInterfaceBlockTypeString(sh::BlockType blockType)
+{
+ switch (blockType)
+ {
+ case sh::BlockType::BLOCK_UNIFORM:
+ return "uniform block";
+ case sh::BlockType::BLOCK_BUFFER:
+ return "shader storage block";
+ default:
+ UNREACHABLE();
+ return "";
+ }
+}
+
+std::string GetInterfaceBlockLimitName(ShaderType shaderType, sh::BlockType blockType)
+{
+ std::ostringstream stream;
+ stream << "GL_MAX_" << GetShaderTypeString(shaderType) << "_";
+
+ switch (blockType)
+ {
+ case sh::BlockType::BLOCK_UNIFORM:
+ stream << "UNIFORM_BUFFERS";
+ break;
+ case sh::BlockType::BLOCK_BUFFER:
+ stream << "SHADER_STORAGE_BLOCKS";
+ break;
+ default:
+ UNREACHABLE();
+ return "";
+ }
+
+ if (shaderType == ShaderType::Geometry)
+ {
+ stream << "_EXT";
+ }
+
+ return stream.str();
+}
+
+void LogInterfaceBlocksExceedLimit(InfoLog &infoLog,
+ ShaderType shaderType,
+ sh::BlockType blockType,
+ GLuint limit)
+{
+ infoLog << GetShaderTypeString(shaderType) << " shader "
+ << GetInterfaceBlockTypeString(blockType) << " count exceeds "
+ << GetInterfaceBlockLimitName(shaderType, blockType) << " (" << limit << ")";
+}
+
+bool ValidateInterfaceBlocksCount(GLuint maxInterfaceBlocks,
+ const std::vector<sh::InterfaceBlock> &interfaceBlocks,
+ ShaderType shaderType,
+ sh::BlockType blockType,
+ GLuint *combinedInterfaceBlocksCount,
+ InfoLog &infoLog)
+{
+ GLuint blockCount = 0;
+ for (const sh::InterfaceBlock &block : interfaceBlocks)
+ {
+ if (IsActiveInterfaceBlock(block))
+ {
+ blockCount += std::max(block.arraySize, 1u);
+ if (blockCount > maxInterfaceBlocks)
+ {
+ LogInterfaceBlocksExceedLimit(infoLog, shaderType, blockType, maxInterfaceBlocks);
+ return false;
+ }
+ }
+ }
+
+ // [OpenGL ES 3.1] Chapter 7.6.2 Page 105:
+ // If a uniform block is used by multiple shader stages, each such use counts separately
+ // against this combined limit.
+ // [OpenGL ES 3.1] Chapter 7.8 Page 111:
+ // If a shader storage block in a program is referenced by multiple shaders, each such
+ // reference counts separately against this combined limit.
+ if (combinedInterfaceBlocksCount)
+ {
+ *combinedInterfaceBlocksCount += blockCount;
+ }
+
+ return true;
+}
+} // anonymous namespace
+
+UniformLinker::UniformLinker(const ShaderBitSet &activeShaderStages,
+ const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms)
+ : mActiveShaderStages(activeShaderStages), mShaderUniforms(shaderUniforms)
+{}
+
+UniformLinker::~UniformLinker() = default;
+
+void UniformLinker::getResults(std::vector<LinkedUniform> *uniforms,
+ std::vector<UnusedUniform> *unusedUniformsOutOrNull,
+ std::vector<VariableLocation> *uniformLocationsOutOrNull)
+{
+ uniforms->swap(mUniforms);
+
+ if (unusedUniformsOutOrNull)
+ {
+ unusedUniformsOutOrNull->swap(mUnusedUniforms);
+ }
+
+ if (uniformLocationsOutOrNull)
+ {
+ uniformLocationsOutOrNull->swap(mUniformLocations);
+ }
+}
+
+bool UniformLinker::link(const Caps &caps,
+ InfoLog &infoLog,
+ const ProgramAliasedBindings &uniformLocationBindings)
+{
+ if (mActiveShaderStages[ShaderType::Vertex] && mActiveShaderStages[ShaderType::Fragment])
+ {
+ if (!validateGraphicsUniforms(infoLog))
+ {
+ return false;
+ }
+ }
+
+ // Flatten the uniforms list (nested fields) into a simple list (no nesting).
+ // Also check the maximum uniform vector and sampler counts.
+ if (!flattenUniformsAndCheckCaps(caps, infoLog))
+ {
+ return false;
+ }
+
+ if (!checkMaxCombinedAtomicCounters(caps, infoLog))
+ {
+ return false;
+ }
+
+ if (!indexUniforms(infoLog, uniformLocationBindings))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool UniformLinker::validateGraphicsUniforms(InfoLog &infoLog) const
+{
+ // Check that uniforms defined in the graphics shaders are identical
+ std::map<std::string, ShaderUniform> linkedUniforms;
+
+ for (const ShaderType shaderType : mActiveShaderStages)
+ {
+ if (shaderType == ShaderType::Vertex)
+ {
+ for (const sh::ShaderVariable &vertexUniform : mShaderUniforms[ShaderType::Vertex])
+ {
+ linkedUniforms[vertexUniform.name] =
+ std::make_pair(ShaderType::Vertex, &vertexUniform);
+ }
+ }
+ else
+ {
+ bool isLastShader = (shaderType == ShaderType::Fragment);
+ if (!validateGraphicsUniformsPerShader(shaderType, !isLastShader, &linkedUniforms,
+ infoLog))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool UniformLinker::validateGraphicsUniformsPerShader(
+ ShaderType shaderToLink,
+ bool extendLinkedUniforms,
+ std::map<std::string, ShaderUniform> *linkedUniforms,
+ InfoLog &infoLog) const
+{
+ ASSERT(mActiveShaderStages[shaderToLink] && linkedUniforms);
+
+ for (const sh::ShaderVariable &uniform : mShaderUniforms[shaderToLink])
+ {
+ const auto &entry = linkedUniforms->find(uniform.name);
+ if (entry != linkedUniforms->end())
+ {
+ const sh::ShaderVariable &linkedUniform = *(entry->second.second);
+ std::string mismatchedStructFieldName;
+ LinkMismatchError linkError =
+ LinkValidateUniforms(uniform, linkedUniform, &mismatchedStructFieldName);
+ if (linkError != LinkMismatchError::NO_MISMATCH)
+ {
+ LogLinkMismatch(infoLog, uniform.name, "uniform", linkError,
+ mismatchedStructFieldName, entry->second.first, shaderToLink);
+ return false;
+ }
+ }
+ else if (extendLinkedUniforms)
+ {
+ (*linkedUniforms)[uniform.name] = std::make_pair(shaderToLink, &uniform);
+ }
+ }
+
+ return true;
+}
+
+bool UniformLinker::indexUniforms(InfoLog &infoLog,
+ const ProgramAliasedBindings &uniformLocationBindings)
+{
+ // Locations which have been allocated for an unused uniform.
+ std::set<GLuint> ignoredLocations;
+
+ int maxUniformLocation = -1;
+
+ // Gather uniform locations that have been set either using the bindUniformLocationCHROMIUM API
+ // or by using a location layout qualifier and check conflicts between them.
+ if (!gatherUniformLocationsAndCheckConflicts(infoLog, uniformLocationBindings,
+ &ignoredLocations, &maxUniformLocation))
+ {
+ return false;
+ }
+
+ // Conflicts have been checked, now we can prune non-statically used uniforms. Code further down
+ // the line relies on only having statically used uniforms in mUniforms.
+ pruneUnusedUniforms();
+
+ // Gather uniforms that have their location pre-set and uniforms that don't yet have a location.
+ std::vector<VariableLocation> unlocatedUniforms;
+ std::map<GLuint, VariableLocation> preLocatedUniforms;
+
+ for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++)
+ {
+ const LinkedUniform &uniform = mUniforms[uniformIndex];
+
+ if ((uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn()) ||
+ IsAtomicCounterType(uniform.type) || uniform.isFragmentInOut)
+ {
+ continue;
+ }
+
+ int preSetLocation = uniformLocationBindings.getBinding(uniform);
+ int shaderLocation = uniform.location;
+
+ if (shaderLocation != -1)
+ {
+ preSetLocation = shaderLocation;
+ }
+
+ unsigned int elementCount = uniform.getBasicTypeElementCount();
+ for (unsigned int arrayIndex = 0; arrayIndex < elementCount; arrayIndex++)
+ {
+ VariableLocation location(arrayIndex, static_cast<unsigned int>(uniformIndex));
+
+ if ((arrayIndex == 0 && preSetLocation != -1) || shaderLocation != -1)
+ {
+ int elementLocation = preSetLocation + arrayIndex;
+ preLocatedUniforms[elementLocation] = location;
+ }
+ else
+ {
+ unlocatedUniforms.push_back(location);
+ }
+ }
+ }
+
+ // Make enough space for all uniforms, with pre-set locations or not.
+ mUniformLocations.resize(
+ std::max(unlocatedUniforms.size() + preLocatedUniforms.size() + ignoredLocations.size(),
+ static_cast<size_t>(maxUniformLocation + 1)));
+
+ // Assign uniforms with pre-set locations
+ for (const auto &uniform : preLocatedUniforms)
+ {
+ mUniformLocations[uniform.first] = uniform.second;
+ }
+
+ // Assign ignored uniforms
+ for (const auto &ignoredLocation : ignoredLocations)
+ {
+ mUniformLocations[ignoredLocation].markIgnored();
+ }
+
+ // Automatically assign locations for the rest of the uniforms
+ size_t nextUniformLocation = 0;
+ for (const auto &unlocatedUniform : unlocatedUniforms)
+ {
+ while (mUniformLocations[nextUniformLocation].used() ||
+ mUniformLocations[nextUniformLocation].ignored)
+ {
+ nextUniformLocation++;
+ }
+
+ ASSERT(nextUniformLocation < mUniformLocations.size());
+ mUniformLocations[nextUniformLocation] = unlocatedUniform;
+ nextUniformLocation++;
+ }
+
+ return true;
+}
+
+bool UniformLinker::gatherUniformLocationsAndCheckConflicts(
+ InfoLog &infoLog,
+ const ProgramAliasedBindings &uniformLocationBindings,
+ std::set<GLuint> *ignoredLocations,
+ int *maxUniformLocation)
+{
+ // All the locations where another uniform can't be located.
+ std::set<GLuint> reservedLocations;
+
+ for (const LinkedUniform &uniform : mUniforms)
+ {
+ if ((uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn()) || uniform.isFragmentInOut)
+ {
+ // The uniform of the fragment inout is not a normal uniform type. So, in the case of
+ // the fragment inout, this routine should be skipped.
+ continue;
+ }
+
+ int apiBoundLocation = uniformLocationBindings.getBinding(uniform);
+ int shaderLocation = uniform.location;
+
+ if (shaderLocation != -1)
+ {
+ unsigned int elementCount = uniform.getBasicTypeElementCount();
+
+ for (unsigned int arrayIndex = 0; arrayIndex < elementCount; arrayIndex++)
+ {
+ // GLSL ES 3.10 section 4.4.3
+ int elementLocation = shaderLocation + arrayIndex;
+ *maxUniformLocation = std::max(*maxUniformLocation, elementLocation);
+ if (reservedLocations.find(elementLocation) != reservedLocations.end())
+ {
+ infoLog << "Multiple uniforms bound to location " << elementLocation << ".";
+ return false;
+ }
+ reservedLocations.insert(elementLocation);
+ if (!uniform.active)
+ {
+ ignoredLocations->insert(elementLocation);
+ }
+ }
+ }
+ else if (apiBoundLocation != -1 && uniform.staticUse)
+ {
+ // Only the first location is reserved even if the uniform is an array.
+ *maxUniformLocation = std::max(*maxUniformLocation, apiBoundLocation);
+ if (reservedLocations.find(apiBoundLocation) != reservedLocations.end())
+ {
+ infoLog << "Multiple uniforms bound to location " << apiBoundLocation << ".";
+ return false;
+ }
+ reservedLocations.insert(apiBoundLocation);
+ if (!uniform.active)
+ {
+ ignoredLocations->insert(apiBoundLocation);
+ }
+ }
+ }
+
+ // Record the uniform locations that were bound using the API for uniforms that were not found
+ // from the shader. Other uniforms should not be assigned to those locations.
+ for (const auto &locationBinding : uniformLocationBindings)
+ {
+ GLuint location = locationBinding.second.location;
+ if (reservedLocations.find(location) == reservedLocations.end())
+ {
+ ignoredLocations->insert(location);
+ *maxUniformLocation = std::max(*maxUniformLocation, static_cast<int>(location));
+ }
+ }
+
+ return true;
+}
+
+void UniformLinker::pruneUnusedUniforms()
+{
+ auto uniformIter = mUniforms.begin();
+ while (uniformIter != mUniforms.end())
+ {
+ if (uniformIter->active)
+ {
+ ++uniformIter;
+ }
+ else
+ {
+ mUnusedUniforms.emplace_back(uniformIter->name, uniformIter->isSampler(),
+ uniformIter->isImage(), uniformIter->isAtomicCounter(),
+ uniformIter->isFragmentInOut);
+ uniformIter = mUniforms.erase(uniformIter);
+ }
+ }
+}
+
+bool UniformLinker::flattenUniformsAndCheckCapsForShader(
+ ShaderType shaderType,
+ const Caps &caps,
+ std::vector<LinkedUniform> &samplerUniforms,
+ std::vector<LinkedUniform> &imageUniforms,
+ std::vector<LinkedUniform> &atomicCounterUniforms,
+ std::vector<LinkedUniform> &inputAttachmentUniforms,
+ std::vector<UnusedUniform> &unusedUniforms,
+ InfoLog &infoLog)
+{
+ ShaderUniformCount shaderUniformCount;
+ for (const sh::ShaderVariable &uniform : mShaderUniforms[shaderType])
+ {
+ FlattenUniformVisitor flattener(shaderType, uniform, &mUniforms, &samplerUniforms,
+ &imageUniforms, &atomicCounterUniforms,
+ &inputAttachmentUniforms, &unusedUniforms);
+ sh::TraverseShaderVariable(uniform, false, &flattener);
+
+ if (uniform.active)
+ {
+ shaderUniformCount += flattener.getCounts();
+ }
+ else
+ {
+ unusedUniforms.emplace_back(uniform.name, IsSamplerType(uniform.type),
+ IsImageType(uniform.type),
+ IsAtomicCounterType(uniform.type), uniform.isFragmentInOut);
+ }
+ }
+
+ // This code does not do fine-grained component counting.
+ GLuint maxUniformVectorsCount = GetMaximumShaderUniformVectors(shaderType, caps);
+ if (shaderUniformCount.vectorCount > maxUniformVectorsCount)
+ {
+ GLuint maxUniforms = 0u;
+
+ // See comments in GetUniformResourceLimitName()
+ if (shaderType == ShaderType::Vertex || shaderType == ShaderType::Fragment)
+ {
+ maxUniforms = maxUniformVectorsCount;
+ }
+ else
+ {
+ maxUniforms = maxUniformVectorsCount * 4;
+ }
+
+ LogUniformsExceedLimit(shaderType, UniformType::Variable, maxUniforms, infoLog);
+ return false;
+ }
+
+ if (shaderUniformCount.samplerCount >
+ static_cast<GLuint>(caps.maxShaderTextureImageUnits[shaderType]))
+ {
+ LogUniformsExceedLimit(shaderType, UniformType::Sampler,
+ caps.maxShaderTextureImageUnits[shaderType], infoLog);
+ return false;
+ }
+
+ if (shaderUniformCount.imageCount >
+ static_cast<GLuint>(caps.maxShaderImageUniforms[shaderType]))
+ {
+ LogUniformsExceedLimit(shaderType, UniformType::Image,
+ caps.maxShaderImageUniforms[shaderType], infoLog);
+ return false;
+ }
+
+ if (shaderUniformCount.atomicCounterCount >
+ static_cast<GLuint>(caps.maxShaderAtomicCounters[shaderType]))
+ {
+ LogUniformsExceedLimit(shaderType, UniformType::AtomicCounter,
+ caps.maxShaderAtomicCounters[shaderType], infoLog);
+ return false;
+ }
+
+ return true;
+}
+
+bool UniformLinker::flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog)
+{
+ std::vector<LinkedUniform> samplerUniforms;
+ std::vector<LinkedUniform> imageUniforms;
+ std::vector<LinkedUniform> atomicCounterUniforms;
+ std::vector<LinkedUniform> inputAttachmentUniforms;
+ std::vector<UnusedUniform> unusedUniforms;
+
+ for (const ShaderType shaderType : mActiveShaderStages)
+ {
+ if (!flattenUniformsAndCheckCapsForShader(shaderType, caps, samplerUniforms, imageUniforms,
+ atomicCounterUniforms, inputAttachmentUniforms,
+ unusedUniforms, infoLog))
+ {
+ return false;
+ }
+ }
+
+ mUniforms.insert(mUniforms.end(), samplerUniforms.begin(), samplerUniforms.end());
+ mUniforms.insert(mUniforms.end(), imageUniforms.begin(), imageUniforms.end());
+ mUniforms.insert(mUniforms.end(), atomicCounterUniforms.begin(), atomicCounterUniforms.end());
+ mUniforms.insert(mUniforms.end(), inputAttachmentUniforms.begin(),
+ inputAttachmentUniforms.end());
+ mUnusedUniforms.insert(mUnusedUniforms.end(), unusedUniforms.begin(), unusedUniforms.end());
+ return true;
+}
+
+bool UniformLinker::checkMaxCombinedAtomicCounters(const Caps &caps, InfoLog &infoLog)
+{
+ unsigned int atomicCounterCount = 0;
+ for (const auto &uniform : mUniforms)
+ {
+ if (IsAtomicCounterType(uniform.type) && uniform.active)
+ {
+ atomicCounterCount += uniform.getBasicTypeElementCount();
+ if (atomicCounterCount > static_cast<GLuint>(caps.maxCombinedAtomicCounters))
+ {
+ infoLog << "atomic counter count exceeds MAX_COMBINED_ATOMIC_COUNTERS"
+ << caps.maxCombinedAtomicCounters << ").";
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+// InterfaceBlockLinker implementation.
+InterfaceBlockLinker::InterfaceBlockLinker() = default;
+
+InterfaceBlockLinker::~InterfaceBlockLinker() = default;
+
+void InterfaceBlockLinker::init(std::vector<InterfaceBlock> *blocksOut,
+ std::vector<std::string> *unusedInterfaceBlocksOut)
+{
+ mBlocksOut = blocksOut;
+ mUnusedInterfaceBlocksOut = unusedInterfaceBlocksOut;
+}
+
+void InterfaceBlockLinker::addShaderBlocks(ShaderType shaderType,
+ const std::vector<sh::InterfaceBlock> *blocks)
+{
+ mShaderBlocks[shaderType] = blocks;
+}
+
+void InterfaceBlockLinker::linkBlocks(const GetBlockSizeFunc &getBlockSize,
+ const GetBlockMemberInfoFunc &getMemberInfo) const
+{
+ ASSERT(mBlocksOut->empty());
+
+ std::set<std::string> visitedList;
+
+ for (const ShaderType shaderType : AllShaderTypes())
+ {
+ if (!mShaderBlocks[shaderType])
+ {
+ continue;
+ }
+
+ for (const sh::InterfaceBlock &block : *mShaderBlocks[shaderType])
+ {
+ if (!IsActiveInterfaceBlock(block))
+ {
+ mUnusedInterfaceBlocksOut->push_back(block.name);
+ continue;
+ }
+
+ if (visitedList.count(block.name) == 0)
+ {
+ defineInterfaceBlock(getBlockSize, getMemberInfo, block, shaderType);
+ visitedList.insert(block.name);
+ continue;
+ }
+
+ if (!block.active)
+ {
+ mUnusedInterfaceBlocksOut->push_back(block.name);
+ continue;
+ }
+
+ for (InterfaceBlock &priorBlock : *mBlocksOut)
+ {
+ if (block.name == priorBlock.name)
+ {
+ priorBlock.setActive(shaderType, true);
+
+ std::unique_ptr<sh::ShaderVariableVisitor> visitor(
+ getVisitor(getMemberInfo, block.fieldPrefix(), block.fieldMappedPrefix(),
+ shaderType, -1));
+
+ sh::TraverseShaderVariables(block.fields, false, visitor.get());
+ }
+ }
+ }
+ }
+}
+
+void InterfaceBlockLinker::defineInterfaceBlock(const GetBlockSizeFunc &getBlockSize,
+ const GetBlockMemberInfoFunc &getMemberInfo,
+ const sh::InterfaceBlock &interfaceBlock,
+ ShaderType shaderType) const
+{
+ size_t blockSize = 0;
+ std::vector<unsigned int> blockIndexes;
+
+ int blockIndex = static_cast<int>(mBlocksOut->size());
+ // Track the first and last block member index to determine the range of active block members in
+ // the block.
+ size_t firstBlockMemberIndex = getCurrentBlockMemberIndex();
+
+ std::unique_ptr<sh::ShaderVariableVisitor> visitor(
+ getVisitor(getMemberInfo, interfaceBlock.fieldPrefix(), interfaceBlock.fieldMappedPrefix(),
+ shaderType, blockIndex));
+ sh::TraverseShaderVariables(interfaceBlock.fields, false, visitor.get());
+
+ size_t lastBlockMemberIndex = getCurrentBlockMemberIndex();
+
+ for (size_t blockMemberIndex = firstBlockMemberIndex; blockMemberIndex < lastBlockMemberIndex;
+ ++blockMemberIndex)
+ {
+ blockIndexes.push_back(static_cast<unsigned int>(blockMemberIndex));
+ }
+
+ unsigned int firstFieldArraySize = interfaceBlock.fields[0].getArraySizeProduct();
+
+ for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.elementCount();
+ ++arrayElement)
+ {
+ std::string blockArrayName = interfaceBlock.name;
+ std::string blockMappedArrayName = interfaceBlock.mappedName;
+ if (interfaceBlock.isArray())
+ {
+ blockArrayName += ArrayString(arrayElement);
+ blockMappedArrayName += ArrayString(arrayElement);
+ }
+
+ // Don't define this block at all if it's not active in the implementation.
+ if (!getBlockSize(blockArrayName, blockMappedArrayName, &blockSize))
+ {
+ continue;
+ }
+
+ // ESSL 3.10 section 4.4.4 page 58:
+ // Any uniform or shader storage block declared without a binding qualifier is initially
+ // assigned to block binding point zero.
+ int blockBinding =
+ (interfaceBlock.binding == -1 ? 0 : interfaceBlock.binding + arrayElement);
+ InterfaceBlock block(interfaceBlock.name, interfaceBlock.mappedName,
+ interfaceBlock.isArray(), arrayElement, firstFieldArraySize,
+ blockBinding);
+ block.memberIndexes = blockIndexes;
+ block.setActive(shaderType, interfaceBlock.active);
+
+ // Since all block elements in an array share the same active interface blocks, they
+ // will all be active once any block member is used. So, since interfaceBlock.name[0]
+ // was active, here we will add every block element in the array.
+ block.dataSize = static_cast<unsigned int>(blockSize);
+ mBlocksOut->push_back(block);
+ }
+}
+
+// UniformBlockLinker implementation.
+UniformBlockLinker::UniformBlockLinker() = default;
+
+UniformBlockLinker::~UniformBlockLinker() {}
+
+void UniformBlockLinker::init(std::vector<InterfaceBlock> *blocksOut,
+ std::vector<LinkedUniform> *uniformsOut,
+ std::vector<std::string> *unusedInterfaceBlocksOut)
+{
+ InterfaceBlockLinker::init(blocksOut, unusedInterfaceBlocksOut);
+ mUniformsOut = uniformsOut;
+}
+
+size_t UniformBlockLinker::getCurrentBlockMemberIndex() const
+{
+ return mUniformsOut->size();
+}
+
+sh::ShaderVariableVisitor *UniformBlockLinker::getVisitor(
+ const GetBlockMemberInfoFunc &getMemberInfo,
+ const std::string &namePrefix,
+ const std::string &mappedNamePrefix,
+ ShaderType shaderType,
+ int blockIndex) const
+{
+ return new UniformBlockEncodingVisitor(getMemberInfo, namePrefix, mappedNamePrefix,
+ mUniformsOut, shaderType, blockIndex);
+}
+
+// ShaderStorageBlockLinker implementation.
+ShaderStorageBlockLinker::ShaderStorageBlockLinker() = default;
+
+ShaderStorageBlockLinker::~ShaderStorageBlockLinker() = default;
+
+void ShaderStorageBlockLinker::init(std::vector<InterfaceBlock> *blocksOut,
+ std::vector<BufferVariable> *bufferVariablesOut,
+ std::vector<std::string> *unusedInterfaceBlocksOut)
+{
+ InterfaceBlockLinker::init(blocksOut, unusedInterfaceBlocksOut);
+ mBufferVariablesOut = bufferVariablesOut;
+}
+
+size_t ShaderStorageBlockLinker::getCurrentBlockMemberIndex() const
+{
+ return mBufferVariablesOut->size();
+}
+
+sh::ShaderVariableVisitor *ShaderStorageBlockLinker::getVisitor(
+ const GetBlockMemberInfoFunc &getMemberInfo,
+ const std::string &namePrefix,
+ const std::string &mappedNamePrefix,
+ ShaderType shaderType,
+ int blockIndex) const
+{
+ return new ShaderStorageBlockVisitor(getMemberInfo, namePrefix, mappedNamePrefix,
+ mBufferVariablesOut, shaderType, blockIndex);
+}
+
+// AtomicCounterBufferLinker implementation.
+AtomicCounterBufferLinker::AtomicCounterBufferLinker() = default;
+
+AtomicCounterBufferLinker::~AtomicCounterBufferLinker() = default;
+
+void AtomicCounterBufferLinker::init(std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut)
+{
+ mAtomicCounterBuffersOut = atomicCounterBuffersOut;
+}
+
+void AtomicCounterBufferLinker::link(const std::map<int, unsigned int> &sizeMap) const
+{
+ for (auto &atomicCounterBuffer : *mAtomicCounterBuffersOut)
+ {
+ auto bufferSize = sizeMap.find(atomicCounterBuffer.binding);
+ ASSERT(bufferSize != sizeMap.end());
+ atomicCounterBuffer.dataSize = bufferSize->second;
+ }
+}
+
+ProgramLinkedResources::ProgramLinkedResources() = default;
+
+ProgramLinkedResources::~ProgramLinkedResources() = default;
+
+LinkingVariables::LinkingVariables(const Context *context, const ProgramState &state)
+{
+ for (ShaderType shaderType : kAllGraphicsShaderTypes)
+ {
+ Shader *shader = state.getAttachedShader(shaderType);
+ if (shader)
+ {
+ outputVaryings[shaderType] = shader->getOutputVaryings(context);
+ inputVaryings[shaderType] = shader->getInputVaryings(context);
+ uniforms[shaderType] = shader->getUniforms(context);
+ uniformBlocks[shaderType] = shader->getUniformBlocks(context);
+ isShaderStageUsedBitset.set(shaderType);
+ }
+ }
+}
+
+LinkingVariables::LinkingVariables(const ProgramPipelineState &state)
+{
+ for (ShaderType shaderType : state.getExecutable().getLinkedShaderStages())
+ {
+ const Program *program = state.getShaderProgram(shaderType);
+ ASSERT(program);
+ outputVaryings[shaderType] = program->getExecutable().getLinkedOutputVaryings(shaderType);
+ inputVaryings[shaderType] = program->getExecutable().getLinkedInputVaryings(shaderType);
+ uniforms[shaderType] = program->getState().getExecutable().getLinkedUniforms(shaderType);
+ uniformBlocks[shaderType] =
+ program->getState().getExecutable().getLinkedUniformBlocks(shaderType);
+ isShaderStageUsedBitset.set(shaderType);
+ }
+}
+
+LinkingVariables::~LinkingVariables() = default;
+
+void ProgramLinkedResources::init(std::vector<InterfaceBlock> *uniformBlocksOut,
+ std::vector<LinkedUniform> *uniformsOut,
+ std::vector<InterfaceBlock> *shaderStorageBlocksOut,
+ std::vector<BufferVariable> *bufferVariablesOut,
+ std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut)
+{
+ uniformBlockLinker.init(uniformBlocksOut, uniformsOut, &unusedInterfaceBlocks);
+ shaderStorageBlockLinker.init(shaderStorageBlocksOut, bufferVariablesOut,
+ &unusedInterfaceBlocks);
+ atomicCounterBufferLinker.init(atomicCounterBuffersOut);
+}
+
+void ProgramLinkedResourcesLinker::linkResources(const Context *context,
+ const ProgramState &programState,
+ const ProgramLinkedResources &resources) const
+{
+ // Gather uniform interface block info.
+ InterfaceBlockInfo uniformBlockInfo(mCustomEncoderFactory);
+ for (const ShaderType shaderType : AllShaderTypes())
+ {
+ Shader *shader = programState.getAttachedShader(shaderType);
+ if (shader)
+ {
+ uniformBlockInfo.getShaderBlockInfo(shader->getUniformBlocks(context));
+ }
+ }
+
+ auto getUniformBlockSize = [&uniformBlockInfo](const std::string &name,
+ const std::string &mappedName, size_t *sizeOut) {
+ return uniformBlockInfo.getBlockSize(name, mappedName, sizeOut);
+ };
+
+ auto getUniformBlockMemberInfo = [&uniformBlockInfo](const std::string &name,
+ const std::string &mappedName,
+ sh::BlockMemberInfo *infoOut) {
+ return uniformBlockInfo.getBlockMemberInfo(name, mappedName, infoOut);
+ };
+
+ // Link uniform interface blocks.
+ resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo);
+
+ // Gather storage buffer interface block info.
+ InterfaceBlockInfo shaderStorageBlockInfo(mCustomEncoderFactory);
+ for (const ShaderType shaderType : AllShaderTypes())
+ {
+ Shader *shader = programState.getAttachedShader(shaderType);
+ if (shader)
+ {
+ shaderStorageBlockInfo.getShaderBlockInfo(shader->getShaderStorageBlocks(context));
+ }
+ }
+ auto getShaderStorageBlockSize = [&shaderStorageBlockInfo](const std::string &name,
+ const std::string &mappedName,
+ size_t *sizeOut) {
+ return shaderStorageBlockInfo.getBlockSize(name, mappedName, sizeOut);
+ };
+
+ auto getShaderStorageBlockMemberInfo = [&shaderStorageBlockInfo](const std::string &name,
+ const std::string &mappedName,
+ sh::BlockMemberInfo *infoOut) {
+ return shaderStorageBlockInfo.getBlockMemberInfo(name, mappedName, infoOut);
+ };
+
+ // Link storage buffer interface blocks.
+ resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
+ getShaderStorageBlockMemberInfo);
+
+ // Gather and link atomic counter buffer interface blocks.
+ std::map<int, unsigned int> sizeMap;
+ getAtomicCounterBufferSizeMap(programState, sizeMap);
+ resources.atomicCounterBufferLinker.link(sizeMap);
+}
+
+void ProgramLinkedResourcesLinker::getAtomicCounterBufferSizeMap(
+ const ProgramState &programState,
+ std::map<int, unsigned int> &sizeMapOut) const
+{
+ for (unsigned int index : programState.getAtomicCounterUniformRange())
+ {
+ const LinkedUniform &glUniform = programState.getUniforms()[index];
+
+ auto &bufferDataSize = sizeMapOut[glUniform.binding];
+
+ // Calculate the size of the buffer by finding the end of the last uniform with the same
+ // binding. The end of the uniform is calculated by finding the initial offset of the
+ // uniform and adding size of the uniform. For arrays, the size is the number of elements
+ // times the element size (should always by 4 for atomic_units).
+ unsigned dataOffset =
+ glUniform.offset + static_cast<unsigned int>(glUniform.getBasicTypeElementCount() *
+ glUniform.getElementSize());
+ if (dataOffset > bufferDataSize)
+ {
+ bufferDataSize = dataOffset;
+ }
+ }
+}
+
+bool LinkValidateProgramGlobalNames(InfoLog &infoLog,
+ const ProgramExecutable &executable,
+ const LinkingVariables &linkingVariables)
+{
+ angle::HashMap<std::string, const sh::ShaderVariable *> uniformMap;
+ using BlockAndFieldPair = std::pair<const sh::InterfaceBlock *, const sh::ShaderVariable *>;
+ angle::HashMap<std::string, std::vector<BlockAndFieldPair>> uniformBlockFieldMap;
+
+ for (ShaderType shaderType : kAllGraphicsShaderTypes)
+ {
+ if (!linkingVariables.isShaderStageUsedBitset[shaderType])
+ {
+ continue;
+ }
+
+ // Build a map of Uniforms
+ const std::vector<sh::ShaderVariable> &uniforms = linkingVariables.uniforms[shaderType];
+ for (const auto &uniform : uniforms)
+ {
+ uniformMap[uniform.name] = &uniform;
+ }
+
+ // Build a map of Uniform Blocks
+ // This will also detect any field name conflicts between Uniform Blocks without instance
+ // names
+ const std::vector<sh::InterfaceBlock> &uniformBlocks =
+ linkingVariables.uniformBlocks[shaderType];
+
+ for (const auto &uniformBlock : uniformBlocks)
+ {
+ // Only uniform blocks without an instance name can create a conflict with their field
+ // names
+ if (!uniformBlock.instanceName.empty())
+ {
+ continue;
+ }
+
+ for (const auto &field : uniformBlock.fields)
+ {
+ if (!uniformBlockFieldMap.count(field.name))
+ {
+ // First time we've seen this uniform block field name, so add the
+ // (Uniform Block, Field) pair immediately since there can't be a conflict yet
+ BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field);
+ std::vector<BlockAndFieldPair> newUniformBlockList;
+ newUniformBlockList.push_back(blockAndFieldPair);
+ uniformBlockFieldMap[field.name] = newUniformBlockList;
+ continue;
+ }
+
+ // We've seen this name before.
+ // We need to check each of the uniform blocks that contain a field with this name
+ // to see if there's a conflict or not.
+ std::vector<BlockAndFieldPair> prevBlockFieldPairs =
+ uniformBlockFieldMap[field.name];
+ for (const auto &prevBlockFieldPair : prevBlockFieldPairs)
+ {
+ const sh::InterfaceBlock *prevUniformBlock = prevBlockFieldPair.first;
+ const sh::ShaderVariable *prevUniformBlockField = prevBlockFieldPair.second;
+
+ if (uniformBlock.isSameInterfaceBlockAtLinkTime(*prevUniformBlock))
+ {
+ // The same uniform block should, by definition, contain the same field name
+ continue;
+ }
+
+ // The uniform blocks don't match, so check if the necessary field properties
+ // also match
+ if ((field.name == prevUniformBlockField->name) &&
+ (field.type == prevUniformBlockField->type) &&
+ (field.precision == prevUniformBlockField->precision))
+ {
+ infoLog << "Name conflicts between uniform block field names: "
+ << field.name;
+ return false;
+ }
+ }
+
+ // No conflict, so record this pair
+ BlockAndFieldPair blockAndFieldPair(&uniformBlock, &field);
+ uniformBlockFieldMap[field.name].push_back(blockAndFieldPair);
+ }
+ }
+ }
+
+ // Validate no uniform names conflict with attribute names
+ if (linkingVariables.isShaderStageUsedBitset[ShaderType::Vertex])
+ {
+ // ESSL 3.00.6 section 4.3.5:
+ // If a uniform variable name is declared in one stage (e.g., a vertex shader)
+ // but not in another (e.g., a fragment shader), then that name is still
+ // available in the other stage for a different use.
+ std::unordered_set<std::string> uniforms;
+ for (const sh::ShaderVariable &uniform : linkingVariables.uniforms[ShaderType::Vertex])
+ {
+ uniforms.insert(uniform.name);
+ }
+ for (const auto &attrib : executable.getProgramInputs())
+ {
+ if (uniforms.count(attrib.name))
+ {
+ infoLog << "Name conflicts between a uniform and an attribute: " << attrib.name;
+ return false;
+ }
+ }
+ }
+
+ // Validate no Uniform Block fields conflict with other Uniforms
+ for (const auto &uniformBlockField : uniformBlockFieldMap)
+ {
+ const std::string &fieldName = uniformBlockField.first;
+ if (uniformMap.count(fieldName))
+ {
+ infoLog << "Name conflicts between a uniform and a uniform block field: " << fieldName;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// [OpenGL ES 3.2] Chapter 7.4.1 "Shader Interface Matching"
+bool LinkValidateShaderInterfaceMatching(const std::vector<sh::ShaderVariable> &outputVaryings,
+ const std::vector<sh::ShaderVariable> &inputVaryings,
+ ShaderType frontShaderType,
+ ShaderType backShaderType,
+ int frontShaderVersion,
+ int backShaderVersion,
+ bool isSeparable,
+ gl::InfoLog &infoLog)
+{
+ ASSERT(frontShaderVersion == backShaderVersion);
+
+ std::vector<const sh::ShaderVariable *> filteredInputVaryings;
+ std::vector<const sh::ShaderVariable *> filteredOutputVaryings;
+
+ GetFilteredVaryings(inputVaryings, &filteredInputVaryings);
+ GetFilteredVaryings(outputVaryings, &filteredOutputVaryings);
+
+ // Separable programs require the number of inputs and outputs match
+ if (isSeparable && filteredInputVaryings.size() < filteredOutputVaryings.size())
+ {
+ infoLog << GetShaderTypeString(backShaderType)
+ << " does not consume all varyings generated by "
+ << GetShaderTypeString(frontShaderType);
+ return false;
+ }
+ if (isSeparable && filteredInputVaryings.size() > filteredOutputVaryings.size())
+ {
+ infoLog << GetShaderTypeString(frontShaderType)
+ << " does not generate all varyings consumed by "
+ << GetShaderTypeString(backShaderType);
+ return false;
+ }
+
+ // All inputs must match all outputs
+ for (const sh::ShaderVariable *input : filteredInputVaryings)
+ {
+ bool match = false;
+ for (const sh::ShaderVariable *output : filteredOutputVaryings)
+ {
+ if (DoShaderVariablesMatch(frontShaderVersion, frontShaderType, backShaderType, *input,
+ *output, isSeparable, infoLog))
+ {
+ match = true;
+ break;
+ }
+ }
+
+ // We permit unmatched, unreferenced varyings. Note that this specifically depends on
+ // whether the input is statically used - a statically used input should fail this test even
+ // if it is not active. GLSL ES 3.00.6 section 4.3.10.
+ if (!match && input->staticUse)
+ {
+ const std::string &name =
+ input->isShaderIOBlock ? input->structOrBlockName : input->name;
+ infoLog << GetShaderTypeString(backShaderType) << " varying " << name
+ << " does not match any " << GetShaderTypeString(frontShaderType) << " varying";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+LinkMismatchError LinkValidateProgramVariables(const sh::ShaderVariable &variable1,
+ const sh::ShaderVariable &variable2,
+ bool validatePrecision,
+ bool treatVariable1AsNonArray,
+ bool treatVariable2AsNonArray,
+ std::string *mismatchedStructOrBlockMemberName)
+{
+ if (variable1.type != variable2.type)
+ {
+ return LinkMismatchError::TYPE_MISMATCH;
+ }
+
+ bool variable1IsArray = variable1.isArray();
+ bool variable2IsArray = variable2.isArray();
+ if (treatVariable1AsNonArray)
+ {
+ ASSERT(variable1IsArray);
+ variable1IsArray = false;
+ }
+ if (treatVariable2AsNonArray)
+ {
+ ASSERT(variable2IsArray);
+ variable2IsArray = false;
+ }
+ // TODO(anglebug.com/5557): Investigate interactions with arrays-of-arrays.
+ if (variable1IsArray != variable2IsArray)
+ {
+ return LinkMismatchError::ARRAYNESS_MISMATCH;
+ }
+ if (!treatVariable1AsNonArray && !treatVariable2AsNonArray &&
+ variable1.arraySizes != variable2.arraySizes)
+ {
+ return LinkMismatchError::ARRAY_SIZE_MISMATCH;
+ }
+ if (validatePrecision && variable1.precision != variable2.precision)
+ {
+ return LinkMismatchError::PRECISION_MISMATCH;
+ }
+ if (!variable1.isShaderIOBlock && !variable2.isShaderIOBlock &&
+ variable1.structOrBlockName != variable2.structOrBlockName)
+ {
+ return LinkMismatchError::STRUCT_NAME_MISMATCH;
+ }
+ if (variable1.imageUnitFormat != variable2.imageUnitFormat)
+ {
+ return LinkMismatchError::FORMAT_MISMATCH;
+ }
+
+ if (variable1.fields.size() != variable2.fields.size())
+ {
+ return LinkMismatchError::FIELD_NUMBER_MISMATCH;
+ }
+ const unsigned int numMembers = static_cast<unsigned int>(variable1.fields.size());
+ for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++)
+ {
+ const sh::ShaderVariable &member1 = variable1.fields[memberIndex];
+ const sh::ShaderVariable &member2 = variable2.fields[memberIndex];
+
+ if (member1.name != member2.name)
+ {
+ return LinkMismatchError::FIELD_NAME_MISMATCH;
+ }
+
+ if (member1.interpolation != member2.interpolation)
+ {
+ return LinkMismatchError::INTERPOLATION_TYPE_MISMATCH;
+ }
+
+ if (variable1.isShaderIOBlock && variable2.isShaderIOBlock)
+ {
+ if (member1.location != member2.location)
+ {
+ return LinkMismatchError::FIELD_LOCATION_MISMATCH;
+ }
+
+ if (member1.structOrBlockName != member2.structOrBlockName)
+ {
+ return LinkMismatchError::FIELD_STRUCT_NAME_MISMATCH;
+ }
+ }
+
+ LinkMismatchError linkErrorOnField = LinkValidateProgramVariables(
+ member1, member2, validatePrecision, false, false, mismatchedStructOrBlockMemberName);
+ if (linkErrorOnField != LinkMismatchError::NO_MISMATCH)
+ {
+ AddProgramVariableParentPrefix(member1.name, mismatchedStructOrBlockMemberName);
+ return linkErrorOnField;
+ }
+ }
+
+ return LinkMismatchError::NO_MISMATCH;
+}
+
+void AddProgramVariableParentPrefix(const std::string &parentName, std::string *mismatchedFieldName)
+{
+ ASSERT(mismatchedFieldName);
+ if (mismatchedFieldName->empty())
+ {
+ *mismatchedFieldName = parentName;
+ }
+ else
+ {
+ std::ostringstream stream;
+ stream << parentName << "." << *mismatchedFieldName;
+ *mismatchedFieldName = stream.str();
+ }
+}
+
+bool LinkValidateBuiltInVaryingsInvariant(const std::vector<sh::ShaderVariable> &vertexVaryings,
+ const std::vector<sh::ShaderVariable> &fragmentVaryings,
+ int vertexShaderVersion,
+ InfoLog &infoLog)
+{
+ bool glPositionIsInvariant = false;
+ bool glPointSizeIsInvariant = false;
+ bool glFragCoordIsInvariant = false;
+ bool glPointCoordIsInvariant = false;
+
+ for (const sh::ShaderVariable &varying : vertexVaryings)
+ {
+ if (!varying.isBuiltIn())
+ {
+ continue;
+ }
+ if (varying.name.compare("gl_Position") == 0)
+ {
+ glPositionIsInvariant = varying.isInvariant;
+ }
+ else if (varying.name.compare("gl_PointSize") == 0)
+ {
+ glPointSizeIsInvariant = varying.isInvariant;
+ }
+ }
+
+ for (const sh::ShaderVariable &varying : fragmentVaryings)
+ {
+ if (!varying.isBuiltIn())
+ {
+ continue;
+ }
+ if (varying.name.compare("gl_FragCoord") == 0)
+ {
+ glFragCoordIsInvariant = varying.isInvariant;
+ }
+ else if (varying.name.compare("gl_PointCoord") == 0)
+ {
+ glPointCoordIsInvariant = varying.isInvariant;
+ }
+ }
+
+ // There is some ambiguity in ESSL 1.00.17 paragraph 4.6.4 interpretation,
+ // for example, https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13842.
+ // Not requiring invariance to match is supported by:
+ // dEQP, WebGL CTS, Nexus 5X GLES
+ if (glFragCoordIsInvariant && !glPositionIsInvariant)
+ {
+ infoLog << "gl_FragCoord can only be declared invariant if and only if gl_Position is "
+ "declared invariant.";
+ return false;
+ }
+ if (glPointCoordIsInvariant && !glPointSizeIsInvariant)
+ {
+ infoLog << "gl_PointCoord can only be declared invariant if and only if gl_PointSize is "
+ "declared invariant.";
+ return false;
+ }
+
+ return true;
+}
+
+bool LinkValidateBuiltInVaryings(const std::vector<sh::ShaderVariable> &outputVaryings,
+ const std::vector<sh::ShaderVariable> &inputVaryings,
+ ShaderType outputShaderType,
+ ShaderType inputShaderType,
+ int outputShaderVersion,
+ int inputShaderVersion,
+ InfoLog &infoLog)
+{
+ ASSERT(outputShaderVersion == inputShaderVersion);
+
+ // Only ESSL 1.0 has restrictions on matching input and output invariance
+ if (inputShaderVersion == 100 && outputShaderType == ShaderType::Vertex &&
+ inputShaderType == ShaderType::Fragment)
+ {
+ return LinkValidateBuiltInVaryingsInvariant(outputVaryings, inputVaryings,
+ outputShaderVersion, infoLog);
+ }
+
+ uint32_t sizeClipDistance = 0;
+ uint32_t sizeCullDistance = 0;
+
+ for (const sh::ShaderVariable &varying : outputVaryings)
+ {
+ if (!varying.isBuiltIn())
+ {
+ continue;
+ }
+ if (varying.name.compare("gl_ClipDistance") == 0)
+ {
+ sizeClipDistance = varying.getOutermostArraySize();
+ }
+ else if (varying.name.compare("gl_CullDistance") == 0)
+ {
+ sizeCullDistance = varying.getOutermostArraySize();
+ }
+ }
+
+ for (const sh::ShaderVariable &varying : inputVaryings)
+ {
+ if (!varying.isBuiltIn())
+ {
+ continue;
+ }
+ if (varying.name.compare("gl_ClipDistance") == 0)
+ {
+ if (sizeClipDistance != varying.getOutermostArraySize())
+ {
+ infoLog << "If either shader redeclares the built-in arrays gl_ClipDistance[] the "
+ "array must have the same size in both shaders.";
+ return false;
+ }
+ }
+ else if (varying.name.compare("gl_CullDistance") == 0)
+ {
+ if (sizeCullDistance != varying.getOutermostArraySize())
+ {
+ infoLog << "If either shader redeclares the built-in arrays gl_CullDistance[] the "
+ "array must have the same size in both shaders.";
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+void LogAmbiguousFieldLinkMismatch(InfoLog &infoLog,
+ const std::string &blockName1,
+ const std::string &blockName2,
+ const std::string &fieldName,
+ ShaderType shaderType1,
+ ShaderType shaderType2)
+{
+ infoLog << "Ambiguous field '" << fieldName << "' in blocks '" << blockName1 << "' ("
+ << GetShaderTypeString(shaderType1) << " shader) and '" << blockName2 << "' ("
+ << GetShaderTypeString(shaderType2) << " shader) which don't have instance names.";
+}
+
+bool ValidateInstancelessGraphicsInterfaceBlocksPerShader(
+ const std::vector<sh::InterfaceBlock> &interfaceBlocks,
+ ShaderType shaderType,
+ InterfaceBlockMap *instancelessBlocksFields,
+ InfoLog &infoLog)
+{
+ ASSERT(instancelessBlocksFields);
+
+ for (const sh::InterfaceBlock &block : interfaceBlocks)
+ {
+ if (!block.instanceName.empty())
+ {
+ continue;
+ }
+
+ for (const sh::ShaderVariable &field : block.fields)
+ {
+ const auto &entry = instancelessBlocksFields->find(field.name);
+ if (entry != instancelessBlocksFields->end())
+ {
+ const sh::InterfaceBlock &linkedBlock = *(entry->second.second);
+ if (block.name != linkedBlock.name)
+ {
+ LogAmbiguousFieldLinkMismatch(infoLog, block.name, linkedBlock.name, field.name,
+ entry->second.first, shaderType);
+ return false;
+ }
+ }
+ else
+ {
+ (*instancelessBlocksFields)[field.name] = std::make_pair(shaderType, &block);
+ }
+ }
+ }
+
+ return true;
+}
+
+LinkMismatchError LinkValidateInterfaceBlockFields(const sh::ShaderVariable &blockField1,
+ const sh::ShaderVariable &blockField2,
+ bool webglCompatibility,
+ std::string *mismatchedBlockFieldName)
+{
+ if (blockField1.name != blockField2.name)
+ {
+ return LinkMismatchError::FIELD_NAME_MISMATCH;
+ }
+
+ // If webgl, validate precision of UBO fields, otherwise don't. See Khronos bug 10287.
+ LinkMismatchError linkError = LinkValidateProgramVariables(
+ blockField1, blockField2, webglCompatibility, false, false, mismatchedBlockFieldName);
+ if (linkError != LinkMismatchError::NO_MISMATCH)
+ {
+ AddProgramVariableParentPrefix(blockField1.name, mismatchedBlockFieldName);
+ return linkError;
+ }
+
+ if (blockField1.isRowMajorLayout != blockField2.isRowMajorLayout)
+ {
+ AddProgramVariableParentPrefix(blockField1.name, mismatchedBlockFieldName);
+ return LinkMismatchError::MATRIX_PACKING_MISMATCH;
+ }
+
+ return LinkMismatchError::NO_MISMATCH;
+}
+
+LinkMismatchError AreMatchingInterfaceBlocks(const sh::InterfaceBlock &interfaceBlock1,
+ const sh::InterfaceBlock &interfaceBlock2,
+ bool webglCompatibility,
+ std::string *mismatchedBlockFieldName)
+{
+ // validate blocks for the same member types
+ if (interfaceBlock1.fields.size() != interfaceBlock2.fields.size())
+ {
+ return LinkMismatchError::FIELD_NUMBER_MISMATCH;
+ }
+ if (interfaceBlock1.arraySize != interfaceBlock2.arraySize)
+ {
+ return LinkMismatchError::ARRAY_SIZE_MISMATCH;
+ }
+ if (interfaceBlock1.layout != interfaceBlock2.layout ||
+ interfaceBlock1.binding != interfaceBlock2.binding)
+ {
+ return LinkMismatchError::LAYOUT_QUALIFIER_MISMATCH;
+ }
+ if (interfaceBlock1.instanceName.empty() != interfaceBlock2.instanceName.empty())
+ {
+ return LinkMismatchError::INSTANCE_NAME_MISMATCH;
+ }
+ const unsigned int numBlockMembers = static_cast<unsigned int>(interfaceBlock1.fields.size());
+ for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
+ {
+ const sh::ShaderVariable &member1 = interfaceBlock1.fields[blockMemberIndex];
+ const sh::ShaderVariable &member2 = interfaceBlock2.fields[blockMemberIndex];
+
+ LinkMismatchError linkError = LinkValidateInterfaceBlockFields(
+ member1, member2, webglCompatibility, mismatchedBlockFieldName);
+ if (linkError != LinkMismatchError::NO_MISMATCH)
+ {
+ return linkError;
+ }
+ }
+ return LinkMismatchError::NO_MISMATCH;
+}
+
+void InitializeInterfaceBlockMap(const std::vector<sh::InterfaceBlock> &interfaceBlocks,
+ ShaderType shaderType,
+ InterfaceBlockMap *linkedInterfaceBlocks)
+{
+ ASSERT(linkedInterfaceBlocks);
+
+ for (const sh::InterfaceBlock &interfaceBlock : interfaceBlocks)
+ {
+ (*linkedInterfaceBlocks)[interfaceBlock.name] = std::make_pair(shaderType, &interfaceBlock);
+ }
+}
+
+bool ValidateGraphicsInterfaceBlocksPerShader(
+ const std::vector<sh::InterfaceBlock> &interfaceBlocksToLink,
+ ShaderType shaderType,
+ bool webglCompatibility,
+ InterfaceBlockMap *linkedBlocks,
+ InfoLog &infoLog)
+{
+ ASSERT(linkedBlocks);
+
+ for (const sh::InterfaceBlock &block : interfaceBlocksToLink)
+ {
+ const auto &entry = linkedBlocks->find(block.name);
+ if (entry != linkedBlocks->end())
+ {
+ const sh::InterfaceBlock &linkedBlock = *(entry->second.second);
+ std::string mismatchedStructFieldName;
+ LinkMismatchError linkError = AreMatchingInterfaceBlocks(
+ block, linkedBlock, webglCompatibility, &mismatchedStructFieldName);
+ if (linkError != LinkMismatchError::NO_MISMATCH)
+ {
+ LogLinkMismatch(infoLog, block.name, GetInterfaceBlockTypeString(block.blockType),
+ linkError, mismatchedStructFieldName, entry->second.first,
+ shaderType);
+ return false;
+ }
+ }
+ else
+ {
+ (*linkedBlocks)[block.name] = std::make_pair(shaderType, &block);
+ }
+ }
+
+ return true;
+}
+
+bool ValidateInterfaceBlocksMatch(
+ GLuint numShadersHasInterfaceBlocks,
+ const ShaderMap<const std::vector<sh::InterfaceBlock> *> &shaderInterfaceBlocks,
+ InfoLog &infoLog,
+ bool webglCompatibility,
+ InterfaceBlockMap *instancelessInterfaceBlocksFields)
+{
+ for (ShaderType shaderType : kAllGraphicsShaderTypes)
+ {
+ // Validate that instanceless blocks of different names don't have fields of the same name.
+ if (shaderInterfaceBlocks[shaderType] &&
+ !ValidateInstancelessGraphicsInterfaceBlocksPerShader(
+ *shaderInterfaceBlocks[shaderType], shaderType, instancelessInterfaceBlocksFields,
+ infoLog))
+ {
+ return false;
+ }
+ }
+
+ if (numShadersHasInterfaceBlocks < 2u)
+ {
+ return true;
+ }
+
+ ASSERT(!shaderInterfaceBlocks[ShaderType::Compute]);
+
+ // Check that interface blocks defined in the graphics shaders are identical
+
+ InterfaceBlockMap linkedInterfaceBlocks;
+
+ bool interfaceBlockMapInitialized = false;
+ for (ShaderType shaderType : kAllGraphicsShaderTypes)
+ {
+ if (!shaderInterfaceBlocks[shaderType])
+ {
+ continue;
+ }
+
+ if (!interfaceBlockMapInitialized)
+ {
+ InitializeInterfaceBlockMap(*shaderInterfaceBlocks[shaderType], shaderType,
+ &linkedInterfaceBlocks);
+ interfaceBlockMapInitialized = true;
+ }
+ else if (!ValidateGraphicsInterfaceBlocksPerShader(*shaderInterfaceBlocks[shaderType],
+ shaderType, webglCompatibility,
+ &linkedInterfaceBlocks, infoLog))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool LinkValidateProgramInterfaceBlocks(const Context *context,
+ ShaderBitSet activeProgramStages,
+ const ProgramLinkedResources &resources,
+ InfoLog &infoLog,
+ GLuint *combinedShaderStorageBlocksCountOut)
+{
+ ASSERT(combinedShaderStorageBlocksCountOut);
+
+ const Caps &caps = context->getCaps();
+ const bool webglCompatibility = context->isWebGL();
+ const Version &version = context->getClientVersion();
+
+ GLuint combinedUniformBlocksCount = 0u;
+ GLuint numShadersHasUniformBlocks = 0u;
+ ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderUniformBlocks = {};
+ InterfaceBlockMap instancelessInterfaceBlocksFields;
+
+ for (ShaderType shaderType : activeProgramStages)
+ {
+ const std::vector<sh::InterfaceBlock> &uniformBlocks =
+ resources.uniformBlockLinker.getShaderBlocks(shaderType);
+ if (!uniformBlocks.empty())
+ {
+ if (!ValidateInterfaceBlocksCount(
+ static_cast<GLuint>(caps.maxShaderUniformBlocks[shaderType]), uniformBlocks,
+ shaderType, sh::BlockType::BLOCK_UNIFORM, &combinedUniformBlocksCount, infoLog))
+ {
+ return false;
+ }
+
+ allShaderUniformBlocks[shaderType] = &uniformBlocks;
+ ++numShadersHasUniformBlocks;
+ }
+ }
+
+ if (combinedUniformBlocksCount > static_cast<GLuint>(caps.maxCombinedUniformBlocks))
+ {
+ infoLog << "The sum of the number of active uniform blocks exceeds "
+ "MAX_COMBINED_UNIFORM_BLOCKS ("
+ << caps.maxCombinedUniformBlocks << ").";
+ return false;
+ }
+
+ if (!ValidateInterfaceBlocksMatch(numShadersHasUniformBlocks, allShaderUniformBlocks, infoLog,
+ webglCompatibility, &instancelessInterfaceBlocksFields))
+ {
+ return false;
+ }
+
+ if (version >= Version(3, 1))
+ {
+ *combinedShaderStorageBlocksCountOut = 0u;
+ GLuint numShadersHasShaderStorageBlocks = 0u;
+ ShaderMap<const std::vector<sh::InterfaceBlock> *> allShaderStorageBlocks = {};
+ for (ShaderType shaderType : activeProgramStages)
+ {
+ const std::vector<sh::InterfaceBlock> &shaderStorageBlocks =
+ resources.shaderStorageBlockLinker.getShaderBlocks(shaderType);
+ if (!shaderStorageBlocks.empty())
+ {
+ if (!ValidateInterfaceBlocksCount(
+ static_cast<GLuint>(caps.maxShaderStorageBlocks[shaderType]),
+ shaderStorageBlocks, shaderType, sh::BlockType::BLOCK_BUFFER,
+ combinedShaderStorageBlocksCountOut, infoLog))
+ {
+ return false;
+ }
+
+ allShaderStorageBlocks[shaderType] = &shaderStorageBlocks;
+ ++numShadersHasShaderStorageBlocks;
+ }
+ }
+
+ if (*combinedShaderStorageBlocksCountOut >
+ static_cast<GLuint>(caps.maxCombinedShaderStorageBlocks))
+ {
+ infoLog << "The sum of the number of active shader storage blocks exceeds "
+ "MAX_COMBINED_SHADER_STORAGE_BLOCKS ("
+ << caps.maxCombinedShaderStorageBlocks << ").";
+ return false;
+ }
+
+ if (!ValidateInterfaceBlocksMatch(numShadersHasShaderStorageBlocks, allShaderStorageBlocks,
+ infoLog, webglCompatibility,
+ &instancelessInterfaceBlocksFields))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/ProgramLinkedResources.h b/gfx/angle/checkout/src/libANGLE/ProgramLinkedResources.h
new file mode 100644
index 0000000000..0bb6cbb96f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/ProgramLinkedResources.h
@@ -0,0 +1,333 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramLinkedResources.h: implements link-time checks for default block uniforms, and generates
+// uniform locations. Populates data structures related to uniforms so that they can be stored in
+// program state.
+
+#ifndef LIBANGLE_UNIFORMLINKER_H_
+#define LIBANGLE_UNIFORMLINKER_H_
+
+#include "angle_gl.h"
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/VaryingPacking.h"
+
+#include <functional>
+
+namespace sh
+{
+class BlockLayoutEncoder;
+struct BlockMemberInfo;
+struct InterfaceBlock;
+struct ShaderVariable;
+class BlockEncoderVisitor;
+class ShaderVariableVisitor;
+struct ShaderVariable;
+} // namespace sh
+
+namespace gl
+{
+struct BufferVariable;
+struct Caps;
+class Context;
+class InfoLog;
+struct InterfaceBlock;
+enum class LinkMismatchError;
+struct LinkedUniform;
+class ProgramState;
+class ProgramPipelineState;
+class ProgramBindings;
+class ProgramAliasedBindings;
+class Shader;
+struct ShaderVariableBuffer;
+struct UnusedUniform;
+struct VariableLocation;
+
+using AtomicCounterBuffer = ShaderVariableBuffer;
+using ShaderUniform = std::pair<ShaderType, const sh::ShaderVariable *>;
+
+class UniformLinker final : angle::NonCopyable
+{
+ public:
+ UniformLinker(const ShaderBitSet &activeShaderStages,
+ const ShaderMap<std::vector<sh::ShaderVariable>> &shaderUniforms);
+ ~UniformLinker();
+
+ bool link(const Caps &caps,
+ InfoLog &infoLog,
+ const ProgramAliasedBindings &uniformLocationBindings);
+
+ void getResults(std::vector<LinkedUniform> *uniforms,
+ std::vector<UnusedUniform> *unusedUniformsOutOrNull,
+ std::vector<VariableLocation> *uniformLocationsOutOrNull);
+
+ private:
+ bool validateGraphicsUniforms(InfoLog &infoLog) const;
+ bool validateGraphicsUniformsPerShader(ShaderType shaderToLink,
+ bool extendLinkedUniforms,
+ std::map<std::string, ShaderUniform> *linkedUniforms,
+ InfoLog &infoLog) const;
+ bool flattenUniformsAndCheckCapsForShader(ShaderType shaderType,
+ const Caps &caps,
+ std::vector<LinkedUniform> &samplerUniforms,
+ std::vector<LinkedUniform> &imageUniforms,
+ std::vector<LinkedUniform> &atomicCounterUniforms,
+ std::vector<LinkedUniform> &inputAttachmentUniforms,
+ std::vector<UnusedUniform> &unusedUniforms,
+ InfoLog &infoLog);
+
+ bool flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog);
+ bool checkMaxCombinedAtomicCounters(const Caps &caps, InfoLog &infoLog);
+
+ bool indexUniforms(InfoLog &infoLog, const ProgramAliasedBindings &uniformLocationBindings);
+ bool gatherUniformLocationsAndCheckConflicts(
+ InfoLog &infoLog,
+ const ProgramAliasedBindings &uniformLocationBindings,
+ std::set<GLuint> *ignoredLocations,
+ int *maxUniformLocation);
+ void pruneUnusedUniforms();
+
+ ShaderBitSet mActiveShaderStages;
+ const ShaderMap<std::vector<sh::ShaderVariable>> &mShaderUniforms;
+ std::vector<LinkedUniform> mUniforms;
+ std::vector<UnusedUniform> mUnusedUniforms;
+ std::vector<VariableLocation> mUniformLocations;
+};
+
+using GetBlockSizeFunc = std::function<
+ bool(const std::string &blockName, const std::string &blockMappedName, size_t *sizeOut)>;
+using GetBlockMemberInfoFunc = std::function<
+ bool(const std::string &name, const std::string &mappedName, sh::BlockMemberInfo *infoOut)>;
+
+// This class is intended to be used during the link step to store interface block information.
+// It is called by the Impl class during ProgramImpl::link so that it has access to the
+// real block size and layout.
+class InterfaceBlockLinker : angle::NonCopyable
+{
+ public:
+ virtual ~InterfaceBlockLinker();
+
+ // This is called once per shader stage. It stores a pointer to the block vector, so it's
+ // important that this class does not persist longer than the duration of Program::link.
+ void addShaderBlocks(ShaderType shader, const std::vector<sh::InterfaceBlock> *blocks);
+
+ // This is called once during a link operation, after all shader blocks are added.
+ void linkBlocks(const GetBlockSizeFunc &getBlockSize,
+ const GetBlockMemberInfoFunc &getMemberInfo) const;
+
+ const std::vector<sh::InterfaceBlock> &getShaderBlocks(ShaderType shaderType) const
+ {
+ ASSERT(mShaderBlocks[shaderType]);
+ return *mShaderBlocks[shaderType];
+ }
+
+ protected:
+ InterfaceBlockLinker();
+ void init(std::vector<InterfaceBlock> *blocksOut,
+ std::vector<std::string> *unusedInterfaceBlocksOut);
+ void defineInterfaceBlock(const GetBlockSizeFunc &getBlockSize,
+ const GetBlockMemberInfoFunc &getMemberInfo,
+ const sh::InterfaceBlock &interfaceBlock,
+ ShaderType shaderType) const;
+
+ virtual size_t getCurrentBlockMemberIndex() const = 0;
+
+ virtual sh::ShaderVariableVisitor *getVisitor(const GetBlockMemberInfoFunc &getMemberInfo,
+ const std::string &namePrefix,
+ const std::string &mappedNamePrefix,
+ ShaderType shaderType,
+ int blockIndex) const = 0;
+
+ ShaderMap<const std::vector<sh::InterfaceBlock> *> mShaderBlocks = {};
+
+ std::vector<InterfaceBlock> *mBlocksOut = nullptr;
+ std::vector<std::string> *mUnusedInterfaceBlocksOut = nullptr;
+};
+
+class UniformBlockLinker final : public InterfaceBlockLinker
+{
+ public:
+ UniformBlockLinker();
+ ~UniformBlockLinker() override;
+
+ void init(std::vector<InterfaceBlock> *blocksOut,
+ std::vector<LinkedUniform> *uniformsOut,
+ std::vector<std::string> *unusedInterfaceBlocksOut);
+
+ private:
+ size_t getCurrentBlockMemberIndex() const override;
+
+ sh::ShaderVariableVisitor *getVisitor(const GetBlockMemberInfoFunc &getMemberInfo,
+ const std::string &namePrefix,
+ const std::string &mappedNamePrefix,
+ ShaderType shaderType,
+ int blockIndex) const override;
+
+ std::vector<LinkedUniform> *mUniformsOut = nullptr;
+};
+
+class ShaderStorageBlockLinker final : public InterfaceBlockLinker
+{
+ public:
+ ShaderStorageBlockLinker();
+ ~ShaderStorageBlockLinker() override;
+
+ void init(std::vector<InterfaceBlock> *blocksOut,
+ std::vector<BufferVariable> *bufferVariablesOut,
+ std::vector<std::string> *unusedInterfaceBlocksOut);
+
+ private:
+ size_t getCurrentBlockMemberIndex() const override;
+
+ sh::ShaderVariableVisitor *getVisitor(const GetBlockMemberInfoFunc &getMemberInfo,
+ const std::string &namePrefix,
+ const std::string &mappedNamePrefix,
+ ShaderType shaderType,
+ int blockIndex) const override;
+
+ std::vector<BufferVariable> *mBufferVariablesOut = nullptr;
+};
+
+class AtomicCounterBufferLinker final : angle::NonCopyable
+{
+ public:
+ AtomicCounterBufferLinker();
+ ~AtomicCounterBufferLinker();
+
+ void init(std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut);
+ void link(const std::map<int, unsigned int> &sizeMap) const;
+
+ private:
+ std::vector<AtomicCounterBuffer> *mAtomicCounterBuffersOut = nullptr;
+};
+
+// The link operation is responsible for finishing the link of uniform and interface blocks.
+// This way it can filter out unreferenced resources and still have access to the info.
+// TODO(jmadill): Integrate uniform linking/filtering as well as interface blocks.
+struct UnusedUniform
+{
+ UnusedUniform(std::string name,
+ bool isSampler,
+ bool isImage,
+ bool isAtomicCounter,
+ bool isFragmentInOut)
+ {
+ this->name = name;
+ this->isSampler = isSampler;
+ this->isImage = isImage;
+ this->isAtomicCounter = isAtomicCounter;
+ this->isFragmentInOut = isFragmentInOut;
+ }
+
+ std::string name;
+ bool isSampler;
+ bool isImage;
+ bool isAtomicCounter;
+ bool isFragmentInOut;
+};
+
+struct ProgramLinkedResources
+{
+ ProgramLinkedResources();
+ ~ProgramLinkedResources();
+
+ void init(std::vector<InterfaceBlock> *uniformBlocksOut,
+ std::vector<LinkedUniform> *uniformsOut,
+ std::vector<InterfaceBlock> *shaderStorageBlocksOut,
+ std::vector<BufferVariable> *bufferVariablesOut,
+ std::vector<AtomicCounterBuffer> *atomicCounterBuffersOut);
+
+ ProgramVaryingPacking varyingPacking;
+ UniformBlockLinker uniformBlockLinker;
+ ShaderStorageBlockLinker shaderStorageBlockLinker;
+ AtomicCounterBufferLinker atomicCounterBufferLinker;
+ std::vector<UnusedUniform> unusedUniforms;
+ std::vector<std::string> unusedInterfaceBlocks;
+};
+
+struct LinkingVariables final : private angle::NonCopyable
+{
+ LinkingVariables(const Context *context, const ProgramState &state);
+ LinkingVariables(const ProgramPipelineState &state);
+ ~LinkingVariables();
+
+ ShaderMap<std::vector<sh::ShaderVariable>> outputVaryings;
+ ShaderMap<std::vector<sh::ShaderVariable>> inputVaryings;
+ ShaderMap<std::vector<sh::ShaderVariable>> uniforms;
+ ShaderMap<std::vector<sh::InterfaceBlock>> uniformBlocks;
+ ShaderBitSet isShaderStageUsedBitset;
+};
+
+class CustomBlockLayoutEncoderFactory : angle::NonCopyable
+{
+ public:
+ virtual ~CustomBlockLayoutEncoderFactory() {}
+
+ virtual sh::BlockLayoutEncoder *makeEncoder() = 0;
+};
+
+// Used by the backends in Program*::linkResources to parse interface blocks and provide
+// information to ProgramLinkedResources' linkers.
+class ProgramLinkedResourcesLinker final : angle::NonCopyable
+{
+ public:
+ ProgramLinkedResourcesLinker(CustomBlockLayoutEncoderFactory *customEncoderFactory)
+ : mCustomEncoderFactory(customEncoderFactory)
+ {}
+
+ void linkResources(const Context *context,
+ const ProgramState &programState,
+ const ProgramLinkedResources &resources) const;
+
+ private:
+ void getAtomicCounterBufferSizeMap(const ProgramState &programState,
+ std::map<int, unsigned int> &sizeMapOut) const;
+
+ CustomBlockLayoutEncoderFactory *mCustomEncoderFactory;
+};
+
+using ShaderInterfaceBlock = std::pair<ShaderType, const sh::InterfaceBlock *>;
+using InterfaceBlockMap = std::map<std::string, ShaderInterfaceBlock>;
+
+bool LinkValidateProgramGlobalNames(InfoLog &infoLog,
+ const ProgramExecutable &executable,
+ const LinkingVariables &linkingVariables);
+bool LinkValidateShaderInterfaceMatching(const std::vector<sh::ShaderVariable> &outputVaryings,
+ const std::vector<sh::ShaderVariable> &inputVaryings,
+ ShaderType frontShaderType,
+ ShaderType backShaderType,
+ int frontShaderVersion,
+ int backShaderVersion,
+ bool isSeparable,
+ InfoLog &infoLog);
+bool LinkValidateBuiltInVaryingsInvariant(const std::vector<sh::ShaderVariable> &vertexVaryings,
+ const std::vector<sh::ShaderVariable> &fragmentVaryings,
+ int vertexShaderVersion,
+ InfoLog &infoLog);
+bool LinkValidateBuiltInVaryings(const std::vector<sh::ShaderVariable> &inputVaryings,
+ const std::vector<sh::ShaderVariable> &outputVaryings,
+ ShaderType inputShaderType,
+ ShaderType outputShaderType,
+ int inputShaderVersion,
+ int outputShaderVersion,
+ InfoLog &infoLog);
+LinkMismatchError LinkValidateProgramVariables(const sh::ShaderVariable &variable1,
+ const sh::ShaderVariable &variable2,
+ bool validatePrecision,
+ bool treatVariable1AsNonArray,
+ bool treatVariable2AsNonArray,
+ std::string *mismatchedStructOrBlockMemberName);
+void AddProgramVariableParentPrefix(const std::string &parentName,
+ std::string *mismatchedFieldName);
+bool LinkValidateProgramInterfaceBlocks(const Context *context,
+ ShaderBitSet activeProgramStages,
+ const ProgramLinkedResources &resources,
+ InfoLog &infoLog,
+ GLuint *combinedShaderStorageBlocksCountOut);
+} // namespace gl
+
+#endif // LIBANGLE_UNIFORMLINKER_H_
diff --git a/gfx/angle/checkout/src/libANGLE/ProgramPipeline.cpp b/gfx/angle/checkout/src/libANGLE/ProgramPipeline.cpp
new file mode 100644
index 0000000000..1675b06705
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/ProgramPipeline.cpp
@@ -0,0 +1,721 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramPipeline.cpp: Implements the gl::ProgramPipeline class.
+// Implements GL program pipeline objects and related functionality.
+// [OpenGL ES 3.1] section 7.4 page 105.
+
+#include "libANGLE/ProgramPipeline.h"
+
+#include <algorithm>
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/ProgramPipelineImpl.h"
+
+namespace gl
+{
+
+enum SubjectIndexes : angle::SubjectIndex
+{
+ kExecutableSubjectIndex = 0
+};
+
+ProgramPipelineState::ProgramPipelineState()
+ : mLabel(),
+ mActiveShaderProgram(nullptr),
+ mValid(false),
+ mExecutable(new ProgramExecutable()),
+ mIsLinked(false)
+{
+ for (const ShaderType shaderType : gl::AllShaderTypes())
+ {
+ mPrograms[shaderType] = nullptr;
+ }
+}
+
+ProgramPipelineState::~ProgramPipelineState()
+{
+ SafeDelete(mExecutable);
+}
+
+const std::string &ProgramPipelineState::getLabel() const
+{
+ return mLabel;
+}
+
+void ProgramPipelineState::activeShaderProgram(Program *shaderProgram)
+{
+ mActiveShaderProgram = shaderProgram;
+}
+
+void ProgramPipelineState::useProgramStage(const Context *context,
+ const ShaderType shaderType,
+ Program *shaderProgram,
+ angle::ObserverBinding *programObserverBindings)
+{
+ Program *oldProgram = mPrograms[shaderType];
+ if (oldProgram)
+ {
+ oldProgram->release(context);
+ }
+
+ // If program refers to a program object with a valid shader attached for the indicated shader
+ // stage, glUseProgramStages installs the executable code for that stage in the indicated
+ // program pipeline object pipeline.
+ if (shaderProgram && (shaderProgram->id().value != 0) &&
+ shaderProgram->getExecutable().hasLinkedShaderStage(shaderType))
+ {
+ mPrograms[shaderType] = shaderProgram;
+ shaderProgram->addRef();
+ }
+ else
+ {
+ // If program is zero, or refers to a program object with no valid shader executable for the
+ // given stage, it is as if the pipeline object has no programmable stage configured for the
+ // indicated shader stage.
+ mPrograms[shaderType] = nullptr;
+ }
+
+ Program *program = mPrograms[shaderType];
+ programObserverBindings->bind(program);
+}
+
+void ProgramPipelineState::useProgramStages(
+ const Context *context,
+ const gl::ShaderBitSet &shaderTypes,
+ Program *shaderProgram,
+ std::vector<angle::ObserverBinding> *programObserverBindings)
+{
+ for (ShaderType shaderType : shaderTypes)
+ {
+ useProgramStage(context, shaderType, shaderProgram,
+ &programObserverBindings->at(static_cast<size_t>(shaderType)));
+ }
+}
+
+bool ProgramPipelineState::usesShaderProgram(ShaderProgramID programId) const
+{
+ for (const Program *program : mPrograms)
+ {
+ if (program && (program->id() == programId))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void ProgramPipelineState::updateExecutableTextures()
+{
+ for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
+ {
+ const Program *program = getShaderProgram(shaderType);
+ ASSERT(program);
+ mExecutable->setActiveTextureMask(mExecutable->getActiveSamplersMask() |
+ program->getExecutable().getActiveSamplersMask());
+ mExecutable->setActiveImagesMask(mExecutable->getActiveImagesMask() |
+ program->getExecutable().getActiveImagesMask());
+ // Updates mActiveSamplerRefCounts, mActiveSamplerTypes, and mActiveSamplerFormats
+ mExecutable->updateActiveSamplers(program->getState());
+ }
+}
+
+rx::SpecConstUsageBits ProgramPipelineState::getSpecConstUsageBits() const
+{
+ rx::SpecConstUsageBits specConstUsageBits;
+ for (const ShaderType shaderType : mExecutable->getLinkedShaderStages())
+ {
+ const Program *program = getShaderProgram(shaderType);
+ ASSERT(program);
+ specConstUsageBits |= program->getState().getSpecConstUsageBits();
+ }
+ return specConstUsageBits;
+}
+
+ProgramPipeline::ProgramPipeline(rx::GLImplFactory *factory, ProgramPipelineID handle)
+ : RefCountObject(factory->generateSerial(), handle),
+ mProgramPipelineImpl(factory->createProgramPipeline(mState)),
+ mExecutableObserverBinding(this, kExecutableSubjectIndex)
+{
+ ASSERT(mProgramPipelineImpl);
+
+ for (const ShaderType shaderType : gl::AllShaderTypes())
+ {
+ mProgramObserverBindings.emplace_back(this, static_cast<angle::SubjectIndex>(shaderType));
+ }
+ mExecutableObserverBinding.bind(mState.mExecutable);
+}
+
+ProgramPipeline::~ProgramPipeline()
+{
+ mProgramPipelineImpl.reset(nullptr);
+}
+
+void ProgramPipeline::onDestroy(const Context *context)
+{
+ for (Program *program : mState.mPrograms)
+ {
+ if (program)
+ {
+ ASSERT(program->getRefCount());
+ program->release(context);
+ }
+ }
+
+ getImplementation()->destroy(context);
+}
+
+angle::Result ProgramPipeline::setLabel(const Context *context, const std::string &label)
+{
+ mState.mLabel = label;
+
+ if (mProgramPipelineImpl)
+ {
+ return mProgramPipelineImpl->onLabelUpdate(context);
+ }
+ return angle::Result::Continue;
+}
+
+const std::string &ProgramPipeline::getLabel() const
+{
+ return mState.mLabel;
+}
+
+rx::ProgramPipelineImpl *ProgramPipeline::getImplementation() const
+{
+ return mProgramPipelineImpl.get();
+}
+
+void ProgramPipeline::activeShaderProgram(Program *shaderProgram)
+{
+ mState.activeShaderProgram(shaderProgram);
+}
+
+angle::Result ProgramPipeline::useProgramStages(const Context *context,
+ GLbitfield stages,
+ Program *shaderProgram)
+{
+ bool needToUpdatePipelineState = false;
+ gl::ShaderBitSet shaderTypes;
+ if (stages != GL_ALL_SHADER_BITS)
+ {
+ ASSERT(stages < 256u);
+ for (size_t singleShaderBit : angle::BitSet<8>(stages))
+ {
+ // Cast back to a bit after the iterator returns an index.
+ ShaderType shaderType = GetShaderTypeFromBitfield(angle::Bit<size_t>(singleShaderBit));
+ ASSERT(shaderType != ShaderType::InvalidEnum);
+ shaderTypes.set(shaderType);
+ }
+ }
+ else
+ {
+ shaderTypes.set();
+ }
+ ASSERT(shaderTypes.any());
+
+ for (ShaderType shaderType : shaderTypes)
+ {
+ if (mState.getShaderProgram(shaderType) != shaderProgram ||
+ (shaderProgram && shaderProgram->hasAnyDirtyBit()))
+ {
+ needToUpdatePipelineState = true;
+ break;
+ }
+ }
+
+ if (!needToUpdatePipelineState)
+ {
+ return angle::Result::Continue;
+ }
+
+ mState.useProgramStages(context, shaderTypes, shaderProgram, &mProgramObserverBindings);
+ updateLinkedShaderStages();
+
+ mState.mIsLinked = false;
+ onStateChange(angle::SubjectMessage::SubjectChanged);
+
+ return angle::Result::Continue;
+}
+
+void ProgramPipeline::updateLinkedShaderStages()
+{
+ mState.mExecutable->resetLinkedShaderStages();
+
+ for (const ShaderType shaderType : gl::AllShaderTypes())
+ {
+ Program *program = mState.mPrograms[shaderType];
+ if (program)
+ {
+ mState.mExecutable->setLinkedShaderStages(shaderType);
+ }
+ }
+
+ mState.mExecutable->updateCanDrawWith();
+}
+
+void ProgramPipeline::updateExecutableAttributes()
+{
+ Program *vertexProgram = getShaderProgram(gl::ShaderType::Vertex);
+
+ if (!vertexProgram)
+ {
+ return;
+ }
+
+ const ProgramExecutable &vertexExecutable = vertexProgram->getExecutable();
+ mState.mExecutable->mActiveAttribLocationsMask = vertexExecutable.mActiveAttribLocationsMask;
+ mState.mExecutable->mMaxActiveAttribLocation = vertexExecutable.mMaxActiveAttribLocation;
+ mState.mExecutable->mAttributesTypeMask = vertexExecutable.mAttributesTypeMask;
+ mState.mExecutable->mAttributesMask = vertexExecutable.mAttributesMask;
+ mState.mExecutable->mProgramInputs = vertexExecutable.mProgramInputs;
+}
+
+void ProgramPipeline::updateTransformFeedbackMembers()
+{
+ ShaderType lastVertexProcessingStage =
+ gl::GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
+ if (lastVertexProcessingStage == ShaderType::InvalidEnum)
+ {
+ return;
+ }
+
+ Program *shaderProgram = getShaderProgram(lastVertexProcessingStage);
+ ASSERT(shaderProgram);
+
+ const ProgramExecutable &lastPreFragmentExecutable = shaderProgram->getExecutable();
+ mState.mExecutable->mTransformFeedbackStrides =
+ lastPreFragmentExecutable.mTransformFeedbackStrides;
+ mState.mExecutable->mLinkedTransformFeedbackVaryings =
+ lastPreFragmentExecutable.mLinkedTransformFeedbackVaryings;
+}
+
+void ProgramPipeline::updateShaderStorageBlocks()
+{
+ mState.mExecutable->mShaderStorageBlocks.clear();
+
+ // Only copy the storage blocks from each Program in the PPO once, since each Program could
+ // contain multiple shader stages.
+ ShaderBitSet handledStages;
+
+ for (const gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ const Program *shaderProgram = getShaderProgram(shaderType);
+ if (shaderProgram && !handledStages.test(shaderType))
+ {
+ // Only add each Program's blocks once.
+ handledStages |= shaderProgram->getExecutable().getLinkedShaderStages();
+
+ for (const InterfaceBlock &block :
+ shaderProgram->getExecutable().getShaderStorageBlocks())
+ {
+ mState.mExecutable->mShaderStorageBlocks.emplace_back(block);
+ }
+ }
+ }
+}
+
+void ProgramPipeline::updateImageBindings()
+{
+ mState.mExecutable->mImageBindings.clear();
+ mState.mExecutable->mActiveImageShaderBits.fill({});
+
+ // Only copy the storage blocks from each Program in the PPO once, since each Program could
+ // contain multiple shader stages.
+ ShaderBitSet handledStages;
+
+ for (const gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ const Program *shaderProgram = getShaderProgram(shaderType);
+ if (shaderProgram && !handledStages.test(shaderType))
+ {
+ // Only add each Program's blocks once.
+ handledStages |= shaderProgram->getExecutable().getLinkedShaderStages();
+
+ for (const ImageBinding &imageBinding : shaderProgram->getState().getImageBindings())
+ {
+ mState.mExecutable->mImageBindings.emplace_back(imageBinding);
+ }
+
+ mState.mExecutable->updateActiveImages(shaderProgram->getExecutable());
+ }
+ }
+}
+
+void ProgramPipeline::updateExecutableGeometryProperties()
+{
+ Program *geometryProgram = getShaderProgram(gl::ShaderType::Geometry);
+
+ if (!geometryProgram)
+ {
+ return;
+ }
+
+ const ProgramExecutable &geometryExecutable = geometryProgram->getExecutable();
+ mState.mExecutable->mGeometryShaderInputPrimitiveType =
+ geometryExecutable.mGeometryShaderInputPrimitiveType;
+ mState.mExecutable->mGeometryShaderOutputPrimitiveType =
+ geometryExecutable.mGeometryShaderOutputPrimitiveType;
+ mState.mExecutable->mGeometryShaderInvocations = geometryExecutable.mGeometryShaderInvocations;
+ mState.mExecutable->mGeometryShaderMaxVertices = geometryExecutable.mGeometryShaderMaxVertices;
+}
+
+void ProgramPipeline::updateExecutableTessellationProperties()
+{
+ Program *tessControlProgram = getShaderProgram(gl::ShaderType::TessControl);
+ Program *tessEvalProgram = getShaderProgram(gl::ShaderType::TessEvaluation);
+
+ if (tessControlProgram)
+ {
+ const ProgramExecutable &tessControlExecutable = tessControlProgram->getExecutable();
+ mState.mExecutable->mTessControlShaderVertices =
+ tessControlExecutable.mTessControlShaderVertices;
+ }
+
+ if (tessEvalProgram)
+ {
+ const ProgramExecutable &tessEvalExecutable = tessEvalProgram->getExecutable();
+ mState.mExecutable->mTessGenMode = tessEvalExecutable.mTessGenMode;
+ mState.mExecutable->mTessGenSpacing = tessEvalExecutable.mTessGenSpacing;
+ mState.mExecutable->mTessGenVertexOrder = tessEvalExecutable.mTessGenVertexOrder;
+ mState.mExecutable->mTessGenPointMode = tessEvalExecutable.mTessGenPointMode;
+ }
+}
+
+void ProgramPipeline::updateFragmentInoutRangeAndEnablesPerSampleShading()
+{
+ Program *fragmentProgram = getShaderProgram(gl::ShaderType::Fragment);
+
+ if (!fragmentProgram)
+ {
+ return;
+ }
+
+ const ProgramExecutable &fragmentExecutable = fragmentProgram->getExecutable();
+ mState.mExecutable->mFragmentInoutRange = fragmentExecutable.mFragmentInoutRange;
+ mState.mExecutable->mHasDiscard = fragmentExecutable.mHasDiscard;
+ mState.mExecutable->mEnablesPerSampleShading = fragmentExecutable.mEnablesPerSampleShading;
+}
+
+void ProgramPipeline::updateLinkedVaryings()
+{
+ // Need to check all of the shader stages, not just linked, so we handle Compute correctly.
+ for (const gl::ShaderType shaderType : kAllGraphicsShaderTypes)
+ {
+ const Program *shaderProgram = getShaderProgram(shaderType);
+ if (shaderProgram && shaderProgram->isLinked())
+ {
+ const ProgramExecutable &executable = shaderProgram->getExecutable();
+ mState.mExecutable->mLinkedOutputVaryings[shaderType] =
+ executable.getLinkedOutputVaryings(shaderType);
+ mState.mExecutable->mLinkedInputVaryings[shaderType] =
+ executable.getLinkedInputVaryings(shaderType);
+ }
+ }
+
+ const Program *computeProgram = getShaderProgram(ShaderType::Compute);
+ if (computeProgram && computeProgram->isLinked())
+ {
+ const ProgramExecutable &executable = computeProgram->getExecutable();
+ mState.mExecutable->mLinkedOutputVaryings[ShaderType::Compute] =
+ executable.getLinkedOutputVaryings(ShaderType::Compute);
+ mState.mExecutable->mLinkedInputVaryings[ShaderType::Compute] =
+ executable.getLinkedInputVaryings(ShaderType::Compute);
+ }
+}
+
+void ProgramPipeline::updateExecutable()
+{
+ // Vertex Shader ProgramExecutable properties
+ updateExecutableAttributes();
+ updateTransformFeedbackMembers();
+ updateShaderStorageBlocks();
+ updateImageBindings();
+
+ // Geometry Shader ProgramExecutable properties
+ updateExecutableGeometryProperties();
+
+ // Tessellation Shaders ProgramExecutable properties
+ updateExecutableTessellationProperties();
+
+ // Fragment Shader ProgramExecutable properties
+ updateFragmentInoutRangeAndEnablesPerSampleShading();
+
+ // All Shader ProgramExecutable properties
+ mState.updateExecutableTextures();
+ updateLinkedVaryings();
+}
+
+// The attached shaders are checked for linking errors by matching up their variables.
+// Uniform, input and output variables get collected.
+// The code gets compiled into binaries.
+angle::Result ProgramPipeline::link(const Context *context)
+{
+ ASSERT(!mState.mIsLinked);
+
+ ProgramMergedVaryings mergedVaryings;
+ ProgramVaryingPacking varyingPacking;
+ LinkingVariables linkingVariables(mState);
+
+ mState.mExecutable->reset(true);
+
+ InfoLog &infoLog = mState.mExecutable->getInfoLog();
+ infoLog.reset();
+
+ // Build shader variable uniforms map for gl::UniformLinker.
+ ShaderMap<std::vector<sh::ShaderVariable>> shaderUniforms;
+ for (ShaderType shaderType : mState.mExecutable->mLinkedShaderStages)
+ {
+ for (const LinkedUniform &uniform : mState.mPrograms[shaderType]->getUniforms())
+ {
+ shaderUniforms[shaderType].push_back(uniform);
+ }
+ }
+
+ if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::Vertex))
+ {
+ if (!linkVaryings(infoLog))
+ {
+ return angle::Result::Stop;
+ }
+
+ if (!LinkValidateProgramGlobalNames(infoLog, getExecutable(), linkingVariables))
+ {
+ return angle::Result::Stop;
+ }
+
+ Program *fragmentShaderProgram = getShaderProgram(ShaderType::Fragment);
+ if (fragmentShaderProgram)
+ {
+ // We should also be validating SSBO and image uniform counts.
+ const GLuint combinedImageUniforms = 0;
+ const GLuint combinedShaderStorageBlocks = 0;
+ const ProgramExecutable &fragmentExecutable = fragmentShaderProgram->getExecutable();
+ if (!mState.mExecutable->linkValidateOutputVariables(
+ context->getCaps(), context->getExtensions(), context->getClientVersion(),
+ combinedImageUniforms, combinedShaderStorageBlocks,
+ fragmentExecutable.getOutputVariables(),
+ fragmentExecutable.getLinkedShaderVersion(ShaderType::Fragment),
+ ProgramAliasedBindings(), ProgramAliasedBindings()))
+ {
+ return angle::Result::Continue;
+ }
+ }
+ mergedVaryings = GetMergedVaryingsFromLinkingVariables(linkingVariables);
+ // If separable program objects are in use, the set of attributes captured is taken
+ // from the program object active on the last vertex processing stage.
+ ShaderType lastVertexProcessingStage =
+ gl::GetLastPreFragmentStage(getExecutable().getLinkedShaderStages());
+ if (lastVertexProcessingStage == ShaderType::InvalidEnum)
+ {
+ // If there is no active program for the vertex or fragment shader stages, the results
+ // of vertex and fragment shader execution will respectively be undefined. However,
+ // this is not an error.
+ return angle::Result::Continue;
+ }
+
+ Program *tfProgram = getShaderProgram(lastVertexProcessingStage);
+ ASSERT(tfProgram);
+
+ if (!tfProgram)
+ {
+ tfProgram = mState.mPrograms[ShaderType::Vertex];
+ }
+
+ const std::vector<std::string> &transformFeedbackVaryingNames =
+ tfProgram->getState().getTransformFeedbackVaryingNames();
+
+ if (!mState.mExecutable->linkMergedVaryings(context, mergedVaryings,
+ transformFeedbackVaryingNames, linkingVariables,
+ false, &varyingPacking))
+ {
+ return angle::Result::Stop;
+ }
+ }
+
+ // Merge uniforms.
+ mState.mExecutable->copyUniformsFromProgramMap(mState.mPrograms);
+
+ if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::Vertex))
+ {
+ const ProgramState &programState = mState.mPrograms[gl::ShaderType::Vertex]->getState();
+ mState.mExecutable->copyInputsFromProgram(programState);
+ }
+
+ // Merge shader buffers (UBOs, SSBOs, and atomic counter buffers) into the executable.
+ // Also copy over image and sampler bindings.
+ for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
+ {
+ const ProgramState &programState = mState.mPrograms[shaderType]->getState();
+ mState.mExecutable->copyShaderBuffersFromProgram(programState, shaderType);
+ mState.mExecutable->copySamplerBindingsFromProgram(programState);
+ mState.mExecutable->copyImageBindingsFromProgram(programState);
+ }
+
+ if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::Fragment))
+ {
+ const ProgramState &programState = mState.mPrograms[gl::ShaderType::Fragment]->getState();
+ mState.mExecutable->copyOutputsFromProgram(programState);
+ }
+
+ if (mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::Vertex) ||
+ mState.mExecutable->hasLinkedShaderStage(gl::ShaderType::Compute))
+ {
+ ANGLE_TRY(getImplementation()->link(context, mergedVaryings, varyingPacking));
+ }
+
+ mState.mExecutable->mActiveSamplerRefCounts.fill(0);
+ updateExecutable();
+
+ mState.mIsLinked = true;
+ onStateChange(angle::SubjectMessage::SubjectChanged);
+
+ return angle::Result::Continue;
+}
+
+bool ProgramPipeline::linkVaryings(InfoLog &infoLog) const
+{
+ ShaderType previousShaderType = ShaderType::InvalidEnum;
+ for (ShaderType shaderType : kAllGraphicsShaderTypes)
+ {
+ Program *program = getShaderProgram(shaderType);
+ if (!program)
+ {
+ continue;
+ }
+ ProgramExecutable &executable = program->getExecutable();
+
+ if (previousShaderType != ShaderType::InvalidEnum)
+ {
+ Program *previousProgram = getShaderProgram(previousShaderType);
+ ASSERT(previousProgram);
+ const ProgramExecutable &previousExecutable = previousProgram->getExecutable();
+
+ if (!LinkValidateShaderInterfaceMatching(
+ previousExecutable.getLinkedOutputVaryings(previousShaderType),
+ executable.getLinkedInputVaryings(shaderType), previousShaderType, shaderType,
+ previousExecutable.getLinkedShaderVersion(previousShaderType),
+ executable.getLinkedShaderVersion(shaderType), true, infoLog))
+ {
+ return false;
+ }
+ }
+ previousShaderType = shaderType;
+ }
+
+ // TODO: http://anglebug.com/3571 and http://anglebug.com/3572
+ // Need to move logic of validating builtin varyings inside the for-loop above.
+ // This is because the built-in symbols `gl_ClipDistance` and `gl_CullDistance`
+ // can be redeclared in Geometry or Tessellation shaders as well.
+ Program *vertexProgram = mState.mPrograms[ShaderType::Vertex];
+ Program *fragmentProgram = mState.mPrograms[ShaderType::Fragment];
+ if (!vertexProgram || !fragmentProgram)
+ {
+ return true;
+ }
+ ProgramExecutable &vertexExecutable = vertexProgram->getExecutable();
+ ProgramExecutable &fragmentExecutable = fragmentProgram->getExecutable();
+ return LinkValidateBuiltInVaryings(
+ vertexExecutable.getLinkedOutputVaryings(ShaderType::Vertex),
+ fragmentExecutable.getLinkedInputVaryings(ShaderType::Fragment), ShaderType::Vertex,
+ ShaderType::Fragment, vertexExecutable.getLinkedShaderVersion(ShaderType::Vertex),
+ fragmentExecutable.getLinkedShaderVersion(ShaderType::Fragment), infoLog);
+}
+
+void ProgramPipeline::validate(const gl::Context *context)
+{
+ const Caps &caps = context->getCaps();
+ mState.mValid = true;
+ InfoLog &infoLog = mState.mExecutable->getInfoLog();
+ infoLog.reset();
+
+ for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
+ {
+ Program *shaderProgram = mState.mPrograms[shaderType];
+ if (shaderProgram)
+ {
+ shaderProgram->resolveLink(context);
+ shaderProgram->validate(caps);
+ std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
+ if (shaderInfoString.length())
+ {
+ mState.mValid = false;
+ infoLog << shaderInfoString << "\n";
+ return;
+ }
+ if (!shaderProgram->isSeparable())
+ {
+ mState.mValid = false;
+ infoLog << GetShaderTypeString(shaderType) << " is not marked separable."
+ << "\n";
+ return;
+ }
+ }
+ }
+
+ intptr_t programPipelineError = context->getStateCache().getProgramPipelineError(context);
+ if (programPipelineError)
+ {
+ mState.mValid = false;
+ const char *errorMessage = reinterpret_cast<const char *>(programPipelineError);
+ infoLog << errorMessage << "\n";
+ return;
+ }
+
+ if (!linkVaryings(infoLog))
+ {
+ mState.mValid = false;
+
+ for (const ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
+ {
+ Program *shaderProgram = mState.mPrograms[shaderType];
+ ASSERT(shaderProgram);
+ shaderProgram->validate(caps);
+ std::string shaderInfoString = shaderProgram->getExecutable().getInfoLogString();
+ if (shaderInfoString.length())
+ {
+ infoLog << shaderInfoString << "\n";
+ }
+ }
+ }
+}
+
+void ProgramPipeline::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
+{
+ switch (message)
+ {
+ case angle::SubjectMessage::ProgramTextureOrImageBindingChanged:
+ mState.mExecutable->mActiveSamplerRefCounts.fill(0);
+ mState.updateExecutableTextures();
+ break;
+
+ case angle::SubjectMessage::ProgramRelinked:
+ mState.mIsLinked = false;
+ onStateChange(angle::SubjectMessage::ProgramRelinked);
+ break;
+ case angle::SubjectMessage::SamplerUniformsUpdated:
+ mState.mExecutable->clearSamplerBindings();
+ for (ShaderType shaderType : mState.mExecutable->getLinkedShaderStages())
+ {
+ const ProgramState &programState = mState.mPrograms[shaderType]->getState();
+ mState.mExecutable->copySamplerBindingsFromProgram(programState);
+ }
+ mState.mExecutable->mActiveSamplerRefCounts.fill(0);
+ mState.updateExecutableTextures();
+ break;
+ case angle::SubjectMessage::ProgramUniformUpdated:
+ mProgramPipelineImpl->onProgramUniformUpdate(static_cast<ShaderType>(index));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/ProgramPipeline.h b/gfx/angle/checkout/src/libANGLE/ProgramPipeline.h
new file mode 100644
index 0000000000..4b394ca3e7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/ProgramPipeline.h
@@ -0,0 +1,176 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramPipeline.h: Defines the gl::ProgramPipeline class.
+// Implements GL program pipeline objects and related functionality.
+// [OpenGL ES 3.1] section 7.4 page 105.
+
+#ifndef LIBANGLE_PROGRAMPIPELINE_H_
+#define LIBANGLE_PROGRAMPIPELINE_H_
+
+#include <memory>
+
+#include "common/angleutils.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/ProgramExecutable.h"
+#include "libANGLE/RefCountObject.h"
+
+namespace rx
+{
+class GLImplFactory;
+class ProgramPipelineImpl;
+} // namespace rx
+
+namespace gl
+{
+class Context;
+class ProgramPipeline;
+
+class ProgramPipelineState final : angle::NonCopyable
+{
+ public:
+ ProgramPipelineState();
+ ~ProgramPipelineState();
+
+ const std::string &getLabel() const;
+
+ ProgramExecutable &getExecutable() const
+ {
+ ASSERT(mExecutable);
+ return *mExecutable;
+ }
+
+ void activeShaderProgram(Program *shaderProgram);
+ void useProgramStages(const Context *context,
+ const gl::ShaderBitSet &shaderTypes,
+ Program *shaderProgram,
+ std::vector<angle::ObserverBinding> *programObserverBindings);
+
+ Program *getActiveShaderProgram() { return mActiveShaderProgram; }
+
+ GLboolean isValid() const { return mValid; }
+
+ const Program *getShaderProgram(ShaderType shaderType) const { return mPrograms[shaderType]; }
+
+ bool usesShaderProgram(ShaderProgramID program) const;
+
+ void updateExecutableTextures();
+
+ rx::SpecConstUsageBits getSpecConstUsageBits() const;
+
+ private:
+ void useProgramStage(const Context *context,
+ ShaderType shaderType,
+ Program *shaderProgram,
+ angle::ObserverBinding *programObserverBindings);
+
+ friend class ProgramPipeline;
+
+ std::string mLabel;
+
+ // The active shader program
+ Program *mActiveShaderProgram;
+ // The shader programs for each stage.
+ ShaderMap<Program *> mPrograms;
+
+ GLboolean mValid;
+
+ ProgramExecutable *mExecutable;
+
+ bool mIsLinked;
+};
+
+class ProgramPipeline final : public RefCountObject<ProgramPipelineID>,
+ public LabeledObject,
+ public angle::ObserverInterface,
+ public angle::Subject
+{
+ public:
+ ProgramPipeline(rx::GLImplFactory *factory, ProgramPipelineID handle);
+ ~ProgramPipeline() override;
+
+ void onDestroy(const Context *context) override;
+
+ angle::Result setLabel(const Context *context, const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ const ProgramPipelineState &getState() const { return mState; }
+ ProgramPipelineState &getState() { return mState; }
+
+ ProgramExecutable &getExecutable() const { return mState.getExecutable(); }
+
+ rx::ProgramPipelineImpl *getImplementation() const;
+
+ Program *getActiveShaderProgram() { return mState.getActiveShaderProgram(); }
+ void activeShaderProgram(Program *shaderProgram);
+ Program *getLinkedActiveShaderProgram(const Context *context)
+ {
+ Program *program = mState.getActiveShaderProgram();
+ if (program)
+ {
+ program->resolveLink(context);
+ }
+ return program;
+ }
+
+ angle::Result useProgramStages(const Context *context,
+ GLbitfield stages,
+ Program *shaderProgram);
+
+ Program *getShaderProgram(ShaderType shaderType) const { return mState.mPrograms[shaderType]; }
+
+ void resetIsLinked() { mState.mIsLinked = false; }
+ angle::Result link(const gl::Context *context);
+
+ // Ensure program pipeline is linked. Inlined to make sure its overhead is as low as possible.
+ void resolveLink(const Context *context)
+ {
+ if (mState.mIsLinked)
+ {
+ // Already linked, nothing to do.
+ return;
+ }
+
+ angle::Result linkResult = link(context);
+ if (linkResult != angle::Result::Continue)
+ {
+ // If the link failed then log a warning, swallow the error and move on.
+ WARN() << "ProgramPipeline link failed" << std::endl;
+ }
+ return;
+ }
+
+ void validate(const gl::Context *context);
+ GLboolean isValid() const { return mState.isValid(); }
+ bool isLinked() const { return mState.mIsLinked; }
+
+ // ObserverInterface implementation.
+ void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
+
+ private:
+ bool linkVaryings(InfoLog &infoLog) const;
+ void updateLinkedShaderStages();
+ void updateExecutableAttributes();
+ void updateTransformFeedbackMembers();
+ void updateShaderStorageBlocks();
+ void updateImageBindings();
+ void updateExecutableGeometryProperties();
+ void updateExecutableTessellationProperties();
+ void updateFragmentInoutRangeAndEnablesPerSampleShading();
+ void updateLinkedVaryings();
+ void updateExecutable();
+
+ std::unique_ptr<rx::ProgramPipelineImpl> mProgramPipelineImpl;
+
+ ProgramPipelineState mState;
+
+ std::vector<angle::ObserverBinding> mProgramObserverBindings;
+ angle::ObserverBinding mExecutableObserverBinding;
+};
+} // namespace gl
+
+#endif // LIBANGLE_PROGRAMPIPELINE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Query.cpp b/gfx/angle/checkout/src/libANGLE/Query.cpp
new file mode 100644
index 0000000000..1e56221077
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Query.cpp
@@ -0,0 +1,96 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Query.cpp: Implements the gl::Query class
+
+#include "libANGLE/Query.h"
+
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/QueryImpl.h"
+
+namespace gl
+{
+Query::Query(rx::GLImplFactory *factory, QueryType type, QueryID id)
+ : RefCountObject(factory->generateSerial(), id), mQuery(factory->createQuery(type)), mLabel()
+{}
+
+Query::~Query()
+{
+ SafeDelete(mQuery);
+}
+
+void Query::onDestroy(const Context *context)
+{
+ ASSERT(mQuery);
+ mQuery->onDestroy(context);
+}
+
+angle::Result Query::setLabel(const Context *context, const std::string &label)
+{
+ mLabel = label;
+
+ if (mQuery)
+ {
+ return mQuery->onLabelUpdate(context);
+ }
+ return angle::Result::Continue;
+}
+
+const std::string &Query::getLabel() const
+{
+ return mLabel;
+}
+
+angle::Result Query::begin(const Context *context)
+{
+ return mQuery->begin(context);
+}
+
+angle::Result Query::end(const Context *context)
+{
+ return mQuery->end(context);
+}
+
+angle::Result Query::queryCounter(const Context *context)
+{
+ return mQuery->queryCounter(context);
+}
+
+angle::Result Query::getResult(const Context *context, GLint *params)
+{
+ return mQuery->getResult(context, params);
+}
+
+angle::Result Query::getResult(const Context *context, GLuint *params)
+{
+ return mQuery->getResult(context, params);
+}
+
+angle::Result Query::getResult(const Context *context, GLint64 *params)
+{
+ return mQuery->getResult(context, params);
+}
+
+angle::Result Query::getResult(const Context *context, GLuint64 *params)
+{
+ return mQuery->getResult(context, params);
+}
+
+angle::Result Query::isResultAvailable(const Context *context, bool *available)
+{
+ return mQuery->isResultAvailable(context, available);
+}
+
+QueryType Query::getType() const
+{
+ return mQuery->getType();
+}
+
+rx::QueryImpl *Query::getImplementation() const
+{
+ return mQuery;
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Query.h b/gfx/angle/checkout/src/libANGLE/Query.h
new file mode 100644
index 0000000000..8d8692b5e8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Query.h
@@ -0,0 +1,60 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Query.h: Defines the gl::Query class
+
+#ifndef LIBANGLE_QUERY_H_
+#define LIBANGLE_QUERY_H_
+
+#include "common/PackedEnums.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+namespace rx
+{
+class GLImplFactory;
+class QueryImpl;
+} // namespace rx
+
+namespace gl
+{
+
+class Query final : public RefCountObject<QueryID>, public LabeledObject
+{
+ public:
+ Query(rx::GLImplFactory *factory, QueryType type, QueryID id);
+ ~Query() override;
+ void onDestroy(const Context *context) override;
+
+ angle::Result setLabel(const Context *context, const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ angle::Result begin(const Context *context);
+ angle::Result end(const Context *context);
+ angle::Result queryCounter(const Context *context);
+ angle::Result getResult(const Context *context, GLint *params);
+ angle::Result getResult(const Context *context, GLuint *params);
+ angle::Result getResult(const Context *context, GLint64 *params);
+ angle::Result getResult(const Context *context, GLuint64 *params);
+ angle::Result isResultAvailable(const Context *context, bool *available);
+
+ QueryType getType() const;
+
+ rx::QueryImpl *getImplementation() const;
+
+ private:
+ rx::QueryImpl *mQuery;
+
+ std::string mLabel;
+};
+} // namespace gl
+
+#endif // LIBANGLE_QUERY_H_
diff --git a/gfx/angle/checkout/src/libANGLE/RefCountObject.h b/gfx/angle/checkout/src/libANGLE/RefCountObject.h
new file mode 100644
index 0000000000..f19b8c434a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/RefCountObject.h
@@ -0,0 +1,327 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RefCountObject.h: Defines the gl::RefCountObject base class that provides
+// lifecycle support for GL objects using the traditional BindObject scheme, but
+// that need to be reference counted for correct cross-context deletion.
+// (Concretely, textures, buffers and renderbuffers.)
+
+#ifndef LIBANGLE_REFCOUNTOBJECT_H_
+#define LIBANGLE_REFCOUNTOBJECT_H_
+
+#include "angle_gl.h"
+#include "common/PackedEnums.h"
+#include "common/debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Observer.h"
+#include "libANGLE/renderer/serial_utils.h"
+
+#include <cstddef>
+
+namespace angle
+{
+
+template <typename ContextT, typename ErrorT>
+class RefCountObject : angle::NonCopyable
+{
+ public:
+ using ContextType = ContextT;
+ using ErrorType = ErrorT;
+
+ RefCountObject() : mRefCount(0) {}
+
+ virtual void onDestroy(const ContextType *context) {}
+
+ void addRef() const { ++mRefCount; }
+
+ ANGLE_INLINE void release(const ContextType *context)
+ {
+ ASSERT(mRefCount > 0);
+ if (--mRefCount == 0)
+ {
+ onDestroy(context);
+ delete this;
+ }
+ }
+
+ size_t getRefCount() const { return mRefCount; }
+
+ protected:
+ virtual ~RefCountObject() { ASSERT(mRefCount == 0); }
+
+ mutable size_t mRefCount;
+};
+
+template <class ObjectType, typename ContextT, typename ErrorT = angle::Result>
+class RefCountObjectReleaser : angle::NonCopyable
+{
+ public:
+ using ContextType = ContextT;
+ using ErrorType = ErrorT;
+
+ RefCountObjectReleaser() {}
+ RefCountObjectReleaser(const ContextType *context, ObjectType *object)
+ : mContext(context), mObject(object)
+ {}
+
+ RefCountObjectReleaser(RefCountObjectReleaser &&other)
+ : mContext(other.mContext), mObject(other.mObject)
+ {
+ other.mContext = nullptr;
+ other.mObject = nullptr;
+ }
+
+ RefCountObjectReleaser &operator=(RefCountObjectReleaser &&other)
+ {
+ mContext = other.mContext;
+ mObject = other.mObject;
+
+ other.mContext = nullptr;
+ other.mObject = nullptr;
+
+ return *this;
+ }
+
+ ~RefCountObjectReleaser()
+ {
+ if (mObject)
+ {
+ reinterpret_cast<RefCountObject<ContextType, ErrorType> *>(mObject)->release(mContext);
+ mObject = nullptr;
+ }
+ }
+
+ private:
+ const ContextType *mContext = nullptr;
+ ObjectType *mObject = nullptr;
+};
+
+template <class ObjectType, typename ContextT, typename ErrorT = angle::Result>
+class BindingPointer
+{
+ public:
+ using ContextType = ContextT;
+ using ErrorType = ErrorT;
+
+ BindingPointer() : mObject(nullptr) {}
+
+ BindingPointer(ObjectType *object) : mObject(object)
+ {
+ if (mObject)
+ {
+ mObject->addRef();
+ }
+ }
+
+ BindingPointer(const BindingPointer &other) : mObject(other.mObject)
+ {
+ if (mObject)
+ {
+ mObject->addRef();
+ }
+ }
+
+ BindingPointer &operator=(BindingPointer &&other)
+ {
+ std::swap(mObject, other.mObject);
+ return *this;
+ }
+
+ virtual ~BindingPointer()
+ {
+ // Objects have to be released before the resource manager is destroyed, so they must be
+ // explicitly cleaned up.
+ ASSERT(mObject == nullptr);
+ }
+
+ RefCountObjectReleaser<ObjectType, ContextType, ErrorT> set(const ContextType *context,
+ ObjectType *newObject)
+ {
+ // addRef first in case newObject == mObject and this is the last reference to it.
+ if (newObject != nullptr)
+ {
+ reinterpret_cast<RefCountObject<ContextType, ErrorType> *>(newObject)->addRef();
+ }
+
+ // Store the old pointer in a temporary so we can set the pointer before calling release.
+ // Otherwise the object could still be referenced when its destructor is called.
+ ObjectType *oldObject = mObject;
+ mObject = newObject;
+ return RefCountObjectReleaser<ObjectType, ContextType, ErrorT>(context, oldObject);
+ }
+
+ void assign(ObjectType *object) { mObject = object; }
+
+ ObjectType *get() const { return mObject; }
+ ObjectType *operator->() const { return mObject; }
+
+ bool operator==(const BindingPointer &other) const { return mObject == other.mObject; }
+
+ bool operator!=(const BindingPointer &other) const { return !(*this == other); }
+
+ protected:
+ ANGLE_INLINE void setImpl(ObjectType *obj) { mObject = obj; }
+
+ private:
+ ObjectType *mObject;
+};
+} // namespace angle
+
+namespace gl
+{
+class Context;
+
+template <class ObjectType>
+class BindingPointer;
+
+using RefCountObjectNoID = angle::RefCountObject<Context, angle::Result>;
+
+template <typename IDType>
+class RefCountObject : public gl::RefCountObjectNoID
+{
+ public:
+ explicit RefCountObject(rx::Serial serial, IDType id) : mSerial(serial), mId(id) {}
+
+ rx::Serial serial() const { return mSerial; }
+ IDType id() const { return mId; }
+
+ protected:
+ ~RefCountObject() override {}
+
+ private:
+ // Unique serials are used to identify resources for frame capture.
+ rx::Serial mSerial;
+ IDType mId;
+};
+
+template <class ObjectType>
+class BindingPointer : public angle::BindingPointer<ObjectType, Context>
+{
+ public:
+ using ContextType = typename angle::BindingPointer<ObjectType, Context>::ContextType;
+ using ErrorType = typename angle::BindingPointer<ObjectType, Context>::ErrorType;
+
+ BindingPointer() {}
+
+ BindingPointer(ObjectType *object) : angle::BindingPointer<ObjectType, Context>(object) {}
+
+ typename ResourceTypeToID<ObjectType>::IDType id() const
+ {
+ ObjectType *obj = this->get();
+ if (obj)
+ return obj->id();
+ return {0};
+ }
+};
+
+template <class ObjectType>
+class OffsetBindingPointer : public BindingPointer<ObjectType>
+{
+ public:
+ using ContextType = typename BindingPointer<ObjectType>::ContextType;
+ using ErrorType = typename BindingPointer<ObjectType>::ErrorType;
+
+ OffsetBindingPointer() : mOffset(0), mSize(0) {}
+
+ void set(const ContextType *context, ObjectType *newObject, GLintptr offset, GLsizeiptr size)
+ {
+ set(context, newObject);
+ updateOffsetAndSize(newObject, offset, size);
+ }
+
+ GLintptr getOffset() const { return mOffset; }
+ GLsizeiptr getSize() const { return mSize; }
+
+ bool operator==(const OffsetBindingPointer<ObjectType> &other) const
+ {
+ return this->get() == other.get() && mOffset == other.mOffset && mSize == other.mSize;
+ }
+
+ bool operator!=(const OffsetBindingPointer<ObjectType> &other) const
+ {
+ return !(*this == other);
+ }
+
+ void assign(ObjectType *newObject, GLintptr offset, GLsizeiptr size)
+ {
+ assign(newObject);
+ updateOffsetAndSize(newObject, offset, size);
+ }
+
+ private:
+ ANGLE_INLINE void updateOffsetAndSize(ObjectType *newObject, GLintptr offset, GLsizeiptr size)
+ {
+ if (newObject)
+ {
+ mOffset = offset;
+ mSize = size;
+ }
+ else
+ {
+ mOffset = 0;
+ mSize = 0;
+ }
+ }
+
+ // Delete the unparameterized functions. This forces an explicit offset and size.
+ using BindingPointer<ObjectType>::set;
+ using BindingPointer<ObjectType>::assign;
+
+ GLintptr mOffset;
+ GLsizeiptr mSize;
+};
+
+template <typename SubjectT>
+class SubjectBindingPointer : protected BindingPointer<SubjectT>, public angle::ObserverBindingBase
+{
+ public:
+ SubjectBindingPointer(angle::ObserverInterface *observer, angle::SubjectIndex index)
+ : ObserverBindingBase(observer, index)
+ {}
+ ~SubjectBindingPointer() override {}
+ SubjectBindingPointer(const SubjectBindingPointer &other) = default;
+ SubjectBindingPointer &operator=(const SubjectBindingPointer &other) = default;
+
+ void bind(const Context *context, SubjectT *subject)
+ {
+ // AddRef first in case subject == get()
+ if (subject)
+ {
+ subject->addObserver(this);
+ subject->addRef();
+ }
+
+ if (get())
+ {
+ get()->removeObserver(this);
+ get()->release(context);
+ }
+
+ this->setImpl(subject);
+ }
+
+ using BindingPointer<SubjectT>::get;
+ using BindingPointer<SubjectT>::operator->;
+
+ friend class State;
+};
+} // namespace gl
+
+namespace egl
+{
+class Display;
+
+using RefCountObject = angle::RefCountObject<Display, Error>;
+
+template <class ObjectType>
+using RefCountObjectReleaser = angle::RefCountObjectReleaser<ObjectType, Display, Error>;
+
+template <class ObjectType>
+using BindingPointer = angle::BindingPointer<ObjectType, Display, Error>;
+
+} // namespace egl
+
+#endif // LIBANGLE_REFCOUNTOBJECT_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Renderbuffer.cpp b/gfx/angle/checkout/src/libANGLE/Renderbuffer.cpp
new file mode 100644
index 0000000000..ce2445c31e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Renderbuffer.cpp
@@ -0,0 +1,423 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Renderbuffer.cpp: Implements the renderer-agnostic gl::Renderbuffer class,
+// GL renderbuffer objects and related functionality.
+// [OpenGL ES 2.0.24] section 4.4.3 page 108.
+
+#include "libANGLE/Renderbuffer.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+
+namespace gl
+{
+namespace
+{
+angle::SubjectIndex kRenderbufferImplSubjectIndex = 0;
+
+InitState DetermineInitState(const Context *context)
+{
+ return (context && context->isRobustResourceInitEnabled()) ? InitState::MayNeedInit
+ : InitState::Initialized;
+}
+} // namespace
+
+// RenderbufferState implementation.
+RenderbufferState::RenderbufferState()
+ : mWidth(0),
+ mHeight(0),
+ mFormat(GL_RGBA4),
+ mSamples(0),
+ mMultisamplingMode(MultisamplingMode::Regular),
+ mHasProtectedContent(false),
+ mInitState(InitState::Initialized)
+{}
+
+RenderbufferState::~RenderbufferState() {}
+
+GLsizei RenderbufferState::getWidth() const
+{
+ return mWidth;
+}
+
+GLsizei RenderbufferState::getHeight() const
+{
+ return mHeight;
+}
+
+const Format &RenderbufferState::getFormat() const
+{
+ return mFormat;
+}
+
+GLsizei RenderbufferState::getSamples() const
+{
+ return mSamples;
+}
+
+MultisamplingMode RenderbufferState::getMultisamplingMode() const
+{
+ return mMultisamplingMode;
+}
+
+InitState RenderbufferState::getInitState() const
+{
+ return mInitState;
+}
+
+void RenderbufferState::update(GLsizei width,
+ GLsizei height,
+ const Format &format,
+ GLsizei samples,
+ MultisamplingMode multisamplingMode,
+ InitState initState)
+{
+ mWidth = width;
+ mHeight = height;
+ mFormat = format;
+ mSamples = samples;
+ mMultisamplingMode = multisamplingMode;
+ mInitState = initState;
+ mHasProtectedContent = false;
+}
+
+void RenderbufferState::setProtectedContent(bool hasProtectedContent)
+{
+ mHasProtectedContent = hasProtectedContent;
+}
+
+// Renderbuffer implementation.
+Renderbuffer::Renderbuffer(rx::GLImplFactory *implFactory, RenderbufferID id)
+ : RefCountObject(implFactory->generateSerial(), id),
+ mState(),
+ mImplementation(implFactory->createRenderbuffer(mState)),
+ mLabel(),
+ mImplObserverBinding(this, kRenderbufferImplSubjectIndex)
+{
+ mImplObserverBinding.bind(mImplementation.get());
+}
+
+void Renderbuffer::onDestroy(const Context *context)
+{
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ (void)orphanImages(context, &releaseImage);
+
+ if (mImplementation)
+ {
+ mImplementation->onDestroy(context);
+ }
+}
+
+Renderbuffer::~Renderbuffer() {}
+
+angle::Result Renderbuffer::setLabel(const Context *context, const std::string &label)
+{
+ mLabel = label;
+
+ if (mImplementation)
+ {
+ return mImplementation->onLabelUpdate(context);
+ }
+ return angle::Result::Continue;
+}
+
+const std::string &Renderbuffer::getLabel() const
+{
+ return mLabel;
+}
+
+angle::Result Renderbuffer::setStorage(const Context *context,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ ANGLE_TRY(orphanImages(context, &releaseImage));
+
+ ANGLE_TRY(mImplementation->setStorage(context, internalformat, width, height));
+
+ mState.update(width, height, Format(internalformat), 0, MultisamplingMode::Regular,
+ DetermineInitState(context));
+ onStateChange(angle::SubjectMessage::SubjectChanged);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderbuffer::setStorageMultisample(const Context *context,
+ GLsizei samplesIn,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ MultisamplingMode mode)
+{
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ ANGLE_TRY(orphanImages(context, &releaseImage));
+
+ // Potentially adjust "samplesIn" to a supported value
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ GLsizei samples = formatCaps.getNearestSamples(samplesIn);
+
+ ANGLE_TRY(mImplementation->setStorageMultisample(context, samples, internalformat, width,
+ height, mode));
+
+ mState.update(width, height, Format(internalformat), samples, mode,
+ DetermineInitState(context));
+ onStateChange(angle::SubjectMessage::SubjectChanged);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderbuffer::setStorageEGLImageTarget(const Context *context, egl::Image *image)
+{
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ ANGLE_TRY(orphanImages(context, &releaseImage));
+
+ ANGLE_TRY(mImplementation->setStorageEGLImageTarget(context, image));
+
+ setTargetImage(context, image);
+
+ mState.update(static_cast<GLsizei>(image->getWidth()), static_cast<GLsizei>(image->getHeight()),
+ Format(image->getFormat()), 0, MultisamplingMode::Regular,
+ image->sourceInitState());
+ mState.setProtectedContent(image->hasProtectedContent());
+
+ onStateChange(angle::SubjectMessage::SubjectChanged);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderbuffer::copyRenderbufferSubData(Context *context,
+ const gl::Renderbuffer *srcBuffer,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth)
+{
+ ANGLE_TRY(mImplementation->copyRenderbufferSubData(context, srcBuffer, srcLevel, srcX, srcY,
+ srcZ, dstLevel, dstX, dstY, dstZ, srcWidth,
+ srcHeight, srcDepth));
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderbuffer::copyTextureSubData(Context *context,
+ const gl::Texture *srcTexture,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth)
+{
+ ANGLE_TRY(mImplementation->copyTextureSubData(context, srcTexture, srcLevel, srcX, srcY, srcZ,
+ dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight,
+ srcDepth));
+
+ return angle::Result::Continue;
+}
+
+rx::RenderbufferImpl *Renderbuffer::getImplementation() const
+{
+ ASSERT(mImplementation);
+ return mImplementation.get();
+}
+
+GLsizei Renderbuffer::getWidth() const
+{
+ return mState.mWidth;
+}
+
+GLsizei Renderbuffer::getHeight() const
+{
+ return mState.mHeight;
+}
+
+const Format &Renderbuffer::getFormat() const
+{
+ return mState.mFormat;
+}
+
+GLsizei Renderbuffer::getSamples() const
+{
+ return mState.mMultisamplingMode == MultisamplingMode::Regular ? mState.mSamples : 0;
+}
+
+MultisamplingMode Renderbuffer::getMultisamplingMode() const
+{
+ return mState.mMultisamplingMode;
+}
+
+GLuint Renderbuffer::getRedSize() const
+{
+ return mState.mFormat.info->redBits;
+}
+
+GLuint Renderbuffer::getGreenSize() const
+{
+ return mState.mFormat.info->greenBits;
+}
+
+GLuint Renderbuffer::getBlueSize() const
+{
+ return mState.mFormat.info->blueBits;
+}
+
+GLuint Renderbuffer::getAlphaSize() const
+{
+ return mState.mFormat.info->alphaBits;
+}
+
+GLuint Renderbuffer::getDepthSize() const
+{
+ return mState.mFormat.info->depthBits;
+}
+
+GLuint Renderbuffer::getStencilSize() const
+{
+ return mState.mFormat.info->stencilBits;
+}
+
+const RenderbufferState &Renderbuffer::getState() const
+{
+ return mState;
+}
+
+GLint Renderbuffer::getMemorySize() const
+{
+ GLint implSize = mImplementation->getMemorySize();
+ if (implSize > 0)
+ {
+ return implSize;
+ }
+
+ // Assume allocated size is around width * height * samples * pixelBytes
+ angle::CheckedNumeric<GLint> size = 1;
+ size *= mState.mFormat.info->pixelBytes;
+ size *= mState.mWidth;
+ size *= mState.mHeight;
+ size *= std::max(mState.mSamples, 1);
+ return size.ValueOrDefault(std::numeric_limits<GLint>::max());
+}
+
+void Renderbuffer::onAttach(const Context *context, rx::Serial framebufferSerial)
+{
+ addRef();
+}
+
+void Renderbuffer::onDetach(const Context *context, rx::Serial framebufferSerial)
+{
+ release(context);
+}
+
+GLuint Renderbuffer::getId() const
+{
+ return id().value;
+}
+
+Extents Renderbuffer::getAttachmentSize(const gl::ImageIndex & /*imageIndex*/) const
+{
+ return Extents(mState.mWidth, mState.mHeight, 1);
+}
+
+Format Renderbuffer::getAttachmentFormat(GLenum /*binding*/,
+ const ImageIndex & /*imageIndex*/) const
+{
+ return getFormat();
+}
+GLsizei Renderbuffer::getAttachmentSamples(const ImageIndex & /*imageIndex*/) const
+{
+ return getSamples();
+}
+
+bool Renderbuffer::isRenderable(const Context *context,
+ GLenum binding,
+ const ImageIndex &imageIndex) const
+{
+ if (isEGLImageTarget())
+ {
+ return ImageSibling::isRenderable(context, binding, imageIndex);
+ }
+ return getFormat().info->renderbufferSupport(context->getClientVersion(),
+ context->getExtensions());
+}
+
+InitState Renderbuffer::initState(GLenum /*binding*/, const gl::ImageIndex & /*imageIndex*/) const
+{
+ if (isEGLImageTarget())
+ {
+ return sourceEGLImageInitState();
+ }
+
+ return mState.mInitState;
+}
+
+void Renderbuffer::setInitState(GLenum /*binding*/,
+ const gl::ImageIndex & /*imageIndex*/,
+ InitState initState)
+{
+ if (isEGLImageTarget())
+ {
+ setSourceEGLImageInitState(initState);
+ }
+ else
+ {
+ mState.mInitState = initState;
+ }
+}
+
+rx::FramebufferAttachmentObjectImpl *Renderbuffer::getAttachmentImpl() const
+{
+ return mImplementation.get();
+}
+
+GLenum Renderbuffer::getImplementationColorReadFormat(const Context *context) const
+{
+ return mImplementation->getColorReadFormat(context);
+}
+
+GLenum Renderbuffer::getImplementationColorReadType(const Context *context) const
+{
+ return mImplementation->getColorReadType(context);
+}
+
+angle::Result Renderbuffer::getRenderbufferImage(const Context *context,
+ const PixelPackState &packState,
+ Buffer *packBuffer,
+ GLenum format,
+ GLenum type,
+ void *pixels) const
+{
+ return mImplementation->getRenderbufferImage(context, packState, packBuffer, format, type,
+ pixels);
+}
+
+void Renderbuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
+{
+ ASSERT(message == angle::SubjectMessage::SubjectChanged);
+ onStateChange(angle::SubjectMessage::ContentsChanged);
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Renderbuffer.h b/gfx/angle/checkout/src/libANGLE/Renderbuffer.h
new file mode 100644
index 0000000000..1f85afc5e5
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Renderbuffer.h
@@ -0,0 +1,181 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Renderbuffer.h: Defines the renderer-agnostic container class gl::Renderbuffer.
+// Implements GL renderbuffer objects and related functionality.
+// [OpenGL ES 2.0.24] section 4.4.3 page 108.
+
+#ifndef LIBANGLE_RENDERBUFFER_H_
+#define LIBANGLE_RENDERBUFFER_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/RenderbufferImpl.h"
+
+namespace rx
+{
+class GLImplFactory;
+} // namespace rx
+
+namespace gl
+{
+// A GL renderbuffer object is usually used as a depth or stencil buffer attachment
+// for a framebuffer object. The renderbuffer itself is a distinct GL object, see
+// FramebufferAttachment and Framebuffer for how they are applied to an FBO via an
+// attachment point.
+
+class RenderbufferState final : angle::NonCopyable
+{
+ public:
+ RenderbufferState();
+ ~RenderbufferState();
+
+ GLsizei getWidth() const;
+ GLsizei getHeight() const;
+ const Format &getFormat() const;
+ GLsizei getSamples() const;
+ MultisamplingMode getMultisamplingMode() const;
+ InitState getInitState() const;
+ void setProtectedContent(bool hasProtectedContent);
+
+ private:
+ friend class Renderbuffer;
+
+ void update(GLsizei width,
+ GLsizei height,
+ const Format &format,
+ GLsizei samples,
+ MultisamplingMode multisamplingMode,
+ InitState initState);
+
+ GLsizei mWidth;
+ GLsizei mHeight;
+ Format mFormat;
+ GLsizei mSamples;
+ MultisamplingMode mMultisamplingMode;
+ bool mHasProtectedContent;
+
+ // For robust resource init.
+ InitState mInitState;
+};
+
+class Renderbuffer final : public RefCountObject<RenderbufferID>,
+ public egl::ImageSibling,
+ public LabeledObject
+{
+ public:
+ Renderbuffer(rx::GLImplFactory *implFactory, RenderbufferID id);
+ ~Renderbuffer() override;
+
+ void onDestroy(const Context *context) override;
+
+ angle::Result setLabel(const Context *context, const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ angle::Result setStorage(const Context *context,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+ angle::Result setStorageMultisample(const Context *context,
+ GLsizei samplesIn,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ MultisamplingMode mode);
+ angle::Result setStorageEGLImageTarget(const Context *context, egl::Image *imageTarget);
+
+ angle::Result copyRenderbufferSubData(Context *context,
+ const gl::Renderbuffer *srcBuffer,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth);
+
+ angle::Result copyTextureSubData(Context *context,
+ const gl::Texture *srcTexture,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth);
+
+ rx::RenderbufferImpl *getImplementation() const;
+
+ GLsizei getWidth() const;
+ GLsizei getHeight() const;
+ const Format &getFormat() const;
+ GLsizei getSamples() const;
+ MultisamplingMode getMultisamplingMode() const;
+ GLuint getRedSize() const;
+ GLuint getGreenSize() const;
+ GLuint getBlueSize() const;
+ GLuint getAlphaSize() const;
+ GLuint getDepthSize() const;
+ GLuint getStencilSize() const;
+ const RenderbufferState &getState() const;
+
+ GLint getMemorySize() const;
+
+ // FramebufferAttachmentObject Impl
+ Extents getAttachmentSize(const ImageIndex &imageIndex) const override;
+ Format getAttachmentFormat(GLenum binding, const ImageIndex &imageIndex) const override;
+ GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const override;
+ bool isRenderable(const Context *context,
+ GLenum binding,
+ const ImageIndex &imageIndex) const override;
+
+ void onAttach(const Context *context, rx::Serial framebufferSerial) override;
+ void onDetach(const Context *context, rx::Serial framebufferSerial) override;
+ GLuint getId() const override;
+
+ InitState initState(GLenum binding, const ImageIndex &imageIndex) const override;
+ void setInitState(GLenum binding, const ImageIndex &imageIndex, InitState initState) override;
+
+ GLenum getImplementationColorReadFormat(const Context *context) const;
+ GLenum getImplementationColorReadType(const Context *context) const;
+
+ // We pass the pack buffer and state explicitly so they can be overridden during capture.
+ angle::Result getRenderbufferImage(const Context *context,
+ const PixelPackState &packState,
+ Buffer *packBuffer,
+ GLenum format,
+ GLenum type,
+ void *pixels) const;
+
+ private:
+ // ObserverInterface implementation.
+ void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
+
+ rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
+
+ RenderbufferState mState;
+ std::unique_ptr<rx::RenderbufferImpl> mImplementation;
+
+ std::string mLabel;
+ angle::ObserverBinding mImplObserverBinding;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_RENDERBUFFER_H_
diff --git a/gfx/angle/checkout/src/libANGLE/ResourceManager.cpp b/gfx/angle/checkout/src/libANGLE/ResourceManager.cpp
new file mode 100644
index 0000000000..d5efce2319
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/ResourceManager.cpp
@@ -0,0 +1,522 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ResourceManager.cpp: Implements the the ResourceManager classes, which handle allocation and
+// lifetime of GL objects.
+
+#include "libANGLE/ResourceManager.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/MemoryObject.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/ProgramPipeline.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Sampler.h"
+#include "libANGLE/Semaphore.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace gl
+{
+
+namespace
+{
+
+template <typename ResourceType, typename IDType>
+IDType AllocateEmptyObject(HandleAllocator *handleAllocator,
+ ResourceMap<ResourceType, IDType> *objectMap)
+{
+ IDType handle = PackParam<IDType>(handleAllocator->allocate());
+ objectMap->assign(handle, nullptr);
+ return handle;
+}
+
+} // anonymous namespace
+
+ResourceManagerBase::ResourceManagerBase() : mRefCount(1) {}
+
+ResourceManagerBase::~ResourceManagerBase() = default;
+
+void ResourceManagerBase::addRef()
+{
+ mRefCount++;
+}
+
+void ResourceManagerBase::release(const Context *context)
+{
+ if (--mRefCount == 0)
+ {
+ reset(context);
+ delete this;
+ }
+}
+
+template <typename ResourceType, typename ImplT, typename IDType>
+TypedResourceManager<ResourceType, ImplT, IDType>::~TypedResourceManager()
+{
+ ASSERT(mObjectMap.empty());
+}
+
+template <typename ResourceType, typename ImplT, typename IDType>
+void TypedResourceManager<ResourceType, ImplT, IDType>::reset(const Context *context)
+{
+ this->mHandleAllocator.reset();
+ for (const auto &resource : mObjectMap)
+ {
+ if (resource.second)
+ {
+ ImplT::DeleteObject(context, resource.second);
+ }
+ }
+ mObjectMap.clear();
+}
+
+template <typename ResourceType, typename ImplT, typename IDType>
+void TypedResourceManager<ResourceType, ImplT, IDType>::deleteObject(const Context *context,
+ IDType handle)
+{
+ ResourceType *resource = nullptr;
+ if (!mObjectMap.erase(handle, &resource))
+ {
+ return;
+ }
+
+ // Requires an explicit this-> because of C++ template rules.
+ this->mHandleAllocator.release(GetIDValue(handle));
+
+ if (resource)
+ {
+ ImplT::DeleteObject(context, resource);
+ }
+}
+
+template class TypedResourceManager<Buffer, BufferManager, BufferID>;
+template class TypedResourceManager<Texture, TextureManager, TextureID>;
+template class TypedResourceManager<Renderbuffer, RenderbufferManager, RenderbufferID>;
+template class TypedResourceManager<Sampler, SamplerManager, SamplerID>;
+template class TypedResourceManager<Sync, SyncManager, GLuint>;
+template class TypedResourceManager<Framebuffer, FramebufferManager, FramebufferID>;
+template class TypedResourceManager<ProgramPipeline, ProgramPipelineManager, ProgramPipelineID>;
+
+// BufferManager Implementation.
+BufferManager::~BufferManager() = default;
+
+// static
+Buffer *BufferManager::AllocateNewObject(rx::GLImplFactory *factory, BufferID handle)
+{
+ Buffer *buffer = new Buffer(factory, handle);
+ buffer->addRef();
+ return buffer;
+}
+
+// static
+void BufferManager::DeleteObject(const Context *context, Buffer *buffer)
+{
+ buffer->release(context);
+}
+
+BufferID BufferManager::createBuffer()
+{
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+Buffer *BufferManager::getBuffer(BufferID handle) const
+{
+ return mObjectMap.query(handle);
+}
+
+// ShaderProgramManager Implementation.
+
+ShaderProgramManager::ShaderProgramManager() {}
+
+ShaderProgramManager::~ShaderProgramManager()
+{
+ ASSERT(mPrograms.empty());
+ ASSERT(mShaders.empty());
+}
+
+void ShaderProgramManager::reset(const Context *context)
+{
+ while (!mPrograms.empty())
+ {
+ deleteProgram(context, {mPrograms.begin()->first});
+ }
+ mPrograms.clear();
+ while (!mShaders.empty())
+ {
+ deleteShader(context, {mShaders.begin()->first});
+ }
+ mShaders.clear();
+}
+
+ShaderProgramID ShaderProgramManager::createShader(rx::GLImplFactory *factory,
+ const gl::Limitations &rendererLimitations,
+ ShaderType type)
+{
+ ASSERT(type != ShaderType::InvalidEnum);
+ ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()};
+ mShaders.assign(handle, new Shader(this, factory, rendererLimitations, type, handle));
+ return handle;
+}
+
+void ShaderProgramManager::deleteShader(const Context *context, ShaderProgramID shader)
+{
+ deleteObject(context, &mShaders, shader);
+}
+
+Shader *ShaderProgramManager::getShader(ShaderProgramID handle) const
+{
+ return mShaders.query(handle);
+}
+
+ShaderProgramID ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
+{
+ ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()};
+ mPrograms.assign(handle, new Program(factory, this, handle));
+ return handle;
+}
+
+void ShaderProgramManager::deleteProgram(const gl::Context *context, ShaderProgramID program)
+{
+ deleteObject(context, &mPrograms, program);
+}
+
+template <typename ObjectType, typename IDType>
+void ShaderProgramManager::deleteObject(const Context *context,
+ ResourceMap<ObjectType, IDType> *objectMap,
+ IDType id)
+{
+ ObjectType *object = objectMap->query(id);
+ if (!object)
+ {
+ return;
+ }
+
+ if (object->getRefCount() == 0)
+ {
+ mHandleAllocator.release(id.value);
+ object->onDestroy(context);
+ objectMap->erase(id, &object);
+ }
+ else
+ {
+ object->flagForDeletion();
+ }
+}
+
+// TextureManager Implementation.
+
+TextureManager::~TextureManager() = default;
+
+// static
+Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory,
+ TextureID handle,
+ TextureType type)
+{
+ Texture *texture = new Texture(factory, handle, type);
+ texture->addRef();
+ return texture;
+}
+
+// static
+void TextureManager::DeleteObject(const Context *context, Texture *texture)
+{
+ texture->release(context);
+}
+
+TextureID TextureManager::createTexture()
+{
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+void TextureManager::signalAllTexturesDirty() const
+{
+ for (const auto &texture : mObjectMap)
+ {
+ if (texture.second)
+ {
+ // We don't know if the Texture needs init, but that's ok, since it will only force
+ // a re-check, and will not initialize the pixels if it's not needed.
+ texture.second->signalDirtyStorage(InitState::MayNeedInit);
+ }
+ }
+}
+
+void TextureManager::enableHandleAllocatorLogging()
+{
+ mHandleAllocator.enableLogging(true);
+}
+
+// RenderbufferManager Implementation.
+
+RenderbufferManager::~RenderbufferManager() = default;
+
+// static
+Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory,
+ RenderbufferID handle)
+{
+ Renderbuffer *renderbuffer = new Renderbuffer(factory, handle);
+ renderbuffer->addRef();
+ return renderbuffer;
+}
+
+// static
+void RenderbufferManager::DeleteObject(const Context *context, Renderbuffer *renderbuffer)
+{
+ renderbuffer->release(context);
+}
+
+RenderbufferID RenderbufferManager::createRenderbuffer()
+{
+ return {AllocateEmptyObject(&mHandleAllocator, &mObjectMap)};
+}
+
+Renderbuffer *RenderbufferManager::getRenderbuffer(RenderbufferID handle) const
+{
+ return mObjectMap.query(handle);
+}
+
+// SamplerManager Implementation.
+
+SamplerManager::~SamplerManager() = default;
+
+// static
+Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, SamplerID handle)
+{
+ Sampler *sampler = new Sampler(factory, handle);
+ sampler->addRef();
+ return sampler;
+}
+
+// static
+void SamplerManager::DeleteObject(const Context *context, Sampler *sampler)
+{
+ sampler->release(context);
+}
+
+SamplerID SamplerManager::createSampler()
+{
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+Sampler *SamplerManager::getSampler(SamplerID handle) const
+{
+ return mObjectMap.query(handle);
+}
+
+bool SamplerManager::isSampler(SamplerID sampler) const
+{
+ return mObjectMap.contains(sampler);
+}
+
+// SyncManager Implementation.
+
+SyncManager::~SyncManager() = default;
+
+// static
+void SyncManager::DeleteObject(const Context *context, Sync *sync)
+{
+ sync->release(context);
+}
+
+GLuint SyncManager::createSync(rx::GLImplFactory *factory)
+{
+ GLuint handle = mHandleAllocator.allocate();
+ Sync *sync = new Sync(factory, handle);
+ sync->addRef();
+ mObjectMap.assign(handle, sync);
+ return handle;
+}
+
+Sync *SyncManager::getSync(GLuint handle) const
+{
+ return mObjectMap.query(handle);
+}
+
+// FramebufferManager Implementation.
+
+FramebufferManager::~FramebufferManager() = default;
+
+// static
+Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
+ FramebufferID handle,
+ const Context *context)
+{
+ // Make sure the caller isn't using a reserved handle.
+ ASSERT(handle != Framebuffer::kDefaultDrawFramebufferHandle);
+ return new Framebuffer(context, factory, handle);
+}
+
+// static
+void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer)
+{
+ framebuffer->onDestroy(context);
+ delete framebuffer;
+}
+
+FramebufferID FramebufferManager::createFramebuffer()
+{
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+Framebuffer *FramebufferManager::getFramebuffer(FramebufferID handle) const
+{
+ return mObjectMap.query(handle);
+}
+
+void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
+{
+ ASSERT(framebuffer == nullptr || framebuffer->isDefault());
+ mObjectMap.assign(Framebuffer::kDefaultDrawFramebufferHandle, framebuffer);
+}
+
+Framebuffer *FramebufferManager::getDefaultFramebuffer() const
+{
+ return getFramebuffer(Framebuffer::kDefaultDrawFramebufferHandle);
+}
+
+void FramebufferManager::invalidateFramebufferCompletenessCache() const
+{
+ for (const auto &framebuffer : mObjectMap)
+ {
+ if (framebuffer.second)
+ {
+ framebuffer.second->invalidateCompletenessCache();
+ }
+ }
+}
+
+// ProgramPipelineManager Implementation.
+
+ProgramPipelineManager::~ProgramPipelineManager() = default;
+
+// static
+ProgramPipeline *ProgramPipelineManager::AllocateNewObject(rx::GLImplFactory *factory,
+ ProgramPipelineID handle)
+{
+ ProgramPipeline *pipeline = new ProgramPipeline(factory, handle);
+ pipeline->addRef();
+ return pipeline;
+}
+
+// static
+void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipeline *pipeline)
+{
+ pipeline->release(context);
+}
+
+ProgramPipelineID ProgramPipelineManager::createProgramPipeline()
+{
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+ProgramPipeline *ProgramPipelineManager::getProgramPipeline(ProgramPipelineID handle) const
+{
+ return mObjectMap.query(handle);
+}
+
+// MemoryObjectManager Implementation.
+
+MemoryObjectManager::MemoryObjectManager() {}
+
+MemoryObjectManager::~MemoryObjectManager()
+{
+ ASSERT(mMemoryObjects.empty());
+}
+
+void MemoryObjectManager::reset(const Context *context)
+{
+ while (!mMemoryObjects.empty())
+ {
+ deleteMemoryObject(context, {mMemoryObjects.begin()->first});
+ }
+ mMemoryObjects.clear();
+}
+
+MemoryObjectID MemoryObjectManager::createMemoryObject(rx::GLImplFactory *factory)
+{
+ MemoryObjectID handle = MemoryObjectID{mHandleAllocator.allocate()};
+ MemoryObject *memoryObject = new MemoryObject(factory, handle);
+ memoryObject->addRef();
+ mMemoryObjects.assign(handle, memoryObject);
+ return handle;
+}
+
+void MemoryObjectManager::deleteMemoryObject(const Context *context, MemoryObjectID handle)
+{
+ MemoryObject *memoryObject = nullptr;
+ if (!mMemoryObjects.erase(handle, &memoryObject))
+ {
+ return;
+ }
+
+ // Requires an explicit this-> because of C++ template rules.
+ this->mHandleAllocator.release(handle.value);
+
+ if (memoryObject)
+ {
+ memoryObject->release(context);
+ }
+}
+
+MemoryObject *MemoryObjectManager::getMemoryObject(MemoryObjectID handle) const
+{
+ return mMemoryObjects.query(handle);
+}
+
+// SemaphoreManager Implementation.
+
+SemaphoreManager::SemaphoreManager() {}
+
+SemaphoreManager::~SemaphoreManager()
+{
+ ASSERT(mSemaphores.empty());
+}
+
+void SemaphoreManager::reset(const Context *context)
+{
+ while (!mSemaphores.empty())
+ {
+ deleteSemaphore(context, {mSemaphores.begin()->first});
+ }
+ mSemaphores.clear();
+}
+
+SemaphoreID SemaphoreManager::createSemaphore(rx::GLImplFactory *factory)
+{
+ SemaphoreID handle = SemaphoreID{mHandleAllocator.allocate()};
+ Semaphore *semaphore = new Semaphore(factory, handle);
+ semaphore->addRef();
+ mSemaphores.assign(handle, semaphore);
+ return handle;
+}
+
+void SemaphoreManager::deleteSemaphore(const Context *context, SemaphoreID handle)
+{
+ Semaphore *semaphore = nullptr;
+ if (!mSemaphores.erase(handle, &semaphore))
+ {
+ return;
+ }
+
+ // Requires an explicit this-> because of C++ template rules.
+ this->mHandleAllocator.release(handle.value);
+
+ if (semaphore)
+ {
+ semaphore->release(context);
+ }
+}
+
+Semaphore *SemaphoreManager::getSemaphore(SemaphoreID handle) const
+{
+ return mSemaphores.query(handle);
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/ResourceManager.h b/gfx/angle/checkout/src/libANGLE/ResourceManager.h
new file mode 100644
index 0000000000..0f8447ed24
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/ResourceManager.h
@@ -0,0 +1,353 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ResourceManager.h : Defines the ResourceManager classes, which handle allocation and lifetime of
+// GL objects.
+
+#ifndef LIBANGLE_RESOURCEMANAGER_H_
+#define LIBANGLE_RESOURCEMANAGER_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/HandleAllocator.h"
+#include "libANGLE/ResourceMap.h"
+
+namespace rx
+{
+class GLImplFactory;
+} // namespace rx
+
+namespace egl
+{
+class ShareGroup;
+} // namespace egl
+
+namespace gl
+{
+class Buffer;
+struct Caps;
+class Context;
+class Framebuffer;
+struct Limitations;
+class MemoryObject;
+class Path;
+class Program;
+class ProgramPipeline;
+class Renderbuffer;
+class Sampler;
+class Semaphore;
+class Shader;
+class Sync;
+class Texture;
+
+class ResourceManagerBase : angle::NonCopyable
+{
+ public:
+ ResourceManagerBase();
+
+ void addRef();
+ void release(const Context *context);
+
+ protected:
+ virtual void reset(const Context *context) = 0;
+ virtual ~ResourceManagerBase();
+
+ HandleAllocator mHandleAllocator;
+
+ private:
+ size_t mRefCount;
+};
+
+template <typename ResourceType, typename ImplT, typename IDType>
+class TypedResourceManager : public ResourceManagerBase
+{
+ public:
+ TypedResourceManager() {}
+
+ void deleteObject(const Context *context, IDType handle);
+ ANGLE_INLINE bool isHandleGenerated(IDType handle) const
+ {
+ // Zero is always assumed to have been generated implicitly.
+ return GetIDValue(handle) == 0 || mObjectMap.contains(handle);
+ }
+
+ typename ResourceMap<ResourceType, IDType>::Iterator begin() const
+ {
+ return mObjectMap.begin();
+ }
+ typename ResourceMap<ResourceType, IDType>::Iterator end() const { return mObjectMap.end(); }
+
+ protected:
+ ~TypedResourceManager() override;
+
+ // Inlined in the header for performance.
+ template <typename... ArgTypes>
+ ANGLE_INLINE ResourceType *checkObjectAllocation(rx::GLImplFactory *factory,
+ IDType handle,
+ ArgTypes... args)
+ {
+ ResourceType *value = mObjectMap.query(handle);
+ if (value)
+ {
+ return value;
+ }
+
+ if (GetIDValue(handle) == 0)
+ {
+ return nullptr;
+ }
+
+ return checkObjectAllocationImpl(factory, handle, args...);
+ }
+
+ void reset(const Context *context) override;
+
+ ResourceMap<ResourceType, IDType> mObjectMap;
+
+ private:
+ template <typename... ArgTypes>
+ ResourceType *checkObjectAllocationImpl(rx::GLImplFactory *factory,
+ IDType handle,
+ ArgTypes... args)
+ {
+ ResourceType *object = ImplT::AllocateNewObject(factory, handle, args...);
+
+ if (!mObjectMap.contains(handle))
+ {
+ this->mHandleAllocator.reserve(GetIDValue(handle));
+ }
+ mObjectMap.assign(handle, object);
+
+ return object;
+ }
+};
+
+class BufferManager : public TypedResourceManager<Buffer, BufferManager, BufferID>
+{
+ public:
+ BufferID createBuffer();
+ Buffer *getBuffer(BufferID handle) const;
+
+ ANGLE_INLINE Buffer *checkBufferAllocation(rx::GLImplFactory *factory, BufferID handle)
+ {
+ return checkObjectAllocation(factory, handle);
+ }
+
+ // TODO(jmadill): Investigate design which doesn't expose these methods publicly.
+ static Buffer *AllocateNewObject(rx::GLImplFactory *factory, BufferID handle);
+ static void DeleteObject(const Context *context, Buffer *buffer);
+
+ protected:
+ ~BufferManager() override;
+};
+
+class ShaderProgramManager : public ResourceManagerBase
+{
+ public:
+ ShaderProgramManager();
+
+ ShaderProgramID createShader(rx::GLImplFactory *factory,
+ const Limitations &rendererLimitations,
+ ShaderType type);
+ void deleteShader(const Context *context, ShaderProgramID shader);
+ Shader *getShader(ShaderProgramID handle) const;
+
+ ShaderProgramID createProgram(rx::GLImplFactory *factory);
+ void deleteProgram(const Context *context, ShaderProgramID program);
+
+ ANGLE_INLINE Program *getProgram(ShaderProgramID handle) const
+ {
+ return mPrograms.query(handle);
+ }
+
+ // For capture and performance counters only.
+ const ResourceMap<Shader, ShaderProgramID> &getShadersForCapture() const { return mShaders; }
+ const ResourceMap<Program, ShaderProgramID> &getProgramsForCaptureAndPerf() const
+ {
+ return mPrograms;
+ }
+
+ protected:
+ ~ShaderProgramManager() override;
+
+ private:
+ template <typename ObjectType, typename IDType>
+ void deleteObject(const Context *context,
+ ResourceMap<ObjectType, IDType> *objectMap,
+ IDType id);
+
+ void reset(const Context *context) override;
+
+ ResourceMap<Shader, ShaderProgramID> mShaders;
+ ResourceMap<Program, ShaderProgramID> mPrograms;
+};
+
+class TextureManager : public TypedResourceManager<Texture, TextureManager, TextureID>
+{
+ public:
+ TextureID createTexture();
+ ANGLE_INLINE Texture *getTexture(TextureID handle) const
+ {
+ ASSERT(mObjectMap.query({0}) == nullptr);
+ return mObjectMap.query(handle);
+ }
+
+ void signalAllTexturesDirty() const;
+
+ ANGLE_INLINE Texture *checkTextureAllocation(rx::GLImplFactory *factory,
+ TextureID handle,
+ TextureType type)
+ {
+ return checkObjectAllocation(factory, handle, type);
+ }
+
+ static Texture *AllocateNewObject(rx::GLImplFactory *factory,
+ TextureID handle,
+ TextureType type);
+ static void DeleteObject(const Context *context, Texture *texture);
+
+ void enableHandleAllocatorLogging();
+
+ protected:
+ ~TextureManager() override;
+};
+
+class RenderbufferManager
+ : public TypedResourceManager<Renderbuffer, RenderbufferManager, RenderbufferID>
+{
+ public:
+ RenderbufferID createRenderbuffer();
+ Renderbuffer *getRenderbuffer(RenderbufferID handle) const;
+
+ Renderbuffer *checkRenderbufferAllocation(rx::GLImplFactory *factory, RenderbufferID handle)
+ {
+ return checkObjectAllocation(factory, handle);
+ }
+
+ static Renderbuffer *AllocateNewObject(rx::GLImplFactory *factory, RenderbufferID handle);
+ static void DeleteObject(const Context *context, Renderbuffer *renderbuffer);
+
+ protected:
+ ~RenderbufferManager() override;
+};
+
+class SamplerManager : public TypedResourceManager<Sampler, SamplerManager, SamplerID>
+{
+ public:
+ SamplerID createSampler();
+ Sampler *getSampler(SamplerID handle) const;
+ bool isSampler(SamplerID sampler) const;
+
+ Sampler *checkSamplerAllocation(rx::GLImplFactory *factory, SamplerID handle)
+ {
+ return checkObjectAllocation(factory, handle);
+ }
+
+ static Sampler *AllocateNewObject(rx::GLImplFactory *factory, SamplerID handle);
+ static void DeleteObject(const Context *context, Sampler *sampler);
+
+ protected:
+ ~SamplerManager() override;
+};
+
+class SyncManager : public TypedResourceManager<Sync, SyncManager, GLuint>
+{
+ public:
+ GLuint createSync(rx::GLImplFactory *factory);
+ Sync *getSync(GLuint handle) const;
+
+ static void DeleteObject(const Context *context, Sync *sync);
+
+ protected:
+ ~SyncManager() override;
+};
+
+class FramebufferManager
+ : public TypedResourceManager<Framebuffer, FramebufferManager, FramebufferID>
+{
+ public:
+ FramebufferID createFramebuffer();
+ Framebuffer *getFramebuffer(FramebufferID handle) const;
+ void setDefaultFramebuffer(Framebuffer *framebuffer);
+ Framebuffer *getDefaultFramebuffer() const;
+
+ void invalidateFramebufferCompletenessCache() const;
+
+ Framebuffer *checkFramebufferAllocation(rx::GLImplFactory *factory,
+ const Context *context,
+ FramebufferID handle)
+ {
+ return checkObjectAllocation(factory, handle, context);
+ }
+
+ static Framebuffer *AllocateNewObject(rx::GLImplFactory *factory,
+ FramebufferID handle,
+ const Context *context);
+ static void DeleteObject(const Context *context, Framebuffer *framebuffer);
+
+ protected:
+ ~FramebufferManager() override;
+};
+
+class ProgramPipelineManager
+ : public TypedResourceManager<ProgramPipeline, ProgramPipelineManager, ProgramPipelineID>
+{
+ public:
+ ProgramPipelineID createProgramPipeline();
+ ProgramPipeline *getProgramPipeline(ProgramPipelineID handle) const;
+
+ ProgramPipeline *checkProgramPipelineAllocation(rx::GLImplFactory *factory,
+ ProgramPipelineID handle)
+ {
+ return checkObjectAllocation(factory, handle);
+ }
+
+ static ProgramPipeline *AllocateNewObject(rx::GLImplFactory *factory, ProgramPipelineID handle);
+ static void DeleteObject(const Context *context, ProgramPipeline *pipeline);
+
+ protected:
+ ~ProgramPipelineManager() override;
+};
+
+class MemoryObjectManager : public ResourceManagerBase
+{
+ public:
+ MemoryObjectManager();
+
+ MemoryObjectID createMemoryObject(rx::GLImplFactory *factory);
+ void deleteMemoryObject(const Context *context, MemoryObjectID handle);
+ MemoryObject *getMemoryObject(MemoryObjectID handle) const;
+
+ protected:
+ ~MemoryObjectManager() override;
+
+ private:
+ void reset(const Context *context) override;
+
+ ResourceMap<MemoryObject, MemoryObjectID> mMemoryObjects;
+};
+
+class SemaphoreManager : public ResourceManagerBase
+{
+ public:
+ SemaphoreManager();
+
+ SemaphoreID createSemaphore(rx::GLImplFactory *factory);
+ void deleteSemaphore(const Context *context, SemaphoreID handle);
+ Semaphore *getSemaphore(SemaphoreID handle) const;
+
+ protected:
+ ~SemaphoreManager() override;
+
+ private:
+ void reset(const Context *context) override;
+
+ ResourceMap<Semaphore, SemaphoreID> mSemaphores;
+};
+} // namespace gl
+
+#endif // LIBANGLE_RESOURCEMANAGER_H_
diff --git a/gfx/angle/checkout/src/libANGLE/ResourceMap.h b/gfx/angle/checkout/src/libANGLE/ResourceMap.h
new file mode 100644
index 0000000000..b24c1e6240
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/ResourceMap.h
@@ -0,0 +1,346 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ResourceMap:
+// An optimized resource map which packs the first set of allocated objects into a
+// flat array, and then falls back to an unordered map for the higher handle values.
+//
+
+#ifndef LIBANGLE_RESOURCE_MAP_H_
+#define LIBANGLE_RESOURCE_MAP_H_
+
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+
+template <typename ResourceType, typename IDType>
+class ResourceMap final : angle::NonCopyable
+{
+ public:
+ ResourceMap();
+ ~ResourceMap();
+
+ ANGLE_INLINE ResourceType *query(IDType id) const
+ {
+ GLuint handle = GetIDValue(id);
+ if (handle < mFlatResourcesSize)
+ {
+ ResourceType *value = mFlatResources[handle];
+ return (value == InvalidPointer() ? nullptr : value);
+ }
+ auto it = mHashedResources.find(handle);
+ return (it == mHashedResources.end() ? nullptr : it->second);
+ }
+
+ // Returns true if the handle was reserved. Not necessarily if the resource is created.
+ bool contains(IDType id) const;
+
+ // Returns the element that was at this location.
+ bool erase(IDType id, ResourceType **resourceOut);
+
+ void assign(IDType id, ResourceType *resource);
+
+ // Clears the map.
+ void clear();
+
+ using IndexAndResource = std::pair<GLuint, ResourceType *>;
+ using HashMap = angle::HashMap<GLuint, ResourceType *>;
+
+ class Iterator final
+ {
+ public:
+ bool operator==(const Iterator &other) const;
+ bool operator!=(const Iterator &other) const;
+ Iterator &operator++();
+ const IndexAndResource *operator->() const;
+ const IndexAndResource &operator*() const;
+
+ private:
+ friend class ResourceMap;
+ Iterator(const ResourceMap &origin,
+ GLuint flatIndex,
+ typename HashMap::const_iterator hashIndex,
+ bool skipNulls);
+ void updateValue();
+
+ const ResourceMap &mOrigin;
+ GLuint mFlatIndex;
+ typename HashMap::const_iterator mHashIndex;
+ IndexAndResource mValue;
+ bool mSkipNulls;
+ };
+
+ // null values represent reserved handles.
+ Iterator begin() const;
+ Iterator end() const;
+ Iterator find(IDType handle) const;
+
+ Iterator beginWithNull() const;
+ Iterator endWithNull() const;
+
+ // Not a constant-time operation, should only be used for verification.
+ bool empty() const;
+
+ private:
+ friend class Iterator;
+
+ GLuint nextResource(size_t flatIndex, bool skipNulls) const;
+
+ // constexpr methods cannot contain reinterpret_cast, so we need a static method.
+ static ResourceType *InvalidPointer();
+ static constexpr intptr_t kInvalidPointer = static_cast<intptr_t>(-1);
+
+ // Start with 32 maximum elements in the map, which can grow.
+ static constexpr size_t kInitialFlatResourcesSize = 0x20;
+
+ // Experimental testing suggests that 16k is a reasonable upper limit.
+ static constexpr size_t kFlatResourcesLimit = 0x4000;
+
+ // Size of one map element.
+ static constexpr size_t kElementSize = sizeof(ResourceType *);
+
+ size_t mFlatResourcesSize;
+ ResourceType **mFlatResources;
+
+ // A map of GL objects indexed by object ID.
+ HashMap mHashedResources;
+};
+
+template <typename ResourceType, typename IDType>
+ResourceMap<ResourceType, IDType>::ResourceMap()
+ : mFlatResourcesSize(kInitialFlatResourcesSize),
+ mFlatResources(new ResourceType *[kInitialFlatResourcesSize])
+{
+ memset(mFlatResources, kInvalidPointer, mFlatResourcesSize * kElementSize);
+}
+
+template <typename ResourceType, typename IDType>
+ResourceMap<ResourceType, IDType>::~ResourceMap()
+{
+ ASSERT(empty());
+ delete[] mFlatResources;
+}
+
+template <typename ResourceType, typename IDType>
+ANGLE_INLINE bool ResourceMap<ResourceType, IDType>::contains(IDType id) const
+{
+ GLuint handle = GetIDValue(id);
+ if (handle < mFlatResourcesSize)
+ {
+ return (mFlatResources[handle] != InvalidPointer());
+ }
+ return (mHashedResources.find(handle) != mHashedResources.end());
+}
+
+template <typename ResourceType, typename IDType>
+bool ResourceMap<ResourceType, IDType>::erase(IDType id, ResourceType **resourceOut)
+{
+ GLuint handle = GetIDValue(id);
+ if (handle < mFlatResourcesSize)
+ {
+ auto &value = mFlatResources[handle];
+ if (value == InvalidPointer())
+ {
+ return false;
+ }
+ *resourceOut = value;
+ value = InvalidPointer();
+ }
+ else
+ {
+ auto it = mHashedResources.find(handle);
+ if (it == mHashedResources.end())
+ {
+ return false;
+ }
+ *resourceOut = it->second;
+ mHashedResources.erase(it);
+ }
+ return true;
+}
+
+template <typename ResourceType, typename IDType>
+void ResourceMap<ResourceType, IDType>::assign(IDType id, ResourceType *resource)
+{
+ GLuint handle = GetIDValue(id);
+ if (handle < kFlatResourcesLimit)
+ {
+ if (handle >= mFlatResourcesSize)
+ {
+ // Use power-of-two.
+ size_t newSize = mFlatResourcesSize;
+ while (newSize <= handle)
+ {
+ newSize *= 2;
+ }
+
+ ResourceType **oldResources = mFlatResources;
+
+ mFlatResources = new ResourceType *[newSize];
+ memset(&mFlatResources[mFlatResourcesSize], kInvalidPointer,
+ (newSize - mFlatResourcesSize) * kElementSize);
+ memcpy(mFlatResources, oldResources, mFlatResourcesSize * kElementSize);
+ mFlatResourcesSize = newSize;
+ delete[] oldResources;
+ }
+ ASSERT(mFlatResourcesSize > handle);
+ mFlatResources[handle] = resource;
+ }
+ else
+ {
+ mHashedResources[handle] = resource;
+ }
+}
+
+template <typename ResourceType, typename IDType>
+typename ResourceMap<ResourceType, IDType>::Iterator ResourceMap<ResourceType, IDType>::begin()
+ const
+{
+ return Iterator(*this, nextResource(0, true), mHashedResources.begin(), true);
+}
+
+template <typename ResourceType, typename IDType>
+typename ResourceMap<ResourceType, IDType>::Iterator ResourceMap<ResourceType, IDType>::end() const
+{
+ return Iterator(*this, static_cast<GLuint>(mFlatResourcesSize), mHashedResources.end(), true);
+}
+
+template <typename ResourceType, typename IDType>
+typename ResourceMap<ResourceType, IDType>::Iterator
+ResourceMap<ResourceType, IDType>::beginWithNull() const
+{
+ return Iterator(*this, nextResource(0, false), mHashedResources.begin(), false);
+}
+
+template <typename ResourceType, typename IDType>
+typename ResourceMap<ResourceType, IDType>::Iterator
+ResourceMap<ResourceType, IDType>::endWithNull() const
+{
+ return Iterator(*this, static_cast<GLuint>(mFlatResourcesSize), mHashedResources.end(), false);
+}
+
+template <typename ResourceType, typename IDType>
+typename ResourceMap<ResourceType, IDType>::Iterator ResourceMap<ResourceType, IDType>::find(
+ IDType handle) const
+{
+ if (handle < mFlatResourcesSize)
+ {
+ return (mFlatResources[handle] != InvalidPointer()
+ ? Iterator(handle, mHashedResources.begin())
+ : end());
+ }
+ else
+ {
+ return mHashedResources.find(handle);
+ }
+}
+
+template <typename ResourceType, typename IDType>
+bool ResourceMap<ResourceType, IDType>::empty() const
+{
+ return (begin() == end());
+}
+
+template <typename ResourceType, typename IDType>
+void ResourceMap<ResourceType, IDType>::clear()
+{
+ memset(mFlatResources, kInvalidPointer, kInitialFlatResourcesSize * kElementSize);
+ mFlatResourcesSize = kInitialFlatResourcesSize;
+ mHashedResources.clear();
+}
+
+template <typename ResourceType, typename IDType>
+GLuint ResourceMap<ResourceType, IDType>::nextResource(size_t flatIndex, bool skipNulls) const
+{
+ for (size_t index = flatIndex; index < mFlatResourcesSize; index++)
+ {
+ if ((mFlatResources[index] != nullptr || !skipNulls) &&
+ mFlatResources[index] != InvalidPointer())
+ {
+ return static_cast<GLuint>(index);
+ }
+ }
+ return static_cast<GLuint>(mFlatResourcesSize);
+}
+
+template <typename ResourceType, typename IDType>
+// static
+ResourceType *ResourceMap<ResourceType, IDType>::InvalidPointer()
+{
+ return reinterpret_cast<ResourceType *>(kInvalidPointer);
+}
+
+template <typename ResourceType, typename IDType>
+ResourceMap<ResourceType, IDType>::Iterator::Iterator(
+ const ResourceMap &origin,
+ GLuint flatIndex,
+ typename ResourceMap<ResourceType, IDType>::HashMap::const_iterator hashIndex,
+ bool skipNulls)
+ : mOrigin(origin), mFlatIndex(flatIndex), mHashIndex(hashIndex), mSkipNulls(skipNulls)
+{
+ updateValue();
+}
+
+template <typename ResourceType, typename IDType>
+bool ResourceMap<ResourceType, IDType>::Iterator::operator==(const Iterator &other) const
+{
+ return (mFlatIndex == other.mFlatIndex && mHashIndex == other.mHashIndex);
+}
+
+template <typename ResourceType, typename IDType>
+bool ResourceMap<ResourceType, IDType>::Iterator::operator!=(const Iterator &other) const
+{
+ return !(*this == other);
+}
+
+template <typename ResourceType, typename IDType>
+typename ResourceMap<ResourceType, IDType>::Iterator &
+ResourceMap<ResourceType, IDType>::Iterator::operator++()
+{
+ if (mFlatIndex < static_cast<GLuint>(mOrigin.mFlatResourcesSize))
+ {
+ mFlatIndex = mOrigin.nextResource(mFlatIndex + 1, mSkipNulls);
+ }
+ else
+ {
+ mHashIndex++;
+ }
+ updateValue();
+ return *this;
+}
+
+template <typename ResourceType, typename IDType>
+const typename ResourceMap<ResourceType, IDType>::IndexAndResource *
+ResourceMap<ResourceType, IDType>::Iterator::operator->() const
+{
+ return &mValue;
+}
+
+template <typename ResourceType, typename IDType>
+const typename ResourceMap<ResourceType, IDType>::IndexAndResource &
+ResourceMap<ResourceType, IDType>::Iterator::operator*() const
+{
+ return mValue;
+}
+
+template <typename ResourceType, typename IDType>
+void ResourceMap<ResourceType, IDType>::Iterator::updateValue()
+{
+ if (mFlatIndex < static_cast<GLuint>(mOrigin.mFlatResourcesSize))
+ {
+ mValue.first = mFlatIndex;
+ mValue.second = mOrigin.mFlatResources[mFlatIndex];
+ }
+ else if (mHashIndex != mOrigin.mHashedResources.end())
+ {
+ mValue.first = mHashIndex->first;
+ mValue.second = mHashIndex->second;
+ }
+}
+
+} // namespace gl
+
+#endif // LIBANGLE_RESOURCE_MAP_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Sampler.cpp b/gfx/angle/checkout/src/libANGLE/Sampler.cpp
new file mode 100644
index 0000000000..3cfdbbdf4f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Sampler.cpp
@@ -0,0 +1,211 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Sampler.cpp : Implements the Sampler class, which represents a GLES 3
+// sampler object. Sampler objects store some state needed to sample textures.
+
+#include "libANGLE/Sampler.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/SamplerImpl.h"
+
+namespace gl
+{
+
+Sampler::Sampler(rx::GLImplFactory *factory, SamplerID id)
+ : RefCountObject(factory->generateSerial(), id),
+ mState(),
+ mDirty(true),
+ mSampler(factory->createSampler(mState)),
+ mLabel()
+{}
+
+Sampler::~Sampler()
+{
+ SafeDelete(mSampler);
+}
+
+void Sampler::onDestroy(const Context *context)
+{
+ if (mSampler)
+ {
+ mSampler->onDestroy(context);
+ }
+}
+
+angle::Result Sampler::setLabel(const Context *context, const std::string &label)
+{
+ mLabel = label;
+
+ if (mSampler)
+ {
+ return mSampler->onLabelUpdate(context);
+ }
+ return angle::Result::Continue;
+}
+
+const std::string &Sampler::getLabel() const
+{
+ return mLabel;
+}
+
+void Sampler::setMinFilter(const Context *context, GLenum minFilter)
+{
+ mState.setMinFilter(minFilter);
+ signalDirtyState();
+}
+
+GLenum Sampler::getMinFilter() const
+{
+ return mState.getMinFilter();
+}
+
+void Sampler::setMagFilter(const Context *context, GLenum magFilter)
+{
+ mState.setMagFilter(magFilter);
+ signalDirtyState();
+}
+
+GLenum Sampler::getMagFilter() const
+{
+ return mState.getMagFilter();
+}
+
+void Sampler::setWrapS(const Context *context, GLenum wrapS)
+{
+ mState.setWrapS(wrapS);
+ signalDirtyState();
+}
+
+GLenum Sampler::getWrapS() const
+{
+ return mState.getWrapS();
+}
+
+void Sampler::setWrapT(const Context *context, GLenum wrapT)
+{
+ mState.setWrapT(wrapT);
+ signalDirtyState();
+}
+
+GLenum Sampler::getWrapT() const
+{
+ return mState.getWrapT();
+}
+
+void Sampler::setWrapR(const Context *context, GLenum wrapR)
+{
+ mState.setWrapR(wrapR);
+ signalDirtyState();
+}
+
+GLenum Sampler::getWrapR() const
+{
+ return mState.getWrapR();
+}
+
+void Sampler::setMaxAnisotropy(const Context *context, float maxAnisotropy)
+{
+ mState.setMaxAnisotropy(maxAnisotropy);
+ signalDirtyState();
+}
+
+float Sampler::getMaxAnisotropy() const
+{
+ return mState.getMaxAnisotropy();
+}
+
+void Sampler::setMinLod(const Context *context, GLfloat minLod)
+{
+ mState.setMinLod(minLod);
+ signalDirtyState();
+}
+
+GLfloat Sampler::getMinLod() const
+{
+ return mState.getMinLod();
+}
+
+void Sampler::setMaxLod(const Context *context, GLfloat maxLod)
+{
+ mState.setMaxLod(maxLod);
+ signalDirtyState();
+}
+
+GLfloat Sampler::getMaxLod() const
+{
+ return mState.getMaxLod();
+}
+
+void Sampler::setCompareMode(const Context *context, GLenum compareMode)
+{
+ mState.setCompareMode(compareMode);
+ signalDirtyState();
+}
+
+GLenum Sampler::getCompareMode() const
+{
+ return mState.getCompareMode();
+}
+
+void Sampler::setCompareFunc(const Context *context, GLenum compareFunc)
+{
+ mState.setCompareFunc(compareFunc);
+ signalDirtyState();
+}
+
+GLenum Sampler::getCompareFunc() const
+{
+ return mState.getCompareFunc();
+}
+
+void Sampler::setSRGBDecode(const Context *context, GLenum sRGBDecode)
+{
+ mState.setSRGBDecode(sRGBDecode);
+ signalDirtyState();
+}
+
+GLenum Sampler::getSRGBDecode() const
+{
+ return mState.getSRGBDecode();
+}
+
+void Sampler::setBorderColor(const Context *context, const ColorGeneric &color)
+{
+ mState.setBorderColor(color);
+ signalDirtyState();
+}
+
+const ColorGeneric &Sampler::getBorderColor() const
+{
+ return mState.getBorderColor();
+}
+
+const SamplerState &Sampler::getSamplerState() const
+{
+ return mState;
+}
+
+rx::SamplerImpl *Sampler::getImplementation() const
+{
+ return mSampler;
+}
+
+angle::Result Sampler::syncState(const Context *context)
+{
+ ASSERT(isDirty());
+ angle::Result result = mSampler->syncState(context, mDirty);
+ mDirty = result != angle::Result::Continue;
+ return result;
+}
+
+void Sampler::signalDirtyState()
+{
+ mDirty = true;
+ onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Sampler.h b/gfx/angle/checkout/src/libANGLE/Sampler.h
new file mode 100644
index 0000000000..b483593780
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Sampler.h
@@ -0,0 +1,92 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Sampler.h : Defines the Sampler class, which represents a GLES 3
+// sampler object. Sampler objects store some state needed to sample textures.
+
+#ifndef LIBANGLE_SAMPLER_H_
+#define LIBANGLE_SAMPLER_H_
+
+#include "libANGLE/Debug.h"
+#include "libANGLE/Observer.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+class GLImplFactory;
+class SamplerImpl;
+} // namespace rx
+
+namespace gl
+{
+
+class Sampler final : public RefCountObject<SamplerID>, public LabeledObject, public angle::Subject
+{
+ public:
+ Sampler(rx::GLImplFactory *factory, SamplerID id);
+ ~Sampler() override;
+
+ void onDestroy(const Context *context) override;
+
+ angle::Result setLabel(const Context *context, const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ void setMinFilter(const Context *context, GLenum minFilter);
+ GLenum getMinFilter() const;
+
+ void setMagFilter(const Context *context, GLenum magFilter);
+ GLenum getMagFilter() const;
+
+ void setWrapS(const Context *context, GLenum wrapS);
+ GLenum getWrapS() const;
+
+ void setWrapT(const Context *context, GLenum wrapT);
+ GLenum getWrapT() const;
+
+ void setWrapR(const Context *context, GLenum wrapR);
+ GLenum getWrapR() const;
+
+ void setMaxAnisotropy(const Context *context, float maxAnisotropy);
+ float getMaxAnisotropy() const;
+
+ void setMinLod(const Context *context, GLfloat minLod);
+ GLfloat getMinLod() const;
+
+ void setMaxLod(const Context *context, GLfloat maxLod);
+ GLfloat getMaxLod() const;
+
+ void setCompareMode(const Context *context, GLenum compareMode);
+ GLenum getCompareMode() const;
+
+ void setCompareFunc(const Context *context, GLenum compareFunc);
+ GLenum getCompareFunc() const;
+
+ void setSRGBDecode(const Context *context, GLenum sRGBDecode);
+ GLenum getSRGBDecode() const;
+
+ void setBorderColor(const Context *context, const ColorGeneric &color);
+ const ColorGeneric &getBorderColor() const;
+
+ const SamplerState &getSamplerState() const;
+
+ rx::SamplerImpl *getImplementation() const;
+
+ angle::Result syncState(const Context *context);
+ bool isDirty() const { return mDirty; }
+
+ private:
+ void signalDirtyState();
+ SamplerState mState;
+ bool mDirty;
+ rx::SamplerImpl *mSampler;
+
+ std::string mLabel;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_SAMPLER_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Semaphore.cpp b/gfx/angle/checkout/src/libANGLE/Semaphore.cpp
new file mode 100644
index 0000000000..45621653e3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Semaphore.cpp
@@ -0,0 +1,52 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Semaphore.h: Implements the gl::Semaphore class [EXT_external_objects]
+
+#include "libANGLE/Semaphore.h"
+
+#include "common/angleutils.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/SemaphoreImpl.h"
+
+namespace gl
+{
+
+Semaphore::Semaphore(rx::GLImplFactory *factory, SemaphoreID id)
+ : RefCountObject(factory->generateSerial(), id), mImplementation(factory->createSemaphore())
+{}
+
+Semaphore::~Semaphore() {}
+
+void Semaphore::onDestroy(const Context *context)
+{
+ mImplementation->onDestroy(context);
+}
+
+angle::Result Semaphore::importFd(Context *context, HandleType handleType, GLint fd)
+{
+ return mImplementation->importFd(context, handleType, fd);
+}
+
+angle::Result Semaphore::importZirconHandle(Context *context, HandleType handleType, GLuint handle)
+{
+ return mImplementation->importZirconHandle(context, handleType, handle);
+}
+
+angle::Result Semaphore::wait(Context *context,
+ const BufferBarrierVector &bufferBarriers,
+ const TextureBarrierVector &textureBarriers)
+{
+ return mImplementation->wait(context, bufferBarriers, textureBarriers);
+}
+
+angle::Result Semaphore::signal(Context *context,
+ const BufferBarrierVector &bufferBarriers,
+ const TextureBarrierVector &textureBarriers)
+{
+ return mImplementation->signal(context, bufferBarriers, textureBarriers);
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Semaphore.h b/gfx/angle/checkout/src/libANGLE/Semaphore.h
new file mode 100644
index 0000000000..02bdabedca
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Semaphore.h
@@ -0,0 +1,57 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Semaphore.h: Defines the gl::Semaphore class [EXT_external_objects]
+
+#ifndef LIBANGLE_SEMAPHORE_H_
+#define LIBANGLE_SEMAPHORE_H_
+
+#include <memory>
+
+#include "angle_gl.h"
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+class GLImplFactory;
+class SemaphoreImpl;
+} // namespace rx
+
+namespace gl
+{
+class Context;
+
+class Semaphore final : public RefCountObject<SemaphoreID>
+{
+ public:
+ Semaphore(rx::GLImplFactory *factory, SemaphoreID id);
+ ~Semaphore() override;
+
+ void onDestroy(const Context *context) override;
+
+ rx::SemaphoreImpl *getImplementation() const { return mImplementation.get(); }
+
+ angle::Result importFd(Context *context, HandleType handleType, GLint fd);
+ angle::Result importZirconHandle(Context *context, HandleType handleType, GLuint handle);
+
+ angle::Result wait(Context *context,
+ const BufferBarrierVector &bufferBarriers,
+ const TextureBarrierVector &textureBarriers);
+
+ angle::Result signal(Context *context,
+ const BufferBarrierVector &bufferBarriers,
+ const TextureBarrierVector &textureBarriers);
+
+ private:
+ std::unique_ptr<rx::SemaphoreImpl> mImplementation;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_SEMAPHORE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Shader.cpp b/gfx/angle/checkout/src/libANGLE/Shader.cpp
new file mode 100644
index 0000000000..b1a718131a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Shader.cpp
@@ -0,0 +1,1331 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Shader.cpp: Implements the gl::Shader class and its derived classes
+// VertexShader and FragmentShader. Implements GL shader objects and related
+// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
+
+#include "libANGLE/Shader.h"
+
+#include <functional>
+#include <sstream>
+
+#include "GLSLANG/ShaderLang.h"
+#include "common/utilities.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/MemoryShaderCache.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/ShaderImpl.h"
+#include "platform/FrontendFeatures_autogen.h"
+
+namespace gl
+{
+
+namespace
+{
+constexpr uint32_t kShaderCacheIdentifier = 0x12345678;
+
+template <typename VarT>
+std::vector<VarT> GetActiveShaderVariables(const std::vector<VarT> *variableList)
+{
+ ASSERT(variableList);
+ std::vector<VarT> result;
+ for (size_t varIndex = 0; varIndex < variableList->size(); varIndex++)
+ {
+ const VarT &var = variableList->at(varIndex);
+ if (var.active)
+ {
+ result.push_back(var);
+ }
+ }
+ return result;
+}
+
+template <typename VarT>
+const std::vector<VarT> &GetShaderVariables(const std::vector<VarT> *variableList)
+{
+ ASSERT(variableList);
+ return *variableList;
+}
+
+void WriteInterfaceBlock(gl::BinaryOutputStream *stream, const sh::InterfaceBlock &block)
+{
+ stream->writeString(block.name);
+ stream->writeString(block.mappedName);
+ stream->writeString(block.instanceName);
+ stream->writeInt(block.arraySize);
+ stream->writeEnum(block.layout);
+ stream->writeBool(block.isRowMajorLayout);
+ stream->writeInt(block.binding);
+ stream->writeBool(block.staticUse);
+ stream->writeBool(block.active);
+ stream->writeEnum(block.blockType);
+
+ stream->writeInt(block.fields.size());
+ for (const sh::ShaderVariable &shaderVariable : block.fields)
+ {
+ WriteShaderVar(stream, shaderVariable);
+ }
+}
+
+void LoadInterfaceBlock(gl::BinaryInputStream *stream, sh::InterfaceBlock &block)
+{
+ stream->readString(&block.name);
+ stream->readString(&block.mappedName);
+ stream->readString(&block.instanceName);
+ stream->readInt(&block.arraySize);
+ stream->readEnum(&block.layout);
+ stream->readBool(&block.isRowMajorLayout);
+ stream->readInt(&block.binding);
+ stream->readBool(&block.staticUse);
+ stream->readBool(&block.active);
+ stream->readEnum(&block.blockType);
+
+ size_t size = stream->readInt<size_t>();
+ block.fields.resize(size);
+ for (sh::ShaderVariable &shaderVariable : block.fields)
+ {
+ LoadShaderVar(stream, &shaderVariable);
+ }
+}
+} // anonymous namespace
+
+// true if varying x has a higher priority in packing than y
+bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y)
+{
+ if (x.type == y.type)
+ {
+ return x.getArraySizeProduct() > y.getArraySizeProduct();
+ }
+
+ // Special case for handling structs: we sort these to the end of the list
+ if (x.type == GL_NONE)
+ {
+ return false;
+ }
+
+ if (y.type == GL_NONE)
+ {
+ return true;
+ }
+
+ return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type);
+}
+
+const char *GetShaderTypeString(ShaderType type)
+{
+ switch (type)
+ {
+ case ShaderType::Vertex:
+ return "VERTEX";
+
+ case ShaderType::Fragment:
+ return "FRAGMENT";
+
+ case ShaderType::Compute:
+ return "COMPUTE";
+
+ case ShaderType::Geometry:
+ return "GEOMETRY";
+
+ case ShaderType::TessControl:
+ return "TESS_CONTROL";
+
+ case ShaderType::TessEvaluation:
+ return "TESS_EVALUATION";
+
+ default:
+ UNREACHABLE();
+ return "";
+ }
+}
+
+class [[nodiscard]] ScopedExit final : angle::NonCopyable
+{
+ public:
+ ScopedExit(std::function<void()> exit) : mExit(exit) {}
+ ~ScopedExit() { mExit(); }
+
+ private:
+ std::function<void()> mExit;
+};
+
+struct Shader::CompilingState
+{
+ std::shared_ptr<rx::WaitableCompileEvent> compileEvent;
+ ShCompilerInstance shCompilerInstance;
+ egl::BlobCache::Key shaderHash;
+};
+
+ShaderState::ShaderState(ShaderType shaderType)
+ : mLabel(),
+ mShaderType(shaderType),
+ mShaderVersion(100),
+ mNumViews(-1),
+ mGeometryShaderInvocations(1),
+ mCompileStatus(CompileStatus::NOT_COMPILED)
+{
+ mLocalSize.fill(-1);
+}
+
+ShaderState::~ShaderState() {}
+
+Shader::Shader(ShaderProgramManager *manager,
+ rx::GLImplFactory *implFactory,
+ const gl::Limitations &rendererLimitations,
+ ShaderType type,
+ ShaderProgramID handle)
+ : mState(type),
+ mImplementation(implFactory->createShader(mState)),
+ mRendererLimitations(rendererLimitations),
+ mHandle(handle),
+ mType(type),
+ mRefCount(0),
+ mDeleteStatus(false),
+ mResourceManager(manager),
+ mCurrentMaxComputeWorkGroupInvocations(0u)
+{
+ ASSERT(mImplementation);
+}
+
+void Shader::onDestroy(const gl::Context *context)
+{
+ resolveCompile(context);
+ mImplementation->destroy();
+ mBoundCompiler.set(context, nullptr);
+ mImplementation.reset(nullptr);
+ delete this;
+}
+
+Shader::~Shader()
+{
+ ASSERT(!mImplementation);
+}
+
+angle::Result Shader::setLabel(const Context *context, const std::string &label)
+{
+ mState.mLabel = label;
+
+ if (mImplementation)
+ {
+ return mImplementation->onLabelUpdate(context);
+ }
+ return angle::Result::Continue;
+}
+
+const std::string &Shader::getLabel() const
+{
+ return mState.mLabel;
+}
+
+ShaderProgramID Shader::getHandle() const
+{
+ return mHandle;
+}
+
+void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
+{
+ std::ostringstream stream;
+
+ for (int i = 0; i < count; i++)
+ {
+ if (length == nullptr || length[i] < 0)
+ {
+ stream.write(string[i], strlen(string[i]));
+ }
+ else
+ {
+ stream.write(string[i], length[i]);
+ }
+ }
+
+ mState.mSource = stream.str();
+}
+
+int Shader::getInfoLogLength(const Context *context)
+{
+ resolveCompile(context);
+ if (mInfoLog.empty())
+ {
+ return 0;
+ }
+
+ return (static_cast<int>(mInfoLog.length()) + 1);
+}
+
+void Shader::getInfoLog(const Context *context, GLsizei bufSize, GLsizei *length, char *infoLog)
+{
+ resolveCompile(context);
+
+ int index = 0;
+
+ if (bufSize > 0)
+ {
+ index = std::min(bufSize - 1, static_cast<GLsizei>(mInfoLog.length()));
+ memcpy(infoLog, mInfoLog.c_str(), index);
+
+ infoLog[index] = '\0';
+ }
+
+ if (length)
+ {
+ *length = index;
+ }
+}
+
+int Shader::getSourceLength() const
+{
+ return mState.mSource.empty() ? 0 : (static_cast<int>(mState.mSource.length()) + 1);
+}
+
+int Shader::getTranslatedSourceLength(const Context *context)
+{
+ resolveCompile(context);
+
+ if (mState.mTranslatedSource.empty())
+ {
+ return 0;
+ }
+
+ return (static_cast<int>(mState.mTranslatedSource.length()) + 1);
+}
+
+int Shader::getTranslatedSourceWithDebugInfoLength(const Context *context)
+{
+ resolveCompile(context);
+
+ const std::string &debugInfo = mImplementation->getDebugInfo();
+ if (debugInfo.empty())
+ {
+ return 0;
+ }
+
+ return (static_cast<int>(debugInfo.length()) + 1);
+}
+
+// static
+void Shader::GetSourceImpl(const std::string &source,
+ GLsizei bufSize,
+ GLsizei *length,
+ char *buffer)
+{
+ int index = 0;
+
+ if (bufSize > 0)
+ {
+ index = std::min(bufSize - 1, static_cast<GLsizei>(source.length()));
+ memcpy(buffer, source.c_str(), index);
+
+ buffer[index] = '\0';
+ }
+
+ if (length)
+ {
+ *length = index;
+ }
+}
+
+void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const
+{
+ GetSourceImpl(mState.mSource, bufSize, length, buffer);
+}
+
+void Shader::getTranslatedSource(const Context *context,
+ GLsizei bufSize,
+ GLsizei *length,
+ char *buffer)
+{
+ GetSourceImpl(getTranslatedSource(context), bufSize, length, buffer);
+}
+
+const std::string &Shader::getTranslatedSource(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mTranslatedSource;
+}
+
+const sh::BinaryBlob &Shader::getCompiledBinary(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mCompiledBinary;
+}
+
+void Shader::getTranslatedSourceWithDebugInfo(const Context *context,
+ GLsizei bufSize,
+ GLsizei *length,
+ char *buffer)
+{
+ resolveCompile(context);
+ const std::string &debugInfo = mImplementation->getDebugInfo();
+ GetSourceImpl(debugInfo, bufSize, length, buffer);
+}
+
+void Shader::compile(const Context *context)
+{
+ resolveCompile(context);
+
+ mState.mTranslatedSource.clear();
+ mState.mCompiledBinary.clear();
+ mInfoLog.clear();
+ mState.mShaderVersion = 100;
+ mState.mInputVaryings.clear();
+ mState.mOutputVaryings.clear();
+ mState.mUniforms.clear();
+ mState.mUniformBlocks.clear();
+ mState.mShaderStorageBlocks.clear();
+ mState.mActiveAttributes.clear();
+ mState.mActiveOutputVariables.clear();
+ mState.mNumViews = -1;
+ mState.mGeometryShaderInputPrimitiveType.reset();
+ mState.mGeometryShaderOutputPrimitiveType.reset();
+ mState.mGeometryShaderMaxVertices.reset();
+ mState.mGeometryShaderInvocations = 1;
+ mState.mTessControlShaderVertices = 0;
+ mState.mTessGenMode = 0;
+ mState.mTessGenSpacing = 0;
+ mState.mTessGenVertexOrder = 0;
+ mState.mTessGenPointMode = 0;
+ mState.mAdvancedBlendEquations.reset();
+ mState.mHasDiscard = false;
+ mState.mEnablesPerSampleShading = false;
+ mState.mSpecConstUsageBits.reset();
+
+ mCurrentMaxComputeWorkGroupInvocations =
+ static_cast<GLuint>(context->getCaps().maxComputeWorkGroupInvocations);
+ mMaxComputeSharedMemory = context->getCaps().maxComputeSharedMemorySize;
+
+ ShCompileOptions options = {};
+ options.objectCode = true;
+ options.variables = true;
+ options.emulateGLDrawID = true;
+
+ // Add default options to WebGL shaders to prevent unexpected behavior during
+ // compilation.
+ if (context->isWebGL())
+ {
+ options.initGLPosition = true;
+ options.limitCallStackDepth = true;
+ options.limitExpressionComplexity = true;
+ options.enforcePackingRestrictions = true;
+ options.initSharedVariables = true;
+ }
+ else
+ {
+ // Per https://github.com/KhronosGroup/WebGL/pull/3278 gl_BaseVertex/gl_BaseInstance are
+ // removed from WebGL
+ options.emulateGLBaseVertexBaseInstance = true;
+ }
+
+ // Some targets (e.g. D3D11 Feature Level 9_3 and below) do not support non-constant loop
+ // indexes in fragment shaders. Shader compilation will fail. To provide a better error
+ // message we can instruct the compiler to pre-validate.
+ if (mRendererLimitations.shadersRequireIndexedLoopValidation)
+ {
+ options.validateLoopIndexing = true;
+ }
+
+ if (context->getFrontendFeatures().scalarizeVecAndMatConstructorArgs.enabled)
+ {
+ options.scalarizeVecAndMatConstructorArgs = true;
+ }
+
+ if (context->getFrontendFeatures().forceInitShaderVariables.enabled)
+ {
+ options.initOutputVariables = true;
+ options.initializeUninitializedLocals = true;
+ }
+
+ mBoundCompiler.set(context, context->getCompiler());
+
+ ASSERT(mBoundCompiler.get());
+ ShCompilerInstance compilerInstance = mBoundCompiler->getInstance(mState.mShaderType);
+ ShHandle compilerHandle = compilerInstance.getHandle();
+ ASSERT(compilerHandle);
+ mCompilerResourcesString = compilerInstance.getBuiltinResourcesString();
+
+ // Find a shader in Blob Cache
+ egl::BlobCache::Key shaderHash = {0};
+ MemoryShaderCache *shaderCache = context->getMemoryShaderCache();
+ if (shaderCache)
+ {
+ angle::Result cacheResult =
+ shaderCache->getShader(context, this, options, compilerInstance, &shaderHash);
+
+ if (cacheResult == angle::Result::Continue)
+ {
+ compilerInstance.destroy();
+ return;
+ }
+ }
+
+ // Cache load failed, fall through normal compiling.
+ mState.mCompileStatus = CompileStatus::COMPILE_REQUESTED;
+ mCompilingState.reset(new CompilingState());
+ mCompilingState->shCompilerInstance = std::move(compilerInstance);
+ mCompilingState->shaderHash = shaderHash;
+ mCompilingState->compileEvent =
+ mImplementation->compile(context, &(mCompilingState->shCompilerInstance), &options);
+}
+
+void Shader::resolveCompile(const Context *context)
+{
+ if (!mState.compilePending())
+ {
+ return;
+ }
+
+ ASSERT(mCompilingState.get());
+
+ mCompilingState->compileEvent->wait();
+
+ mInfoLog += mCompilingState->compileEvent->getInfoLog();
+
+ ScopedExit exit([this]() {
+ mBoundCompiler->putInstance(std::move(mCompilingState->shCompilerInstance));
+ mCompilingState->compileEvent.reset();
+ mCompilingState.reset();
+ });
+
+ ShHandle compilerHandle = mCompilingState->shCompilerInstance.getHandle();
+ if (!mCompilingState->compileEvent->getResult())
+ {
+ mInfoLog += sh::GetInfoLog(compilerHandle);
+ INFO() << std::endl << mInfoLog;
+ mState.mCompileStatus = CompileStatus::NOT_COMPILED;
+ return;
+ }
+
+ const ShShaderOutput outputType = mCompilingState->shCompilerInstance.getShaderOutputType();
+ const bool isBinaryOutput =
+ outputType == SH_SPIRV_VULKAN_OUTPUT || outputType == SH_SPIRV_METAL_OUTPUT;
+
+ if (isBinaryOutput)
+ {
+ mState.mCompiledBinary = sh::GetObjectBinaryBlob(compilerHandle);
+ }
+ else
+ {
+ mState.mTranslatedSource = sh::GetObjectCode(compilerHandle);
+
+#if !defined(NDEBUG)
+ // Prefix translated shader with commented out un-translated shader.
+ // Useful in diagnostics tools which capture the shader source.
+ std::ostringstream shaderStream;
+ shaderStream << "// GLSL\n";
+ shaderStream << "//\n";
+
+ std::istringstream inputSourceStream(mState.mSource);
+ std::string line;
+ while (std::getline(inputSourceStream, line))
+ {
+ // Remove null characters from the source line
+ line.erase(std::remove(line.begin(), line.end(), '\0'), line.end());
+
+ shaderStream << "// " << line;
+
+ // glslang complains if a comment ends with backslash
+ if (!line.empty() && line.back() == '\\')
+ {
+ shaderStream << "\\";
+ }
+
+ shaderStream << std::endl;
+ }
+ shaderStream << "\n\n";
+ shaderStream << mState.mTranslatedSource;
+ mState.mTranslatedSource = shaderStream.str();
+#endif // !defined(NDEBUG)
+ }
+
+ // Gather the shader information
+ mState.mShaderVersion = sh::GetShaderVersion(compilerHandle);
+
+ mState.mUniforms = GetShaderVariables(sh::GetUniforms(compilerHandle));
+ mState.mUniformBlocks = GetShaderVariables(sh::GetUniformBlocks(compilerHandle));
+ mState.mShaderStorageBlocks = GetShaderVariables(sh::GetShaderStorageBlocks(compilerHandle));
+ mState.mSpecConstUsageBits =
+ rx::SpecConstUsageBits(sh::GetShaderSpecConstUsageBits(compilerHandle));
+
+ switch (mState.mShaderType)
+ {
+ case ShaderType::Compute:
+ {
+ mState.mAllAttributes = GetShaderVariables(sh::GetAttributes(compilerHandle));
+ mState.mActiveAttributes = GetActiveShaderVariables(&mState.mAllAttributes);
+ mState.mLocalSize = sh::GetComputeShaderLocalGroupSize(compilerHandle);
+ if (mState.mLocalSize.isDeclared())
+ {
+ angle::CheckedNumeric<uint32_t> checked_local_size_product(mState.mLocalSize[0]);
+ checked_local_size_product *= mState.mLocalSize[1];
+ checked_local_size_product *= mState.mLocalSize[2];
+
+ if (!checked_local_size_product.IsValid())
+ {
+ WARN() << std::endl
+ << "Integer overflow when computing the product of local_size_x, "
+ << "local_size_y and local_size_z.";
+ mState.mCompileStatus = CompileStatus::NOT_COMPILED;
+ return;
+ }
+ if (checked_local_size_product.ValueOrDie() >
+ mCurrentMaxComputeWorkGroupInvocations)
+ {
+ WARN() << std::endl
+ << "The total number of invocations within a work group exceeds "
+ << "MAX_COMPUTE_WORK_GROUP_INVOCATIONS.";
+ mState.mCompileStatus = CompileStatus::NOT_COMPILED;
+ return;
+ }
+ }
+
+ unsigned int sharedMemSize = sh::GetShaderSharedMemorySize(compilerHandle);
+ if (sharedMemSize > mMaxComputeSharedMemory)
+ {
+ WARN() << std::endl << "Exceeded maximum shared memory size";
+ mState.mCompileStatus = CompileStatus::NOT_COMPILED;
+ return;
+ }
+ break;
+ }
+ case ShaderType::Vertex:
+ {
+ mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
+ mState.mAllAttributes = GetShaderVariables(sh::GetAttributes(compilerHandle));
+ mState.mActiveAttributes = GetActiveShaderVariables(&mState.mAllAttributes);
+ mState.mNumViews = sh::GetVertexShaderNumViews(compilerHandle);
+ break;
+ }
+ case ShaderType::Fragment:
+ {
+ mState.mAllAttributes = GetShaderVariables(sh::GetAttributes(compilerHandle));
+ mState.mActiveAttributes = GetActiveShaderVariables(&mState.mAllAttributes);
+ mState.mInputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
+ // TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
+ std::sort(mState.mInputVaryings.begin(), mState.mInputVaryings.end(), CompareShaderVar);
+ mState.mActiveOutputVariables =
+ GetActiveShaderVariables(sh::GetOutputVariables(compilerHandle));
+ mState.mHasDiscard = sh::HasDiscardInFragmentShader(compilerHandle);
+ mState.mEnablesPerSampleShading = sh::EnablesPerSampleShading(compilerHandle);
+ mState.mAdvancedBlendEquations =
+ BlendEquationBitSet(sh::GetAdvancedBlendEquations(compilerHandle));
+ break;
+ }
+ case ShaderType::Geometry:
+ {
+ mState.mInputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
+ mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
+
+ if (sh::HasValidGeometryShaderInputPrimitiveType(compilerHandle))
+ {
+ mState.mGeometryShaderInputPrimitiveType = FromGLenum<PrimitiveMode>(
+ sh::GetGeometryShaderInputPrimitiveType(compilerHandle));
+ }
+ if (sh::HasValidGeometryShaderOutputPrimitiveType(compilerHandle))
+ {
+ mState.mGeometryShaderOutputPrimitiveType = FromGLenum<PrimitiveMode>(
+ sh::GetGeometryShaderOutputPrimitiveType(compilerHandle));
+ }
+ if (sh::HasValidGeometryShaderMaxVertices(compilerHandle))
+ {
+ mState.mGeometryShaderMaxVertices =
+ sh::GetGeometryShaderMaxVertices(compilerHandle);
+ }
+ mState.mGeometryShaderInvocations = sh::GetGeometryShaderInvocations(compilerHandle);
+ break;
+ }
+ case ShaderType::TessControl:
+ {
+ mState.mInputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
+ mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
+ mState.mTessControlShaderVertices = sh::GetTessControlShaderVertices(compilerHandle);
+ break;
+ }
+ case ShaderType::TessEvaluation:
+ {
+ mState.mInputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
+ mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
+ if (sh::HasValidTessGenMode(compilerHandle))
+ {
+ mState.mTessGenMode = sh::GetTessGenMode(compilerHandle);
+ }
+ if (sh::HasValidTessGenSpacing(compilerHandle))
+ {
+ mState.mTessGenSpacing = sh::GetTessGenSpacing(compilerHandle);
+ }
+ if (sh::HasValidTessGenVertexOrder(compilerHandle))
+ {
+ mState.mTessGenVertexOrder = sh::GetTessGenVertexOrder(compilerHandle);
+ }
+ if (sh::HasValidTessGenPointMode(compilerHandle))
+ {
+ mState.mTessGenPointMode = sh::GetTessGenPointMode(compilerHandle);
+ }
+ break;
+ }
+
+ default:
+ UNREACHABLE();
+ }
+
+ ASSERT(!mState.mTranslatedSource.empty() || !mState.mCompiledBinary.empty());
+
+ bool success = mCompilingState->compileEvent->postTranslate(&mInfoLog);
+ mState.mCompileStatus = success ? CompileStatus::COMPILED : CompileStatus::NOT_COMPILED;
+
+ MemoryShaderCache *shaderCache = context->getMemoryShaderCache();
+ if (success && shaderCache)
+ {
+ // Save to the shader cache.
+ if (shaderCache->putShader(context, mCompilingState->shaderHash, this) !=
+ angle::Result::Continue)
+ {
+ ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
+ "Failed to save compiled shader to memory shader cache.");
+ }
+ }
+}
+
+void Shader::addRef()
+{
+ mRefCount++;
+}
+
+void Shader::release(const Context *context)
+{
+ mRefCount--;
+
+ if (mRefCount == 0 && mDeleteStatus)
+ {
+ mResourceManager->deleteShader(context, mHandle);
+ }
+}
+
+unsigned int Shader::getRefCount() const
+{
+ return mRefCount;
+}
+
+bool Shader::isFlaggedForDeletion() const
+{
+ return mDeleteStatus;
+}
+
+void Shader::flagForDeletion()
+{
+ mDeleteStatus = true;
+}
+
+bool Shader::isCompiled(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mCompileStatus == CompileStatus::COMPILED;
+}
+
+bool Shader::isCompleted()
+{
+ return (!mState.compilePending() || mCompilingState->compileEvent->isReady());
+}
+
+int Shader::getShaderVersion(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mShaderVersion;
+}
+
+const std::vector<sh::ShaderVariable> &Shader::getInputVaryings(const Context *context)
+{
+ resolveCompile(context);
+ return mState.getInputVaryings();
+}
+
+const std::vector<sh::ShaderVariable> &Shader::getOutputVaryings(const Context *context)
+{
+ resolveCompile(context);
+ return mState.getOutputVaryings();
+}
+
+const std::vector<sh::ShaderVariable> &Shader::getUniforms(const Context *context)
+{
+ resolveCompile(context);
+ return mState.getUniforms();
+}
+
+const std::vector<sh::InterfaceBlock> &Shader::getUniformBlocks(const Context *context)
+{
+ resolveCompile(context);
+ return mState.getUniformBlocks();
+}
+
+const std::vector<sh::InterfaceBlock> &Shader::getShaderStorageBlocks(const Context *context)
+{
+ resolveCompile(context);
+ return mState.getShaderStorageBlocks();
+}
+
+const std::vector<sh::ShaderVariable> &Shader::getActiveAttributes(const Context *context)
+{
+ resolveCompile(context);
+ return mState.getActiveAttributes();
+}
+
+const std::vector<sh::ShaderVariable> &Shader::getAllAttributes(const Context *context)
+{
+ resolveCompile(context);
+ return mState.getAllAttributes();
+}
+
+const std::vector<sh::ShaderVariable> &Shader::getActiveOutputVariables(const Context *context)
+{
+ resolveCompile(context);
+ return mState.getActiveOutputVariables();
+}
+
+std::string Shader::getTransformFeedbackVaryingMappedName(const Context *context,
+ const std::string &tfVaryingName)
+{
+ ASSERT(mState.getShaderType() != ShaderType::Fragment &&
+ mState.getShaderType() != ShaderType::Compute);
+ const auto &varyings = getOutputVaryings(context);
+ auto bracketPos = tfVaryingName.find("[");
+ if (bracketPos != std::string::npos)
+ {
+ auto tfVaryingBaseName = tfVaryingName.substr(0, bracketPos);
+ for (const auto &varying : varyings)
+ {
+ if (varying.name == tfVaryingBaseName)
+ {
+ std::string mappedNameWithArrayIndex =
+ varying.mappedName + tfVaryingName.substr(bracketPos);
+ return mappedNameWithArrayIndex;
+ }
+ }
+ }
+ else
+ {
+ for (const auto &varying : varyings)
+ {
+ if (varying.name == tfVaryingName)
+ {
+ return varying.mappedName;
+ }
+ else if (varying.isStruct())
+ {
+ GLuint fieldIndex = 0;
+ const auto *field = varying.findField(tfVaryingName, &fieldIndex);
+ if (field == nullptr)
+ {
+ continue;
+ }
+ ASSERT(field != nullptr && !field->isStruct() &&
+ (!field->isArray() || varying.isShaderIOBlock));
+ std::string mappedName;
+ // If it's an I/O block without an instance name, don't include the block name.
+ if (!varying.isShaderIOBlock || !varying.name.empty())
+ {
+ mappedName = varying.isShaderIOBlock ? varying.mappedStructOrBlockName
+ : varying.mappedName;
+ mappedName += '.';
+ }
+ return mappedName + field->mappedName;
+ }
+ }
+ }
+ UNREACHABLE();
+ return std::string();
+}
+
+const sh::WorkGroupSize &Shader::getWorkGroupSize(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mLocalSize;
+}
+
+int Shader::getNumViews(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mNumViews;
+}
+
+Optional<PrimitiveMode> Shader::getGeometryShaderInputPrimitiveType(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mGeometryShaderInputPrimitiveType;
+}
+
+Optional<PrimitiveMode> Shader::getGeometryShaderOutputPrimitiveType(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mGeometryShaderOutputPrimitiveType;
+}
+
+int Shader::getGeometryShaderInvocations(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mGeometryShaderInvocations;
+}
+
+Optional<GLint> Shader::getGeometryShaderMaxVertices(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mGeometryShaderMaxVertices;
+}
+
+int Shader::getTessControlShaderVertices(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mTessControlShaderVertices;
+}
+
+GLenum Shader::getTessGenMode(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mTessGenMode;
+}
+
+GLenum Shader::getTessGenSpacing(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mTessGenSpacing;
+}
+
+GLenum Shader::getTessGenVertexOrder(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mTessGenVertexOrder;
+}
+
+GLenum Shader::getTessGenPointMode(const Context *context)
+{
+ resolveCompile(context);
+ return mState.mTessGenPointMode;
+}
+
+const std::string &Shader::getCompilerResourcesString() const
+{
+ return mCompilerResourcesString;
+}
+
+angle::Result Shader::serialize(const Context *context, angle::MemoryBuffer *binaryOut) const
+{
+ BinaryOutputStream stream;
+
+ stream.writeInt(kShaderCacheIdentifier);
+ stream.writeString(mState.mLabel);
+ stream.writeInt(mState.mShaderVersion);
+ stream.writeString(mCompilerResourcesString);
+
+ stream.writeInt(mState.mUniforms.size());
+ for (const sh::ShaderVariable &shaderVariable : mState.mUniforms)
+ {
+ WriteShaderVar(&stream, shaderVariable);
+ }
+
+ stream.writeInt(mState.mUniformBlocks.size());
+ for (const sh::InterfaceBlock &interfaceBlock : mState.mUniformBlocks)
+ {
+ WriteInterfaceBlock(&stream, interfaceBlock);
+ }
+
+ stream.writeInt(mState.mShaderStorageBlocks.size());
+ for (const sh::InterfaceBlock &interfaceBlock : mState.mShaderStorageBlocks)
+ {
+ WriteInterfaceBlock(&stream, interfaceBlock);
+ }
+
+ stream.writeInt(mState.mSpecConstUsageBits.bits());
+
+ switch (mType)
+ {
+ case ShaderType::Compute:
+ {
+ stream.writeInt(mState.mAllAttributes.size());
+ for (const sh::ShaderVariable &shaderVariable : mState.mAllAttributes)
+ {
+ WriteShaderVar(&stream, shaderVariable);
+ }
+ stream.writeInt(mState.mActiveAttributes.size());
+ for (const sh::ShaderVariable &shaderVariable : mState.mActiveAttributes)
+ {
+ WriteShaderVar(&stream, shaderVariable);
+ }
+ stream.writeInt(mState.mLocalSize[0]);
+ stream.writeInt(mState.mLocalSize[1]);
+ stream.writeInt(mState.mLocalSize[2]);
+ break;
+ }
+
+ case ShaderType::Vertex:
+ {
+ stream.writeInt(mState.mOutputVaryings.size());
+ for (const sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
+ {
+ WriteShaderVar(&stream, shaderVariable);
+ }
+ stream.writeInt(mState.mAllAttributes.size());
+ for (const sh::ShaderVariable &shaderVariable : mState.mAllAttributes)
+ {
+ WriteShaderVar(&stream, shaderVariable);
+ }
+ stream.writeInt(mState.mActiveAttributes.size());
+ for (const sh::ShaderVariable &shaderVariable : mState.mActiveAttributes)
+ {
+ WriteShaderVar(&stream, shaderVariable);
+ }
+ stream.writeInt(mState.mNumViews);
+ break;
+ }
+ case ShaderType::Fragment:
+ {
+ stream.writeInt(mState.mInputVaryings.size());
+ for (const sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
+ {
+ WriteShaderVar(&stream, shaderVariable);
+ }
+ stream.writeInt(mState.mActiveOutputVariables.size());
+ for (const sh::ShaderVariable &shaderVariable : mState.mActiveOutputVariables)
+ {
+ WriteShaderVar(&stream, shaderVariable);
+ }
+ stream.writeBool(mState.mEnablesPerSampleShading);
+ stream.writeInt(mState.mAdvancedBlendEquations.bits());
+ break;
+ }
+ case ShaderType::Geometry:
+ {
+ bool valid;
+
+ stream.writeInt(mState.mInputVaryings.size());
+ for (const sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
+ {
+ WriteShaderVar(&stream, shaderVariable);
+ }
+ stream.writeInt(mState.mOutputVaryings.size());
+ for (const sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
+ {
+ WriteShaderVar(&stream, shaderVariable);
+ }
+
+ valid = (bool)mState.mGeometryShaderInputPrimitiveType.valid();
+ stream.writeBool(valid);
+ if (valid)
+ {
+ unsigned char value =
+ (unsigned char)mState.mGeometryShaderInputPrimitiveType.value();
+ stream.writeBytes(&value, 1);
+ }
+ valid = (bool)mState.mGeometryShaderOutputPrimitiveType.valid();
+ stream.writeBool(valid);
+ if (valid)
+ {
+ unsigned char value =
+ (unsigned char)mState.mGeometryShaderOutputPrimitiveType.value();
+ stream.writeBytes(&value, 1);
+ }
+ valid = mState.mGeometryShaderMaxVertices.valid();
+ stream.writeBool(valid);
+ if (valid)
+ {
+ int value = (int)mState.mGeometryShaderMaxVertices.value();
+ stream.writeInt(value);
+ }
+
+ stream.writeInt(mState.mGeometryShaderInvocations);
+ break;
+ }
+ case ShaderType::TessControl:
+ {
+ stream.writeInt(mState.mInputVaryings.size());
+ for (const sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
+ {
+ WriteShaderVar(&stream, shaderVariable);
+ }
+ stream.writeInt(mState.mOutputVaryings.size());
+ for (const sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
+ {
+ WriteShaderVar(&stream, shaderVariable);
+ }
+ stream.writeInt(mState.mTessControlShaderVertices);
+ break;
+ }
+ case ShaderType::TessEvaluation:
+ {
+ unsigned int value;
+
+ stream.writeInt(mState.mInputVaryings.size());
+ for (const sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
+ {
+ WriteShaderVar(&stream, shaderVariable);
+ }
+ stream.writeInt(mState.mOutputVaryings.size());
+ for (const sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
+ {
+ WriteShaderVar(&stream, shaderVariable);
+ }
+
+ value = (unsigned int)(mState.mTessGenMode);
+ stream.writeInt(value);
+
+ value = (unsigned int)mState.mTessGenSpacing;
+ stream.writeInt(value);
+
+ value = (unsigned int)mState.mTessGenVertexOrder;
+ stream.writeInt(value);
+
+ value = (unsigned int)mState.mTessGenPointMode;
+ stream.writeInt(value);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+
+ stream.writeIntVector(mState.mCompiledBinary);
+ stream.writeEnum(mState.mCompileStatus);
+
+ ASSERT(binaryOut);
+ if (!binaryOut->resize(stream.length()))
+ {
+ std::stringstream sstream;
+ sstream << "Failed to allocate enough memory to serialize a shader. (" << stream.length()
+ << " bytes )";
+ ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
+ sstream.str().c_str());
+ return angle::Result::Incomplete;
+ }
+
+ memcpy(binaryOut->data(), stream.data(), stream.length());
+
+ return angle::Result::Continue;
+}
+
+angle::Result Shader::deserialize(const Context *context, BinaryInputStream &stream)
+{
+ size_t size;
+
+ if (stream.readInt<uint32_t>() != kShaderCacheIdentifier)
+ {
+ return angle::Result::Stop;
+ }
+
+ stream.readString(&mState.mLabel);
+ stream.readInt(&mState.mShaderVersion);
+ stream.readString(&mCompilerResourcesString);
+
+ size = stream.readInt<size_t>();
+ mState.mUniforms.resize(size);
+ for (sh::ShaderVariable &shaderVariable : mState.mUniforms)
+ {
+ LoadShaderVar(&stream, &shaderVariable);
+ }
+
+ size = stream.readInt<size_t>();
+ mState.mUniformBlocks.resize(size);
+ for (sh::InterfaceBlock &interfaceBlock : mState.mUniformBlocks)
+ {
+ LoadInterfaceBlock(&stream, interfaceBlock);
+ }
+
+ size = stream.readInt<size_t>();
+ mState.mShaderStorageBlocks.resize(size);
+ for (sh::InterfaceBlock &interfaceBlock : mState.mShaderStorageBlocks)
+ {
+ LoadInterfaceBlock(&stream, interfaceBlock);
+ }
+
+ mState.mSpecConstUsageBits = rx::SpecConstUsageBits(stream.readInt<uint32_t>());
+
+ switch (mType)
+ {
+ case ShaderType::Compute:
+ {
+ size = stream.readInt<size_t>();
+ mState.mAllAttributes.resize(size);
+ for (sh::ShaderVariable &shaderVariable : mState.mAllAttributes)
+ {
+ LoadShaderVar(&stream, &shaderVariable);
+ }
+ size = stream.readInt<size_t>();
+ mState.mActiveAttributes.resize(size);
+ for (sh::ShaderVariable &shaderVariable : mState.mActiveAttributes)
+ {
+ LoadShaderVar(&stream, &shaderVariable);
+ }
+ stream.readInt(&mState.mLocalSize[0]);
+ stream.readInt(&mState.mLocalSize[1]);
+ stream.readInt(&mState.mLocalSize[2]);
+ break;
+ }
+ case ShaderType::Vertex:
+ {
+ size = stream.readInt<size_t>();
+ mState.mOutputVaryings.resize(size);
+ for (sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
+ {
+ LoadShaderVar(&stream, &shaderVariable);
+ }
+ size = stream.readInt<size_t>();
+ mState.mAllAttributes.resize(size);
+ for (sh::ShaderVariable &shaderVariable : mState.mAllAttributes)
+ {
+ LoadShaderVar(&stream, &shaderVariable);
+ }
+ size = stream.readInt<size_t>();
+ mState.mActiveAttributes.resize(size);
+ for (sh::ShaderVariable &shaderVariable : mState.mActiveAttributes)
+ {
+ LoadShaderVar(&stream, &shaderVariable);
+ }
+ stream.readInt(&mState.mNumViews);
+ break;
+ }
+ case ShaderType::Fragment:
+ {
+ size = stream.readInt<size_t>();
+ mState.mInputVaryings.resize(size);
+ for (sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
+ {
+ LoadShaderVar(&stream, &shaderVariable);
+ }
+ size = stream.readInt<size_t>();
+ mState.mActiveOutputVariables.resize(size);
+ for (sh::ShaderVariable &shaderVariable : mState.mActiveOutputVariables)
+ {
+ LoadShaderVar(&stream, &shaderVariable);
+ }
+ stream.readBool(&mState.mEnablesPerSampleShading);
+ int advancedBlendEquationBits;
+ stream.readInt(&advancedBlendEquationBits);
+ mState.mAdvancedBlendEquations = BlendEquationBitSet(advancedBlendEquationBits);
+ break;
+ }
+ case ShaderType::Geometry:
+ {
+ bool valid;
+
+ size = stream.readInt<size_t>();
+ mState.mInputVaryings.resize(size);
+ for (sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
+ {
+ LoadShaderVar(&stream, &shaderVariable);
+ }
+ size = stream.readInt<size_t>();
+ mState.mOutputVaryings.resize(size);
+ for (sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
+ {
+ LoadShaderVar(&stream, &shaderVariable);
+ }
+
+ stream.readBool(&valid);
+ if (valid)
+ {
+ unsigned char value;
+ stream.readBytes(&value, 1);
+ mState.mGeometryShaderInputPrimitiveType = static_cast<PrimitiveMode>(value);
+ }
+ else
+ {
+ mState.mGeometryShaderInputPrimitiveType.reset();
+ }
+
+ stream.readBool(&valid);
+ if (valid)
+ {
+ unsigned char value;
+ stream.readBytes(&value, 1);
+ mState.mGeometryShaderOutputPrimitiveType = static_cast<PrimitiveMode>(value);
+ }
+ else
+ {
+ mState.mGeometryShaderOutputPrimitiveType.reset();
+ }
+
+ stream.readBool(&valid);
+ if (valid)
+ {
+ int value;
+ stream.readInt(&value);
+ mState.mGeometryShaderMaxVertices = static_cast<GLint>(value);
+ }
+ else
+ {
+ mState.mGeometryShaderMaxVertices.reset();
+ }
+
+ stream.readInt(&mState.mGeometryShaderInvocations);
+ break;
+ }
+ case ShaderType::TessControl:
+ {
+ size = stream.readInt<size_t>();
+ mState.mInputVaryings.resize(size);
+ for (sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
+ {
+ LoadShaderVar(&stream, &shaderVariable);
+ }
+ size = stream.readInt<size_t>();
+ mState.mOutputVaryings.resize(size);
+ for (sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
+ {
+ LoadShaderVar(&stream, &shaderVariable);
+ }
+ stream.readInt(&mState.mTessControlShaderVertices);
+ break;
+ }
+ case ShaderType::TessEvaluation:
+ {
+ unsigned int value;
+
+ size = stream.readInt<size_t>();
+ mState.mInputVaryings.resize(size);
+ for (sh::ShaderVariable &shaderVariable : mState.mInputVaryings)
+ {
+ LoadShaderVar(&stream, &shaderVariable);
+ }
+ size = stream.readInt<size_t>();
+ mState.mOutputVaryings.resize(size);
+ for (sh::ShaderVariable &shaderVariable : mState.mOutputVaryings)
+ {
+ LoadShaderVar(&stream, &shaderVariable);
+ }
+
+ stream.readInt(&value);
+ mState.mTessGenMode = (GLenum)value;
+
+ stream.readInt(&value);
+ mState.mTessGenSpacing = (GLenum)value;
+
+ stream.readInt(&value);
+ mState.mTessGenVertexOrder = (GLenum)value;
+
+ stream.readInt(&value);
+ mState.mTessGenPointMode = (GLenum)value;
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+
+ stream.readIntVector<unsigned int>(&mState.mCompiledBinary);
+ mState.mCompileStatus = stream.readEnum<CompileStatus>();
+
+ return angle::Result::Continue;
+}
+
+angle::Result Shader::loadBinary(const Context *context, const void *binary, GLsizei length)
+{
+ BinaryInputStream stream(binary, length);
+ ANGLE_TRY(deserialize(context, stream));
+
+ return angle::Result::Continue;
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Shader.h b/gfx/angle/checkout/src/libANGLE/Shader.h
new file mode 100644
index 0000000000..59b1f3cc3e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Shader.h
@@ -0,0 +1,305 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Shader.h: Defines the abstract gl::Shader class and its concrete derived
+// classes VertexShader and FragmentShader. Implements GL shader objects and
+// related functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section
+// 3.8 page 84.
+
+#ifndef LIBANGLE_SHADER_H_
+#define LIBANGLE_SHADER_H_
+
+#include <list>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <GLSLANG/ShaderLang.h>
+#include "angle_gl.h"
+
+#include "common/MemoryBuffer.h"
+#include "common/Optional.h"
+#include "common/angleutils.h"
+#include "libANGLE/BinaryStream.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+class GLImplFactory;
+class ShaderImpl;
+class ShaderSh;
+class WaitableCompileEvent;
+} // namespace rx
+
+namespace angle
+{
+class WaitableEvent;
+class WorkerThreadPool;
+} // namespace angle
+
+namespace gl
+{
+class CompileTask;
+class Context;
+class ShaderProgramManager;
+class State;
+class BinaryInputStream;
+class BinaryOutputStream;
+
+// We defer the compile until link time, or until properties are queried.
+enum class CompileStatus
+{
+ NOT_COMPILED,
+ COMPILE_REQUESTED,
+ COMPILED,
+};
+
+class ShaderState final : angle::NonCopyable
+{
+ public:
+ ShaderState(ShaderType shaderType);
+ ~ShaderState();
+
+ const std::string &getLabel() const { return mLabel; }
+
+ const std::string &getSource() const { return mSource; }
+ bool isCompiledToBinary() const { return !mCompiledBinary.empty(); }
+ const std::string &getTranslatedSource() const { return mTranslatedSource; }
+ const sh::BinaryBlob &getCompiledBinary() const { return mCompiledBinary; }
+
+ ShaderType getShaderType() const { return mShaderType; }
+ int getShaderVersion() const { return mShaderVersion; }
+
+ const std::vector<sh::ShaderVariable> &getInputVaryings() const { return mInputVaryings; }
+ const std::vector<sh::ShaderVariable> &getOutputVaryings() const { return mOutputVaryings; }
+ const std::vector<sh::ShaderVariable> &getUniforms() const { return mUniforms; }
+ const std::vector<sh::InterfaceBlock> &getUniformBlocks() const { return mUniformBlocks; }
+ const std::vector<sh::InterfaceBlock> &getShaderStorageBlocks() const
+ {
+ return mShaderStorageBlocks;
+ }
+ const std::vector<sh::ShaderVariable> &getActiveAttributes() const { return mActiveAttributes; }
+ const std::vector<sh::ShaderVariable> &getAllAttributes() const { return mAllAttributes; }
+ const std::vector<sh::ShaderVariable> &getActiveOutputVariables() const
+ {
+ return mActiveOutputVariables;
+ }
+
+ bool compilePending() const { return mCompileStatus == CompileStatus::COMPILE_REQUESTED; }
+
+ const sh::WorkGroupSize &getLocalSize() const { return mLocalSize; }
+
+ bool hasDiscard() const { return mHasDiscard; }
+ bool enablesPerSampleShading() const { return mEnablesPerSampleShading; }
+ rx::SpecConstUsageBits getSpecConstUsageBits() const { return mSpecConstUsageBits; }
+
+ int getNumViews() const { return mNumViews; }
+
+ Optional<PrimitiveMode> getGeometryShaderInputPrimitiveType() const
+ {
+ return mGeometryShaderInputPrimitiveType;
+ }
+
+ Optional<PrimitiveMode> getGeometryShaderOutputPrimitiveType() const
+ {
+ return mGeometryShaderOutputPrimitiveType;
+ }
+
+ Optional<GLint> geoGeometryShaderMaxVertices() const { return mGeometryShaderMaxVertices; }
+
+ Optional<GLint> getGeometryShaderInvocations() const { return mGeometryShaderInvocations; }
+
+ CompileStatus getCompileStatus() const { return mCompileStatus; }
+
+ private:
+ friend class Shader;
+
+ std::string mLabel;
+
+ ShaderType mShaderType;
+ int mShaderVersion;
+ std::string mTranslatedSource;
+ sh::BinaryBlob mCompiledBinary;
+ std::string mSource;
+
+ sh::WorkGroupSize mLocalSize;
+
+ std::vector<sh::ShaderVariable> mInputVaryings;
+ std::vector<sh::ShaderVariable> mOutputVaryings;
+ std::vector<sh::ShaderVariable> mUniforms;
+ std::vector<sh::InterfaceBlock> mUniformBlocks;
+ std::vector<sh::InterfaceBlock> mShaderStorageBlocks;
+ std::vector<sh::ShaderVariable> mAllAttributes;
+ std::vector<sh::ShaderVariable> mActiveAttributes;
+ std::vector<sh::ShaderVariable> mActiveOutputVariables;
+
+ bool mHasDiscard;
+ bool mEnablesPerSampleShading;
+ BlendEquationBitSet mAdvancedBlendEquations;
+ rx::SpecConstUsageBits mSpecConstUsageBits;
+
+ // ANGLE_multiview.
+ int mNumViews;
+
+ // Geometry Shader.
+ Optional<PrimitiveMode> mGeometryShaderInputPrimitiveType;
+ Optional<PrimitiveMode> mGeometryShaderOutputPrimitiveType;
+ Optional<GLint> mGeometryShaderMaxVertices;
+ int mGeometryShaderInvocations;
+
+ // Tessellation Shader
+ int mTessControlShaderVertices;
+ GLenum mTessGenMode;
+ GLenum mTessGenSpacing;
+ GLenum mTessGenVertexOrder;
+ GLenum mTessGenPointMode;
+
+ // Indicates if this shader has been successfully compiled
+ CompileStatus mCompileStatus;
+};
+
+class Shader final : angle::NonCopyable, public LabeledObject
+{
+ public:
+ Shader(ShaderProgramManager *manager,
+ rx::GLImplFactory *implFactory,
+ const gl::Limitations &rendererLimitations,
+ ShaderType type,
+ ShaderProgramID handle);
+
+ void onDestroy(const Context *context);
+
+ angle::Result setLabel(const Context *context, const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ ShaderType getType() const { return mType; }
+ ShaderProgramID getHandle() const;
+
+ rx::ShaderImpl *getImplementation() const { return mImplementation.get(); }
+
+ void setSource(GLsizei count, const char *const *string, const GLint *length);
+ int getInfoLogLength(const Context *context);
+ void getInfoLog(const Context *context, GLsizei bufSize, GLsizei *length, char *infoLog);
+ std::string getInfoLogString() const { return mInfoLog; }
+ int getSourceLength() const;
+ const std::string &getSourceString() const { return mState.getSource(); }
+ void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
+ int getTranslatedSourceLength(const Context *context);
+ int getTranslatedSourceWithDebugInfoLength(const Context *context);
+ const std::string &getTranslatedSource(const Context *context);
+ void getTranslatedSource(const Context *context,
+ GLsizei bufSize,
+ GLsizei *length,
+ char *buffer);
+ void getTranslatedSourceWithDebugInfo(const Context *context,
+ GLsizei bufSize,
+ GLsizei *length,
+ char *buffer);
+ const sh::BinaryBlob &getCompiledBinary(const Context *context);
+
+ void compile(const Context *context);
+ bool isCompiled(const Context *context);
+ bool isCompleted();
+
+ void addRef();
+ void release(const Context *context);
+ unsigned int getRefCount() const;
+ bool isFlaggedForDeletion() const;
+ void flagForDeletion();
+ bool hasDiscard() const { return mState.mHasDiscard; }
+ bool enablesPerSampleShading() const { return mState.mEnablesPerSampleShading; }
+ BlendEquationBitSet getAdvancedBlendEquations() const { return mState.mAdvancedBlendEquations; }
+ rx::SpecConstUsageBits getSpecConstUsageBits() const { return mState.mSpecConstUsageBits; }
+
+ int getShaderVersion(const Context *context);
+
+ const std::vector<sh::ShaderVariable> &getInputVaryings(const Context *context);
+ const std::vector<sh::ShaderVariable> &getOutputVaryings(const Context *context);
+ const std::vector<sh::ShaderVariable> &getUniforms(const Context *context);
+ const std::vector<sh::InterfaceBlock> &getUniformBlocks(const Context *context);
+ const std::vector<sh::InterfaceBlock> &getShaderStorageBlocks(const Context *context);
+ const std::vector<sh::ShaderVariable> &getActiveAttributes(const Context *context);
+ const std::vector<sh::ShaderVariable> &getAllAttributes(const Context *context);
+ const std::vector<sh::ShaderVariable> &getActiveOutputVariables(const Context *context);
+
+ // Returns mapped name of a transform feedback varying. The original name may contain array
+ // brackets with an index inside, which will get copied to the mapped name. The varying must be
+ // known to be declared in the shader.
+ std::string getTransformFeedbackVaryingMappedName(const Context *context,
+ const std::string &tfVaryingName);
+
+ const sh::WorkGroupSize &getWorkGroupSize(const Context *context);
+
+ int getNumViews(const Context *context);
+
+ Optional<PrimitiveMode> getGeometryShaderInputPrimitiveType(const Context *context);
+ Optional<PrimitiveMode> getGeometryShaderOutputPrimitiveType(const Context *context);
+ int getGeometryShaderInvocations(const Context *context);
+ Optional<GLint> getGeometryShaderMaxVertices(const Context *context);
+ int getTessControlShaderVertices(const Context *context);
+ GLenum getTessGenMode(const Context *context);
+ GLenum getTessGenSpacing(const Context *context);
+ GLenum getTessGenVertexOrder(const Context *context);
+ GLenum getTessGenPointMode(const Context *context);
+
+ const std::string &getCompilerResourcesString() const;
+
+ const ShaderState &getState() const { return mState; }
+
+ GLuint getCurrentMaxComputeWorkGroupInvocations() const
+ {
+ return mCurrentMaxComputeWorkGroupInvocations;
+ }
+
+ unsigned int getMaxComputeSharedMemory() const { return mMaxComputeSharedMemory; }
+ bool hasBeenDeleted() const { return mDeleteStatus; }
+
+ // Block until compiling is finished and resolve it.
+ void resolveCompile(const Context *context);
+
+ // Writes a shader's binary to the output memory buffer.
+ angle::Result serialize(const Context *context, angle::MemoryBuffer *binaryOut) const;
+ angle::Result deserialize(const Context *context, BinaryInputStream &stream);
+ angle::Result loadBinary(const Context *context, const void *binary, GLsizei length);
+
+ private:
+ struct CompilingState;
+
+ ~Shader() override;
+ static void GetSourceImpl(const std::string &source,
+ GLsizei bufSize,
+ GLsizei *length,
+ char *buffer);
+
+ ShaderState mState;
+ std::unique_ptr<rx::ShaderImpl> mImplementation;
+ const gl::Limitations mRendererLimitations;
+ const ShaderProgramID mHandle;
+ const ShaderType mType;
+ unsigned int mRefCount; // Number of program objects this shader is attached to
+ bool mDeleteStatus; // Flag to indicate that the shader can be deleted when no longer in use
+ std::string mInfoLog;
+
+ // We keep a reference to the translator in order to defer compiles while preserving settings.
+ BindingPointer<Compiler> mBoundCompiler;
+ std::unique_ptr<CompilingState> mCompilingState;
+ std::string mCompilerResourcesString;
+
+ ShaderProgramManager *mResourceManager;
+
+ GLuint mCurrentMaxComputeWorkGroupInvocations;
+ unsigned int mMaxComputeSharedMemory;
+};
+
+bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y);
+
+const char *GetShaderTypeString(ShaderType type);
+} // namespace gl
+
+#endif // LIBANGLE_SHADER_H_
diff --git a/gfx/angle/checkout/src/libANGLE/SizedMRUCache.h b/gfx/angle/checkout/src/libANGLE/SizedMRUCache.h
new file mode 100644
index 0000000000..b557e657ec
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/SizedMRUCache.h
@@ -0,0 +1,156 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SizedMRUCache.h: A hashing map that stores blobs of sized, untyped data.
+
+#ifndef LIBANGLE_SIZED_MRU_CACHE_H_
+#define LIBANGLE_SIZED_MRU_CACHE_H_
+
+#include <anglebase/containers/mru_cache.h>
+
+namespace angle
+{
+
+template <typename Key, typename Value>
+class SizedMRUCache final : angle::NonCopyable
+{
+ public:
+ SizedMRUCache(size_t maximumTotalSize)
+ : mMaximumTotalSize(maximumTotalSize),
+ mCurrentSize(0),
+ mStore(SizedMRUCacheStore::NO_AUTO_EVICT)
+ {}
+
+ // Returns nullptr on failure.
+ const Value *put(const Key &key, Value &&value, size_t size)
+ {
+ if (size > mMaximumTotalSize)
+ {
+ return nullptr;
+ }
+
+ // Check for existing key.
+ eraseByKey(key);
+
+ auto retVal = mStore.Put(key, ValueAndSize(std::move(value), size));
+ mCurrentSize += size;
+
+ shrinkToSize(mMaximumTotalSize);
+
+ return &retVal->second.value;
+ }
+
+ bool get(const Key &key, const Value **valueOut)
+ {
+ const auto &iter = mStore.Get(key);
+ if (iter == mStore.end())
+ {
+ return false;
+ }
+ *valueOut = &iter->second.value;
+ return true;
+ }
+
+ bool getAt(size_t index, const Key **keyOut, const Value **valueOut)
+ {
+ if (index < mStore.size())
+ {
+ auto it = mStore.begin();
+ std::advance(it, index);
+ *keyOut = &it->first;
+ *valueOut = &it->second.value;
+ return true;
+ }
+ *valueOut = nullptr;
+ return false;
+ }
+
+ bool empty() const { return mStore.empty(); }
+
+ void clear()
+ {
+ mStore.Clear();
+ mCurrentSize = 0;
+ }
+
+ void eraseByKey(const Key &key)
+ {
+ // Check for existing key.
+ auto existing = mStore.Peek(key);
+ if (existing != mStore.end())
+ {
+ mCurrentSize -= existing->second.size;
+ mStore.Erase(existing);
+ }
+ }
+
+ size_t entryCount() const { return mStore.size(); }
+
+ size_t size() const { return mCurrentSize; }
+
+ // Also discards the cache contents.
+ void resize(size_t maximumTotalSize)
+ {
+ clear();
+ mMaximumTotalSize = maximumTotalSize;
+ }
+
+ // Reduce current memory usage.
+ size_t shrinkToSize(size_t limit)
+ {
+ size_t initialSize = mCurrentSize;
+
+ while (mCurrentSize > limit)
+ {
+ ASSERT(!mStore.empty());
+ auto iter = mStore.rbegin();
+ mCurrentSize -= iter->second.size;
+ mStore.Erase(iter);
+ }
+
+ return (initialSize - mCurrentSize);
+ }
+
+ size_t maxSize() const { return mMaximumTotalSize; }
+
+ private:
+ struct ValueAndSize
+ {
+ ValueAndSize() : value(), size(0) {}
+ ValueAndSize(Value &&value, size_t size) : value(std::move(value)), size(size) {}
+ ValueAndSize(ValueAndSize &&other) : ValueAndSize() { *this = std::move(other); }
+ ValueAndSize &operator=(ValueAndSize &&other)
+ {
+ std::swap(value, other.value);
+ std::swap(size, other.size);
+ return *this;
+ }
+
+ Value value;
+ size_t size;
+ };
+
+ using SizedMRUCacheStore = base::HashingMRUCache<Key, ValueAndSize>;
+
+ size_t mMaximumTotalSize;
+ size_t mCurrentSize;
+ SizedMRUCacheStore mStore;
+};
+
+// Helper function used in a few places.
+template <typename T>
+void TrimCache(size_t maxStates, size_t gcLimit, const char *name, T *cache)
+{
+ const size_t kGarbageCollectionLimit = maxStates / 2 + gcLimit;
+
+ if (cache->size() >= kGarbageCollectionLimit)
+ {
+ WARN() << "Overflowed the " << name << " cache limit of " << (maxStates / 2)
+ << " elements, removing the least recently used to make room.";
+ cache->ShrinkToSize(maxStates / 2);
+ }
+}
+} // namespace angle
+#endif // LIBANGLE_SIZED_MRU_CACHE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/State.cpp b/gfx/angle/checkout/src/libANGLE/State.cpp
new file mode 100644
index 0000000000..8f99a238a6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/State.cpp
@@ -0,0 +1,3866 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// State.cpp: Implements the State class, encapsulating raw GL state.
+
+#include "libANGLE/State.h"
+
+#include <string.h>
+#include <limits>
+
+#include "common/bitset_utils.h"
+#include "common/mathutil.h"
+#include "common/matrix_utils.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/PixelLocalStorage.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/queryutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/TextureImpl.h"
+
+namespace gl
+{
+
+namespace
+{
+bool GetAlternativeQueryType(QueryType type, QueryType *alternativeType)
+{
+ switch (type)
+ {
+ case QueryType::AnySamples:
+ *alternativeType = QueryType::AnySamplesConservative;
+ return true;
+ case QueryType::AnySamplesConservative:
+ *alternativeType = QueryType::AnySamples;
+ return true;
+ default:
+ return false;
+ }
+}
+
+// Mapping from a buffer binding type to a dirty bit type.
+constexpr angle::PackedEnumMap<BufferBinding, size_t> kBufferBindingDirtyBits = {{
+ {BufferBinding::AtomicCounter, State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING},
+ {BufferBinding::DispatchIndirect, State::DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING},
+ {BufferBinding::DrawIndirect, State::DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING},
+ {BufferBinding::PixelPack, State::DIRTY_BIT_PACK_BUFFER_BINDING},
+ {BufferBinding::PixelUnpack, State::DIRTY_BIT_UNPACK_BUFFER_BINDING},
+ {BufferBinding::ShaderStorage, State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING},
+ {BufferBinding::Uniform, State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS},
+}};
+
+// Returns a buffer binding function depending on if a dirty bit is set.
+template <BufferBinding Target>
+constexpr std::pair<BufferBinding, State::BufferBindingSetter> GetBufferBindingSetter()
+{
+ return std::make_pair(Target, kBufferBindingDirtyBits[Target] != 0
+ ? &State::setGenericBufferBindingWithBit<Target>
+ : &State::setGenericBufferBinding<Target>);
+}
+
+template <typename T>
+using ContextStateMember = T *(State::*);
+
+template <typename T>
+T *AllocateOrGetSharedResourceManager(const State *shareContextState,
+ ContextStateMember<T> member,
+ T *shareResources = nullptr)
+{
+ if (shareContextState)
+ {
+ T *resourceManager = (*shareContextState).*member;
+ ASSERT(!resourceManager || resourceManager == shareResources || !shareResources);
+ resourceManager->addRef();
+ return resourceManager;
+ }
+ else if (shareResources)
+ {
+ shareResources->addRef();
+ return shareResources;
+ }
+ else
+ {
+ return new T();
+ }
+}
+
+// TODO(https://anglebug.com/3889): Remove this helper function after blink and chromium part
+// refactory done.
+bool IsTextureCompatibleWithSampler(TextureType texture, TextureType sampler)
+{
+ if (sampler == texture)
+ {
+ return true;
+ }
+
+ if (sampler == TextureType::VideoImage)
+ {
+ if (texture == TextureType::VideoImage || texture == TextureType::_2D)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+uint32_t gIDCounter = 1;
+} // namespace
+
+template <typename BindingT, typename... ArgsT>
+ANGLE_INLINE void UpdateNonTFBufferBindingWebGL(const Context *context,
+ BindingT *binding,
+ Buffer *buffer,
+ ArgsT... args)
+{
+ Buffer *oldBuffer = binding->get();
+ if (oldBuffer)
+ {
+ oldBuffer->onNonTFBindingChanged(-1);
+ oldBuffer->release(context);
+ }
+ binding->assign(buffer, args...);
+ if (buffer)
+ {
+ buffer->addRef();
+ buffer->onNonTFBindingChanged(1);
+ }
+}
+
+template <typename BindingT, typename... ArgsT>
+void UpdateTFBufferBindingWebGL(const Context *context,
+ BindingT *binding,
+ bool indexed,
+ ArgsT... args)
+{
+ if (binding->get())
+ (*binding)->onTFBindingChanged(context, false, indexed);
+ binding->set(context, args...);
+ if (binding->get())
+ (*binding)->onTFBindingChanged(context, true, indexed);
+}
+
+void UpdateBufferBinding(const Context *context,
+ BindingPointer<Buffer> *binding,
+ Buffer *buffer,
+ BufferBinding target)
+{
+ if (context->isWebGL())
+ {
+ if (target == BufferBinding::TransformFeedback)
+ {
+ UpdateTFBufferBindingWebGL(context, binding, false, buffer);
+ }
+ else
+ {
+ UpdateNonTFBufferBindingWebGL(context, binding, buffer);
+ }
+ }
+ else
+ {
+ binding->set(context, buffer);
+ }
+}
+
+void UpdateIndexedBufferBinding(const Context *context,
+ OffsetBindingPointer<Buffer> *binding,
+ Buffer *buffer,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ if (context->isWebGL())
+ {
+ if (target == BufferBinding::TransformFeedback)
+ {
+ UpdateTFBufferBindingWebGL(context, binding, true, buffer, offset, size);
+ }
+ else
+ {
+ UpdateNonTFBufferBindingWebGL(context, binding, buffer, offset, size);
+ }
+ }
+ else
+ {
+ binding->set(context, buffer, offset, size);
+ }
+}
+
+// These template functions must be defined before they are instantiated in kBufferSetters.
+template <BufferBinding Target>
+void State::setGenericBufferBindingWithBit(const Context *context, Buffer *buffer)
+{
+ if (context->isWebGL())
+ {
+ UpdateNonTFBufferBindingWebGL(context, &mBoundBuffers[Target], buffer);
+ }
+ else
+ {
+ mBoundBuffers[Target].set(context, buffer);
+ }
+ mDirtyBits.set(kBufferBindingDirtyBits[Target]);
+}
+
+template <BufferBinding Target>
+void State::setGenericBufferBinding(const Context *context, Buffer *buffer)
+{
+ if (context->isWebGL())
+ {
+ UpdateNonTFBufferBindingWebGL(context, &mBoundBuffers[Target], buffer);
+ }
+ else
+ {
+ mBoundBuffers[Target].set(context, buffer);
+ }
+}
+
+template <>
+void State::setGenericBufferBinding<BufferBinding::TransformFeedback>(const Context *context,
+ Buffer *buffer)
+{
+ if (context->isWebGL())
+ {
+ UpdateTFBufferBindingWebGL(context, &mBoundBuffers[BufferBinding::TransformFeedback], false,
+ buffer);
+ }
+ else
+ {
+ mBoundBuffers[BufferBinding::TransformFeedback].set(context, buffer);
+ }
+}
+
+template <>
+void State::setGenericBufferBinding<BufferBinding::ElementArray>(const Context *context,
+ Buffer *buffer)
+{
+ Buffer *oldBuffer = mVertexArray->mState.mElementArrayBuffer.get();
+ if (oldBuffer)
+ {
+ oldBuffer->removeObserver(&mVertexArray->mState.mElementArrayBuffer);
+ oldBuffer->removeContentsObserver(mVertexArray, kElementArrayBufferIndex);
+ if (context->isWebGL())
+ {
+ oldBuffer->onNonTFBindingChanged(-1);
+ }
+ oldBuffer->release(context);
+ }
+ mVertexArray->mState.mElementArrayBuffer.assign(buffer);
+ if (buffer)
+ {
+ buffer->addObserver(&mVertexArray->mState.mElementArrayBuffer);
+ buffer->addContentsObserver(mVertexArray, kElementArrayBufferIndex);
+ if (context->isWebGL())
+ {
+ buffer->onNonTFBindingChanged(1);
+ }
+ buffer->addRef();
+ }
+ mVertexArray->mDirtyBits.set(VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
+ mVertexArray->mIndexRangeCache.invalidate();
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+const angle::PackedEnumMap<BufferBinding, State::BufferBindingSetter> State::kBufferSetters = {{
+ GetBufferBindingSetter<BufferBinding::Array>(),
+ GetBufferBindingSetter<BufferBinding::AtomicCounter>(),
+ GetBufferBindingSetter<BufferBinding::CopyRead>(),
+ GetBufferBindingSetter<BufferBinding::CopyWrite>(),
+ GetBufferBindingSetter<BufferBinding::DispatchIndirect>(),
+ GetBufferBindingSetter<BufferBinding::DrawIndirect>(),
+ GetBufferBindingSetter<BufferBinding::ElementArray>(),
+ GetBufferBindingSetter<BufferBinding::PixelPack>(),
+ GetBufferBindingSetter<BufferBinding::PixelUnpack>(),
+ GetBufferBindingSetter<BufferBinding::ShaderStorage>(),
+ GetBufferBindingSetter<BufferBinding::Texture>(),
+ GetBufferBindingSetter<BufferBinding::TransformFeedback>(),
+ GetBufferBindingSetter<BufferBinding::Uniform>(),
+}};
+
+ActiveTexturesCache::ActiveTexturesCache() : mTextures{} {}
+
+ActiveTexturesCache::~ActiveTexturesCache()
+{
+ ASSERT(empty());
+}
+
+void ActiveTexturesCache::clear()
+{
+ for (size_t textureIndex = 0; textureIndex < mTextures.size(); ++textureIndex)
+ {
+ reset(textureIndex);
+ }
+}
+
+bool ActiveTexturesCache::empty() const
+{
+ for (Texture *texture : mTextures)
+ {
+ if (texture)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+ANGLE_INLINE void ActiveTexturesCache::reset(size_t textureIndex)
+{
+ if (mTextures[textureIndex])
+ {
+ mTextures[textureIndex] = nullptr;
+ }
+}
+
+ANGLE_INLINE void ActiveTexturesCache::set(size_t textureIndex, Texture *texture)
+{
+ ASSERT(texture);
+ mTextures[textureIndex] = texture;
+}
+
+State::State(const State *shareContextState,
+ egl::ShareGroup *shareGroup,
+ TextureManager *shareTextures,
+ SemaphoreManager *shareSemaphores,
+ const OverlayType *overlay,
+ const EGLenum clientType,
+ const Version &clientVersion,
+ EGLint profileMask,
+ bool debug,
+ bool bindGeneratesResourceCHROMIUM,
+ bool clientArraysEnabled,
+ bool robustResourceInit,
+ bool programBinaryCacheEnabled,
+ EGLenum contextPriority,
+ bool hasRobustAccess,
+ bool hasProtectedContent)
+ : mID({gIDCounter++}),
+ mClientType(clientType),
+ mProfileMask(profileMask),
+ mContextPriority(contextPriority),
+ mHasRobustAccess(hasRobustAccess),
+ mHasProtectedContent(hasProtectedContent),
+ mIsDebugContext(debug),
+ mClientVersion(clientVersion),
+ mShareGroup(shareGroup),
+ mBufferManager(AllocateOrGetSharedResourceManager(shareContextState, &State::mBufferManager)),
+ mShaderProgramManager(
+ AllocateOrGetSharedResourceManager(shareContextState, &State::mShaderProgramManager)),
+ mTextureManager(AllocateOrGetSharedResourceManager(shareContextState,
+ &State::mTextureManager,
+ shareTextures)),
+ mRenderbufferManager(
+ AllocateOrGetSharedResourceManager(shareContextState, &State::mRenderbufferManager)),
+ mSamplerManager(
+ AllocateOrGetSharedResourceManager(shareContextState, &State::mSamplerManager)),
+ mSyncManager(AllocateOrGetSharedResourceManager(shareContextState, &State::mSyncManager)),
+ mFramebufferManager(new FramebufferManager()),
+ mProgramPipelineManager(new ProgramPipelineManager()),
+ mMemoryObjectManager(
+ AllocateOrGetSharedResourceManager(shareContextState, &State::mMemoryObjectManager)),
+ mSemaphoreManager(AllocateOrGetSharedResourceManager(shareContextState,
+ &State::mSemaphoreManager,
+ shareSemaphores)),
+ mDepthClearValue(0),
+ mStencilClearValue(0),
+ mScissorTest(false),
+ mSampleAlphaToCoverage(false),
+ mSampleCoverage(false),
+ mSampleCoverageValue(0),
+ mSampleCoverageInvert(false),
+ mSampleMask(false),
+ mMaxSampleMaskWords(0),
+ mIsSampleShadingEnabled(false),
+ mMinSampleShading(0.0f),
+ mStencilRef(0),
+ mStencilBackRef(0),
+ mLineWidth(0),
+ mGenerateMipmapHint(GL_NONE),
+ mTextureFilteringHint(GL_NONE),
+ mFragmentShaderDerivativeHint(GL_NONE),
+ mBindGeneratesResource(bindGeneratesResourceCHROMIUM),
+ mClientArraysEnabled(clientArraysEnabled),
+ mNearZ(0),
+ mFarZ(0),
+ mReadFramebuffer(nullptr),
+ mDrawFramebuffer(nullptr),
+ mProgram(nullptr),
+ mExecutable(nullptr),
+ mProvokingVertex(gl::ProvokingVertexConvention::LastVertexConvention),
+ mVertexArray(nullptr),
+ mActiveSampler(0),
+ mPrimitiveRestart(false),
+ mDebug(debug),
+ mMultiSampling(false),
+ mSampleAlphaToOne(false),
+ mFramebufferSRGB(true),
+ mRobustResourceInit(robustResourceInit),
+ mProgramBinaryCacheEnabled(programBinaryCacheEnabled),
+ mTextureRectangleEnabled(true),
+ mLogicOpEnabled(false),
+ mLogicOp(LogicalOperation::Copy),
+ mMaxShaderCompilerThreads(std::numeric_limits<GLuint>::max()),
+ mPatchVertices(3),
+ mPixelLocalStorageActive(false),
+ mOverlay(overlay),
+ mNoSimultaneousConstantColorAndAlphaBlendFunc(false),
+ mSetBlendIndexedInvoked(false),
+ mSetBlendFactorsIndexedInvoked(false),
+ mSetBlendEquationsIndexedInvoked(false),
+ mDisplayTextureShareGroup(shareTextures != nullptr),
+ mBoundingBoxMinX(-1.0f),
+ mBoundingBoxMinY(-1.0f),
+ mBoundingBoxMinZ(-1.0f),
+ mBoundingBoxMinW(1.0f),
+ mBoundingBoxMaxX(1.0f),
+ mBoundingBoxMaxY(1.0f),
+ mBoundingBoxMaxZ(1.0f),
+ mBoundingBoxMaxW(1.0f),
+ mShadingRatePreserveAspectRatio(false),
+ mShadingRate(ShadingRate::Undefined)
+{}
+
+State::~State() {}
+
+void State::initialize(Context *context)
+{
+ const Extensions &nativeExtensions = context->getImplementation()->getNativeExtensions();
+ const Version &clientVersion = context->getClientVersion();
+
+ mBlendStateExt = BlendStateExt(mCaps.maxDrawBuffers);
+
+ setColorClearValue(0.0f, 0.0f, 0.0f, 0.0f);
+
+ mDepthClearValue = 1.0f;
+ mStencilClearValue = 0;
+
+ mScissorTest = false;
+ mScissor.x = 0;
+ mScissor.y = 0;
+ mScissor.width = 0;
+ mScissor.height = 0;
+
+ mBlendColor.red = 0;
+ mBlendColor.green = 0;
+ mBlendColor.blue = 0;
+ mBlendColor.alpha = 0;
+
+ mStencilRef = 0;
+ mStencilBackRef = 0;
+
+ mSampleCoverage = false;
+ mSampleCoverageValue = 1.0f;
+ mSampleCoverageInvert = false;
+
+ mMaxSampleMaskWords = static_cast<GLuint>(mCaps.maxSampleMaskWords);
+ mSampleMask = false;
+ mSampleMaskValues.fill(~GLbitfield(0));
+
+ mGenerateMipmapHint = GL_DONT_CARE;
+ mTextureFilteringHint = GL_DONT_CARE;
+ mFragmentShaderDerivativeHint = GL_DONT_CARE;
+
+ mLineWidth = 1.0f;
+
+ mViewport.x = 0;
+ mViewport.y = 0;
+ mViewport.width = 0;
+ mViewport.height = 0;
+ mNearZ = 0.0f;
+ mFarZ = 1.0f;
+
+ mClipControlOrigin = GL_LOWER_LEFT_EXT;
+ mClipControlDepth = GL_NEGATIVE_ONE_TO_ONE_EXT;
+
+ mActiveSampler = 0;
+
+ mVertexAttribCurrentValues.resize(mCaps.maxVertexAttributes);
+
+ // Set all indexes in state attributes type mask to float (default)
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ SetComponentTypeMask(ComponentType::Float, i, &mCurrentValuesTypeMask);
+ }
+
+ mUniformBuffers.resize(mCaps.maxUniformBufferBindings);
+
+ mSamplerTextures[TextureType::_2D].resize(mCaps.maxCombinedTextureImageUnits);
+ mSamplerTextures[TextureType::CubeMap].resize(mCaps.maxCombinedTextureImageUnits);
+ if (clientVersion >= Version(3, 0) || nativeExtensions.texture3DOES)
+ {
+ mSamplerTextures[TextureType::_3D].resize(mCaps.maxCombinedTextureImageUnits);
+ }
+ if (clientVersion >= Version(3, 0))
+ {
+ mSamplerTextures[TextureType::_2DArray].resize(mCaps.maxCombinedTextureImageUnits);
+ }
+ if (clientVersion >= Version(3, 1) || nativeExtensions.textureMultisampleANGLE)
+ {
+ mSamplerTextures[TextureType::_2DMultisample].resize(mCaps.maxCombinedTextureImageUnits);
+ }
+ if (clientVersion >= Version(3, 1))
+ {
+ mSamplerTextures[TextureType::_2DMultisampleArray].resize(
+ mCaps.maxCombinedTextureImageUnits);
+
+ mAtomicCounterBuffers.resize(mCaps.maxAtomicCounterBufferBindings);
+ mShaderStorageBuffers.resize(mCaps.maxShaderStorageBufferBindings);
+ }
+ if (clientVersion >= Version(3, 1) ||
+ (mExtensions.shaderPixelLocalStorageANGLE &&
+ ShPixelLocalStorageTypeUsesImages(
+ context->getImplementation()->getNativePixelLocalStorageType())))
+ {
+ mImageUnits.resize(mCaps.maxImageUnits);
+ }
+ if (clientVersion >= Version(3, 2) || mExtensions.textureCubeMapArrayAny())
+ {
+ mSamplerTextures[TextureType::CubeMapArray].resize(mCaps.maxCombinedTextureImageUnits);
+ }
+ if (clientVersion >= Version(3, 2) || mExtensions.textureBufferAny())
+ {
+ mSamplerTextures[TextureType::Buffer].resize(mCaps.maxCombinedTextureImageUnits);
+ }
+ if (nativeExtensions.textureRectangleANGLE)
+ {
+ mSamplerTextures[TextureType::Rectangle].resize(mCaps.maxCombinedTextureImageUnits);
+ }
+ if (nativeExtensions.EGLImageExternalOES || nativeExtensions.EGLStreamConsumerExternalNV)
+ {
+ mSamplerTextures[TextureType::External].resize(mCaps.maxCombinedTextureImageUnits);
+ }
+ if (nativeExtensions.videoTextureWEBGL)
+ {
+ mSamplerTextures[TextureType::VideoImage].resize(mCaps.maxCombinedTextureImageUnits);
+ }
+ mCompleteTextureBindings.reserve(mCaps.maxCombinedTextureImageUnits);
+ for (int32_t textureIndex = 0; textureIndex < mCaps.maxCombinedTextureImageUnits;
+ ++textureIndex)
+ {
+ mCompleteTextureBindings.emplace_back(context, textureIndex);
+ }
+
+ mSamplers.resize(mCaps.maxCombinedTextureImageUnits);
+
+ for (QueryType type : angle::AllEnums<QueryType>())
+ {
+ mActiveQueries[type].set(context, nullptr);
+ }
+
+ mProgram = nullptr;
+ mExecutable = nullptr;
+
+ mReadFramebuffer = nullptr;
+ mDrawFramebuffer = nullptr;
+
+ mPrimitiveRestart = false;
+
+ mDebug.setMaxLoggedMessages(mCaps.maxDebugLoggedMessages);
+
+ mMultiSampling = true;
+ mSampleAlphaToOne = false;
+
+ mCoverageModulation = GL_NONE;
+
+ mNoSimultaneousConstantColorAndAlphaBlendFunc =
+ context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
+ context->getExtensions().webglCompatibilityANGLE;
+
+ mNoUnclampedBlendColor = context->getLimitations().noUnclampedBlendColor;
+
+ // GLES1 emulation: Initialize state for GLES1 if version applies
+ // TODO(http://anglebug.com/3745): When on desktop client only do this in compatibility profile
+ if (clientVersion < Version(2, 0) || mClientType == EGL_OPENGL_API)
+ {
+ mGLES1State.initialize(context, this);
+ }
+}
+
+void State::reset(const Context *context)
+{
+ // Force a sync so clear doesn't end up dereferencing stale pointers.
+ (void)syncActiveTextures(context, Command::Other);
+ mActiveTexturesCache.clear();
+
+ for (TextureBindingVector &bindingVec : mSamplerTextures)
+ {
+ for (BindingPointer<Texture> &texBinding : bindingVec)
+ {
+ texBinding.set(context, nullptr);
+ }
+ }
+ for (size_t samplerIdx = 0; samplerIdx < mSamplers.size(); samplerIdx++)
+ {
+ mSamplers[samplerIdx].set(context, nullptr);
+ }
+
+ for (ImageUnit &imageUnit : mImageUnits)
+ {
+ imageUnit.texture.set(context, nullptr);
+ imageUnit.level = 0;
+ imageUnit.layered = false;
+ imageUnit.layer = 0;
+ imageUnit.access = GL_READ_ONLY;
+ imageUnit.format = GL_R32UI;
+ }
+
+ mRenderbuffer.set(context, nullptr);
+
+ for (BufferBinding type : angle::AllEnums<BufferBinding>())
+ {
+ UpdateBufferBinding(context, &mBoundBuffers[type], nullptr, type);
+ }
+
+ if (mProgram)
+ {
+ mProgram->release(context);
+ }
+ mProgram = nullptr;
+ mProgramPipeline.set(context, nullptr);
+ mExecutable = nullptr;
+
+ if (mTransformFeedback.get())
+ {
+ mTransformFeedback->onBindingChanged(context, false);
+ }
+ mTransformFeedback.set(context, nullptr);
+
+ for (QueryType type : angle::AllEnums<QueryType>())
+ {
+ mActiveQueries[type].set(context, nullptr);
+ }
+
+ for (OffsetBindingPointer<Buffer> &buf : mUniformBuffers)
+ {
+ UpdateIndexedBufferBinding(context, &buf, nullptr, BufferBinding::Uniform, 0, 0);
+ }
+ mBoundUniformBuffersMask.reset();
+
+ for (OffsetBindingPointer<Buffer> &buf : mAtomicCounterBuffers)
+ {
+ UpdateIndexedBufferBinding(context, &buf, nullptr, BufferBinding::AtomicCounter, 0, 0);
+ }
+ mBoundAtomicCounterBuffersMask.reset();
+
+ for (OffsetBindingPointer<Buffer> &buf : mShaderStorageBuffers)
+ {
+ UpdateIndexedBufferBinding(context, &buf, nullptr, BufferBinding::ShaderStorage, 0, 0);
+ }
+ mBoundShaderStorageBuffersMask.reset();
+
+ mClipDistancesEnabled.reset();
+
+ setAllDirtyBits();
+}
+
+ANGLE_INLINE void State::unsetActiveTextures(const ActiveTextureMask &textureMask)
+{
+ // Unset any relevant bound textures.
+ for (size_t textureIndex : textureMask)
+ {
+ mActiveTexturesCache.reset(textureIndex);
+ mCompleteTextureBindings[textureIndex].reset();
+ }
+}
+
+ANGLE_INLINE void State::updateActiveTextureStateOnSync(const Context *context,
+ size_t textureIndex,
+ const Sampler *sampler,
+ Texture *texture)
+{
+ if (!texture || !texture->isSamplerComplete(context, sampler))
+ {
+ mActiveTexturesCache.reset(textureIndex);
+ }
+ else
+ {
+ mActiveTexturesCache.set(textureIndex, texture);
+ }
+
+ mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
+}
+
+ANGLE_INLINE void State::setActiveTextureDirty(size_t textureIndex, Texture *texture)
+{
+ mDirtyObjects.set(DIRTY_OBJECT_ACTIVE_TEXTURES);
+ mDirtyActiveTextures.set(textureIndex);
+
+ if (!texture)
+ {
+ return;
+ }
+
+ if (texture->hasAnyDirtyBit())
+ {
+ setTextureDirty(textureIndex);
+ }
+
+ if (mRobustResourceInit && texture->initState() == InitState::MayNeedInit)
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_TEXTURES_INIT);
+ }
+
+ // This cache is updated immediately because we use the cache in the validation layer.
+ // If we defer the update until syncState it's too late and we've already passed validation.
+ if (texture && mExecutable)
+ {
+ // It is invalid to try to sample a non-yuv texture with a yuv sampler.
+ mTexturesIncompatibleWithSamplers[textureIndex] =
+ mExecutable->getActiveYUVSamplers().test(textureIndex) && !texture->isYUV();
+
+ if (isWebGL())
+ {
+ const Sampler *sampler = mSamplers[textureIndex].get();
+ const SamplerState &samplerState =
+ sampler ? sampler->getSamplerState() : texture->getSamplerState();
+ if (!texture->getTextureState().compatibleWithSamplerFormatForWebGL(
+ mExecutable->getSamplerFormatForTextureUnitIndex(textureIndex), samplerState))
+ {
+ mTexturesIncompatibleWithSamplers[textureIndex] = true;
+ }
+ }
+ }
+ else
+ {
+ mTexturesIncompatibleWithSamplers[textureIndex] = false;
+ }
+}
+
+ANGLE_INLINE void State::updateTextureBinding(const Context *context,
+ size_t textureIndex,
+ Texture *texture)
+{
+ mCompleteTextureBindings[textureIndex].bind(texture);
+ mActiveTexturesCache.reset(textureIndex);
+ setActiveTextureDirty(textureIndex, texture);
+}
+
+ANGLE_INLINE bool State::hasConstantColor(GLenum sourceRGB, GLenum destRGB) const
+{
+ return sourceRGB == GL_CONSTANT_COLOR || sourceRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
+ destRGB == GL_CONSTANT_COLOR || destRGB == GL_ONE_MINUS_CONSTANT_COLOR;
+}
+
+ANGLE_INLINE bool State::hasConstantAlpha(GLenum sourceRGB, GLenum destRGB) const
+{
+ return sourceRGB == GL_CONSTANT_ALPHA || sourceRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
+ destRGB == GL_CONSTANT_ALPHA || destRGB == GL_ONE_MINUS_CONSTANT_ALPHA;
+}
+
+const RasterizerState &State::getRasterizerState() const
+{
+ return mRasterizer;
+}
+
+const DepthStencilState &State::getDepthStencilState() const
+{
+ return mDepthStencil;
+}
+
+void State::setColorClearValue(float red, float green, float blue, float alpha)
+{
+ mColorClearValue.red = red;
+ mColorClearValue.green = green;
+ mColorClearValue.blue = blue;
+ mColorClearValue.alpha = alpha;
+ mDirtyBits.set(DIRTY_BIT_CLEAR_COLOR);
+}
+
+void State::setDepthClearValue(float depth)
+{
+ mDepthClearValue = depth;
+ mDirtyBits.set(DIRTY_BIT_CLEAR_DEPTH);
+}
+
+void State::setStencilClearValue(int stencil)
+{
+ mStencilClearValue = stencil;
+ mDirtyBits.set(DIRTY_BIT_CLEAR_STENCIL);
+}
+
+void State::setColorMask(bool red, bool green, bool blue, bool alpha)
+{
+ mBlendState.colorMaskRed = red;
+ mBlendState.colorMaskGreen = green;
+ mBlendState.colorMaskBlue = blue;
+ mBlendState.colorMaskAlpha = alpha;
+
+ mBlendStateExt.setColorMask(red, green, blue, alpha);
+ mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+}
+
+void State::setColorMaskIndexed(bool red, bool green, bool blue, bool alpha, GLuint index)
+{
+ mBlendStateExt.setColorMaskIndexed(index, red, green, blue, alpha);
+ mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+}
+
+bool State::allActiveDrawBufferChannelsMasked() const
+{
+ // Compare current color mask with all-disabled color mask, while ignoring disabled draw
+ // buffers.
+ return (mBlendStateExt.compareColorMask(0) & mDrawFramebuffer->getDrawBufferMask()).none();
+}
+
+bool State::anyActiveDrawBufferChannelMasked() const
+{
+ // Compare current color mask with all-enabled color mask, while ignoring disabled draw
+ // buffers.
+ return (mBlendStateExt.compareColorMask(mBlendStateExt.getAllColorMaskBits()) &
+ mDrawFramebuffer->getDrawBufferMask())
+ .any();
+}
+
+void State::setDepthMask(bool mask)
+{
+ if (mDepthStencil.depthMask != mask)
+ {
+ mDepthStencil.depthMask = mask;
+ mDirtyBits.set(DIRTY_BIT_DEPTH_MASK);
+ }
+}
+
+void State::setRasterizerDiscard(bool enabled)
+{
+ if (mRasterizer.rasterizerDiscard != enabled)
+ {
+ mRasterizer.rasterizerDiscard = enabled;
+ mDirtyBits.set(DIRTY_BIT_RASTERIZER_DISCARD_ENABLED);
+ }
+}
+
+void State::setCullFace(bool enabled)
+{
+ if (mRasterizer.cullFace != enabled)
+ {
+ mRasterizer.cullFace = enabled;
+ mDirtyBits.set(DIRTY_BIT_CULL_FACE_ENABLED);
+ }
+}
+
+void State::setCullMode(CullFaceMode mode)
+{
+ if (mRasterizer.cullMode != mode)
+ {
+ mRasterizer.cullMode = mode;
+ mDirtyBits.set(DIRTY_BIT_CULL_FACE);
+ }
+}
+
+void State::setFrontFace(GLenum front)
+{
+ if (mRasterizer.frontFace != front)
+ {
+ mRasterizer.frontFace = front;
+ mDirtyBits.set(DIRTY_BIT_FRONT_FACE);
+ }
+}
+
+void State::setDepthTest(bool enabled)
+{
+ if (mDepthStencil.depthTest != enabled)
+ {
+ mDepthStencil.depthTest = enabled;
+ mDirtyBits.set(DIRTY_BIT_DEPTH_TEST_ENABLED);
+ }
+}
+
+void State::setDepthFunc(GLenum depthFunc)
+{
+ if (mDepthStencil.depthFunc != depthFunc)
+ {
+ mDepthStencil.depthFunc = depthFunc;
+ mDirtyBits.set(DIRTY_BIT_DEPTH_FUNC);
+ }
+}
+
+void State::setDepthRange(float zNear, float zFar)
+{
+ if (mNearZ != zNear || mFarZ != zFar)
+ {
+ mNearZ = zNear;
+ mFarZ = zFar;
+ mDirtyBits.set(DIRTY_BIT_DEPTH_RANGE);
+ }
+}
+
+void State::setClipControl(GLenum origin, GLenum depth)
+{
+ bool updated = false;
+ if (mClipControlOrigin != origin)
+ {
+ mClipControlOrigin = origin;
+ updated = true;
+ }
+
+ if (mClipControlDepth != depth)
+ {
+ mClipControlDepth = depth;
+ updated = true;
+ }
+
+ if (updated)
+ {
+ mDirtyBits.set(DIRTY_BIT_EXTENDED);
+ mExtendedDirtyBits.set(EXTENDED_DIRTY_BIT_CLIP_CONTROL);
+ }
+}
+
+void State::setBlend(bool enabled)
+{
+ if (mSetBlendIndexedInvoked || mBlendState.blend != enabled)
+ {
+ mBlendState.blend = enabled;
+
+ mSetBlendIndexedInvoked = false;
+ mBlendStateExt.setEnabled(enabled);
+ mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
+ }
+}
+
+void State::setBlendIndexed(bool enabled, GLuint index)
+{
+ mSetBlendIndexedInvoked = true;
+ mBlendStateExt.setEnabledIndexed(index, enabled);
+ mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
+}
+
+void State::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
+{
+ if (!mSetBlendFactorsIndexedInvoked && mBlendState.sourceBlendRGB == sourceRGB &&
+ mBlendState.destBlendRGB == destRGB && mBlendState.sourceBlendAlpha == sourceAlpha &&
+ mBlendState.destBlendAlpha == destAlpha)
+ {
+ return;
+ }
+
+ mBlendState.sourceBlendRGB = sourceRGB;
+ mBlendState.destBlendRGB = destRGB;
+ mBlendState.sourceBlendAlpha = sourceAlpha;
+ mBlendState.destBlendAlpha = destAlpha;
+
+ if (mNoSimultaneousConstantColorAndAlphaBlendFunc)
+ {
+ if (hasConstantColor(sourceRGB, destRGB))
+ {
+ mBlendFuncConstantColorDrawBuffers.set();
+ }
+ else
+ {
+ mBlendFuncConstantColorDrawBuffers.reset();
+ }
+
+ if (hasConstantAlpha(sourceRGB, destRGB))
+ {
+ mBlendFuncConstantAlphaDrawBuffers.set();
+ }
+ else
+ {
+ mBlendFuncConstantAlphaDrawBuffers.reset();
+ }
+ }
+
+ mSetBlendFactorsIndexedInvoked = false;
+ mBlendStateExt.setFactors(sourceRGB, destRGB, sourceAlpha, destAlpha);
+ mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS);
+}
+
+void State::setBlendFactorsIndexed(GLenum sourceRGB,
+ GLenum destRGB,
+ GLenum sourceAlpha,
+ GLenum destAlpha,
+ GLuint index)
+{
+ if (mNoSimultaneousConstantColorAndAlphaBlendFunc)
+ {
+ mBlendFuncConstantColorDrawBuffers.set(index, hasConstantColor(sourceRGB, destRGB));
+ mBlendFuncConstantAlphaDrawBuffers.set(index, hasConstantAlpha(sourceRGB, destRGB));
+ }
+
+ mSetBlendFactorsIndexedInvoked = true;
+ mBlendStateExt.setFactorsIndexed(index, sourceRGB, destRGB, sourceAlpha, destAlpha);
+ mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS);
+}
+
+void State::setBlendColor(float red, float green, float blue, float alpha)
+{
+ // In ES2 without render-to-float extensions, BlendColor clamps to [0,1] on store.
+ // On ES3+, or with render-to-float exts enabled, it does not clamp on store.
+ const bool isES2 = mClientVersion.major == 2;
+ const bool hasFloatBlending =
+ mExtensions.colorBufferFloatEXT || mExtensions.colorBufferHalfFloatEXT ||
+ mExtensions.colorBufferFloatRgbCHROMIUM || mExtensions.colorBufferFloatRgbaCHROMIUM;
+ if ((isES2 && !hasFloatBlending) || mNoUnclampedBlendColor)
+ {
+ red = clamp01(red);
+ green = clamp01(green);
+ blue = clamp01(blue);
+ alpha = clamp01(alpha);
+ }
+
+ if (mBlendColor.red != red || mBlendColor.green != green || mBlendColor.blue != blue ||
+ mBlendColor.alpha != alpha)
+ {
+ mBlendColor.red = red;
+ mBlendColor.green = green;
+ mBlendColor.blue = blue;
+ mBlendColor.alpha = alpha;
+ mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
+ }
+}
+
+void State::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
+{
+ if (mSetBlendEquationsIndexedInvoked || mBlendState.blendEquationRGB != rgbEquation ||
+ mBlendState.blendEquationAlpha != alphaEquation)
+ {
+ mBlendState.blendEquationRGB = rgbEquation;
+ mBlendState.blendEquationAlpha = alphaEquation;
+
+ mSetBlendEquationsIndexedInvoked = false;
+ mBlendStateExt.setEquations(rgbEquation, alphaEquation);
+ mDirtyBits.set(DIRTY_BIT_BLEND_EQUATIONS);
+ }
+}
+
+void State::setBlendEquationIndexed(GLenum rgbEquation, GLenum alphaEquation, GLuint index)
+{
+ mSetBlendEquationsIndexedInvoked = true;
+ mBlendStateExt.setEquationsIndexed(index, rgbEquation, alphaEquation);
+ mDirtyBits.set(DIRTY_BIT_BLEND_EQUATIONS);
+}
+
+void State::setStencilTest(bool enabled)
+{
+ if (mDepthStencil.stencilTest != enabled)
+ {
+ mDepthStencil.stencilTest = enabled;
+ mDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED);
+ }
+}
+
+void State::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
+{
+ if (mDepthStencil.stencilFunc != stencilFunc || mStencilRef != stencilRef ||
+ mDepthStencil.stencilMask != stencilMask)
+ {
+ mDepthStencil.stencilFunc = stencilFunc;
+ mStencilRef = stencilRef;
+ mDepthStencil.stencilMask = stencilMask;
+ mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
+ }
+}
+
+void State::setStencilBackParams(GLenum stencilBackFunc,
+ GLint stencilBackRef,
+ GLuint stencilBackMask)
+{
+ if (mDepthStencil.stencilBackFunc != stencilBackFunc || mStencilBackRef != stencilBackRef ||
+ mDepthStencil.stencilBackMask != stencilBackMask)
+ {
+ mDepthStencil.stencilBackFunc = stencilBackFunc;
+ mStencilBackRef = stencilBackRef;
+ mDepthStencil.stencilBackMask = stencilBackMask;
+ mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
+ }
+}
+
+void State::setStencilWritemask(GLuint stencilWritemask)
+{
+ if (mDepthStencil.stencilWritemask != stencilWritemask)
+ {
+ mDepthStencil.stencilWritemask = stencilWritemask;
+ mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+ }
+}
+
+void State::setStencilBackWritemask(GLuint stencilBackWritemask)
+{
+ if (mDepthStencil.stencilBackWritemask != stencilBackWritemask)
+ {
+ mDepthStencil.stencilBackWritemask = stencilBackWritemask;
+ mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+ }
+}
+
+void State::setStencilOperations(GLenum stencilFail,
+ GLenum stencilPassDepthFail,
+ GLenum stencilPassDepthPass)
+{
+ if (mDepthStencil.stencilFail != stencilFail ||
+ mDepthStencil.stencilPassDepthFail != stencilPassDepthFail ||
+ mDepthStencil.stencilPassDepthPass != stencilPassDepthPass)
+ {
+ mDepthStencil.stencilFail = stencilFail;
+ mDepthStencil.stencilPassDepthFail = stencilPassDepthFail;
+ mDepthStencil.stencilPassDepthPass = stencilPassDepthPass;
+ mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT);
+ }
+}
+
+void State::setStencilBackOperations(GLenum stencilBackFail,
+ GLenum stencilBackPassDepthFail,
+ GLenum stencilBackPassDepthPass)
+{
+ if (mDepthStencil.stencilBackFail != stencilBackFail ||
+ mDepthStencil.stencilBackPassDepthFail != stencilBackPassDepthFail ||
+ mDepthStencil.stencilBackPassDepthPass != stencilBackPassDepthPass)
+ {
+ mDepthStencil.stencilBackFail = stencilBackFail;
+ mDepthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail;
+ mDepthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass;
+ mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK);
+ }
+}
+
+void State::setPolygonOffsetFill(bool enabled)
+{
+ if (mRasterizer.polygonOffsetFill != enabled)
+ {
+ mRasterizer.polygonOffsetFill = enabled;
+ mDirtyBits.set(DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED);
+ }
+}
+
+void State::setPolygonOffsetParams(GLfloat factor, GLfloat units)
+{
+ // An application can pass NaN values here, so handle this gracefully
+ mRasterizer.polygonOffsetFactor = factor != factor ? 0.0f : factor;
+ mRasterizer.polygonOffsetUnits = units != units ? 0.0f : units;
+ mDirtyBits.set(DIRTY_BIT_POLYGON_OFFSET);
+}
+
+void State::setSampleAlphaToCoverage(bool enabled)
+{
+ if (mSampleAlphaToCoverage != enabled)
+ {
+ mSampleAlphaToCoverage = enabled;
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED);
+ }
+}
+
+void State::setSampleCoverage(bool enabled)
+{
+ if (mSampleCoverage != enabled)
+ {
+ mSampleCoverage = enabled;
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_COVERAGE_ENABLED);
+ }
+}
+
+void State::setSampleCoverageParams(GLclampf value, bool invert)
+{
+ mSampleCoverageValue = value;
+ mSampleCoverageInvert = invert;
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_COVERAGE);
+}
+
+void State::setSampleMaskEnabled(bool enabled)
+{
+ if (mSampleMask != enabled)
+ {
+ mSampleMask = enabled;
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_MASK_ENABLED);
+ }
+}
+
+void State::setSampleMaskParams(GLuint maskNumber, GLbitfield mask)
+{
+ ASSERT(maskNumber < mMaxSampleMaskWords);
+ mSampleMaskValues[maskNumber] = mask;
+ // TODO(jmadill): Use a child dirty bit if we ever use more than two words.
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_MASK);
+}
+
+void State::setSampleAlphaToOne(bool enabled)
+{
+ if (mSampleAlphaToOne != enabled)
+ {
+ mSampleAlphaToOne = enabled;
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_ONE);
+ }
+}
+
+void State::setMultisampling(bool enabled)
+{
+ if (mMultiSampling != enabled)
+ {
+ mMultiSampling = enabled;
+ mDirtyBits.set(DIRTY_BIT_MULTISAMPLING);
+ }
+}
+
+void State::setSampleShading(bool enabled)
+{
+ if (mIsSampleShadingEnabled != enabled)
+ {
+ mIsSampleShadingEnabled = enabled;
+ mMinSampleShading = (enabled) ? 1.0f : mMinSampleShading;
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_SHADING);
+ }
+}
+
+void State::setMinSampleShading(float value)
+{
+ value = gl::clamp01(value);
+
+ if (mMinSampleShading != value)
+ {
+ mMinSampleShading = value;
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_SHADING);
+ }
+}
+
+void State::setScissorTest(bool enabled)
+{
+ if (mScissorTest != enabled)
+ {
+ mScissorTest = enabled;
+ mDirtyBits.set(DIRTY_BIT_SCISSOR_TEST_ENABLED);
+ }
+}
+
+void State::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ // Skip if same scissor info
+ if (mScissor.x != x || mScissor.y != y || mScissor.width != width || mScissor.height != height)
+ {
+ mScissor.x = x;
+ mScissor.y = y;
+ mScissor.width = width;
+ mScissor.height = height;
+ mDirtyBits.set(DIRTY_BIT_SCISSOR);
+ }
+}
+
+void State::setDither(bool enabled)
+{
+ if (mRasterizer.dither != enabled)
+ {
+ mRasterizer.dither = enabled;
+ mDirtyBits.set(DIRTY_BIT_DITHER_ENABLED);
+ }
+}
+
+void State::setPrimitiveRestart(bool enabled)
+{
+ if (mPrimitiveRestart != enabled)
+ {
+ mPrimitiveRestart = enabled;
+ mDirtyBits.set(DIRTY_BIT_PRIMITIVE_RESTART_ENABLED);
+ }
+}
+
+void State::setClipDistanceEnable(int idx, bool enable)
+{
+ if (enable)
+ {
+ mClipDistancesEnabled.set(idx);
+ }
+ else
+ {
+ mClipDistancesEnabled.reset(idx);
+ }
+
+ mDirtyBits.set(DIRTY_BIT_EXTENDED);
+ mExtendedDirtyBits.set(EXTENDED_DIRTY_BIT_CLIP_DISTANCES);
+}
+
+void State::setEnableFeature(GLenum feature, bool enabled)
+{
+ switch (feature)
+ {
+ case GL_MULTISAMPLE_EXT:
+ setMultisampling(enabled);
+ return;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ setSampleAlphaToOne(enabled);
+ return;
+ case GL_CULL_FACE:
+ setCullFace(enabled);
+ return;
+ case GL_POLYGON_OFFSET_FILL:
+ setPolygonOffsetFill(enabled);
+ return;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE:
+ setSampleAlphaToCoverage(enabled);
+ return;
+ case GL_SAMPLE_COVERAGE:
+ setSampleCoverage(enabled);
+ return;
+ case GL_SCISSOR_TEST:
+ setScissorTest(enabled);
+ return;
+ case GL_STENCIL_TEST:
+ setStencilTest(enabled);
+ return;
+ case GL_DEPTH_TEST:
+ setDepthTest(enabled);
+ return;
+ case GL_BLEND:
+ setBlend(enabled);
+ return;
+ case GL_DITHER:
+ setDither(enabled);
+ return;
+ case GL_COLOR_LOGIC_OP:
+ if (mClientVersion.major == 1)
+ {
+ // Handle logicOp in GLES1 through the GLES1 state management and emulation.
+ // Otherwise this state could be set as part of ANGLE_logic_op.
+ break;
+ }
+ setLogicOpEnabled(enabled);
+ return;
+ case GL_PRIMITIVE_RESTART_FIXED_INDEX:
+ setPrimitiveRestart(enabled);
+ return;
+ case GL_RASTERIZER_DISCARD:
+ setRasterizerDiscard(enabled);
+ return;
+ case GL_SAMPLE_MASK:
+ setSampleMaskEnabled(enabled);
+ return;
+ case GL_DEBUG_OUTPUT_SYNCHRONOUS:
+ mDebug.setOutputSynchronous(enabled);
+ return;
+ case GL_DEBUG_OUTPUT:
+ mDebug.setOutputEnabled(enabled);
+ return;
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ setFramebufferSRGB(enabled);
+ return;
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ mTextureRectangleEnabled = enabled;
+ return;
+ case GL_SAMPLE_SHADING:
+ setSampleShading(enabled);
+ return;
+ // GL_APPLE_clip_distance/GL_EXT_clip_cull_distance
+ case GL_CLIP_DISTANCE0_EXT:
+ case GL_CLIP_DISTANCE1_EXT:
+ case GL_CLIP_DISTANCE2_EXT:
+ case GL_CLIP_DISTANCE3_EXT:
+ case GL_CLIP_DISTANCE4_EXT:
+ case GL_CLIP_DISTANCE5_EXT:
+ case GL_CLIP_DISTANCE6_EXT:
+ case GL_CLIP_DISTANCE7_EXT:
+ // NOTE(hqle): These enums are conflicted with GLES1's enums, need
+ // to do additional check here:
+ if (mClientVersion.major >= 2)
+ {
+ setClipDistanceEnable(feature - GL_CLIP_DISTANCE0_EXT, enabled);
+ return;
+ }
+ break;
+ case GL_SHADING_RATE_PRESERVE_ASPECT_RATIO_QCOM:
+ mShadingRatePreserveAspectRatio = enabled;
+ return;
+ }
+
+ ASSERT(mClientVersion.major == 1);
+
+ // GLES1 emulation. Need to separate from main switch due to conflict enum between
+ // GL_CLIP_DISTANCE0_EXT & GL_CLIP_PLANE0
+ switch (feature)
+ {
+ case GL_ALPHA_TEST:
+ mGLES1State.mAlphaTestEnabled = enabled;
+ break;
+ case GL_TEXTURE_2D:
+ mGLES1State.mTexUnitEnables[mActiveSampler].set(TextureType::_2D, enabled);
+ break;
+ case GL_TEXTURE_CUBE_MAP:
+ mGLES1State.mTexUnitEnables[mActiveSampler].set(TextureType::CubeMap, enabled);
+ break;
+ case GL_LIGHTING:
+ mGLES1State.mLightingEnabled = enabled;
+ break;
+ case GL_LIGHT0:
+ case GL_LIGHT1:
+ case GL_LIGHT2:
+ case GL_LIGHT3:
+ case GL_LIGHT4:
+ case GL_LIGHT5:
+ case GL_LIGHT6:
+ case GL_LIGHT7:
+ mGLES1State.mLights[feature - GL_LIGHT0].enabled = enabled;
+ break;
+ case GL_NORMALIZE:
+ mGLES1State.mNormalizeEnabled = enabled;
+ break;
+ case GL_RESCALE_NORMAL:
+ mGLES1State.mRescaleNormalEnabled = enabled;
+ break;
+ case GL_COLOR_MATERIAL:
+ mGLES1State.mColorMaterialEnabled = enabled;
+ break;
+ case GL_CLIP_PLANE0:
+ case GL_CLIP_PLANE1:
+ case GL_CLIP_PLANE2:
+ case GL_CLIP_PLANE3:
+ case GL_CLIP_PLANE4:
+ case GL_CLIP_PLANE5:
+ mGLES1State.mClipPlanes[feature - GL_CLIP_PLANE0].enabled = enabled;
+ break;
+ case GL_FOG:
+ mGLES1State.mFogEnabled = enabled;
+ break;
+ case GL_POINT_SMOOTH:
+ mGLES1State.mPointSmoothEnabled = enabled;
+ break;
+ case GL_LINE_SMOOTH:
+ mGLES1State.mLineSmoothEnabled = enabled;
+ break;
+ case GL_POINT_SPRITE_OES:
+ mGLES1State.mPointSpriteEnabled = enabled;
+ break;
+ case GL_COLOR_LOGIC_OP:
+ mGLES1State.setLogicOpEnabled(enabled);
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+void State::setEnableFeatureIndexed(GLenum feature, bool enabled, GLuint index)
+{
+ switch (feature)
+ {
+ case GL_BLEND:
+ setBlendIndexed(enabled, index);
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+bool State::getEnableFeature(GLenum feature) const
+{
+ switch (feature)
+ {
+ case GL_MULTISAMPLE_EXT:
+ return isMultisamplingEnabled();
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ return isSampleAlphaToOneEnabled();
+ case GL_CULL_FACE:
+ return isCullFaceEnabled();
+ case GL_POLYGON_OFFSET_FILL:
+ return isPolygonOffsetFillEnabled();
+ case GL_SAMPLE_ALPHA_TO_COVERAGE:
+ return isSampleAlphaToCoverageEnabled();
+ case GL_SAMPLE_COVERAGE:
+ return isSampleCoverageEnabled();
+ case GL_SCISSOR_TEST:
+ return isScissorTestEnabled();
+ case GL_STENCIL_TEST:
+ return isStencilTestEnabled();
+ case GL_DEPTH_TEST:
+ return isDepthTestEnabled();
+ case GL_BLEND:
+ return isBlendEnabled();
+ case GL_DITHER:
+ return isDitherEnabled();
+ case GL_COLOR_LOGIC_OP:
+ if (mClientVersion.major == 1)
+ {
+ // Handle logicOp in GLES1 through the GLES1 state management and emulation.
+ break;
+ }
+ return isLogicOpEnabled();
+ case GL_PRIMITIVE_RESTART_FIXED_INDEX:
+ return isPrimitiveRestartEnabled();
+ case GL_RASTERIZER_DISCARD:
+ return isRasterizerDiscardEnabled();
+ case GL_SAMPLE_MASK:
+ return isSampleMaskEnabled();
+ case GL_DEBUG_OUTPUT_SYNCHRONOUS:
+ return mDebug.isOutputSynchronous();
+ case GL_DEBUG_OUTPUT:
+ return mDebug.isOutputEnabled();
+ case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+ return isBindGeneratesResourceEnabled();
+ case GL_CLIENT_ARRAYS_ANGLE:
+ return areClientArraysEnabled();
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ return getFramebufferSRGB();
+ case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ return mRobustResourceInit;
+ case GL_PROGRAM_CACHE_ENABLED_ANGLE:
+ return mProgramBinaryCacheEnabled;
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ return mTextureRectangleEnabled;
+ case GL_SAMPLE_SHADING:
+ return isSampleShadingEnabled();
+ // GL_APPLE_clip_distance/GL_EXT_clip_cull_distance
+ case GL_CLIP_DISTANCE0_EXT:
+ case GL_CLIP_DISTANCE1_EXT:
+ case GL_CLIP_DISTANCE2_EXT:
+ case GL_CLIP_DISTANCE3_EXT:
+ case GL_CLIP_DISTANCE4_EXT:
+ case GL_CLIP_DISTANCE5_EXT:
+ case GL_CLIP_DISTANCE6_EXT:
+ case GL_CLIP_DISTANCE7_EXT:
+ if (mClientVersion.major >= 2)
+ {
+ // If GLES version is 1, the GL_CLIP_DISTANCE0_EXT enum will be used as
+ // GL_CLIP_PLANE0 instead.
+ return mClipDistancesEnabled.test(feature - GL_CLIP_DISTANCE0_EXT);
+ }
+ break;
+ case GL_SHADING_RATE_PRESERVE_ASPECT_RATIO_QCOM:
+ return mShadingRatePreserveAspectRatio;
+ }
+
+ ASSERT(mClientVersion.major == 1);
+
+ switch (feature)
+ {
+ // GLES1 emulation
+ case GL_ALPHA_TEST:
+ return mGLES1State.mAlphaTestEnabled;
+ case GL_VERTEX_ARRAY:
+ return mGLES1State.mVertexArrayEnabled;
+ case GL_NORMAL_ARRAY:
+ return mGLES1State.mNormalArrayEnabled;
+ case GL_COLOR_ARRAY:
+ return mGLES1State.mColorArrayEnabled;
+ case GL_POINT_SIZE_ARRAY_OES:
+ return mGLES1State.mPointSizeArrayEnabled;
+ case GL_TEXTURE_COORD_ARRAY:
+ return mGLES1State.mTexCoordArrayEnabled[mGLES1State.mClientActiveTexture];
+ case GL_TEXTURE_2D:
+ return mGLES1State.isTextureTargetEnabled(getActiveSampler(), TextureType::_2D);
+ case GL_TEXTURE_CUBE_MAP:
+ return mGLES1State.isTextureTargetEnabled(getActiveSampler(), TextureType::CubeMap);
+ case GL_LIGHTING:
+ return mGLES1State.mLightingEnabled;
+ case GL_LIGHT0:
+ case GL_LIGHT1:
+ case GL_LIGHT2:
+ case GL_LIGHT3:
+ case GL_LIGHT4:
+ case GL_LIGHT5:
+ case GL_LIGHT6:
+ case GL_LIGHT7:
+ return mGLES1State.mLights[feature - GL_LIGHT0].enabled;
+ case GL_NORMALIZE:
+ return mGLES1State.mNormalizeEnabled;
+ case GL_RESCALE_NORMAL:
+ return mGLES1State.mRescaleNormalEnabled;
+ case GL_COLOR_MATERIAL:
+ return mGLES1State.mColorMaterialEnabled;
+ case GL_CLIP_PLANE0:
+ case GL_CLIP_PLANE1:
+ case GL_CLIP_PLANE2:
+ case GL_CLIP_PLANE3:
+ case GL_CLIP_PLANE4:
+ case GL_CLIP_PLANE5:
+ return mGLES1State.mClipPlanes[feature - GL_CLIP_PLANE0].enabled;
+ case GL_FOG:
+ return mGLES1State.mFogEnabled;
+ case GL_POINT_SMOOTH:
+ return mGLES1State.mPointSmoothEnabled;
+ case GL_LINE_SMOOTH:
+ return mGLES1State.mLineSmoothEnabled;
+ case GL_POINT_SPRITE_OES:
+ return mGLES1State.mPointSpriteEnabled;
+ case GL_COLOR_LOGIC_OP:
+ return mGLES1State.mLogicOpEnabled;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool State::getEnableFeatureIndexed(GLenum feature, GLuint index) const
+{
+ switch (feature)
+ {
+ case GL_BLEND:
+ return isBlendEnabledIndexed(index);
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+void State::setLineWidth(GLfloat width)
+{
+ mLineWidth = width;
+ mDirtyBits.set(DIRTY_BIT_LINE_WIDTH);
+}
+
+void State::setGenerateMipmapHint(GLenum hint)
+{
+ mGenerateMipmapHint = hint;
+ mDirtyBits.set(DIRTY_BIT_EXTENDED);
+ mExtendedDirtyBits.set(EXTENDED_DIRTY_BIT_MIPMAP_GENERATION_HINT);
+}
+
+GLenum State::getGenerateMipmapHint() const
+{
+ return mGenerateMipmapHint;
+}
+
+void State::setTextureFilteringHint(GLenum hint)
+{
+ mTextureFilteringHint = hint;
+ // Note: we don't add a dirty bit for this flag as it's not expected to be toggled at
+ // runtime.
+}
+
+GLenum State::getTextureFilteringHint() const
+{
+ return mTextureFilteringHint;
+}
+
+void State::setFragmentShaderDerivativeHint(GLenum hint)
+{
+ mFragmentShaderDerivativeHint = hint;
+ mDirtyBits.set(DIRTY_BIT_EXTENDED);
+ mExtendedDirtyBits.set(EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT);
+ // TODO: Propagate the hint to shader translator so we can write
+ // ddx, ddx_coarse, or ddx_fine depending on the hint.
+ // Ignore for now. It is valid for implementations to ignore hint.
+}
+
+void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ // [OpenGL ES 2.0.25] section 2.12.1 page 45:
+ // Viewport width and height are clamped to implementation-dependent maximums when specified.
+ width = std::min(width, mCaps.maxViewportWidth);
+ height = std::min(height, mCaps.maxViewportHeight);
+
+ // Skip if same viewport info
+ if (mViewport.x != x || mViewport.y != y || mViewport.width != width ||
+ mViewport.height != height)
+ {
+ mViewport.x = x;
+ mViewport.y = y;
+ mViewport.width = width;
+ mViewport.height = height;
+ mDirtyBits.set(DIRTY_BIT_VIEWPORT);
+ }
+}
+
+void State::setActiveSampler(unsigned int active)
+{
+ mActiveSampler = active;
+}
+
+void State::setSamplerTexture(const Context *context, TextureType type, Texture *texture)
+{
+ if (mExecutable && mExecutable->getActiveSamplersMask()[mActiveSampler] &&
+ IsTextureCompatibleWithSampler(type, mExecutable->getActiveSamplerTypes()[mActiveSampler]))
+ {
+ updateTextureBinding(context, mActiveSampler, texture);
+ }
+
+ mSamplerTextures[type][mActiveSampler].set(context, texture);
+
+ mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
+}
+
+Texture *State::getTargetTexture(TextureType type) const
+{
+ return getSamplerTexture(static_cast<unsigned int>(mActiveSampler), type);
+}
+
+TextureID State::getSamplerTextureId(unsigned int sampler, TextureType type) const
+{
+ ASSERT(sampler < mSamplerTextures[type].size());
+ return mSamplerTextures[type][sampler].id();
+}
+
+void State::detachTexture(const Context *context, const TextureMap &zeroTextures, TextureID texture)
+{
+ // Textures have a detach method on State rather than a simple
+ // removeBinding, because the zero/null texture objects are managed
+ // separately, and don't have to go through the Context's maps or
+ // the ResourceManager.
+
+ // [OpenGL ES 2.0.24] section 3.8 page 84:
+ // If a texture object is deleted, it is as if all texture units which are bound to that texture
+ // object are rebound to texture object zero
+
+ for (TextureType type : angle::AllEnums<TextureType>())
+ {
+ TextureBindingVector &textureVector = mSamplerTextures[type];
+
+ for (size_t bindingIndex = 0; bindingIndex < textureVector.size(); ++bindingIndex)
+ {
+ BindingPointer<Texture> &binding = textureVector[bindingIndex];
+ if (binding.id() == texture)
+ {
+ // Zero textures are the "default" textures instead of NULL
+ Texture *zeroTexture = zeroTextures[type].get();
+ ASSERT(zeroTexture != nullptr);
+ if (mCompleteTextureBindings[bindingIndex].getSubject() == binding.get())
+ {
+ updateTextureBinding(context, bindingIndex, zeroTexture);
+ }
+ binding.set(context, zeroTexture);
+ }
+ }
+ }
+
+ for (auto &bindingImageUnit : mImageUnits)
+ {
+ if (bindingImageUnit.texture.id() == texture)
+ {
+ bindingImageUnit.texture.set(context, nullptr);
+ bindingImageUnit.level = 0;
+ bindingImageUnit.layered = false;
+ bindingImageUnit.layer = 0;
+ bindingImageUnit.access = GL_READ_ONLY;
+ bindingImageUnit.format = GL_R32UI;
+ }
+ }
+
+ // [OpenGL ES 2.0.24] section 4.4 page 112:
+ // If a texture object is deleted while its image is attached to the currently bound
+ // framebuffer, then it is as if Texture2DAttachment had been called, with a texture of 0, for
+ // each attachment point to which this image was attached in the currently bound framebuffer.
+
+ if (mReadFramebuffer && mReadFramebuffer->detachTexture(context, texture))
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
+ }
+
+ if (mDrawFramebuffer && mDrawFramebuffer->detachTexture(context, texture))
+ {
+ setDrawFramebufferDirty();
+ }
+}
+
+void State::initializeZeroTextures(const Context *context, const TextureMap &zeroTextures)
+{
+ for (TextureType type : angle::AllEnums<TextureType>())
+ {
+ for (size_t textureUnit = 0; textureUnit < mSamplerTextures[type].size(); ++textureUnit)
+ {
+ mSamplerTextures[type][textureUnit].set(context, zeroTextures[type].get());
+ }
+ }
+}
+
+void State::invalidateTextureBindings(TextureType type)
+{
+ mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS);
+}
+
+void State::setSamplerBinding(const Context *context, GLuint textureUnit, Sampler *sampler)
+{
+ if (mSamplers[textureUnit].get() == sampler)
+ {
+ return;
+ }
+
+ mSamplers[textureUnit].set(context, sampler);
+ mDirtyBits.set(DIRTY_BIT_SAMPLER_BINDINGS);
+ // This is overly conservative as it assumes the sampler has never been bound.
+ setSamplerDirty(textureUnit);
+ onActiveTextureChange(context, textureUnit);
+}
+
+void State::detachSampler(const Context *context, SamplerID sampler)
+{
+ // [OpenGL ES 3.0.2] section 3.8.2 pages 123-124:
+ // If a sampler object that is currently bound to one or more texture units is
+ // deleted, it is as though BindSampler is called once for each texture unit to
+ // which the sampler is bound, with unit set to the texture unit and sampler set to zero.
+ for (size_t i = 0; i < mSamplers.size(); i++)
+ {
+ if (mSamplers[i].id() == sampler)
+ {
+ setSamplerBinding(context, static_cast<GLuint>(i), nullptr);
+ }
+ }
+}
+
+void State::setRenderbufferBinding(const Context *context, Renderbuffer *renderbuffer)
+{
+ mRenderbuffer.set(context, renderbuffer);
+ mDirtyBits.set(DIRTY_BIT_RENDERBUFFER_BINDING);
+}
+
+void State::detachRenderbuffer(const Context *context, RenderbufferID renderbuffer)
+{
+ // [OpenGL ES 2.0.24] section 4.4 page 109:
+ // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though
+ // BindRenderbuffer had been executed with the target RENDERBUFFER and name of zero.
+
+ if (mRenderbuffer.id() == renderbuffer)
+ {
+ setRenderbufferBinding(context, nullptr);
+ }
+
+ // [OpenGL ES 2.0.24] section 4.4 page 111:
+ // If a renderbuffer object is deleted while its image is attached to the currently bound
+ // framebuffer, then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of
+ // 0, for each attachment point to which this image was attached in the currently bound
+ // framebuffer.
+
+ Framebuffer *readFramebuffer = mReadFramebuffer;
+ Framebuffer *drawFramebuffer = mDrawFramebuffer;
+
+ if (readFramebuffer && readFramebuffer->detachRenderbuffer(context, renderbuffer))
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
+ }
+
+ if (drawFramebuffer && drawFramebuffer != readFramebuffer)
+ {
+ if (drawFramebuffer->detachRenderbuffer(context, renderbuffer))
+ {
+ setDrawFramebufferDirty();
+ }
+ }
+}
+
+void State::setReadFramebufferBinding(Framebuffer *framebuffer)
+{
+ if (mReadFramebuffer == framebuffer)
+ return;
+
+ mReadFramebuffer = framebuffer;
+ mDirtyBits.set(DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
+
+ if (mReadFramebuffer && mReadFramebuffer->hasAnyDirtyBit())
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
+ }
+}
+
+void State::setDrawFramebufferBinding(Framebuffer *framebuffer)
+{
+ if (mDrawFramebuffer == framebuffer)
+ return;
+
+ mDrawFramebuffer = framebuffer;
+ mDirtyBits.set(DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
+
+ if (mDrawFramebuffer)
+ {
+ mDrawFramebuffer->setWriteControlMode(getFramebufferSRGB() ? SrgbWriteControlMode::Default
+ : SrgbWriteControlMode::Linear);
+
+ if (mDrawFramebuffer->hasAnyDirtyBit())
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+ }
+
+ if (mRobustResourceInit && mDrawFramebuffer->hasResourceThatNeedsInit())
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_DRAW_ATTACHMENTS);
+ }
+ }
+}
+
+Framebuffer *State::getTargetFramebuffer(GLenum target) const
+{
+ switch (target)
+ {
+ case GL_READ_FRAMEBUFFER_ANGLE:
+ return mReadFramebuffer;
+ case GL_DRAW_FRAMEBUFFER_ANGLE:
+ case GL_FRAMEBUFFER:
+ return mDrawFramebuffer;
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+
+Framebuffer *State::getDefaultFramebuffer() const
+{
+ return mFramebufferManager->getDefaultFramebuffer();
+}
+
+bool State::removeReadFramebufferBinding(FramebufferID framebuffer)
+{
+ if (mReadFramebuffer != nullptr && mReadFramebuffer->id() == framebuffer)
+ {
+ setReadFramebufferBinding(nullptr);
+ return true;
+ }
+
+ return false;
+}
+
+bool State::removeDrawFramebufferBinding(FramebufferID framebuffer)
+{
+ if (mReadFramebuffer != nullptr && mDrawFramebuffer->id() == framebuffer)
+ {
+ setDrawFramebufferBinding(nullptr);
+ return true;
+ }
+
+ return false;
+}
+
+void State::setVertexArrayBinding(const Context *context, VertexArray *vertexArray)
+{
+ if (mVertexArray == vertexArray)
+ {
+ return;
+ }
+
+ if (mVertexArray)
+ {
+ mVertexArray->onBindingChanged(context, -1);
+ }
+ if (vertexArray)
+ {
+ vertexArray->onBindingChanged(context, 1);
+ }
+
+ mVertexArray = vertexArray;
+ mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING);
+
+ if (mVertexArray && mVertexArray->hasAnyDirtyBit())
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+ }
+}
+
+bool State::removeVertexArrayBinding(const Context *context, VertexArrayID vertexArray)
+{
+ if (mVertexArray && mVertexArray->id().value == vertexArray.value)
+ {
+ mVertexArray->onBindingChanged(context, -1);
+ mVertexArray = nullptr;
+ mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+ return true;
+ }
+
+ return false;
+}
+
+VertexArrayID State::getVertexArrayId() const
+{
+ ASSERT(mVertexArray != nullptr);
+ return mVertexArray->id();
+}
+
+void State::bindVertexBuffer(const Context *context,
+ GLuint bindingIndex,
+ Buffer *boundBuffer,
+ GLintptr offset,
+ GLsizei stride)
+{
+ getVertexArray()->bindVertexBuffer(context, bindingIndex, boundBuffer, offset, stride);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setVertexAttribFormat(GLuint attribIndex,
+ GLint size,
+ VertexAttribType type,
+ bool normalized,
+ bool pureInteger,
+ GLuint relativeOffset)
+{
+ getVertexArray()->setVertexAttribFormat(attribIndex, size, type, normalized, pureInteger,
+ relativeOffset);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setVertexBindingDivisor(const Context *context, GLuint bindingIndex, GLuint divisor)
+{
+ getVertexArray()->setVertexBindingDivisor(context, bindingIndex, divisor);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+angle::Result State::setProgram(const Context *context, Program *newProgram)
+{
+ if (newProgram && !newProgram->isLinked())
+ {
+ // Protect against applications that disable validation and try to use a program that was
+ // not successfully linked.
+ WARN() << "Attempted to use a program that was not successfully linked";
+ return angle::Result::Continue;
+ }
+
+ if (mProgram != newProgram)
+ {
+ if (mProgram)
+ {
+ unsetActiveTextures(mExecutable->getActiveSamplersMask());
+ mProgram->release(context);
+ }
+
+ mProgram = newProgram;
+ mExecutable = nullptr;
+
+ if (mProgram)
+ {
+ mExecutable = &mProgram->getExecutable();
+ newProgram->addRef();
+ ANGLE_TRY(onProgramExecutableChange(context, newProgram));
+ }
+ else if (mProgramPipeline.get())
+ {
+ mExecutable = &mProgramPipeline->getExecutable();
+ ANGLE_TRY(onProgramPipelineExecutableChange(context));
+ }
+
+ // Note that rendering is undefined if glUseProgram(0) is called. But ANGLE will generate
+ // an error if the app tries to draw in this case.
+
+ mDirtyBits.set(DIRTY_BIT_PROGRAM_BINDING);
+ }
+
+ return angle::Result::Continue;
+}
+
+void State::setTransformFeedbackBinding(const Context *context,
+ TransformFeedback *transformFeedback)
+{
+ if (transformFeedback == mTransformFeedback.get())
+ return;
+ if (mTransformFeedback.get())
+ mTransformFeedback->onBindingChanged(context, false);
+ mTransformFeedback.set(context, transformFeedback);
+ if (mTransformFeedback.get())
+ mTransformFeedback->onBindingChanged(context, true);
+ mDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING);
+}
+
+bool State::removeTransformFeedbackBinding(const Context *context,
+ TransformFeedbackID transformFeedback)
+{
+ if (mTransformFeedback.id() == transformFeedback)
+ {
+ if (mTransformFeedback.get())
+ mTransformFeedback->onBindingChanged(context, false);
+ mTransformFeedback.set(context, nullptr);
+ return true;
+ }
+
+ return false;
+}
+
+angle::Result State::setProgramPipelineBinding(const Context *context, ProgramPipeline *pipeline)
+{
+ if (mProgramPipeline.get() == pipeline)
+ {
+ return angle::Result::Continue;
+ }
+
+ if (mProgramPipeline.get())
+ {
+ unsetActiveTextures(mProgramPipeline->getExecutable().getActiveSamplersMask());
+ }
+
+ mProgramPipeline.set(context, pipeline);
+ mDirtyBits.set(DIRTY_BIT_PROGRAM_BINDING);
+
+ // A bound Program always overrides the ProgramPipeline, so only update the
+ // current ProgramExecutable if there isn't currently a Program bound.
+ if (!mProgram)
+ {
+ if (mProgramPipeline.get())
+ {
+ mExecutable = &mProgramPipeline->getExecutable();
+ ANGLE_TRY(onProgramPipelineExecutableChange(context));
+ }
+ else
+ {
+ mExecutable = nullptr;
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+void State::detachProgramPipeline(const Context *context, ProgramPipelineID pipeline)
+{
+ mProgramPipeline.set(context, nullptr);
+
+ // A bound Program always overrides the ProgramPipeline, so only update the
+ // current ProgramExecutable if there isn't currently a Program bound.
+ if (!mProgram)
+ {
+ mExecutable = nullptr;
+ }
+}
+
+bool State::isQueryActive(QueryType type) const
+{
+ const Query *query = mActiveQueries[type].get();
+ if (query != nullptr)
+ {
+ return true;
+ }
+
+ QueryType alternativeType;
+ if (GetAlternativeQueryType(type, &alternativeType))
+ {
+ query = mActiveQueries[alternativeType].get();
+ return query != nullptr;
+ }
+
+ return false;
+}
+
+bool State::isQueryActive(Query *query) const
+{
+ for (auto &queryPointer : mActiveQueries)
+ {
+ if (queryPointer.get() == query)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void State::setActiveQuery(const Context *context, QueryType type, Query *query)
+{
+ mActiveQueries[type].set(context, query);
+}
+
+QueryID State::getActiveQueryId(QueryType type) const
+{
+ const Query *query = getActiveQuery(type);
+ if (query)
+ {
+ return query->id();
+ }
+ return {0};
+}
+
+Query *State::getActiveQuery(QueryType type) const
+{
+ return mActiveQueries[type].get();
+}
+
+angle::Result State::setIndexedBufferBinding(const Context *context,
+ BufferBinding target,
+ GLuint index,
+ Buffer *buffer,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ setBufferBinding(context, target, buffer);
+
+ switch (target)
+ {
+ case BufferBinding::TransformFeedback:
+ ANGLE_TRY(mTransformFeedback->bindIndexedBuffer(context, index, buffer, offset, size));
+ setBufferBinding(context, target, buffer);
+ break;
+ case BufferBinding::Uniform:
+ mBoundUniformBuffersMask.set(index, buffer != nullptr);
+ UpdateIndexedBufferBinding(context, &mUniformBuffers[index], buffer, target, offset,
+ size);
+ break;
+ case BufferBinding::AtomicCounter:
+ mBoundAtomicCounterBuffersMask.set(index, buffer != nullptr);
+ UpdateIndexedBufferBinding(context, &mAtomicCounterBuffers[index], buffer, target,
+ offset, size);
+ break;
+ case BufferBinding::ShaderStorage:
+ mBoundShaderStorageBuffersMask.set(index, buffer != nullptr);
+ UpdateIndexedBufferBinding(context, &mShaderStorageBuffers[index], buffer, target,
+ offset, size);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return angle::Result::Continue;
+}
+
+const OffsetBindingPointer<Buffer> &State::getIndexedUniformBuffer(size_t index) const
+{
+ ASSERT(index < mUniformBuffers.size());
+ return mUniformBuffers[index];
+}
+
+const OffsetBindingPointer<Buffer> &State::getIndexedAtomicCounterBuffer(size_t index) const
+{
+ ASSERT(index < mAtomicCounterBuffers.size());
+ return mAtomicCounterBuffers[index];
+}
+
+const OffsetBindingPointer<Buffer> &State::getIndexedShaderStorageBuffer(size_t index) const
+{
+ ASSERT(index < mShaderStorageBuffers.size());
+ return mShaderStorageBuffers[index];
+}
+
+angle::Result State::detachBuffer(Context *context, const Buffer *buffer)
+{
+ BufferID bufferID = buffer->id();
+ for (gl::BufferBinding target : angle::AllEnums<BufferBinding>())
+ {
+ if (mBoundBuffers[target].id() == bufferID)
+ {
+ UpdateBufferBinding(context, &mBoundBuffers[target], nullptr, target);
+ }
+ }
+
+ TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
+ if (curTransformFeedback)
+ {
+ ANGLE_TRY(curTransformFeedback->detachBuffer(context, bufferID));
+ context->getStateCache().onActiveTransformFeedbackChange(context);
+ }
+
+ if (getVertexArray()->detachBuffer(context, bufferID))
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+ context->getStateCache().onVertexArrayStateChange(context);
+ }
+
+ for (size_t uniformBufferIndex : mBoundUniformBuffersMask)
+ {
+ OffsetBindingPointer<Buffer> &binding = mUniformBuffers[uniformBufferIndex];
+
+ if (binding.id() == bufferID)
+ {
+ UpdateIndexedBufferBinding(context, &binding, nullptr, BufferBinding::Uniform, 0, 0);
+ mBoundUniformBuffersMask.reset(uniformBufferIndex);
+ }
+ }
+
+ for (size_t atomicCounterBufferIndex : mBoundAtomicCounterBuffersMask)
+ {
+ OffsetBindingPointer<Buffer> &binding = mAtomicCounterBuffers[atomicCounterBufferIndex];
+
+ if (binding.id() == bufferID)
+ {
+ UpdateIndexedBufferBinding(context, &binding, nullptr, BufferBinding::AtomicCounter, 0,
+ 0);
+ mBoundAtomicCounterBuffersMask.reset(atomicCounterBufferIndex);
+ }
+ }
+
+ for (size_t shaderStorageBufferIndex : mBoundShaderStorageBuffersMask)
+ {
+ OffsetBindingPointer<Buffer> &binding = mShaderStorageBuffers[shaderStorageBufferIndex];
+
+ if (binding.id() == bufferID)
+ {
+ UpdateIndexedBufferBinding(context, &binding, nullptr, BufferBinding::ShaderStorage, 0,
+ 0);
+ mBoundShaderStorageBuffersMask.reset(shaderStorageBufferIndex);
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
+{
+ getVertexArray()->enableAttribute(attribNum, enabled);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+void State::setVertexAttribf(GLuint index, const GLfloat values[4])
+{
+ ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
+ mVertexAttribCurrentValues[index].setFloatValues(values);
+ mDirtyBits.set(DIRTY_BIT_CURRENT_VALUES);
+ mDirtyCurrentValues.set(index);
+ SetComponentTypeMask(ComponentType::Float, index, &mCurrentValuesTypeMask);
+}
+
+void State::setVertexAttribu(GLuint index, const GLuint values[4])
+{
+ ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
+ mVertexAttribCurrentValues[index].setUnsignedIntValues(values);
+ mDirtyBits.set(DIRTY_BIT_CURRENT_VALUES);
+ mDirtyCurrentValues.set(index);
+ SetComponentTypeMask(ComponentType::UnsignedInt, index, &mCurrentValuesTypeMask);
+}
+
+void State::setVertexAttribi(GLuint index, const GLint values[4])
+{
+ ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size());
+ mVertexAttribCurrentValues[index].setIntValues(values);
+ mDirtyBits.set(DIRTY_BIT_CURRENT_VALUES);
+ mDirtyCurrentValues.set(index);
+ SetComponentTypeMask(ComponentType::Int, index, &mCurrentValuesTypeMask);
+}
+
+void State::setVertexAttribDivisor(const Context *context, GLuint index, GLuint divisor)
+{
+ getVertexArray()->setVertexAttribDivisor(context, index, divisor);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+}
+
+const void *State::getVertexAttribPointer(unsigned int attribNum) const
+{
+ return getVertexArray()->getVertexAttribute(attribNum).pointer;
+}
+
+void State::setPackAlignment(GLint alignment)
+{
+ mPack.alignment = alignment;
+ mDirtyBits.set(DIRTY_BIT_PACK_STATE);
+}
+
+void State::setPackReverseRowOrder(bool reverseRowOrder)
+{
+ mPack.reverseRowOrder = reverseRowOrder;
+ mDirtyBits.set(DIRTY_BIT_PACK_STATE);
+}
+
+void State::setPackRowLength(GLint rowLength)
+{
+ mPack.rowLength = rowLength;
+ mDirtyBits.set(DIRTY_BIT_PACK_STATE);
+}
+
+void State::setPackSkipRows(GLint skipRows)
+{
+ mPack.skipRows = skipRows;
+ mDirtyBits.set(DIRTY_BIT_PACK_STATE);
+}
+
+void State::setPackSkipPixels(GLint skipPixels)
+{
+ mPack.skipPixels = skipPixels;
+ mDirtyBits.set(DIRTY_BIT_PACK_STATE);
+}
+
+void State::setUnpackAlignment(GLint alignment)
+{
+ mUnpack.alignment = alignment;
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
+}
+
+void State::setUnpackRowLength(GLint rowLength)
+{
+ mUnpack.rowLength = rowLength;
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
+}
+
+void State::setUnpackImageHeight(GLint imageHeight)
+{
+ mUnpack.imageHeight = imageHeight;
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
+}
+
+void State::setUnpackSkipImages(GLint skipImages)
+{
+ mUnpack.skipImages = skipImages;
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
+}
+
+void State::setUnpackSkipRows(GLint skipRows)
+{
+ mUnpack.skipRows = skipRows;
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
+}
+
+void State::setUnpackSkipPixels(GLint skipPixels)
+{
+ mUnpack.skipPixels = skipPixels;
+ mDirtyBits.set(DIRTY_BIT_UNPACK_STATE);
+}
+
+void State::setCoverageModulation(GLenum components)
+{
+ if (mCoverageModulation != components)
+ {
+ mCoverageModulation = components;
+ mDirtyBits.set(DIRTY_BIT_COVERAGE_MODULATION);
+ }
+}
+
+void State::setFramebufferSRGB(bool sRGB)
+{
+ if (mFramebufferSRGB != sRGB)
+ {
+ mFramebufferSRGB = sRGB;
+ mDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE);
+ setDrawFramebufferDirty();
+ }
+}
+
+void State::setMaxShaderCompilerThreads(GLuint count)
+{
+ mMaxShaderCompilerThreads = count;
+}
+
+void State::setPatchVertices(GLuint value)
+{
+ if (mPatchVertices != value)
+ {
+ mPatchVertices = value;
+ mDirtyBits.set(DIRTY_BIT_PATCH_VERTICES);
+ }
+}
+
+void State::setPixelLocalStorageActive(bool active)
+{
+ mPixelLocalStorageActive = active;
+}
+
+void State::setShadingRate(GLenum rate)
+{
+ mShadingRate = FromGLenum<ShadingRate>(rate);
+ mDirtyBits.set(DIRTY_BIT_EXTENDED);
+ mExtendedDirtyBits.set(EXTENDED_DIRTY_BIT_SHADING_RATE);
+}
+
+void State::getBooleanv(GLenum pname, GLboolean *params) const
+{
+ switch (pname)
+ {
+ case GL_SAMPLE_COVERAGE_INVERT:
+ *params = mSampleCoverageInvert;
+ break;
+ case GL_DEPTH_WRITEMASK:
+ *params = mDepthStencil.depthMask;
+ break;
+ case GL_COLOR_WRITEMASK:
+ {
+ // non-indexed get returns the state of draw buffer zero
+ bool r, g, b, a;
+ mBlendStateExt.getColorMaskIndexed(0, &r, &g, &b, &a);
+ params[0] = r;
+ params[1] = g;
+ params[2] = b;
+ params[3] = a;
+ break;
+ }
+ case GL_CULL_FACE:
+ *params = mRasterizer.cullFace;
+ break;
+ case GL_POLYGON_OFFSET_FILL:
+ *params = mRasterizer.polygonOffsetFill;
+ break;
+ case GL_SAMPLE_ALPHA_TO_COVERAGE:
+ *params = mSampleAlphaToCoverage;
+ break;
+ case GL_SAMPLE_COVERAGE:
+ *params = mSampleCoverage;
+ break;
+ case GL_SAMPLE_MASK:
+ *params = mSampleMask;
+ break;
+ case GL_SCISSOR_TEST:
+ *params = mScissorTest;
+ break;
+ case GL_STENCIL_TEST:
+ *params = mDepthStencil.stencilTest;
+ break;
+ case GL_DEPTH_TEST:
+ *params = mDepthStencil.depthTest;
+ break;
+ case GL_BLEND:
+ // non-indexed get returns the state of draw buffer zero
+ *params = mBlendStateExt.getEnabledMask().test(0);
+ break;
+ case GL_DITHER:
+ *params = mRasterizer.dither;
+ break;
+ case GL_COLOR_LOGIC_OP:
+ ASSERT(mClientVersion.major > 1);
+ *params = mLogicOpEnabled;
+ break;
+ case GL_TRANSFORM_FEEDBACK_ACTIVE:
+ *params = getCurrentTransformFeedback()->isActive() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_TRANSFORM_FEEDBACK_PAUSED:
+ *params = getCurrentTransformFeedback()->isPaused() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_PRIMITIVE_RESTART_FIXED_INDEX:
+ *params = mPrimitiveRestart;
+ break;
+ case GL_RASTERIZER_DISCARD:
+ *params = isRasterizerDiscardEnabled() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_DEBUG_OUTPUT_SYNCHRONOUS:
+ *params = mDebug.isOutputSynchronous() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_DEBUG_OUTPUT:
+ *params = mDebug.isOutputEnabled() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_MULTISAMPLE_EXT:
+ *params = mMultiSampling;
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ *params = mSampleAlphaToOne;
+ break;
+ case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+ *params = isBindGeneratesResourceEnabled() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_CLIENT_ARRAYS_ANGLE:
+ *params = areClientArraysEnabled() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ *params = getFramebufferSRGB() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ *params = mRobustResourceInit ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_PROGRAM_CACHE_ENABLED_ANGLE:
+ *params = mProgramBinaryCacheEnabled ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ *params = mTextureRectangleEnabled ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ *params = IsLightModelTwoSided(&mGLES1State);
+ break;
+ case GL_SAMPLE_SHADING:
+ *params = mIsSampleShadingEnabled;
+ break;
+ case GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED:
+ *params = isPrimitiveRestartEnabled() && getExtensions().tessellationShaderEXT;
+ break;
+ // 2.2.2 Data Conversions For State Query Commands, in GLES 3.2 spec.
+ // If a command returning boolean data is called, such as GetBooleanv, a floating-point or
+ // integer value converts to FALSE if and only if it is zero. Otherwise it converts to TRUE.
+ // GL_EXT_clip_control
+ case GL_CLIP_ORIGIN_EXT:
+ *params = GL_TRUE;
+ break;
+ case GL_CLIP_DEPTH_MODE_EXT:
+ *params = GL_TRUE;
+ break;
+ case GL_ROBUST_FRAGMENT_SHADER_OUTPUT_ANGLE:
+ *params = mExtensions.robustFragmentShaderOutputANGLE ? GL_TRUE : GL_FALSE;
+ break;
+ // GL_ANGLE_shader_pixel_local_storage
+ case GL_PIXEL_LOCAL_STORAGE_ACTIVE_ANGLE:
+ *params = mPixelLocalStorageActive ? GL_TRUE : GL_FALSE;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void State::getFloatv(GLenum pname, GLfloat *params) const
+{
+ // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
+ // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
+ // GetIntegerv as its native query function. As it would require conversion in any
+ // case, this should make no difference to the calling application.
+ switch (pname)
+ {
+ case GL_LINE_WIDTH:
+ *params = mLineWidth;
+ break;
+ case GL_SAMPLE_COVERAGE_VALUE:
+ *params = mSampleCoverageValue;
+ break;
+ case GL_DEPTH_CLEAR_VALUE:
+ *params = mDepthClearValue;
+ break;
+ case GL_POLYGON_OFFSET_FACTOR:
+ *params = mRasterizer.polygonOffsetFactor;
+ break;
+ case GL_POLYGON_OFFSET_UNITS:
+ *params = mRasterizer.polygonOffsetUnits;
+ break;
+ case GL_DEPTH_RANGE:
+ params[0] = mNearZ;
+ params[1] = mFarZ;
+ break;
+ case GL_COLOR_CLEAR_VALUE:
+ params[0] = mColorClearValue.red;
+ params[1] = mColorClearValue.green;
+ params[2] = mColorClearValue.blue;
+ params[3] = mColorClearValue.alpha;
+ break;
+ case GL_BLEND_COLOR:
+ params[0] = mBlendColor.red;
+ params[1] = mBlendColor.green;
+ params[2] = mBlendColor.blue;
+ params[3] = mBlendColor.alpha;
+ break;
+ case GL_MULTISAMPLE_EXT:
+ *params = static_cast<GLfloat>(mMultiSampling);
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ *params = static_cast<GLfloat>(mSampleAlphaToOne);
+ break;
+ case GL_COVERAGE_MODULATION_CHROMIUM:
+ params[0] = static_cast<GLfloat>(mCoverageModulation);
+ break;
+ case GL_ALPHA_TEST_REF:
+ *params = mGLES1State.mAlphaTestRef;
+ break;
+ case GL_CURRENT_COLOR:
+ {
+ const auto &color = mGLES1State.mCurrentColor;
+ params[0] = color.red;
+ params[1] = color.green;
+ params[2] = color.blue;
+ params[3] = color.alpha;
+ break;
+ }
+ case GL_CURRENT_NORMAL:
+ {
+ const auto &normal = mGLES1State.mCurrentNormal;
+ params[0] = normal[0];
+ params[1] = normal[1];
+ params[2] = normal[2];
+ break;
+ }
+ case GL_CURRENT_TEXTURE_COORDS:
+ {
+ const auto &texcoord = mGLES1State.mCurrentTextureCoords[mActiveSampler];
+ params[0] = texcoord.s;
+ params[1] = texcoord.t;
+ params[2] = texcoord.r;
+ params[3] = texcoord.q;
+ break;
+ }
+ case GL_MODELVIEW_MATRIX:
+ memcpy(params, mGLES1State.mModelviewMatrices.back().constData(), 16 * sizeof(GLfloat));
+ break;
+ case GL_PROJECTION_MATRIX:
+ memcpy(params, mGLES1State.mProjectionMatrices.back().constData(),
+ 16 * sizeof(GLfloat));
+ break;
+ case GL_TEXTURE_MATRIX:
+ memcpy(params, mGLES1State.mTextureMatrices[mActiveSampler].back().constData(),
+ 16 * sizeof(GLfloat));
+ break;
+ case GL_LIGHT_MODEL_AMBIENT:
+ GetLightModelParameters(&mGLES1State, pname, params);
+ break;
+ case GL_FOG_MODE:
+ case GL_FOG_DENSITY:
+ case GL_FOG_START:
+ case GL_FOG_END:
+ case GL_FOG_COLOR:
+ GetFogParameters(&mGLES1State, pname, params);
+ break;
+ case GL_POINT_SIZE:
+ GetPointSize(&mGLES1State, params);
+ break;
+ case GL_POINT_SIZE_MIN:
+ case GL_POINT_SIZE_MAX:
+ case GL_POINT_FADE_THRESHOLD_SIZE:
+ case GL_POINT_DISTANCE_ATTENUATION:
+ GetPointParameter(&mGLES1State, FromGLenum<PointParameter>(pname), params);
+ break;
+ case GL_MIN_SAMPLE_SHADING_VALUE:
+ *params = mMinSampleShading;
+ break;
+ // 2.2.2 Data Conversions For State Query Commands, in GLES 3.2 spec.
+ // If a command returning floating-point data is called, such as GetFloatv, ... An integer
+ // value is coerced to floating-point.
+ case GL_CLIP_ORIGIN_EXT:
+ *params = static_cast<float>(mClipControlOrigin);
+ break;
+ case GL_CLIP_DEPTH_MODE_EXT:
+ *params = static_cast<float>(mClipControlDepth);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+angle::Result State::getIntegerv(const Context *context, GLenum pname, GLint *params) const
+{
+ if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
+ {
+ size_t drawBuffer = (pname - GL_DRAW_BUFFER0_EXT);
+ ASSERT(drawBuffer < static_cast<size_t>(mCaps.maxDrawBuffers));
+ Framebuffer *framebuffer = mDrawFramebuffer;
+ // The default framebuffer may have fewer draw buffer states than a user-created one. The
+ // user is always allowed to query up to GL_MAX_DRAWBUFFERS so just return GL_NONE here if
+ // the draw buffer is out of range for this framebuffer.
+ *params = drawBuffer < framebuffer->getDrawbufferStateCount()
+ ? framebuffer->getDrawBufferState(drawBuffer)
+ : GL_NONE;
+ return angle::Result::Continue;
+ }
+
+ // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
+ // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
+ // GetIntegerv as its native query function. As it would require conversion in any
+ // case, this should make no difference to the calling application. You may find it in
+ // State::getFloatv.
+ switch (pname)
+ {
+ case GL_ARRAY_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::Array].id().value;
+ break;
+ case GL_DRAW_INDIRECT_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::DrawIndirect].id().value;
+ break;
+ case GL_ELEMENT_ARRAY_BUFFER_BINDING:
+ {
+ Buffer *elementArrayBuffer = getVertexArray()->getElementArrayBuffer();
+ *params = elementArrayBuffer ? elementArrayBuffer->id().value : 0;
+ break;
+ }
+ case GL_DRAW_FRAMEBUFFER_BINDING:
+ static_assert(GL_DRAW_FRAMEBUFFER_BINDING == GL_DRAW_FRAMEBUFFER_BINDING_ANGLE,
+ "Enum mismatch");
+ *params = mDrawFramebuffer->id().value;
+ break;
+ case GL_READ_FRAMEBUFFER_BINDING:
+ static_assert(GL_READ_FRAMEBUFFER_BINDING == GL_READ_FRAMEBUFFER_BINDING_ANGLE,
+ "Enum mismatch");
+ *params = mReadFramebuffer->id().value;
+ break;
+ case GL_RENDERBUFFER_BINDING:
+ *params = mRenderbuffer.id().value;
+ break;
+ case GL_VERTEX_ARRAY_BINDING:
+ *params = mVertexArray->id().value;
+ break;
+ case GL_CURRENT_PROGRAM:
+ *params = mProgram ? mProgram->id().value : 0;
+ break;
+ case GL_PACK_ALIGNMENT:
+ *params = mPack.alignment;
+ break;
+ case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+ *params = mPack.reverseRowOrder;
+ break;
+ case GL_PACK_ROW_LENGTH:
+ *params = mPack.rowLength;
+ break;
+ case GL_PACK_SKIP_ROWS:
+ *params = mPack.skipRows;
+ break;
+ case GL_PACK_SKIP_PIXELS:
+ *params = mPack.skipPixels;
+ break;
+ case GL_UNPACK_ALIGNMENT:
+ *params = mUnpack.alignment;
+ break;
+ case GL_UNPACK_ROW_LENGTH:
+ *params = mUnpack.rowLength;
+ break;
+ case GL_UNPACK_IMAGE_HEIGHT:
+ *params = mUnpack.imageHeight;
+ break;
+ case GL_UNPACK_SKIP_IMAGES:
+ *params = mUnpack.skipImages;
+ break;
+ case GL_UNPACK_SKIP_ROWS:
+ *params = mUnpack.skipRows;
+ break;
+ case GL_UNPACK_SKIP_PIXELS:
+ *params = mUnpack.skipPixels;
+ break;
+ case GL_GENERATE_MIPMAP_HINT:
+ *params = mGenerateMipmapHint;
+ break;
+ case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
+ *params = mTextureFilteringHint;
+ break;
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
+ *params = mFragmentShaderDerivativeHint;
+ break;
+ case GL_ACTIVE_TEXTURE:
+ *params = (static_cast<GLint>(mActiveSampler) + GL_TEXTURE0);
+ break;
+ case GL_STENCIL_FUNC:
+ *params = mDepthStencil.stencilFunc;
+ break;
+ case GL_STENCIL_REF:
+ *params = mStencilRef;
+ break;
+ case GL_STENCIL_VALUE_MASK:
+ *params = CastMaskValue(mDepthStencil.stencilMask);
+ break;
+ case GL_STENCIL_BACK_FUNC:
+ *params = mDepthStencil.stencilBackFunc;
+ break;
+ case GL_STENCIL_BACK_REF:
+ *params = mStencilBackRef;
+ break;
+ case GL_STENCIL_BACK_VALUE_MASK:
+ *params = CastMaskValue(mDepthStencil.stencilBackMask);
+ break;
+ case GL_STENCIL_FAIL:
+ *params = mDepthStencil.stencilFail;
+ break;
+ case GL_STENCIL_PASS_DEPTH_FAIL:
+ *params = mDepthStencil.stencilPassDepthFail;
+ break;
+ case GL_STENCIL_PASS_DEPTH_PASS:
+ *params = mDepthStencil.stencilPassDepthPass;
+ break;
+ case GL_STENCIL_BACK_FAIL:
+ *params = mDepthStencil.stencilBackFail;
+ break;
+ case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
+ *params = mDepthStencil.stencilBackPassDepthFail;
+ break;
+ case GL_STENCIL_BACK_PASS_DEPTH_PASS:
+ *params = mDepthStencil.stencilBackPassDepthPass;
+ break;
+ case GL_DEPTH_FUNC:
+ *params = mDepthStencil.depthFunc;
+ break;
+ case GL_BLEND_SRC_RGB:
+ // non-indexed get returns the state of draw buffer zero
+ *params = mBlendStateExt.getSrcColorIndexed(0);
+ break;
+ case GL_BLEND_SRC_ALPHA:
+ *params = mBlendStateExt.getSrcAlphaIndexed(0);
+ break;
+ case GL_BLEND_DST_RGB:
+ *params = mBlendStateExt.getDstColorIndexed(0);
+ break;
+ case GL_BLEND_DST_ALPHA:
+ *params = mBlendStateExt.getDstAlphaIndexed(0);
+ break;
+ case GL_BLEND_EQUATION_RGB:
+ *params = mBlendStateExt.getEquationColorIndexed(0);
+ break;
+ case GL_BLEND_EQUATION_ALPHA:
+ *params = mBlendStateExt.getEquationAlphaIndexed(0);
+ break;
+ case GL_STENCIL_WRITEMASK:
+ *params = CastMaskValue(mDepthStencil.stencilWritemask);
+ break;
+ case GL_STENCIL_BACK_WRITEMASK:
+ *params = CastMaskValue(mDepthStencil.stencilBackWritemask);
+ break;
+ case GL_STENCIL_CLEAR_VALUE:
+ *params = mStencilClearValue;
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+ *params = mReadFramebuffer->getImplementationColorReadType(context);
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+ *params = mReadFramebuffer->getImplementationColorReadFormat(context);
+ break;
+ case GL_SAMPLE_BUFFERS:
+ case GL_SAMPLES:
+ {
+ Framebuffer *framebuffer = mDrawFramebuffer;
+ if (framebuffer->isComplete(context))
+ {
+ GLint samples = framebuffer->getSamples(context);
+ switch (pname)
+ {
+ case GL_SAMPLE_BUFFERS:
+ if (samples != 0)
+ {
+ *params = 1;
+ }
+ else
+ {
+ *params = 0;
+ }
+ break;
+ case GL_SAMPLES:
+ *params = samples;
+ break;
+ }
+ }
+ else
+ {
+ *params = 0;
+ }
+ }
+ break;
+ case GL_VIEWPORT:
+ params[0] = mViewport.x;
+ params[1] = mViewport.y;
+ params[2] = mViewport.width;
+ params[3] = mViewport.height;
+ break;
+ case GL_SCISSOR_BOX:
+ params[0] = mScissor.x;
+ params[1] = mScissor.y;
+ params[2] = mScissor.width;
+ params[3] = mScissor.height;
+ break;
+ case GL_CULL_FACE_MODE:
+ *params = ToGLenum(mRasterizer.cullMode);
+ break;
+ case GL_FRONT_FACE:
+ *params = mRasterizer.frontFace;
+ break;
+ case GL_RED_BITS:
+ case GL_GREEN_BITS:
+ case GL_BLUE_BITS:
+ case GL_ALPHA_BITS:
+ {
+ Framebuffer *framebuffer = getDrawFramebuffer();
+ const FramebufferAttachment *colorbuffer = framebuffer->getFirstColorAttachment();
+
+ if (colorbuffer)
+ {
+ switch (pname)
+ {
+ case GL_RED_BITS:
+ *params = colorbuffer->getRedSize();
+ break;
+ case GL_GREEN_BITS:
+ *params = colorbuffer->getGreenSize();
+ break;
+ case GL_BLUE_BITS:
+ *params = colorbuffer->getBlueSize();
+ break;
+ case GL_ALPHA_BITS:
+ *params = colorbuffer->getAlphaSize();
+ break;
+ }
+ }
+ else
+ {
+ *params = 0;
+ }
+ }
+ break;
+ case GL_DEPTH_BITS:
+ {
+ const Framebuffer *framebuffer = getDrawFramebuffer();
+ const FramebufferAttachment *depthbuffer = framebuffer->getDepthAttachment();
+
+ if (depthbuffer)
+ {
+ *params = depthbuffer->getDepthSize();
+ }
+ else
+ {
+ *params = 0;
+ }
+ }
+ break;
+ case GL_STENCIL_BITS:
+ {
+ const Framebuffer *framebuffer = getDrawFramebuffer();
+ const FramebufferAttachment *stencilbuffer = framebuffer->getStencilAttachment();
+
+ if (stencilbuffer)
+ {
+ *params = stencilbuffer->getStencilSize();
+ }
+ else
+ {
+ *params = 0;
+ }
+ }
+ break;
+ case GL_TEXTURE_BINDING_2D:
+ ASSERT(mActiveSampler < mCaps.maxCombinedTextureImageUnits);
+ *params =
+ getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), TextureType::_2D)
+ .value;
+ break;
+ case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
+ ASSERT(mActiveSampler < mCaps.maxCombinedTextureImageUnits);
+ *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler),
+ TextureType::Rectangle)
+ .value;
+ break;
+ case GL_TEXTURE_BINDING_CUBE_MAP:
+ ASSERT(mActiveSampler < mCaps.maxCombinedTextureImageUnits);
+ *params =
+ getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), TextureType::CubeMap)
+ .value;
+ break;
+ case GL_TEXTURE_BINDING_3D:
+ ASSERT(mActiveSampler < mCaps.maxCombinedTextureImageUnits);
+ *params =
+ getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), TextureType::_3D)
+ .value;
+ break;
+ case GL_TEXTURE_BINDING_2D_ARRAY:
+ ASSERT(mActiveSampler < mCaps.maxCombinedTextureImageUnits);
+ *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler),
+ TextureType::_2DArray)
+ .value;
+ break;
+ case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
+ ASSERT(mActiveSampler < mCaps.maxCombinedTextureImageUnits);
+ *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler),
+ TextureType::_2DMultisample)
+ .value;
+ break;
+ case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
+ ASSERT(mActiveSampler < mCaps.maxCombinedTextureImageUnits);
+ *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler),
+ TextureType::_2DMultisampleArray)
+ .value;
+ break;
+ case GL_TEXTURE_BINDING_CUBE_MAP_ARRAY:
+ ASSERT(mActiveSampler < mCaps.maxCombinedTextureImageUnits);
+ *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler),
+ TextureType::CubeMapArray)
+ .value;
+ break;
+ case GL_TEXTURE_BINDING_EXTERNAL_OES:
+ ASSERT(mActiveSampler < mCaps.maxCombinedTextureImageUnits);
+ *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler),
+ TextureType::External)
+ .value;
+ break;
+
+ // GL_OES_texture_buffer
+ case GL_TEXTURE_BINDING_BUFFER:
+ ASSERT(mActiveSampler < mCaps.maxCombinedTextureImageUnits);
+ *params =
+ getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), TextureType::Buffer)
+ .value;
+ break;
+ case GL_TEXTURE_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::Texture].id().value;
+ break;
+
+ case GL_UNIFORM_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::Uniform].id().value;
+ break;
+ case GL_TRANSFORM_FEEDBACK_BINDING:
+ *params = mTransformFeedback.id().value;
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::TransformFeedback].id().value;
+ break;
+ case GL_COPY_READ_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::CopyRead].id().value;
+ break;
+ case GL_COPY_WRITE_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::CopyWrite].id().value;
+ break;
+ case GL_PIXEL_PACK_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::PixelPack].id().value;
+ break;
+ case GL_PIXEL_UNPACK_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::PixelUnpack].id().value;
+ break;
+
+ case GL_READ_BUFFER:
+ *params = mReadFramebuffer->getReadBufferState();
+ break;
+ case GL_SAMPLER_BINDING:
+ ASSERT(mActiveSampler < mCaps.maxCombinedTextureImageUnits);
+ *params = getSamplerId(static_cast<GLuint>(mActiveSampler)).value;
+ break;
+ case GL_DEBUG_LOGGED_MESSAGES:
+ *params = static_cast<GLint>(mDebug.getMessageCount());
+ break;
+ case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
+ *params = static_cast<GLint>(mDebug.getNextMessageLength());
+ break;
+ case GL_DEBUG_GROUP_STACK_DEPTH:
+ *params = static_cast<GLint>(mDebug.getGroupStackDepth());
+ break;
+ case GL_MULTISAMPLE_EXT:
+ *params = static_cast<GLint>(mMultiSampling);
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ *params = static_cast<GLint>(mSampleAlphaToOne);
+ break;
+ case GL_COVERAGE_MODULATION_CHROMIUM:
+ *params = static_cast<GLint>(mCoverageModulation);
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::AtomicCounter].id().value;
+ break;
+ case GL_SHADER_STORAGE_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::ShaderStorage].id().value;
+ break;
+ case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
+ *params = mBoundBuffers[BufferBinding::DispatchIndirect].id().value;
+ break;
+ case GL_ALPHA_TEST_FUNC:
+ *params = ToGLenum(mGLES1State.mAlphaTestFunc);
+ break;
+ case GL_CLIENT_ACTIVE_TEXTURE:
+ *params = mGLES1State.mClientActiveTexture + GL_TEXTURE0;
+ break;
+ case GL_MATRIX_MODE:
+ *params = ToGLenum(mGLES1State.mMatrixMode);
+ break;
+ case GL_SHADE_MODEL:
+ *params = ToGLenum(mGLES1State.mShadeModel);
+ break;
+ case GL_MODELVIEW_STACK_DEPTH:
+ case GL_PROJECTION_STACK_DEPTH:
+ case GL_TEXTURE_STACK_DEPTH:
+ *params = mGLES1State.getCurrentMatrixStackDepth(pname);
+ break;
+ case GL_LOGIC_OP_MODE:
+ *params = ToGLenum(mGLES1State.mLogicOp);
+ break;
+ case GL_BLEND_SRC:
+ // non-indexed get returns the state of draw buffer zero
+ *params = mBlendStateExt.getSrcColorIndexed(0);
+ break;
+ case GL_BLEND_DST:
+ *params = mBlendStateExt.getDstColorIndexed(0);
+ break;
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ case GL_POINT_SMOOTH_HINT:
+ case GL_LINE_SMOOTH_HINT:
+ case GL_FOG_HINT:
+ *params = mGLES1State.getHint(pname);
+ break;
+
+ // GL_ANGLE_provoking_vertex
+ case GL_PROVOKING_VERTEX:
+ *params = ToGLenum(mProvokingVertex);
+ break;
+
+ case GL_PROGRAM_PIPELINE_BINDING:
+ {
+ ProgramPipeline *pipeline = getProgramPipeline();
+ if (pipeline)
+ {
+ *params = pipeline->id().value;
+ }
+ else
+ {
+ *params = 0;
+ }
+ break;
+ }
+ case GL_PATCH_VERTICES:
+ *params = mPatchVertices;
+ break;
+
+ // GL_EXT_clip_control
+ case GL_CLIP_ORIGIN_EXT:
+ *params = mClipControlOrigin;
+ break;
+ case GL_CLIP_DEPTH_MODE_EXT:
+ *params = mClipControlDepth;
+ break;
+
+ // GL_QCOM_shading_rate
+ case GL_SHADING_RATE_QCOM:
+ *params = ToGLenum(mShadingRate);
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return angle::Result::Continue;
+}
+
+void State::getPointerv(const Context *context, GLenum pname, void **params) const
+{
+ switch (pname)
+ {
+ case GL_DEBUG_CALLBACK_FUNCTION:
+ *params = reinterpret_cast<void *>(mDebug.getCallback());
+ break;
+ case GL_DEBUG_CALLBACK_USER_PARAM:
+ *params = const_cast<void *>(mDebug.getUserParam());
+ break;
+ case GL_VERTEX_ARRAY_POINTER:
+ case GL_NORMAL_ARRAY_POINTER:
+ case GL_COLOR_ARRAY_POINTER:
+ case GL_TEXTURE_COORD_ARRAY_POINTER:
+ case GL_POINT_SIZE_ARRAY_POINTER_OES:
+ QueryVertexAttribPointerv(getVertexArray()->getVertexAttribute(
+ context->vertexArrayIndex(ParamToVertexArrayType(pname))),
+ GL_VERTEX_ATTRIB_ARRAY_POINTER, params);
+ return;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void State::getIntegeri_v(const Context *context, GLenum target, GLuint index, GLint *data) const
+{
+ switch (target)
+ {
+ case GL_BLEND_SRC_RGB:
+ ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
+ *data = mBlendStateExt.getSrcColorIndexed(index);
+ break;
+ case GL_BLEND_SRC_ALPHA:
+ ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
+ *data = mBlendStateExt.getSrcAlphaIndexed(index);
+ break;
+ case GL_BLEND_DST_RGB:
+ ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
+ *data = mBlendStateExt.getDstColorIndexed(index);
+ break;
+ case GL_BLEND_DST_ALPHA:
+ ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
+ *data = mBlendStateExt.getDstAlphaIndexed(index);
+ break;
+ case GL_BLEND_EQUATION_RGB:
+ ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
+ *data = mBlendStateExt.getEquationColorIndexed(index);
+ break;
+ case GL_BLEND_EQUATION_ALPHA:
+ ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
+ *data = mBlendStateExt.getEquationAlphaIndexed(index);
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
+ *data = mTransformFeedback->getIndexedBuffer(index).id().value;
+ break;
+ case GL_UNIFORM_BUFFER_BINDING:
+ ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+ *data = mUniformBuffers[index].id().value;
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+ *data = mAtomicCounterBuffers[index].id().value;
+ break;
+ case GL_SHADER_STORAGE_BUFFER_BINDING:
+ ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+ *data = mShaderStorageBuffers[index].id().value;
+ break;
+ case GL_VERTEX_BINDING_BUFFER:
+ ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+ *data = mVertexArray->getVertexBinding(index).getBuffer().id().value;
+ break;
+ case GL_VERTEX_BINDING_DIVISOR:
+ ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+ *data = mVertexArray->getVertexBinding(index).getDivisor();
+ break;
+ case GL_VERTEX_BINDING_OFFSET:
+ ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+ *data = static_cast<GLuint>(mVertexArray->getVertexBinding(index).getOffset());
+ break;
+ case GL_VERTEX_BINDING_STRIDE:
+ ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings());
+ *data = mVertexArray->getVertexBinding(index).getStride();
+ break;
+ case GL_SAMPLE_MASK_VALUE:
+ ASSERT(static_cast<size_t>(index) < mSampleMaskValues.size());
+ *data = mSampleMaskValues[index];
+ break;
+ case GL_IMAGE_BINDING_NAME:
+ ASSERT(static_cast<size_t>(index) < mImageUnits.size());
+ *data = mImageUnits[index].texture.id().value;
+ break;
+ case GL_IMAGE_BINDING_LEVEL:
+ ASSERT(static_cast<size_t>(index) < mImageUnits.size());
+ *data = mImageUnits[index].level;
+ break;
+ case GL_IMAGE_BINDING_LAYER:
+ ASSERT(static_cast<size_t>(index) < mImageUnits.size());
+ *data = mImageUnits[index].layer;
+ break;
+ case GL_IMAGE_BINDING_ACCESS:
+ ASSERT(static_cast<size_t>(index) < mImageUnits.size());
+ *data = mImageUnits[index].access;
+ break;
+ case GL_IMAGE_BINDING_FORMAT:
+ ASSERT(static_cast<size_t>(index) < mImageUnits.size());
+ *data = mImageUnits[index].format;
+ break;
+ // GL_ANGLE_shader_pixel_local_storage.
+ case GL_PIXEL_LOCAL_FORMAT_ANGLE:
+ case GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE:
+ case GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE:
+ case GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE:
+ {
+ ASSERT(mDrawFramebuffer);
+ *data = mDrawFramebuffer->getPixelLocalStorage(context).getPlane(index).getIntegeri(
+ context, target, index);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void State::getInteger64i_v(GLenum target, GLuint index, GLint64 *data) const
+{
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
+ *data = mTransformFeedback->getIndexedBuffer(index).getOffset();
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount());
+ *data = mTransformFeedback->getIndexedBuffer(index).getSize();
+ break;
+ case GL_UNIFORM_BUFFER_START:
+ ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+ *data = mUniformBuffers[index].getOffset();
+ break;
+ case GL_UNIFORM_BUFFER_SIZE:
+ ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+ *data = mUniformBuffers[index].getSize();
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER_START:
+ ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+ *data = mAtomicCounterBuffers[index].getOffset();
+ break;
+ case GL_ATOMIC_COUNTER_BUFFER_SIZE:
+ ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size());
+ *data = mAtomicCounterBuffers[index].getSize();
+ break;
+ case GL_SHADER_STORAGE_BUFFER_START:
+ ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+ *data = mShaderStorageBuffers[index].getOffset();
+ break;
+ case GL_SHADER_STORAGE_BUFFER_SIZE:
+ ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size());
+ *data = mShaderStorageBuffers[index].getSize();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void State::getBooleani_v(GLenum target, GLuint index, GLboolean *data) const
+{
+ switch (target)
+ {
+ case GL_COLOR_WRITEMASK:
+ {
+ ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
+ bool r, g, b, a;
+ mBlendStateExt.getColorMaskIndexed(index, &r, &g, &b, &a);
+ data[0] = r;
+ data[1] = g;
+ data[2] = b;
+ data[3] = a;
+ break;
+ }
+ case GL_IMAGE_BINDING_LAYERED:
+ ASSERT(static_cast<size_t>(index) < mImageUnits.size());
+ *data = mImageUnits[index].layered;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+// TODO(http://anglebug.com/3889): Remove this helper function after blink and chromium part
+// refactor done.
+Texture *State::getTextureForActiveSampler(TextureType type, size_t index)
+{
+ if (type != TextureType::VideoImage)
+ {
+ return mSamplerTextures[type][index].get();
+ }
+
+ ASSERT(type == TextureType::VideoImage);
+
+ Texture *candidateTexture = mSamplerTextures[type][index].get();
+ if (candidateTexture->getWidth(TextureTarget::VideoImage, 0) == 0 ||
+ candidateTexture->getHeight(TextureTarget::VideoImage, 0) == 0 ||
+ candidateTexture->getDepth(TextureTarget::VideoImage, 0) == 0)
+ {
+ return mSamplerTextures[TextureType::_2D][index].get();
+ }
+
+ return mSamplerTextures[type][index].get();
+}
+
+angle::Result State::syncActiveTextures(const Context *context, Command command)
+{
+ if (mDirtyActiveTextures.none())
+ {
+ return angle::Result::Continue;
+ }
+
+ for (size_t textureUnit : mDirtyActiveTextures)
+ {
+ if (mExecutable)
+ {
+ TextureType type = mExecutable->getActiveSamplerTypes()[textureUnit];
+ Texture *activeTexture = (type != TextureType::InvalidEnum)
+ ? getTextureForActiveSampler(type, textureUnit)
+ : nullptr;
+ const Sampler *sampler = mSamplers[textureUnit].get();
+
+ updateActiveTextureStateOnSync(context, textureUnit, sampler, activeTexture);
+ }
+ }
+
+ mDirtyActiveTextures.reset();
+ return angle::Result::Continue;
+}
+
+angle::Result State::syncTexturesInit(const Context *context, Command command)
+{
+ ASSERT(mRobustResourceInit);
+
+ if (!mProgram)
+ return angle::Result::Continue;
+
+ for (size_t textureUnitIndex : mExecutable->getActiveSamplersMask())
+ {
+ Texture *texture = mActiveTexturesCache[textureUnitIndex];
+ if (texture)
+ {
+ ANGLE_TRY(texture->ensureInitialized(context));
+ }
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result State::syncImagesInit(const Context *context, Command command)
+{
+ ASSERT(mRobustResourceInit);
+ ASSERT(mExecutable);
+ for (size_t imageUnitIndex : mExecutable->getActiveImagesMask())
+ {
+ Texture *texture = mImageUnits[imageUnitIndex].texture.get();
+ if (texture)
+ {
+ ANGLE_TRY(texture->ensureInitialized(context));
+ }
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result State::syncReadAttachments(const Context *context, Command command)
+{
+ ASSERT(mReadFramebuffer);
+ ASSERT(mRobustResourceInit);
+ return mReadFramebuffer->ensureReadAttachmentsInitialized(context);
+}
+
+angle::Result State::syncDrawAttachments(const Context *context, Command command)
+{
+ ASSERT(mDrawFramebuffer);
+ ASSERT(mRobustResourceInit);
+ return mDrawFramebuffer->ensureDrawAttachmentsInitialized(context);
+}
+
+angle::Result State::syncReadFramebuffer(const Context *context, Command command)
+{
+ ASSERT(mReadFramebuffer);
+ return mReadFramebuffer->syncState(context, GL_READ_FRAMEBUFFER, command);
+}
+
+angle::Result State::syncDrawFramebuffer(const Context *context, Command command)
+{
+ ASSERT(mDrawFramebuffer);
+ mDrawFramebuffer->setWriteControlMode(context->getState().getFramebufferSRGB()
+ ? SrgbWriteControlMode::Default
+ : SrgbWriteControlMode::Linear);
+ return mDrawFramebuffer->syncState(context, GL_DRAW_FRAMEBUFFER, command);
+}
+
+angle::Result State::syncTextures(const Context *context, Command command)
+{
+ if (mDirtyTextures.none())
+ return angle::Result::Continue;
+
+ for (size_t textureIndex : mDirtyTextures)
+ {
+ Texture *texture = mActiveTexturesCache[textureIndex];
+ if (texture && texture->hasAnyDirtyBit())
+ {
+ ANGLE_TRY(texture->syncState(context, Command::Other));
+ }
+ }
+
+ mDirtyTextures.reset();
+ return angle::Result::Continue;
+}
+
+angle::Result State::syncImages(const Context *context, Command command)
+{
+ if (mDirtyImages.none())
+ return angle::Result::Continue;
+
+ for (size_t imageUnitIndex : mDirtyImages)
+ {
+ Texture *texture = mImageUnits[imageUnitIndex].texture.get();
+ if (texture && texture->hasAnyDirtyBit())
+ {
+ ANGLE_TRY(texture->syncState(context, Command::Other));
+ }
+ }
+
+ mDirtyImages.reset();
+ return angle::Result::Continue;
+}
+
+angle::Result State::syncSamplers(const Context *context, Command command)
+{
+ if (mDirtySamplers.none())
+ return angle::Result::Continue;
+
+ for (size_t samplerIndex : mDirtySamplers)
+ {
+ BindingPointer<Sampler> &sampler = mSamplers[samplerIndex];
+ if (sampler.get() && sampler->isDirty())
+ {
+ ANGLE_TRY(sampler->syncState(context));
+ }
+ }
+
+ mDirtySamplers.reset();
+
+ return angle::Result::Continue;
+}
+
+angle::Result State::syncVertexArray(const Context *context, Command command)
+{
+ ASSERT(mVertexArray);
+ return mVertexArray->syncState(context);
+}
+
+angle::Result State::syncProgram(const Context *context, Command command)
+{
+ // There may not be a program if the calling application only uses program pipelines.
+ if (mProgram)
+ {
+ return mProgram->syncState(context);
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result State::syncProgramPipelineObject(const Context *context, Command command)
+{
+ // If a ProgramPipeline is bound, ensure it is linked.
+ if (mProgramPipeline.get())
+ {
+ mProgramPipeline->resolveLink(context);
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result State::syncDirtyObject(const Context *context, GLenum target)
+{
+ DirtyObjects localSet;
+
+ switch (target)
+ {
+ case GL_READ_FRAMEBUFFER:
+ localSet.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
+ break;
+ case GL_DRAW_FRAMEBUFFER:
+ localSet.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+ break;
+ case GL_FRAMEBUFFER:
+ localSet.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
+ localSet.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+ break;
+ case GL_VERTEX_ARRAY:
+ localSet.set(DIRTY_OBJECT_VERTEX_ARRAY);
+ break;
+ case GL_TEXTURE:
+ localSet.set(DIRTY_OBJECT_TEXTURES);
+ break;
+ case GL_SAMPLER:
+ localSet.set(DIRTY_OBJECT_SAMPLERS);
+ break;
+ case GL_PROGRAM:
+ localSet.set(DIRTY_OBJECT_PROGRAM);
+ break;
+ }
+
+ return syncDirtyObjects(context, localSet, Command::Other);
+}
+
+void State::setObjectDirty(GLenum target)
+{
+ switch (target)
+ {
+ case GL_READ_FRAMEBUFFER:
+ mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
+ break;
+ case GL_DRAW_FRAMEBUFFER:
+ setDrawFramebufferDirty();
+ break;
+ case GL_FRAMEBUFFER:
+ mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
+ setDrawFramebufferDirty();
+ break;
+ case GL_VERTEX_ARRAY:
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+ break;
+ case GL_PROGRAM:
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM);
+ break;
+ default:
+ break;
+ }
+}
+
+angle::Result State::onProgramExecutableChange(const Context *context, Program *program)
+{
+ // OpenGL Spec:
+ // "If LinkProgram or ProgramBinary successfully re-links a program object
+ // that was already in use as a result of a previous call to UseProgram, then the
+ // generated executable code will be installed as part of the current rendering state."
+ ASSERT(program->isLinked());
+
+ // If this Program is currently active, we need to update the State's pointer to the current
+ // ProgramExecutable if we just changed it.
+ if (mProgram == program)
+ {
+ mExecutable = &program->getExecutable();
+ }
+
+ mDirtyBits.set(DIRTY_BIT_PROGRAM_EXECUTABLE);
+
+ if (program->hasAnyDirtyBit())
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM);
+ }
+
+ // Set any bound textures.
+ const ProgramExecutable &executable = program->getExecutable();
+ const ActiveTextureTypeArray &textureTypes = executable.getActiveSamplerTypes();
+ for (size_t textureIndex : executable.getActiveSamplersMask())
+ {
+ TextureType type = textureTypes[textureIndex];
+
+ // This can happen if there is a conflicting texture type.
+ if (type == TextureType::InvalidEnum)
+ continue;
+
+ Texture *texture = getTextureForActiveSampler(type, textureIndex);
+ updateTextureBinding(context, textureIndex, texture);
+ }
+
+ for (size_t imageUnitIndex : executable.getActiveImagesMask())
+ {
+ Texture *image = mImageUnits[imageUnitIndex].texture.get();
+ if (!image)
+ continue;
+
+ if (image->hasAnyDirtyBit())
+ {
+ ANGLE_TRY(image->syncState(context, Command::Other));
+ }
+
+ if (mRobustResourceInit && image->initState() == InitState::MayNeedInit)
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_IMAGES_INIT);
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result State::onProgramPipelineExecutableChange(const Context *context)
+{
+ mDirtyBits.set(DIRTY_BIT_PROGRAM_EXECUTABLE);
+
+ if (!mProgramPipeline->isLinked())
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT);
+ }
+
+ // Set any bound textures.
+ const ProgramExecutable &executable = mProgramPipeline->getExecutable();
+ const ActiveTextureTypeArray &textureTypes = executable.getActiveSamplerTypes();
+
+ for (size_t textureIndex : executable.getActiveSamplersMask())
+ {
+ TextureType type = textureTypes[textureIndex];
+
+ // This can happen if there is a conflicting texture type.
+ if (type == TextureType::InvalidEnum)
+ continue;
+
+ Texture *texture = getTextureForActiveSampler(type, textureIndex);
+ updateTextureBinding(context, textureIndex, texture);
+ }
+
+ for (size_t imageUnitIndex : executable.getActiveImagesMask())
+ {
+ Texture *image = mImageUnits[imageUnitIndex].texture.get();
+ if (!image)
+ continue;
+
+ if (image->hasAnyDirtyBit())
+ {
+ ANGLE_TRY(image->syncState(context, Command::Other));
+ }
+
+ if (mRobustResourceInit && image->initState() == InitState::MayNeedInit)
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_IMAGES_INIT);
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+void State::setTextureDirty(size_t textureUnitIndex)
+{
+ mDirtyObjects.set(DIRTY_OBJECT_TEXTURES);
+ mDirtyTextures.set(textureUnitIndex);
+}
+
+void State::setSamplerDirty(size_t samplerIndex)
+{
+ mDirtyObjects.set(DIRTY_OBJECT_SAMPLERS);
+ mDirtySamplers.set(samplerIndex);
+}
+
+void State::setImageUnit(const Context *context,
+ size_t unit,
+ Texture *texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format)
+{
+ ASSERT(!mImageUnits.empty());
+
+ ImageUnit &imageUnit = mImageUnits[unit];
+
+ if (texture)
+ {
+ texture->onBindAsImageTexture();
+
+ // Using individual layers of a 3d image as 2d may require that the image be respecified in
+ // a compatible layout
+ if (!layered && texture->getType() == TextureType::_3D)
+ {
+ texture->onBind3DTextureAs2DImage();
+ }
+ }
+ imageUnit.texture.set(context, texture);
+ imageUnit.level = level;
+ imageUnit.layered = layered;
+ imageUnit.layer = layer;
+ imageUnit.access = access;
+ imageUnit.format = format;
+ mDirtyBits.set(DIRTY_BIT_IMAGE_BINDINGS);
+
+ onImageStateChange(context, unit);
+}
+
+// Handle a dirty texture event.
+void State::onActiveTextureChange(const Context *context, size_t textureUnit)
+{
+ if (mExecutable)
+ {
+ TextureType type = mExecutable->getActiveSamplerTypes()[textureUnit];
+ Texture *activeTexture = (type != TextureType::InvalidEnum)
+ ? getTextureForActiveSampler(type, textureUnit)
+ : nullptr;
+ updateTextureBinding(context, textureUnit, activeTexture);
+
+ mExecutable->onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
+ }
+}
+
+void State::onActiveTextureStateChange(const Context *context, size_t textureUnit)
+{
+ if (mExecutable)
+ {
+ TextureType type = mExecutable->getActiveSamplerTypes()[textureUnit];
+ Texture *activeTexture = (type != TextureType::InvalidEnum)
+ ? getTextureForActiveSampler(type, textureUnit)
+ : nullptr;
+ setActiveTextureDirty(textureUnit, activeTexture);
+ }
+}
+
+void State::onImageStateChange(const Context *context, size_t unit)
+{
+ if (mExecutable)
+ {
+ const ImageUnit &image = mImageUnits[unit];
+
+ // Have nothing to do here if no texture bound
+ if (!image.texture.get())
+ return;
+
+ if (image.texture->hasAnyDirtyBit())
+ {
+ mDirtyImages.set(unit);
+ mDirtyObjects.set(DIRTY_OBJECT_IMAGES);
+ }
+
+ if (mRobustResourceInit && image.texture->initState() == InitState::MayNeedInit)
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_IMAGES_INIT);
+ }
+
+ mExecutable->onStateChange(angle::SubjectMessage::ProgramTextureOrImageBindingChanged);
+ }
+}
+
+void State::onUniformBufferStateChange(size_t uniformBufferIndex)
+{
+ // This could be represented by a different dirty bit. Using the same one keeps it simple.
+ mDirtyBits.set(DIRTY_BIT_UNIFORM_BUFFER_BINDINGS);
+}
+
+void State::onAtomicCounterBufferStateChange(size_t atomicCounterBufferIndex)
+{
+ mDirtyBits.set(DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING);
+}
+
+void State::onShaderStorageBufferStateChange(size_t shaderStorageBufferIndex)
+{
+ mDirtyBits.set(DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING);
+}
+
+AttributesMask State::getAndResetDirtyCurrentValues() const
+{
+ AttributesMask retVal = mDirtyCurrentValues;
+ mDirtyCurrentValues.reset();
+ return retVal;
+}
+
+State::ExtendedDirtyBits State::getAndResetExtendedDirtyBits() const
+{
+ ExtendedDirtyBits retVal = mExtendedDirtyBits;
+ mExtendedDirtyBits.reset();
+ return retVal;
+}
+
+void State::initializeForCapture(const Context *context)
+{
+ mCaps = context->getCaps();
+ mExtensions = context->getExtensions();
+
+ // This little kludge gets around the frame capture "constness". It should be safe because
+ // nothing in the context is modified in a non-compatible way during capture.
+ Context *mutableContext = const_cast<Context *>(context);
+ initialize(mutableContext);
+}
+
+void State::setLogicOpEnabled(bool enabled)
+{
+ if (mLogicOpEnabled != enabled)
+ {
+ mLogicOpEnabled = enabled;
+ mDirtyBits.set(DIRTY_BIT_EXTENDED);
+ mExtendedDirtyBits.set(EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED);
+ }
+}
+
+void State::setLogicOp(LogicalOperation opcode)
+{
+ if (mLogicOp != opcode)
+ {
+ mLogicOp = opcode;
+ mDirtyBits.set(DIRTY_BIT_EXTENDED);
+ mExtendedDirtyBits.set(EXTENDED_DIRTY_BIT_LOGIC_OP);
+ }
+}
+
+constexpr State::DirtyObjectHandler State::kDirtyObjectHandlers[DIRTY_OBJECT_MAX];
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/State.h b/gfx/angle/checkout/src/libANGLE/State.h
new file mode 100644
index 0000000000..08098599e1
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/State.h
@@ -0,0 +1,1258 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// State.h: Defines the State class, encapsulating raw GL state
+
+#ifndef LIBANGLE_STATE_H_
+#define LIBANGLE_STATE_H_
+
+#include <bitset>
+#include <memory>
+
+#include "common/Color.h"
+#include "common/angleutils.h"
+#include "common/bitset_utils.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/GLES1State.h"
+#include "libANGLE/Overlay.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/ProgramExecutable.h"
+#include "libANGLE/ProgramPipeline.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Sampler.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/angletypes.h"
+
+namespace egl
+{
+class ShareGroup;
+} // namespace egl
+
+namespace gl
+{
+class BufferManager;
+struct Caps;
+class Context;
+class FramebufferManager;
+class MemoryObjectManager;
+class ProgramPipelineManager;
+class Query;
+class RenderbufferManager;
+class SamplerManager;
+class SemaphoreManager;
+class ShaderProgramManager;
+class SyncManager;
+class TextureManager;
+class VertexArray;
+
+static constexpr Version ES_1_0 = Version(1, 0);
+static constexpr Version ES_1_1 = Version(1, 1);
+static constexpr Version ES_2_0 = Version(2, 0);
+static constexpr Version ES_3_0 = Version(3, 0);
+static constexpr Version ES_3_1 = Version(3, 1);
+static constexpr Version ES_3_2 = Version(3, 2);
+
+template <typename T>
+using BufferBindingMap = angle::PackedEnumMap<BufferBinding, T>;
+using BoundBufferMap = BufferBindingMap<BindingPointer<Buffer>>;
+using TextureBindingVector = std::vector<BindingPointer<Texture>>;
+using TextureBindingMap = angle::PackedEnumMap<TextureType, TextureBindingVector>;
+using ActiveQueryMap = angle::PackedEnumMap<QueryType, BindingPointer<Query>>;
+
+class ActiveTexturesCache final : angle::NonCopyable
+{
+ public:
+ ActiveTexturesCache();
+ ~ActiveTexturesCache();
+
+ Texture *operator[](size_t textureIndex) const { return mTextures[textureIndex]; }
+
+ void clear();
+ void set(size_t textureIndex, Texture *texture);
+ void reset(size_t textureIndex);
+ bool empty() const;
+ size_t size() const { return mTextures.size(); }
+
+ private:
+ ActiveTextureArray<Texture *> mTextures;
+};
+
+class State : angle::NonCopyable
+{
+ public:
+ State(const State *shareContextState,
+ egl::ShareGroup *shareGroup,
+ TextureManager *shareTextures,
+ SemaphoreManager *shareSemaphores,
+ const OverlayType *overlay,
+ const EGLenum clientType,
+ const Version &clientVersion,
+ EGLint profileMask,
+ bool debug,
+ bool bindGeneratesResourceCHROMIUM,
+ bool clientArraysEnabled,
+ bool robustResourceInit,
+ bool programBinaryCacheEnabled,
+ EGLenum contextPriority,
+ bool hasRobustAccess,
+ bool hasProtectedContent);
+ ~State();
+
+ void initialize(Context *context);
+ void reset(const Context *context);
+
+ // Getters
+ ContextID getContextID() const { return mID; }
+ EGLenum getClientType() const { return mClientType; }
+ EGLint getProfileMask() const { return mProfileMask; }
+ EGLenum getContextPriority() const { return mContextPriority; }
+ bool hasRobustAccess() const { return mHasRobustAccess; }
+ bool hasProtectedContent() const { return mHasProtectedContent; }
+ bool isDebugContext() const { return mIsDebugContext; }
+ GLint getClientMajorVersion() const { return mClientVersion.major; }
+ GLint getClientMinorVersion() const { return mClientVersion.minor; }
+ const Version &getClientVersion() const { return mClientVersion; }
+ const Caps &getCaps() const { return mCaps; }
+ const TextureCapsMap &getTextureCaps() const { return mTextureCaps; }
+ const Extensions &getExtensions() const { return mExtensions; }
+ const Limitations &getLimitations() const { return mLimitations; }
+ egl::ShareGroup *getShareGroup() const { return mShareGroup; }
+
+ bool isWebGL() const { return mExtensions.webglCompatibilityANGLE; }
+
+ bool isWebGL1() const { return (isWebGL() && mClientVersion.major == 2); }
+
+ bool isGLES1() const { return mClientVersion < ES_2_0; }
+
+ const TextureCaps &getTextureCap(GLenum internalFormat) const
+ {
+ return mTextureCaps.get(internalFormat);
+ }
+
+ // State chunk getters
+ bool allActiveDrawBufferChannelsMasked() const;
+ bool anyActiveDrawBufferChannelMasked() const;
+ const RasterizerState &getRasterizerState() const;
+ const BlendState &getBlendState() const { return mBlendState; }
+ const BlendStateExt &getBlendStateExt() const { return mBlendStateExt; }
+ const DepthStencilState &getDepthStencilState() const;
+
+ // Clear behavior setters & state parameter block generation function
+ void setColorClearValue(float red, float green, float blue, float alpha);
+ void setDepthClearValue(float depth);
+ void setStencilClearValue(int stencil);
+
+ const ColorF &getColorClearValue() const { return mColorClearValue; }
+ float getDepthClearValue() const { return mDepthClearValue; }
+ int getStencilClearValue() const { return mStencilClearValue; }
+
+ // Write mask manipulation
+ void setColorMask(bool red, bool green, bool blue, bool alpha);
+ void setColorMaskIndexed(bool red, bool green, bool blue, bool alpha, GLuint index);
+ void setDepthMask(bool mask);
+
+ // Discard toggle & query
+ bool isRasterizerDiscardEnabled() const { return mRasterizer.rasterizerDiscard; }
+ void setRasterizerDiscard(bool enabled);
+
+ // Primitive restart
+ bool isPrimitiveRestartEnabled() const { return mPrimitiveRestart; }
+ void setPrimitiveRestart(bool enabled);
+
+ // Face culling state manipulation
+ bool isCullFaceEnabled() const { return mRasterizer.cullFace; }
+ void setCullFace(bool enabled);
+ void setCullMode(CullFaceMode mode);
+ void setFrontFace(GLenum front);
+
+ // Depth test state manipulation
+ bool isDepthTestEnabled() const { return mDepthStencil.depthTest; }
+ bool isDepthWriteEnabled() const { return mDepthStencil.depthTest && mDepthStencil.depthMask; }
+ void setDepthTest(bool enabled);
+ void setDepthFunc(GLenum depthFunc);
+ void setDepthRange(float zNear, float zFar);
+ float getNearPlane() const { return mNearZ; }
+ float getFarPlane() const { return mFarZ; }
+
+ // Clip control extension
+ void setClipControl(GLenum origin, GLenum depth);
+ bool isClipControlDepthZeroToOne() const { return mClipControlDepth == GL_ZERO_TO_ONE_EXT; }
+ gl::ClipSpaceOrigin getClipSpaceOrigin() const
+ {
+ return mClipControlOrigin == GL_UPPER_LEFT_EXT ? ClipSpaceOrigin::UpperLeft
+ : ClipSpaceOrigin::LowerLeft;
+ }
+
+ // Blend state manipulation
+ bool isBlendEnabled() const { return mBlendStateExt.getEnabledMask().test(0); }
+ bool isBlendEnabledIndexed(GLuint index) const
+ {
+ ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount());
+ return mBlendStateExt.getEnabledMask().test(index);
+ }
+ DrawBufferMask getBlendEnabledDrawBufferMask() const { return mBlendStateExt.getEnabledMask(); }
+ void setBlend(bool enabled);
+ void setBlendIndexed(bool enabled, GLuint index);
+ void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha);
+ void setBlendFactorsIndexed(GLenum sourceRGB,
+ GLenum destRGB,
+ GLenum sourceAlpha,
+ GLenum destAlpha,
+ GLuint index);
+ void setBlendColor(float red, float green, float blue, float alpha);
+ void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation);
+ void setBlendEquationIndexed(GLenum rgbEquation, GLenum alphaEquation, GLuint index);
+ const ColorF &getBlendColor() const { return mBlendColor; }
+
+ // Stencil state maniupulation
+ bool isStencilTestEnabled() const { return mDepthStencil.stencilTest; }
+ void setStencilTest(bool enabled);
+ void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask);
+ void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask);
+ void setStencilWritemask(GLuint stencilWritemask);
+ void setStencilBackWritemask(GLuint stencilBackWritemask);
+ void setStencilOperations(GLenum stencilFail,
+ GLenum stencilPassDepthFail,
+ GLenum stencilPassDepthPass);
+ void setStencilBackOperations(GLenum stencilBackFail,
+ GLenum stencilBackPassDepthFail,
+ GLenum stencilBackPassDepthPass);
+ GLint getStencilRef() const { return mStencilRef; }
+ GLint getStencilBackRef() const { return mStencilBackRef; }
+
+ // Depth bias/polygon offset state manipulation
+ bool isPolygonOffsetFillEnabled() const { return mRasterizer.polygonOffsetFill; }
+ void setPolygonOffsetFill(bool enabled);
+ void setPolygonOffsetParams(GLfloat factor, GLfloat units);
+
+ // Multisample coverage state manipulation
+ bool isSampleAlphaToCoverageEnabled() const { return mSampleAlphaToCoverage; }
+ void setSampleAlphaToCoverage(bool enabled);
+ bool isSampleCoverageEnabled() const { return mSampleCoverage; }
+ void setSampleCoverage(bool enabled);
+ void setSampleCoverageParams(GLclampf value, bool invert);
+ GLclampf getSampleCoverageValue() const { return mSampleCoverageValue; }
+ bool getSampleCoverageInvert() const { return mSampleCoverageInvert; }
+
+ // Multisample mask state manipulation.
+ bool isSampleMaskEnabled() const { return mSampleMask; }
+ void setSampleMaskEnabled(bool enabled);
+ void setSampleMaskParams(GLuint maskNumber, GLbitfield mask);
+ GLbitfield getSampleMaskWord(GLuint maskNumber) const
+ {
+ ASSERT(maskNumber < mMaxSampleMaskWords);
+ return mSampleMaskValues[maskNumber];
+ }
+ SampleMaskArray<GLbitfield> getSampleMaskValues() const { return mSampleMaskValues; }
+ GLuint getMaxSampleMaskWords() const { return mMaxSampleMaskWords; }
+
+ // Multisampling/alpha to one manipulation.
+ void setSampleAlphaToOne(bool enabled);
+ bool isSampleAlphaToOneEnabled() const { return mSampleAlphaToOne; }
+ void setMultisampling(bool enabled);
+ bool isMultisamplingEnabled() const { return mMultiSampling; }
+
+ void setSampleShading(bool enabled);
+ bool isSampleShadingEnabled() const { return mIsSampleShadingEnabled; }
+ void setMinSampleShading(float value);
+ float getMinSampleShading() const { return mMinSampleShading; }
+
+ // Scissor test state toggle & query
+ bool isScissorTestEnabled() const { return mScissorTest; }
+ void setScissorTest(bool enabled);
+ void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height);
+ const Rectangle &getScissor() const { return mScissor; }
+
+ // Dither state toggle & query
+ bool isDitherEnabled() const { return mRasterizer.dither; }
+ void setDither(bool enabled);
+
+ // Generic state toggle & query
+ void setEnableFeature(GLenum feature, bool enabled);
+ void setEnableFeatureIndexed(GLenum feature, bool enabled, GLuint index);
+ bool getEnableFeature(GLenum feature) const;
+ bool getEnableFeatureIndexed(GLenum feature, GLuint index) const;
+
+ // Line width state setter
+ void setLineWidth(GLfloat width);
+ float getLineWidth() const { return mLineWidth; }
+
+ // Hint setters
+ void setGenerateMipmapHint(GLenum hint);
+ GLenum getGenerateMipmapHint() const;
+ void setTextureFilteringHint(GLenum hint);
+ GLenum getTextureFilteringHint() const;
+ GLenum getFragmentShaderDerivativeHint() const { return mFragmentShaderDerivativeHint; }
+ void setFragmentShaderDerivativeHint(GLenum hint);
+
+ // GL_CHROMIUM_bind_generates_resource
+ bool isBindGeneratesResourceEnabled() const { return mBindGeneratesResource; }
+
+ // GL_ANGLE_client_arrays
+ bool areClientArraysEnabled() const { return mClientArraysEnabled; }
+
+ // Viewport state setter/getter
+ void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height);
+ const Rectangle &getViewport() const { return mViewport; }
+
+ // Texture binding & active texture unit manipulation
+ void setActiveSampler(unsigned int active);
+ unsigned int getActiveSampler() const { return static_cast<unsigned int>(mActiveSampler); }
+
+ void setSamplerTexture(const Context *context, TextureType type, Texture *texture);
+ Texture *getTargetTexture(TextureType type) const;
+
+ Texture *getSamplerTexture(unsigned int sampler, TextureType type) const
+ {
+ ASSERT(sampler < mSamplerTextures[type].size());
+ return mSamplerTextures[type][sampler].get();
+ }
+
+ TextureID getSamplerTextureId(unsigned int sampler, TextureType type) const;
+ void detachTexture(const Context *context, const TextureMap &zeroTextures, TextureID texture);
+ void initializeZeroTextures(const Context *context, const TextureMap &zeroTextures);
+
+ void invalidateTextureBindings(TextureType type);
+
+ // Sampler object binding manipulation
+ void setSamplerBinding(const Context *context, GLuint textureUnit, Sampler *sampler);
+ SamplerID getSamplerId(GLuint textureUnit) const
+ {
+ ASSERT(textureUnit < mSamplers.size());
+ return mSamplers[textureUnit].id();
+ }
+
+ Sampler *getSampler(GLuint textureUnit) const { return mSamplers[textureUnit].get(); }
+
+ const SamplerBindingVector &getSamplers() const { return mSamplers; }
+
+ void detachSampler(const Context *context, SamplerID sampler);
+
+ // Renderbuffer binding manipulation
+ void setRenderbufferBinding(const Context *context, Renderbuffer *renderbuffer);
+ RenderbufferID getRenderbufferId() const { return mRenderbuffer.id(); }
+ Renderbuffer *getCurrentRenderbuffer() const { return mRenderbuffer.get(); }
+ void detachRenderbuffer(const Context *context, RenderbufferID renderbuffer);
+
+ // Framebuffer binding manipulation
+ void setReadFramebufferBinding(Framebuffer *framebuffer);
+ void setDrawFramebufferBinding(Framebuffer *framebuffer);
+ Framebuffer *getTargetFramebuffer(GLenum target) const;
+ Framebuffer *getReadFramebuffer() const { return mReadFramebuffer; }
+ Framebuffer *getDrawFramebuffer() const { return mDrawFramebuffer; }
+ Framebuffer *getDefaultFramebuffer() const;
+
+ bool removeReadFramebufferBinding(FramebufferID framebuffer);
+ bool removeDrawFramebufferBinding(FramebufferID framebuffer);
+
+ // Vertex array object binding manipulation
+ void setVertexArrayBinding(const Context *context, VertexArray *vertexArray);
+ bool removeVertexArrayBinding(const Context *context, VertexArrayID vertexArray);
+ VertexArrayID getVertexArrayId() const;
+
+ VertexArray *getVertexArray() const
+ {
+ ASSERT(mVertexArray != nullptr);
+ return mVertexArray;
+ }
+
+ // QCOM_shading_rate helpers
+ void setShadingRate(GLenum rate);
+ ShadingRate getShadingRate() const { return mShadingRate; }
+
+ // If both a Program and a ProgramPipeline are bound, the Program will
+ // always override the ProgramPipeline.
+ ProgramExecutable *getProgramExecutable() const { return mExecutable; }
+ ProgramExecutable *getLinkedProgramExecutable(const Context *context) const
+ {
+ if (mProgram)
+ {
+ mProgram->resolveLink(context);
+ }
+ else if (mProgramPipeline.get())
+ {
+ mProgramPipeline->resolveLink(context);
+ }
+ return mExecutable;
+ }
+
+ // Program binding manipulation
+ angle::Result setProgram(const Context *context, Program *newProgram);
+
+ Program *getProgram() const
+ {
+ ASSERT(!mProgram || !mProgram->isLinking());
+ return mProgram;
+ }
+
+ Program *getLinkedProgram(const Context *context) const
+ {
+ if (mProgram)
+ {
+ mProgram->resolveLink(context);
+ }
+ return mProgram;
+ }
+
+ ProgramPipeline *getProgramPipeline() const { return mProgramPipeline.get(); }
+
+ ProgramPipeline *getLinkedProgramPipeline(const Context *context) const
+ {
+ if (mProgramPipeline.get())
+ {
+ mProgramPipeline->resolveLink(context);
+ }
+ return mProgramPipeline.get();
+ }
+
+ // Transform feedback object (not buffer) binding manipulation
+ void setTransformFeedbackBinding(const Context *context, TransformFeedback *transformFeedback);
+ TransformFeedback *getCurrentTransformFeedback() const { return mTransformFeedback.get(); }
+
+ ANGLE_INLINE bool isTransformFeedbackActive() const
+ {
+ TransformFeedback *curTransformFeedback = mTransformFeedback.get();
+ return curTransformFeedback && curTransformFeedback->isActive();
+ }
+ ANGLE_INLINE bool isTransformFeedbackActiveUnpaused() const
+ {
+ TransformFeedback *curTransformFeedback = mTransformFeedback.get();
+ return curTransformFeedback && curTransformFeedback->isActive() &&
+ !curTransformFeedback->isPaused();
+ }
+
+ bool removeTransformFeedbackBinding(const Context *context,
+ TransformFeedbackID transformFeedback);
+
+ // Query binding manipulation
+ bool isQueryActive(QueryType type) const;
+ bool isQueryActive(Query *query) const;
+ void setActiveQuery(const Context *context, QueryType type, Query *query);
+ QueryID getActiveQueryId(QueryType type) const;
+ Query *getActiveQuery(QueryType type) const;
+
+ // Program Pipeline binding manipulation
+ angle::Result setProgramPipelineBinding(const Context *context, ProgramPipeline *pipeline);
+ void detachProgramPipeline(const Context *context, ProgramPipelineID pipeline);
+
+ //// Typed buffer binding point manipulation ////
+ ANGLE_INLINE void setBufferBinding(const Context *context, BufferBinding target, Buffer *buffer)
+ {
+ (this->*(kBufferSetters[target]))(context, buffer);
+ }
+
+ ANGLE_INLINE Buffer *getTargetBuffer(BufferBinding target) const
+ {
+ switch (target)
+ {
+ case BufferBinding::ElementArray:
+ return getVertexArray()->getElementArrayBuffer();
+ default:
+ return mBoundBuffers[target].get();
+ }
+ }
+
+ ANGLE_INLINE Buffer *getArrayBuffer() const { return getTargetBuffer(BufferBinding::Array); }
+
+ angle::Result setIndexedBufferBinding(const Context *context,
+ BufferBinding target,
+ GLuint index,
+ Buffer *buffer,
+ GLintptr offset,
+ GLsizeiptr size);
+
+ size_t getAtomicCounterBufferCount() const { return mAtomicCounterBuffers.size(); }
+
+ ANGLE_INLINE bool hasValidAtomicCounterBuffer() const
+ {
+ return mBoundAtomicCounterBuffersMask.any();
+ }
+
+ const OffsetBindingPointer<Buffer> &getIndexedUniformBuffer(size_t index) const;
+ const OffsetBindingPointer<Buffer> &getIndexedAtomicCounterBuffer(size_t index) const;
+ const OffsetBindingPointer<Buffer> &getIndexedShaderStorageBuffer(size_t index) const;
+
+ const angle::BitSet<gl::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS> &getUniformBuffersMask()
+ const
+ {
+ return mBoundUniformBuffersMask;
+ }
+ const angle::BitSet<gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS>
+ &getAtomicCounterBuffersMask() const
+ {
+ return mBoundAtomicCounterBuffersMask;
+ }
+ const angle::BitSet<gl::IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>
+ &getShaderStorageBuffersMask() const
+ {
+ return mBoundShaderStorageBuffersMask;
+ }
+
+ // Detach a buffer from all bindings
+ angle::Result detachBuffer(Context *context, const Buffer *buffer);
+
+ // Vertex attrib manipulation
+ void setEnableVertexAttribArray(unsigned int attribNum, bool enabled);
+ void setVertexAttribf(GLuint index, const GLfloat values[4]);
+ void setVertexAttribu(GLuint index, const GLuint values[4]);
+ void setVertexAttribi(GLuint index, const GLint values[4]);
+
+ ANGLE_INLINE void setVertexAttribPointer(const Context *context,
+ unsigned int attribNum,
+ Buffer *boundBuffer,
+ GLint size,
+ VertexAttribType type,
+ bool normalized,
+ GLsizei stride,
+ const void *pointer)
+ {
+ mVertexArray->setVertexAttribPointer(context, attribNum, boundBuffer, size, type,
+ normalized, stride, pointer);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+ }
+
+ ANGLE_INLINE void setVertexAttribIPointer(const Context *context,
+ unsigned int attribNum,
+ Buffer *boundBuffer,
+ GLint size,
+ VertexAttribType type,
+ GLsizei stride,
+ const void *pointer)
+ {
+ mVertexArray->setVertexAttribIPointer(context, attribNum, boundBuffer, size, type, stride,
+ pointer);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+ }
+
+ void setVertexAttribDivisor(const Context *context, GLuint index, GLuint divisor);
+ const VertexAttribCurrentValueData &getVertexAttribCurrentValue(size_t attribNum) const
+ {
+ ASSERT(attribNum < mVertexAttribCurrentValues.size());
+ return mVertexAttribCurrentValues[attribNum];
+ }
+
+ const std::vector<VertexAttribCurrentValueData> &getVertexAttribCurrentValues() const
+ {
+ return mVertexAttribCurrentValues;
+ }
+
+ const void *getVertexAttribPointer(unsigned int attribNum) const;
+
+ void bindVertexBuffer(const Context *context,
+ GLuint bindingIndex,
+ Buffer *boundBuffer,
+ GLintptr offset,
+ GLsizei stride);
+ void setVertexAttribFormat(GLuint attribIndex,
+ GLint size,
+ VertexAttribType type,
+ bool normalized,
+ bool pureInteger,
+ GLuint relativeOffset);
+
+ void setVertexAttribBinding(const Context *context, GLuint attribIndex, GLuint bindingIndex)
+ {
+ mVertexArray->setVertexAttribBinding(context, attribIndex, bindingIndex);
+ mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY);
+ }
+
+ void setVertexBindingDivisor(const Context *context, GLuint bindingIndex, GLuint divisor);
+
+ // Pixel pack state manipulation
+ void setPackAlignment(GLint alignment);
+ GLint getPackAlignment() const { return mPack.alignment; }
+ void setPackReverseRowOrder(bool reverseRowOrder);
+ bool getPackReverseRowOrder() const { return mPack.reverseRowOrder; }
+ void setPackRowLength(GLint rowLength);
+ GLint getPackRowLength() const { return mPack.rowLength; }
+ void setPackSkipRows(GLint skipRows);
+ GLint getPackSkipRows() const { return mPack.skipRows; }
+ void setPackSkipPixels(GLint skipPixels);
+ GLint getPackSkipPixels() const { return mPack.skipPixels; }
+ const PixelPackState &getPackState() const { return mPack; }
+ PixelPackState &getPackState() { return mPack; }
+
+ // Pixel unpack state manipulation
+ void setUnpackAlignment(GLint alignment);
+ GLint getUnpackAlignment() const { return mUnpack.alignment; }
+ void setUnpackRowLength(GLint rowLength);
+ GLint getUnpackRowLength() const { return mUnpack.rowLength; }
+ void setUnpackImageHeight(GLint imageHeight);
+ GLint getUnpackImageHeight() const { return mUnpack.imageHeight; }
+ void setUnpackSkipImages(GLint skipImages);
+ GLint getUnpackSkipImages() const { return mUnpack.skipImages; }
+ void setUnpackSkipRows(GLint skipRows);
+ GLint getUnpackSkipRows() const { return mUnpack.skipRows; }
+ void setUnpackSkipPixels(GLint skipPixels);
+ GLint getUnpackSkipPixels() const { return mUnpack.skipPixels; }
+ const PixelUnpackState &getUnpackState() const { return mUnpack; }
+ PixelUnpackState &getUnpackState() { return mUnpack; }
+
+ // Debug state
+ const Debug &getDebug() const { return mDebug; }
+ Debug &getDebug() { return mDebug; }
+
+ // CHROMIUM_framebuffer_mixed_samples coverage modulation
+ void setCoverageModulation(GLenum components);
+ GLenum getCoverageModulation() const { return mCoverageModulation; }
+
+ // GL_EXT_sRGB_write_control
+ void setFramebufferSRGB(bool sRGB);
+ bool getFramebufferSRGB() const { return mFramebufferSRGB; }
+
+ // GL_KHR_parallel_shader_compile
+ void setMaxShaderCompilerThreads(GLuint count);
+ GLuint getMaxShaderCompilerThreads() const { return mMaxShaderCompilerThreads; }
+
+ // GL_EXT_tessellation_shader
+ void setPatchVertices(GLuint value);
+ GLuint getPatchVertices() const { return mPatchVertices; }
+
+ // GL_ANGLE_shader_pixel_local_storage
+ void setPixelLocalStorageActive(bool active);
+ bool getPixelLocalStorageActive() const { return mPixelLocalStorageActive; }
+
+ // State query functions
+ void getBooleanv(GLenum pname, GLboolean *params) const;
+ void getFloatv(GLenum pname, GLfloat *params) const;
+ angle::Result getIntegerv(const Context *context, GLenum pname, GLint *params) const;
+ void getPointerv(const Context *context, GLenum pname, void **params) const;
+ void getIntegeri_v(const Context *context, GLenum target, GLuint index, GLint *data) const;
+ void getInteger64i_v(GLenum target, GLuint index, GLint64 *data) const;
+ void getBooleani_v(GLenum target, GLuint index, GLboolean *data) const;
+
+ bool isRobustResourceInitEnabled() const { return mRobustResourceInit; }
+
+ bool isDrawFramebufferBindingDirty() const
+ {
+ return mDirtyBits.test(DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
+ }
+
+ // Sets the dirty bit for the program executable.
+ angle::Result onProgramExecutableChange(const Context *context, Program *program);
+ // Sets the dirty bit for the program pipeline executable.
+ angle::Result onProgramPipelineExecutableChange(const Context *context);
+
+ enum DirtyBitType
+ {
+ // Note: process draw framebuffer binding first, so that other dirty bits whose effect
+ // depend on the current draw framebuffer are not processed while the old framebuffer is
+ // still bound.
+ DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING,
+ DIRTY_BIT_READ_FRAMEBUFFER_BINDING,
+ DIRTY_BIT_SCISSOR_TEST_ENABLED,
+ DIRTY_BIT_SCISSOR,
+ DIRTY_BIT_VIEWPORT,
+ DIRTY_BIT_DEPTH_RANGE,
+ DIRTY_BIT_BLEND_ENABLED,
+ DIRTY_BIT_BLEND_COLOR,
+ DIRTY_BIT_BLEND_FUNCS,
+ DIRTY_BIT_BLEND_EQUATIONS,
+ DIRTY_BIT_COLOR_MASK,
+ DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED,
+ DIRTY_BIT_SAMPLE_COVERAGE_ENABLED,
+ DIRTY_BIT_SAMPLE_COVERAGE,
+ DIRTY_BIT_SAMPLE_MASK_ENABLED,
+ DIRTY_BIT_SAMPLE_MASK,
+ DIRTY_BIT_DEPTH_TEST_ENABLED,
+ DIRTY_BIT_DEPTH_FUNC,
+ DIRTY_BIT_DEPTH_MASK,
+ DIRTY_BIT_STENCIL_TEST_ENABLED,
+ DIRTY_BIT_STENCIL_FUNCS_FRONT,
+ DIRTY_BIT_STENCIL_FUNCS_BACK,
+ DIRTY_BIT_STENCIL_OPS_FRONT,
+ DIRTY_BIT_STENCIL_OPS_BACK,
+ DIRTY_BIT_STENCIL_WRITEMASK_FRONT,
+ DIRTY_BIT_STENCIL_WRITEMASK_BACK,
+ DIRTY_BIT_CULL_FACE_ENABLED,
+ DIRTY_BIT_CULL_FACE,
+ DIRTY_BIT_FRONT_FACE,
+ DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED,
+ DIRTY_BIT_POLYGON_OFFSET,
+ DIRTY_BIT_RASTERIZER_DISCARD_ENABLED,
+ DIRTY_BIT_LINE_WIDTH,
+ DIRTY_BIT_PRIMITIVE_RESTART_ENABLED,
+ DIRTY_BIT_CLEAR_COLOR,
+ DIRTY_BIT_CLEAR_DEPTH,
+ DIRTY_BIT_CLEAR_STENCIL,
+ DIRTY_BIT_UNPACK_STATE,
+ DIRTY_BIT_UNPACK_BUFFER_BINDING,
+ DIRTY_BIT_PACK_STATE,
+ DIRTY_BIT_PACK_BUFFER_BINDING,
+ DIRTY_BIT_DITHER_ENABLED,
+ DIRTY_BIT_RENDERBUFFER_BINDING,
+ DIRTY_BIT_VERTEX_ARRAY_BINDING,
+ DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING,
+ DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING,
+ // TODO(jmadill): Fine-grained dirty bits for each index.
+ DIRTY_BIT_PROGRAM_BINDING, // Must be before DIRTY_BIT_PROGRAM_EXECUTABLE
+ DIRTY_BIT_PROGRAM_EXECUTABLE,
+ // TODO(jmadill): Fine-grained dirty bits for each texture/sampler.
+ DIRTY_BIT_SAMPLER_BINDINGS,
+ DIRTY_BIT_TEXTURE_BINDINGS,
+ DIRTY_BIT_IMAGE_BINDINGS,
+ DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING,
+ DIRTY_BIT_UNIFORM_BUFFER_BINDINGS,
+ DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING,
+ DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING,
+ DIRTY_BIT_MULTISAMPLING,
+ DIRTY_BIT_SAMPLE_ALPHA_TO_ONE,
+ DIRTY_BIT_COVERAGE_MODULATION, // CHROMIUM_framebuffer_mixed_samples
+ DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE, // GL_EXT_sRGB_write_control
+ DIRTY_BIT_CURRENT_VALUES,
+ DIRTY_BIT_PROVOKING_VERTEX,
+ DIRTY_BIT_SAMPLE_SHADING,
+ DIRTY_BIT_PATCH_VERTICES,
+ DIRTY_BIT_EXTENDED, // clip distances, mipmap generation hint, derivative hint,
+ // EXT_clip_control
+ DIRTY_BIT_INVALID,
+ DIRTY_BIT_MAX = DIRTY_BIT_INVALID,
+ };
+
+ static_assert(DIRTY_BIT_MAX <= 64, "State dirty bits must be capped at 64");
+
+ enum ExtendedDirtyBitType
+ {
+ EXTENDED_DIRTY_BIT_CLIP_CONTROL, // EXT_clip_control
+ EXTENDED_DIRTY_BIT_CLIP_DISTANCES, // clip distances
+ EXTENDED_DIRTY_BIT_MIPMAP_GENERATION_HINT, // mipmap generation hint
+ EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT, // shader derivative hint
+ EXTENDED_DIRTY_BIT_SHADING_RATE, // QCOM_shading_rate
+ EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED, // ANGLE_logic_op
+ EXTENDED_DIRTY_BIT_LOGIC_OP, // ANGLE_logic_op
+ EXTENDED_DIRTY_BIT_INVALID,
+ EXTENDED_DIRTY_BIT_MAX = EXTENDED_DIRTY_BIT_INVALID,
+ };
+
+ static_assert(EXTENDED_DIRTY_BIT_MAX <= 32, "State extended dirty bits must be capped at 32");
+
+ // TODO(jmadill): Consider storing dirty objects in a list instead of by binding.
+ enum DirtyObjectType
+ {
+ DIRTY_OBJECT_ACTIVE_TEXTURES, // Top-level dirty bit. Also see mDirtyActiveTextures.
+ DIRTY_OBJECT_TEXTURES_INIT,
+ DIRTY_OBJECT_IMAGES_INIT,
+ DIRTY_OBJECT_READ_ATTACHMENTS,
+ DIRTY_OBJECT_DRAW_ATTACHMENTS,
+ DIRTY_OBJECT_READ_FRAMEBUFFER,
+ DIRTY_OBJECT_DRAW_FRAMEBUFFER,
+ DIRTY_OBJECT_VERTEX_ARRAY,
+ DIRTY_OBJECT_TEXTURES, // Top-level dirty bit. Also see mDirtyTextures.
+ DIRTY_OBJECT_IMAGES, // Top-level dirty bit. Also see mDirtyImages.
+ DIRTY_OBJECT_SAMPLERS, // Top-level dirty bit. Also see mDirtySamplers.
+ DIRTY_OBJECT_PROGRAM,
+ DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT,
+ DIRTY_OBJECT_UNKNOWN,
+ DIRTY_OBJECT_MAX = DIRTY_OBJECT_UNKNOWN,
+ };
+
+ using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
+ const DirtyBits &getDirtyBits() const { return mDirtyBits; }
+ void clearDirtyBits() { mDirtyBits.reset(); }
+ void clearDirtyBits(const DirtyBits &bitset) { mDirtyBits &= ~bitset; }
+ void setAllDirtyBits()
+ {
+ mDirtyBits.set();
+ mExtendedDirtyBits.set();
+ mDirtyCurrentValues.set();
+ }
+
+ using ExtendedDirtyBits = angle::BitSet32<EXTENDED_DIRTY_BIT_MAX>;
+ const ExtendedDirtyBits &getExtendedDirtyBits() const { return mExtendedDirtyBits; }
+ // TODO(https://anglebug.com/5631): Handle extended dirty bits on non-vulkan backends
+ ExtendedDirtyBits getAndResetExtendedDirtyBits() const;
+ void clearExtendedDirtyBits() { mExtendedDirtyBits.reset(); }
+
+ using DirtyObjects = angle::BitSet<DIRTY_OBJECT_MAX>;
+ void clearDirtyObjects() { mDirtyObjects.reset(); }
+ void setAllDirtyObjects() { mDirtyObjects.set(); }
+ angle::Result syncDirtyObjects(const Context *context,
+ const DirtyObjects &bitset,
+ Command command);
+ angle::Result syncDirtyObject(const Context *context, GLenum target);
+ void setObjectDirty(GLenum target);
+ void setTextureDirty(size_t textureUnitIndex);
+ void setSamplerDirty(size_t samplerIndex);
+
+ ANGLE_INLINE void setReadFramebufferDirty()
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER);
+ mDirtyObjects.set(DIRTY_OBJECT_READ_ATTACHMENTS);
+ }
+
+ ANGLE_INLINE void setDrawFramebufferDirty()
+ {
+ mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER);
+ mDirtyObjects.set(DIRTY_OBJECT_DRAW_ATTACHMENTS);
+ }
+
+ // This actually clears the current value dirty bits.
+ // TODO(jmadill): Pass mutable dirty bits into Impl.
+ AttributesMask getAndResetDirtyCurrentValues() const;
+
+ void setImageUnit(const Context *context,
+ size_t unit,
+ Texture *texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format);
+
+ const ImageUnit &getImageUnit(size_t unit) const { return mImageUnits[unit]; }
+ const ActiveTexturesCache &getActiveTexturesCache() const { return mActiveTexturesCache; }
+ ComponentTypeMask getCurrentValuesTypeMask() const { return mCurrentValuesTypeMask; }
+
+ // "onActiveTextureChange" is called when a texture binding changes.
+ void onActiveTextureChange(const Context *context, size_t textureUnit);
+
+ // "onActiveTextureStateChange" is called when the Texture changed but the binding did not.
+ void onActiveTextureStateChange(const Context *context, size_t textureUnit);
+
+ void onImageStateChange(const Context *context, size_t unit);
+
+ void onUniformBufferStateChange(size_t uniformBufferIndex);
+ void onAtomicCounterBufferStateChange(size_t atomicCounterBufferIndex);
+ void onShaderStorageBufferStateChange(size_t shaderStorageBufferIndex);
+
+ bool isCurrentTransformFeedback(const TransformFeedback *tf) const
+ {
+ return tf == mTransformFeedback.get();
+ }
+ bool isCurrentVertexArray(const VertexArray *va) const { return va == mVertexArray; }
+
+ GLES1State &gles1() { return mGLES1State; }
+ const GLES1State &gles1() const { return mGLES1State; }
+
+ // Helpers for setting bound buffers. They should all have the same signature.
+ // Not meant to be called externally. Used for local helpers in State.cpp.
+ template <BufferBinding Target>
+ void setGenericBufferBindingWithBit(const Context *context, Buffer *buffer);
+
+ template <BufferBinding Target>
+ void setGenericBufferBinding(const Context *context, Buffer *buffer);
+
+ using BufferBindingSetter = void (State::*)(const Context *, Buffer *);
+
+ ANGLE_INLINE bool validateSamplerFormats() const
+ {
+ return (!mExecutable || !(mTexturesIncompatibleWithSamplers.intersects(
+ mExecutable->getActiveSamplersMask())));
+ }
+
+ ProvokingVertexConvention getProvokingVertex() const { return mProvokingVertex; }
+ void setProvokingVertex(ProvokingVertexConvention val)
+ {
+ mDirtyBits.set(State::DIRTY_BIT_PROVOKING_VERTEX);
+ mProvokingVertex = val;
+ }
+
+ ANGLE_INLINE void setReadFramebufferBindingDirty()
+ {
+ mDirtyBits.set(State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING);
+ }
+
+ ANGLE_INLINE void setDrawFramebufferBindingDirty()
+ {
+ mDirtyBits.set(State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
+ }
+
+ using ClipDistanceEnableBits = angle::BitSet32<IMPLEMENTATION_MAX_CLIP_DISTANCES>;
+ const ClipDistanceEnableBits &getEnabledClipDistances() const { return mClipDistancesEnabled; }
+ void setClipDistanceEnable(int idx, bool enable);
+
+ const OverlayType *getOverlay() const { return mOverlay; }
+
+ // Not for general use.
+ const BufferManager &getBufferManagerForCapture() const { return *mBufferManager; }
+ const BoundBufferMap &getBoundBuffersForCapture() const { return mBoundBuffers; }
+ const TextureManager &getTextureManagerForCapture() const { return *mTextureManager; }
+ const TextureBindingMap &getBoundTexturesForCapture() const { return mSamplerTextures; }
+ const RenderbufferManager &getRenderbufferManagerForCapture() const
+ {
+ return *mRenderbufferManager;
+ }
+ const FramebufferManager &getFramebufferManagerForCapture() const
+ {
+ return *mFramebufferManager;
+ }
+ const ShaderProgramManager &getShaderProgramManagerForCapture() const
+ {
+ return *mShaderProgramManager;
+ }
+ const SyncManager &getSyncManagerForCapture() const { return *mSyncManager; }
+ const SamplerManager &getSamplerManagerForCapture() const { return *mSamplerManager; }
+ const ProgramPipelineManager *getProgramPipelineManagerForCapture() const
+ {
+ return mProgramPipelineManager;
+ }
+ const SamplerBindingVector &getSamplerBindingsForCapture() const { return mSamplers; }
+ const ActiveQueryMap &getActiveQueriesForCapture() const { return mActiveQueries; }
+ void initializeForCapture(const Context *context);
+
+ bool hasConstantAlphaBlendFunc() const
+ {
+ return (mBlendFuncConstantAlphaDrawBuffers & mBlendStateExt.getEnabledMask()).any();
+ }
+
+ bool hasSimultaneousConstantColorAndAlphaBlendFunc() const
+ {
+ return (mBlendFuncConstantColorDrawBuffers & mBlendStateExt.getEnabledMask()).any() &&
+ hasConstantAlphaBlendFunc();
+ }
+
+ bool noSimultaneousConstantColorAndAlphaBlendFunc() const
+ {
+ return mNoSimultaneousConstantColorAndAlphaBlendFunc;
+ }
+
+ const BufferVector &getOffsetBindingPointerUniformBuffers() const { return mUniformBuffers; }
+
+ const BufferVector &getOffsetBindingPointerAtomicCounterBuffers() const
+ {
+ return mAtomicCounterBuffers;
+ }
+
+ const BufferVector &getOffsetBindingPointerShaderStorageBuffers() const
+ {
+ return mShaderStorageBuffers;
+ }
+
+ ActiveTextureMask getTexturesIncompatibleWithSamplers() const
+ {
+ return mTexturesIncompatibleWithSamplers;
+ }
+
+ bool isProgramBinaryCacheEnabled() const { return mProgramBinaryCacheEnabled; }
+
+ bool isTextureRectangleEnabled() const { return mTextureRectangleEnabled; }
+
+ DrawBufferMask getBlendFuncConstantAlphaDrawBuffers() const
+ {
+ return mBlendFuncConstantAlphaDrawBuffers;
+ }
+
+ DrawBufferMask getBlendFuncConstantColorDrawBuffers() const
+ {
+ return mBlendFuncConstantColorDrawBuffers;
+ }
+
+ const std::vector<ImageUnit> &getImageUnits() const { return mImageUnits; }
+
+ bool hasDisplayTextureShareGroup() const { return mDisplayTextureShareGroup; }
+
+ void setLogicOpEnabled(bool enabled);
+ bool isLogicOpEnabled() const { return mLogicOpEnabled; }
+
+ void setLogicOp(LogicalOperation opcode);
+ LogicalOperation getLogicOp() const { return mLogicOp; }
+
+ private:
+ friend class Context;
+
+ void unsetActiveTextures(const ActiveTextureMask &textureMask);
+ void setActiveTextureDirty(size_t textureIndex, Texture *texture);
+ void updateTextureBinding(const Context *context, size_t textureIndex, Texture *texture);
+ void updateActiveTextureStateOnSync(const Context *context,
+ size_t textureIndex,
+ const Sampler *sampler,
+ Texture *texture);
+ Texture *getTextureForActiveSampler(TextureType type, size_t index);
+
+ bool hasConstantColor(GLenum sourceRGB, GLenum destRGB) const;
+ bool hasConstantAlpha(GLenum sourceRGB, GLenum destRGB) const;
+
+ // Functions to synchronize dirty states
+ angle::Result syncActiveTextures(const Context *context, Command command);
+ angle::Result syncTexturesInit(const Context *context, Command command);
+ angle::Result syncImagesInit(const Context *context, Command command);
+ angle::Result syncReadAttachments(const Context *context, Command command);
+ angle::Result syncDrawAttachments(const Context *context, Command command);
+ angle::Result syncReadFramebuffer(const Context *context, Command command);
+ angle::Result syncDrawFramebuffer(const Context *context, Command command);
+ angle::Result syncVertexArray(const Context *context, Command command);
+ angle::Result syncTextures(const Context *context, Command command);
+ angle::Result syncImages(const Context *context, Command command);
+ angle::Result syncSamplers(const Context *context, Command command);
+ angle::Result syncProgram(const Context *context, Command command);
+ angle::Result syncProgramPipelineObject(const Context *context, Command command);
+
+ using DirtyObjectHandler = angle::Result (State::*)(const Context *context, Command command);
+
+ static constexpr DirtyObjectHandler kDirtyObjectHandlers[DIRTY_OBJECT_MAX] = {
+ &State::syncActiveTextures,
+ &State::syncTexturesInit,
+ &State::syncImagesInit,
+ &State::syncReadAttachments,
+ &State::syncDrawAttachments,
+ &State::syncReadFramebuffer,
+ &State::syncDrawFramebuffer,
+ &State::syncVertexArray,
+ &State::syncTextures,
+ &State::syncImages,
+ &State::syncSamplers,
+ &State::syncProgram,
+ &State::syncProgramPipelineObject};
+
+ // Robust init must happen before Framebuffer init for the Vulkan back-end.
+ static_assert(DIRTY_OBJECT_ACTIVE_TEXTURES < DIRTY_OBJECT_TEXTURES_INIT, "init order");
+ static_assert(DIRTY_OBJECT_TEXTURES_INIT < DIRTY_OBJECT_DRAW_FRAMEBUFFER, "init order");
+ static_assert(DIRTY_OBJECT_IMAGES_INIT < DIRTY_OBJECT_DRAW_FRAMEBUFFER, "init order");
+ static_assert(DIRTY_OBJECT_DRAW_ATTACHMENTS < DIRTY_OBJECT_DRAW_FRAMEBUFFER, "init order");
+ static_assert(DIRTY_OBJECT_READ_ATTACHMENTS < DIRTY_OBJECT_READ_FRAMEBUFFER, "init order");
+
+ static_assert(DIRTY_OBJECT_ACTIVE_TEXTURES == 0, "check DIRTY_OBJECT_ACTIVE_TEXTURES index");
+ static_assert(DIRTY_OBJECT_TEXTURES_INIT == 1, "check DIRTY_OBJECT_TEXTURES_INIT index");
+ static_assert(DIRTY_OBJECT_IMAGES_INIT == 2, "check DIRTY_OBJECT_IMAGES_INIT index");
+ static_assert(DIRTY_OBJECT_READ_ATTACHMENTS == 3, "check DIRTY_OBJECT_READ_ATTACHMENTS index");
+ static_assert(DIRTY_OBJECT_DRAW_ATTACHMENTS == 4, "check DIRTY_OBJECT_DRAW_ATTACHMENTS index");
+ static_assert(DIRTY_OBJECT_READ_FRAMEBUFFER == 5, "check DIRTY_OBJECT_READ_FRAMEBUFFER index");
+ static_assert(DIRTY_OBJECT_DRAW_FRAMEBUFFER == 6, "check DIRTY_OBJECT_DRAW_FRAMEBUFFER index");
+ static_assert(DIRTY_OBJECT_VERTEX_ARRAY == 7, "check DIRTY_OBJECT_VERTEX_ARRAY index");
+ static_assert(DIRTY_OBJECT_TEXTURES == 8, "check DIRTY_OBJECT_TEXTURES index");
+ static_assert(DIRTY_OBJECT_IMAGES == 9, "check DIRTY_OBJECT_IMAGES index");
+ static_assert(DIRTY_OBJECT_SAMPLERS == 10, "check DIRTY_OBJECT_SAMPLERS index");
+ static_assert(DIRTY_OBJECT_PROGRAM == 11, "check DIRTY_OBJECT_PROGRAM index");
+ static_assert(DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT == 12,
+ "check DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT index");
+
+ // Dispatch table for buffer update functions.
+ static const angle::PackedEnumMap<BufferBinding, BufferBindingSetter> kBufferSetters;
+
+ ContextID mID;
+
+ EGLenum mClientType;
+ EGLint mProfileMask;
+ EGLenum mContextPriority;
+ bool mHasRobustAccess;
+ bool mHasProtectedContent;
+ bool mIsDebugContext;
+ Version mClientVersion;
+
+ // Caps to use for validation
+ Caps mCaps;
+ TextureCapsMap mTextureCaps;
+ Extensions mExtensions;
+ Limitations mLimitations;
+
+ egl::ShareGroup *mShareGroup;
+
+ // Resource managers.
+ BufferManager *mBufferManager;
+ ShaderProgramManager *mShaderProgramManager;
+ TextureManager *mTextureManager;
+ RenderbufferManager *mRenderbufferManager;
+ SamplerManager *mSamplerManager;
+ SyncManager *mSyncManager;
+ FramebufferManager *mFramebufferManager;
+ ProgramPipelineManager *mProgramPipelineManager;
+ MemoryObjectManager *mMemoryObjectManager;
+ SemaphoreManager *mSemaphoreManager;
+
+ ColorF mColorClearValue;
+ GLfloat mDepthClearValue;
+ int mStencilClearValue;
+
+ RasterizerState mRasterizer;
+ bool mScissorTest;
+ Rectangle mScissor;
+
+ bool mNoUnclampedBlendColor;
+
+ BlendState mBlendState; // Buffer zero blend state legacy struct
+ BlendStateExt mBlendStateExt;
+ ColorF mBlendColor;
+ bool mSampleAlphaToCoverage;
+ bool mSampleCoverage;
+ GLfloat mSampleCoverageValue;
+ bool mSampleCoverageInvert;
+ bool mSampleMask;
+ GLuint mMaxSampleMaskWords;
+ SampleMaskArray<GLbitfield> mSampleMaskValues;
+ bool mIsSampleShadingEnabled;
+ float mMinSampleShading;
+
+ DepthStencilState mDepthStencil;
+ GLint mStencilRef;
+ GLint mStencilBackRef;
+
+ GLfloat mLineWidth;
+
+ GLenum mGenerateMipmapHint;
+ GLenum mTextureFilteringHint;
+ GLenum mFragmentShaderDerivativeHint;
+
+ const bool mBindGeneratesResource;
+ const bool mClientArraysEnabled;
+
+ Rectangle mViewport;
+ float mNearZ;
+ float mFarZ;
+
+ GLenum mClipControlOrigin;
+ GLenum mClipControlDepth;
+
+ Framebuffer *mReadFramebuffer;
+ Framebuffer *mDrawFramebuffer;
+ BindingPointer<Renderbuffer> mRenderbuffer;
+ Program *mProgram;
+ BindingPointer<ProgramPipeline> mProgramPipeline;
+ ProgramExecutable *mExecutable;
+
+ // GL_ANGLE_provoking_vertex
+ ProvokingVertexConvention mProvokingVertex;
+
+ using VertexAttribVector = std::vector<VertexAttribCurrentValueData>;
+ VertexAttribVector mVertexAttribCurrentValues; // From glVertexAttrib
+ VertexArray *mVertexArray;
+ ComponentTypeMask mCurrentValuesTypeMask;
+
+ // Texture and sampler bindings
+ GLint mActiveSampler; // Active texture unit selector - GL_TEXTURE0
+
+ TextureBindingMap mSamplerTextures;
+
+ // Active Textures Cache
+ // ---------------------
+ // The active textures cache gives ANGLE components access to a complete array of textures
+ // on a draw call. gl::State implements angle::Observer and watches gl::Texture for state
+ // changes via the onSubjectStateChange method above. We update the cache before draws.
+ // See Observer.h and the design doc linked there for more info on Subject/Observer events.
+ //
+ // On state change events (re-binding textures, samplers, programs etc) we clear the cache
+ // and flag dirty bits. nullptr indicates unbound or incomplete.
+ ActiveTexturesCache mActiveTexturesCache;
+ std::vector<angle::ObserverBinding> mCompleteTextureBindings;
+
+ ActiveTextureMask mTexturesIncompatibleWithSamplers;
+
+ SamplerBindingVector mSamplers;
+
+ // It would be nice to merge the image and observer binding. Same for textures.
+ std::vector<ImageUnit> mImageUnits;
+
+ ActiveQueryMap mActiveQueries;
+
+ // Stores the currently bound buffer for each binding point. It has an entry for the element
+ // array buffer but it should not be used. Instead this bind point is owned by the current
+ // vertex array object.
+ BoundBufferMap mBoundBuffers;
+
+ BufferVector mUniformBuffers;
+ BufferVector mAtomicCounterBuffers;
+ BufferVector mShaderStorageBuffers;
+
+ angle::BitSet<gl::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS> mBoundUniformBuffersMask;
+ angle::BitSet<gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS>
+ mBoundAtomicCounterBuffersMask;
+ angle::BitSet<gl::IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>
+ mBoundShaderStorageBuffersMask;
+
+ BindingPointer<TransformFeedback> mTransformFeedback;
+
+ PixelUnpackState mUnpack;
+ PixelPackState mPack;
+
+ bool mPrimitiveRestart;
+
+ Debug mDebug;
+
+ bool mMultiSampling;
+ bool mSampleAlphaToOne;
+
+ GLenum mCoverageModulation;
+
+ // GL_EXT_sRGB_write_control
+ bool mFramebufferSRGB;
+
+ // GL_ANGLE_robust_resource_initialization
+ const bool mRobustResourceInit;
+
+ // GL_ANGLE_program_cache_control
+ const bool mProgramBinaryCacheEnabled;
+
+ // GL_ANGLE_webgl_compatibility
+ bool mTextureRectangleEnabled;
+
+ // GL_ANGLE_logic_op
+ bool mLogicOpEnabled;
+ LogicalOperation mLogicOp;
+
+ // GL_KHR_parallel_shader_compile
+ GLuint mMaxShaderCompilerThreads;
+
+ // GL_APPLE_clip_distance/GL_EXT_clip_cull_distance
+ ClipDistanceEnableBits mClipDistancesEnabled;
+
+ // GL_EXT_tessellation_shader
+ GLuint mPatchVertices;
+
+ // GL_ANGLE_shader_pixel_local_storage
+ bool mPixelLocalStorageActive;
+
+ // GLES1 emulation: state specific to GLES1
+ GLES1State mGLES1State;
+
+ DirtyBits mDirtyBits;
+ mutable ExtendedDirtyBits mExtendedDirtyBits;
+ DirtyObjects mDirtyObjects;
+ mutable AttributesMask mDirtyCurrentValues;
+ ActiveTextureMask mDirtyActiveTextures;
+ ActiveTextureMask mDirtyTextures;
+ ActiveTextureMask mDirtySamplers;
+ ImageUnitMask mDirtyImages;
+
+ // The Overlay object, used by the backend to render the overlay.
+ const OverlayType *mOverlay;
+
+ // OES_draw_buffers_indexed
+ DrawBufferMask mBlendFuncConstantAlphaDrawBuffers;
+ DrawBufferMask mBlendFuncConstantColorDrawBuffers;
+ bool mNoSimultaneousConstantColorAndAlphaBlendFunc;
+ // Whether the indexed variants of setBlend* have been called. If so, the call to the
+ // non-indexed variants are not no-oped.
+ bool mSetBlendIndexedInvoked;
+ bool mSetBlendFactorsIndexedInvoked;
+ bool mSetBlendEquationsIndexedInvoked;
+ bool mDisplayTextureShareGroup;
+
+ // GL_EXT_primitive_bounding_box
+ GLfloat mBoundingBoxMinX;
+ GLfloat mBoundingBoxMinY;
+ GLfloat mBoundingBoxMinZ;
+ GLfloat mBoundingBoxMinW;
+ GLfloat mBoundingBoxMaxX;
+ GLfloat mBoundingBoxMaxY;
+ GLfloat mBoundingBoxMaxZ;
+ GLfloat mBoundingBoxMaxW;
+
+ // QCOM_shading_rate
+ bool mShadingRatePreserveAspectRatio;
+ ShadingRate mShadingRate;
+};
+
+ANGLE_INLINE angle::Result State::syncDirtyObjects(const Context *context,
+ const DirtyObjects &bitset,
+ Command command)
+{
+ const DirtyObjects &dirtyObjects = mDirtyObjects & bitset;
+
+ for (size_t dirtyObject : dirtyObjects)
+ {
+ ANGLE_TRY((this->*kDirtyObjectHandlers[dirtyObject])(context, command));
+ }
+
+ mDirtyObjects &= ~dirtyObjects;
+ return angle::Result::Continue;
+}
+
+} // namespace gl
+
+#endif // LIBANGLE_STATE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Stream.cpp b/gfx/angle/checkout/src/libANGLE/Stream.cpp
new file mode 100644
index 0000000000..8d2830287f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Stream.cpp
@@ -0,0 +1,282 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Stream.cpp: Implements the egl::Stream class, representing the stream
+// where frames are streamed in. Implements EGLStreanKHR.
+
+#include "libANGLE/Stream.h"
+
+#include <EGL/eglext.h>
+#include <platform/PlatformMethods.h>
+
+#include "common/debug.h"
+#include "common/mathutil.h"
+#include "common/platform.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/renderer/DisplayImpl.h"
+#include "libANGLE/renderer/StreamProducerImpl.h"
+
+namespace egl
+{
+
+Stream::Stream(Display *display, const AttributeMap &attribs)
+ : mLabel(nullptr),
+ mDisplay(display),
+ mProducerImplementation(nullptr),
+ mState(EGL_STREAM_STATE_CREATED_KHR),
+ mProducerFrame(0),
+ mConsumerFrame(0),
+ mConsumerLatency(attribs.getAsInt(EGL_CONSUMER_LATENCY_USEC_KHR, 0)),
+ mConsumerAcquireTimeout(attribs.getAsInt(EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR, 0)),
+ mPlaneCount(0),
+ mConsumerType(ConsumerType::NoConsumer),
+ mProducerType(ProducerType::NoProducer)
+{
+ for (auto &plane : mPlanes)
+ {
+ plane.textureUnit = -1;
+ plane.texture = nullptr;
+ }
+}
+
+Stream::~Stream()
+{
+ SafeDelete(mProducerImplementation);
+ for (auto &plane : mPlanes)
+ {
+ if (plane.texture != nullptr)
+ {
+ plane.texture->releaseStream();
+ }
+ }
+}
+
+void Stream::setLabel(EGLLabelKHR label)
+{
+ mLabel = label;
+}
+
+EGLLabelKHR Stream::getLabel() const
+{
+ return mLabel;
+}
+
+void Stream::setConsumerLatency(EGLint latency)
+{
+ mConsumerLatency = latency;
+}
+
+EGLint Stream::getConsumerLatency() const
+{
+ return mConsumerLatency;
+}
+
+EGLuint64KHR Stream::getProducerFrame() const
+{
+ return mProducerFrame;
+}
+
+EGLuint64KHR Stream::getConsumerFrame() const
+{
+ return mConsumerFrame;
+}
+
+EGLenum Stream::getState() const
+{
+ return mState;
+}
+
+void Stream::setConsumerAcquireTimeout(EGLint timeout)
+{
+ mConsumerAcquireTimeout = timeout;
+}
+
+EGLint Stream::getConsumerAcquireTimeout() const
+{
+ return mConsumerAcquireTimeout;
+}
+
+Stream::ProducerType Stream::getProducerType() const
+{
+ return mProducerType;
+}
+
+Stream::ConsumerType Stream::getConsumerType() const
+{
+ return mConsumerType;
+}
+
+EGLint Stream::getPlaneCount() const
+{
+ return mPlaneCount;
+}
+
+rx::StreamProducerImpl *Stream::getImplementation()
+{
+ return mProducerImplementation;
+}
+
+Error Stream::createConsumerGLTextureExternal(const AttributeMap &attributes, gl::Context *context)
+{
+ ASSERT(mState == EGL_STREAM_STATE_CREATED_KHR);
+ ASSERT(mConsumerType == ConsumerType::NoConsumer);
+ ASSERT(mProducerType == ProducerType::NoProducer);
+ ASSERT(context != nullptr);
+
+ const auto &glState = context->getState();
+ EGLenum bufferType = attributes.getAsInt(EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
+ if (bufferType == EGL_RGB_BUFFER)
+ {
+ mPlanes[0].texture = glState.getTargetTexture(gl::TextureType::External);
+ ASSERT(mPlanes[0].texture != nullptr);
+ mPlanes[0].texture->bindStream(this);
+ mConsumerType = ConsumerType::GLTextureRGB;
+ mPlaneCount = 1;
+ }
+ else
+ {
+ mPlaneCount = attributes.getAsInt(EGL_YUV_NUMBER_OF_PLANES_EXT, 2);
+ ASSERT(mPlaneCount <= 3);
+ for (EGLint i = 0; i < mPlaneCount; i++)
+ {
+ // Fetch all the textures
+ mPlanes[i].textureUnit = attributes.getAsInt(EGL_YUV_PLANE0_TEXTURE_UNIT_NV + i, -1);
+ if (mPlanes[i].textureUnit != EGL_NONE)
+ {
+ mPlanes[i].texture =
+ glState.getSamplerTexture(mPlanes[i].textureUnit, gl::TextureType::External);
+ ASSERT(mPlanes[i].texture != nullptr);
+ }
+ }
+
+ // Bind them to the stream
+ for (EGLint i = 0; i < mPlaneCount; i++)
+ {
+ if (mPlanes[i].textureUnit != EGL_NONE)
+ {
+ mPlanes[i].texture->bindStream(this);
+ }
+ }
+ mConsumerType = ConsumerType::GLTextureYUV;
+ }
+
+ mContext = context;
+ mState = EGL_STREAM_STATE_CONNECTING_KHR;
+
+ return NoError();
+}
+
+Error Stream::createProducerD3D11Texture(const AttributeMap &attributes)
+{
+ ASSERT(mState == EGL_STREAM_STATE_CONNECTING_KHR);
+ ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
+ mConsumerType == ConsumerType::GLTextureYUV);
+ ASSERT(mProducerType == ProducerType::NoProducer);
+
+ mProducerImplementation =
+ mDisplay->getImplementation()->createStreamProducerD3DTexture(mConsumerType, attributes);
+ mProducerType = ProducerType::D3D11Texture;
+ mState = EGL_STREAM_STATE_EMPTY_KHR;
+
+ return NoError();
+}
+
+// Called when the consumer of this stream starts using the stream
+Error Stream::consumerAcquire(const gl::Context *context)
+{
+ ASSERT(mState == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR ||
+ mState == EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR);
+ ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
+ mConsumerType == ConsumerType::GLTextureYUV);
+ ASSERT(mProducerType == ProducerType::D3D11Texture);
+
+ mState = EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR;
+ mConsumerFrame++;
+
+ // Bind the planes to the gl textures
+ for (int i = 0; i < mPlaneCount; i++)
+ {
+ if (mPlanes[i].texture != nullptr)
+ {
+ ANGLE_TRY(ResultToEGL(mPlanes[i].texture->acquireImageFromStream(
+ context, mProducerImplementation->getGLFrameDescription(i))));
+ }
+ }
+
+ return NoError();
+}
+
+Error Stream::consumerRelease(const gl::Context *context)
+{
+ ASSERT(mState == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR ||
+ mState == EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR);
+ ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
+ mConsumerType == ConsumerType::GLTextureYUV);
+ ASSERT(mProducerType == ProducerType::D3D11Texture);
+
+ // Release the images
+ for (int i = 0; i < mPlaneCount; i++)
+ {
+ if (mPlanes[i].texture != nullptr)
+ {
+ ANGLE_TRY(ResultToEGL(mPlanes[i].texture->releaseImageFromStream(context)));
+ }
+ }
+
+ return NoError();
+}
+
+bool Stream::isConsumerBoundToContext(const gl::Context *context) const
+{
+ ASSERT(context != nullptr);
+ return (context == mContext);
+}
+
+Error Stream::validateD3D11Texture(const void *texture, const AttributeMap &attributes) const
+{
+ ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
+ mConsumerType == ConsumerType::GLTextureYUV);
+ ASSERT(mProducerType == ProducerType::D3D11Texture);
+ ASSERT(mProducerImplementation != nullptr);
+
+ return mProducerImplementation->validateD3DTexture(texture, attributes);
+}
+
+Error Stream::postD3D11Texture(void *texture, const AttributeMap &attributes)
+{
+ ASSERT(mConsumerType == ConsumerType::GLTextureRGB ||
+ mConsumerType == ConsumerType::GLTextureYUV);
+ ASSERT(mProducerType == ProducerType::D3D11Texture);
+
+ mProducerImplementation->postD3DTexture(texture, attributes);
+ mProducerFrame++;
+
+ mState = EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR;
+
+ return NoError();
+}
+
+// This is called when a texture object associated with this stream is destroyed. Even if multiple
+// textures are bound, one being destroyed invalidates the stream, so all the remaining textures
+// will be released and the stream will be invalidated.
+void Stream::releaseTextures()
+{
+ for (auto &plane : mPlanes)
+ {
+ if (plane.texture != nullptr)
+ {
+ plane.texture->releaseStream();
+ plane.texture = nullptr;
+ }
+ }
+ mConsumerType = ConsumerType::NoConsumer;
+ mProducerType = ProducerType::NoProducer;
+ mState = EGL_STREAM_STATE_DISCONNECTED_KHR;
+}
+
+} // namespace egl
diff --git a/gfx/angle/checkout/src/libANGLE/Stream.h b/gfx/angle/checkout/src/libANGLE/Stream.h
new file mode 100644
index 0000000000..b53c90b764
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Stream.h
@@ -0,0 +1,149 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Stream.h: Defines the egl::Stream class, representing the stream
+// where frames are streamed in. Implements EGLStreanKHR.
+
+#ifndef LIBANGLE_STREAM_H_
+#define LIBANGLE_STREAM_H_
+
+#include <array>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "common/angleutils.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Debug.h"
+
+namespace rx
+{
+class StreamProducerImpl;
+}
+
+namespace gl
+{
+class Context;
+class Texture;
+} // namespace gl
+
+namespace egl
+{
+class Display;
+class Error;
+class Thread;
+
+class Stream final : public LabeledObject, angle::NonCopyable
+{
+ public:
+ Stream(Display *display, const AttributeMap &attribs);
+ ~Stream() override;
+
+ void setLabel(EGLLabelKHR label) override;
+ EGLLabelKHR getLabel() const override;
+
+ enum class ConsumerType
+ {
+ NoConsumer,
+ GLTextureRGB,
+ GLTextureYUV,
+ };
+
+ enum class ProducerType
+ {
+ NoProducer,
+ D3D11Texture,
+ };
+
+ // A GL texture interpretation of a part of a producer frame. For use with GL texture consumers
+ struct GLTextureDescription
+ {
+ unsigned int width;
+ unsigned int height;
+ unsigned int internalFormat;
+ unsigned int mipLevels;
+ };
+
+ EGLenum getState() const;
+
+ void setConsumerLatency(EGLint latency);
+ EGLint getConsumerLatency() const;
+
+ EGLuint64KHR getProducerFrame() const;
+ EGLuint64KHR getConsumerFrame() const;
+
+ void setConsumerAcquireTimeout(EGLint timeout);
+ EGLint getConsumerAcquireTimeout() const;
+
+ ConsumerType getConsumerType() const;
+ ProducerType getProducerType() const;
+
+ EGLint getPlaneCount() const;
+
+ rx::StreamProducerImpl *getImplementation();
+
+ // Consumer creation methods
+ Error createConsumerGLTextureExternal(const AttributeMap &attributes, gl::Context *context);
+
+ // Producer creation methods
+ Error createProducerD3D11Texture(const AttributeMap &attributes);
+
+ // Consumer methods
+ Error consumerAcquire(const gl::Context *context);
+ Error consumerRelease(const gl::Context *context);
+
+ // Some consumers are bound to GL contexts. This validates that a given context is bound to the
+ // stream's consumer
+ bool isConsumerBoundToContext(const gl::Context *context) const;
+
+ // Producer methods
+ Error validateD3D11Texture(const void *texture, const AttributeMap &attributes) const;
+ Error postD3D11Texture(void *texture, const AttributeMap &attributes);
+
+ private:
+ EGLLabelKHR mLabel;
+
+ // Associated display
+ Display *mDisplay;
+
+ // Producer Implementation
+ rx::StreamProducerImpl *mProducerImplementation;
+
+ // Associated GL context. Note that this is a weak pointer used for validation purposes only,
+ // and should never be arbitrarily dereferenced without knowing the context still exists as it
+ // can become dangling at any time.
+ gl::Context *mContext;
+
+ // EGL defined attributes
+ EGLint mState;
+ EGLuint64KHR mProducerFrame;
+ EGLuint64KHR mConsumerFrame;
+ EGLint mConsumerLatency;
+
+ // EGL gltexture consumer attributes
+ EGLint mConsumerAcquireTimeout;
+
+ // EGL gltexture yuv consumer attributes
+ EGLint mPlaneCount;
+ struct PlaneTexture
+ {
+ EGLint textureUnit;
+ gl::Texture *texture;
+ };
+ // Texture units and textures for all the planes
+ std::array<PlaneTexture, 3> mPlanes;
+
+ // Consumer and producer types
+ ConsumerType mConsumerType;
+ ProducerType mProducerType;
+
+ // ANGLE-only method, used internally
+ friend class gl::Texture;
+ void releaseTextures();
+};
+} // namespace egl
+
+#endif // LIBANGLE_STREAM_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Surface.cpp b/gfx/angle/checkout/src/libANGLE/Surface.cpp
new file mode 100644
index 0000000000..acb382dd10
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Surface.cpp
@@ -0,0 +1,941 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Surface.cpp: Implements the egl::Surface class, representing a drawing surface
+// such as the client area of a window, including any back buffers.
+// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
+
+#include "libANGLE/Surface.h"
+
+#include <EGL/eglext.h>
+
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
+#include "libANGLE/trace.h"
+
+namespace egl
+{
+namespace
+{
+angle::SubjectIndex kSurfaceImplSubjectIndex = 0;
+} // namespace
+
+SurfaceState::SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn)
+ : label(nullptr),
+ config((configIn != nullptr) ? new egl::Config(*configIn) : nullptr),
+ attributes(attributesIn),
+ timestampsEnabled(false),
+ autoRefreshEnabled(false),
+ directComposition(false),
+ swapBehavior(EGL_NONE)
+{
+ directComposition = attributes.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE;
+}
+
+SurfaceState::~SurfaceState()
+{
+ delete config;
+}
+
+bool SurfaceState::isRobustResourceInitEnabled() const
+{
+ return attributes.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE;
+}
+
+bool SurfaceState::hasProtectedContent() const
+{
+ return attributes.get(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) == EGL_TRUE;
+}
+
+EGLint SurfaceState::getPreferredSwapInterval() const
+{
+ return attributes.getAsInt(EGL_SWAP_INTERVAL_ANGLE, 1);
+}
+
+Surface::Surface(EGLint surfaceType,
+ GLuint serialId,
+ const egl::Config *config,
+ const AttributeMap &attributes,
+ bool forceRobustResourceInit,
+ EGLenum buftype)
+ : FramebufferAttachmentObject(),
+ mState(config, attributes),
+ mImplementation(nullptr),
+ mRefCount(0),
+ mDestroyed(false),
+ mType(surfaceType),
+ mBuftype(buftype),
+ mPostSubBufferRequested(false),
+ mLargestPbuffer(false),
+ mGLColorspace(EGL_GL_COLORSPACE_LINEAR),
+ mVGAlphaFormat(EGL_VG_ALPHA_FORMAT_NONPRE),
+ mVGColorspace(EGL_VG_COLORSPACE_sRGB),
+ mMipmapTexture(false),
+ mMipmapLevel(0),
+ mHorizontalResolution(EGL_UNKNOWN),
+ mVerticalResolution(EGL_UNKNOWN),
+ mMultisampleResolve(EGL_MULTISAMPLE_RESOLVE_DEFAULT),
+ mFixedSize(false),
+ mFixedWidth(0),
+ mFixedHeight(0),
+ mTextureFormat(TextureFormat::NoTexture),
+ mTextureTarget(EGL_NO_TEXTURE),
+ // FIXME: Determine actual pixel aspect ratio
+ mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
+ mRenderBuffer(EGL_BACK_BUFFER),
+ mOrientation(0),
+ mTexture(nullptr),
+ mColorFormat(config->renderTargetFormat),
+ mDSFormat(config->depthStencilFormat),
+ mIsCurrentOnAnyContext(false),
+ mLockBufferPtr(nullptr),
+ mLockBufferPitch(0),
+ mBufferAgeQueriedSinceLastSwap(false),
+ mIsDamageRegionSet(false),
+ mColorInitState(gl::InitState::Initialized),
+ mDepthStencilInitState(gl::InitState::Initialized),
+ mImplObserverBinding(this, kSurfaceImplSubjectIndex),
+ mSerialId(serialId)
+{
+ mPostSubBufferRequested =
+ (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE);
+
+ if (mType == EGL_PBUFFER_BIT)
+ {
+ mLargestPbuffer = (attributes.get(EGL_LARGEST_PBUFFER, EGL_FALSE) == EGL_TRUE);
+ }
+
+ if (mType == EGL_PIXMAP_BIT)
+ {
+ mRenderBuffer = EGL_SINGLE_BUFFER;
+ }
+
+ if (mType == EGL_WINDOW_BIT)
+ {
+ mRenderBuffer = mState.attributes.getAsInt(EGL_RENDER_BUFFER, EGL_BACK_BUFFER);
+ }
+
+ mGLColorspace =
+ static_cast<EGLenum>(attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR));
+ mVGAlphaFormat =
+ static_cast<EGLenum>(attributes.get(EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_NONPRE));
+ mVGColorspace = static_cast<EGLenum>(attributes.get(EGL_VG_COLORSPACE, EGL_VG_COLORSPACE_sRGB));
+ mMipmapTexture = (attributes.get(EGL_MIPMAP_TEXTURE, EGL_FALSE) == EGL_TRUE);
+
+ mRobustResourceInitialization =
+ forceRobustResourceInit ||
+ (attributes.get(EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE, EGL_FALSE) == EGL_TRUE);
+ if (mRobustResourceInitialization)
+ {
+ mColorInitState = gl::InitState::MayNeedInit;
+ mDepthStencilInitState = gl::InitState::MayNeedInit;
+ }
+
+ mFixedSize = (attributes.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE);
+ if (mFixedSize)
+ {
+ mFixedWidth = static_cast<size_t>(attributes.get(EGL_WIDTH, 0));
+ mFixedHeight = static_cast<size_t>(attributes.get(EGL_HEIGHT, 0));
+ }
+
+ if (mType != EGL_WINDOW_BIT)
+ {
+ mTextureFormat = attributes.getAsPackedEnum(EGL_TEXTURE_FORMAT, TextureFormat::NoTexture);
+ mTextureTarget = static_cast<EGLenum>(attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE));
+ }
+
+ mOrientation = static_cast<EGLint>(attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
+
+ mTextureOffset.x = static_cast<int>(mState.attributes.get(EGL_TEXTURE_OFFSET_X_ANGLE, 0));
+ mTextureOffset.y = static_cast<int>(mState.attributes.get(EGL_TEXTURE_OFFSET_Y_ANGLE, 0));
+}
+
+Surface::~Surface() {}
+
+rx::FramebufferAttachmentObjectImpl *Surface::getAttachmentImpl() const
+{
+ return mImplementation;
+}
+
+Error Surface::destroyImpl(const Display *display)
+{
+ if (mImplementation)
+ {
+ mImplementation->destroy(display);
+ }
+
+ ASSERT(!mTexture);
+
+ SafeDelete(mImplementation);
+
+ delete this;
+ return NoError();
+}
+
+void Surface::postSwap(const gl::Context *context)
+{
+ if (mRobustResourceInitialization && mState.swapBehavior != EGL_BUFFER_PRESERVED)
+ {
+ mColorInitState = gl::InitState::MayNeedInit;
+ mDepthStencilInitState = gl::InitState::MayNeedInit;
+ onStateChange(angle::SubjectMessage::SubjectChanged);
+ }
+
+ mBufferAgeQueriedSinceLastSwap = false;
+
+ mIsDamageRegionSet = false;
+}
+
+Error Surface::initialize(const Display *display)
+{
+ GLenum overrideRenderTargetFormat = mState.config->renderTargetFormat;
+
+ // To account for color space differences, override the renderTargetFormat with the
+ // non-linear format. If no suitable non-linear format was found, return
+ // EGL_BAD_MATCH error
+ if (!gl::ColorspaceFormatOverride(mGLColorspace, &overrideRenderTargetFormat))
+ {
+ return egl::EglBadMatch();
+ }
+
+ // If an override is required update mState.config as well
+ if (mState.config->renderTargetFormat != overrideRenderTargetFormat)
+ {
+ egl::Config *overrideConfig = new egl::Config(*(mState.config));
+ overrideConfig->renderTargetFormat = overrideRenderTargetFormat;
+ delete mState.config;
+ mState.config = overrideConfig;
+
+ mColorFormat = gl::Format(mState.config->renderTargetFormat);
+ mDSFormat = gl::Format(mState.config->depthStencilFormat);
+ }
+
+ ANGLE_TRY(mImplementation->initialize(display));
+
+ // Initialized here since impl is nullptr in the constructor.
+ // Must happen after implementation initialize for Android.
+ mState.swapBehavior = mImplementation->getSwapBehavior();
+
+ if (mBuftype == EGL_IOSURFACE_ANGLE)
+ {
+ GLenum internalFormat =
+ static_cast<GLenum>(mState.attributes.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE));
+ GLenum type = static_cast<GLenum>(mState.attributes.get(EGL_TEXTURE_TYPE_ANGLE));
+
+ // GL_RGBA + GL_HALF_FLOAT is not a valid format/type combination in GLES like it is in
+ // desktop GL. Adjust the frontend format to be sized RGBA16F.
+ if (internalFormat == GL_RGBA && type == GL_HALF_FLOAT)
+ {
+ internalFormat = GL_RGBA16F;
+ }
+ mColorFormat = gl::Format(internalFormat, type);
+ }
+ if (mBuftype == EGL_D3D_TEXTURE_ANGLE)
+ {
+ const angle::Format *colorFormat = mImplementation->getD3DTextureColorFormat();
+ ASSERT(colorFormat != nullptr);
+ GLenum internalFormat = colorFormat->fboImplementationInternalFormat;
+ mColorFormat = gl::Format(internalFormat, colorFormat->componentType);
+ mGLColorspace = EGL_GL_COLORSPACE_LINEAR;
+ if (mColorFormat.info->colorEncoding == GL_SRGB)
+ {
+ mGLColorspace = EGL_GL_COLORSPACE_SRGB;
+ }
+ }
+
+ if (mType == EGL_WINDOW_BIT && display->getExtensions().getFrameTimestamps)
+ {
+ mState.supportedCompositorTimings = mImplementation->getSupportedCompositorTimings();
+ mState.supportedTimestamps = mImplementation->getSupportedTimestamps();
+ }
+
+ mImplObserverBinding.bind(mImplementation);
+
+ return NoError();
+}
+
+Error Surface::makeCurrent(const gl::Context *context)
+{
+ if (isLocked())
+ {
+ return EglBadAccess();
+ }
+ ANGLE_TRY(mImplementation->makeCurrent(context));
+ mIsCurrentOnAnyContext = true;
+ addRef();
+ return NoError();
+}
+
+Error Surface::unMakeCurrent(const gl::Context *context)
+{
+ ANGLE_TRY(mImplementation->unMakeCurrent(context));
+ mIsCurrentOnAnyContext = false;
+ return releaseRef(context->getDisplay());
+}
+
+Error Surface::releaseRef(const Display *display)
+{
+ ASSERT(mRefCount > 0);
+ mRefCount--;
+ if (mRefCount == 0 && mDestroyed)
+ {
+ ASSERT(display);
+ return destroyImpl(display);
+ }
+
+ return NoError();
+}
+
+Error Surface::onDestroy(const Display *display)
+{
+ mDestroyed = true;
+ if (mRefCount == 0)
+ {
+ return destroyImpl(display);
+ }
+ return NoError();
+}
+
+void Surface::setLabel(EGLLabelKHR label)
+{
+ mState.label = label;
+}
+
+EGLLabelKHR Surface::getLabel() const
+{
+ return mState.label;
+}
+
+EGLint Surface::getType() const
+{
+ return mType;
+}
+
+Error Surface::prepareSwap(const gl::Context *context)
+{
+ ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::prepareSwap");
+ return mImplementation->prepareSwap(context);
+}
+
+Error Surface::swap(const gl::Context *context)
+{
+ ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::swap");
+ context->onPreSwap();
+
+ context->getState().getOverlay()->onSwap();
+
+ ANGLE_TRY(mImplementation->swap(context));
+ postSwap(context);
+ return NoError();
+}
+
+Error Surface::swapWithDamage(const gl::Context *context, const EGLint *rects, EGLint n_rects)
+{
+ ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::swapWithDamage");
+ context->onPreSwap();
+
+ context->getState().getOverlay()->onSwap();
+
+ ANGLE_TRY(mImplementation->swapWithDamage(context, rects, n_rects));
+ postSwap(context);
+ return NoError();
+}
+
+Error Surface::swapWithFrameToken(const gl::Context *context, EGLFrameTokenANGLE frameToken)
+{
+ ANGLE_TRACE_EVENT0("gpu.angle", "egl::Surface::swapWithFrameToken");
+ context->onPreSwap();
+
+ context->getState().getOverlay()->onSwap();
+
+ ANGLE_TRY(mImplementation->swapWithFrameToken(context, frameToken));
+ postSwap(context);
+ return NoError();
+}
+
+Error Surface::postSubBuffer(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height)
+{
+ if (width == 0 || height == 0)
+ {
+ return egl::NoError();
+ }
+
+ context->getState().getOverlay()->onSwap();
+
+ ANGLE_TRY(mImplementation->postSubBuffer(context, x, y, width, height));
+ postSwap(context);
+ return NoError();
+}
+
+Error Surface::setPresentationTime(EGLnsecsANDROID time)
+{
+ return mImplementation->setPresentationTime(time);
+}
+
+Error Surface::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ return mImplementation->querySurfacePointerANGLE(attribute, value);
+}
+
+EGLint Surface::isPostSubBufferSupported() const
+{
+ return mPostSubBufferRequested && mImplementation->isPostSubBufferSupported();
+}
+
+void Surface::setSwapInterval(EGLint interval)
+{
+ mImplementation->setSwapInterval(interval);
+}
+
+void Surface::setMipmapLevel(EGLint level)
+{
+ // Level is set but ignored
+ UNIMPLEMENTED();
+ mMipmapLevel = level;
+}
+
+void Surface::setMultisampleResolve(EGLenum resolve)
+{
+ // Behaviour is set but ignored
+ UNIMPLEMENTED();
+ mMultisampleResolve = resolve;
+}
+
+void Surface::setSwapBehavior(EGLenum behavior)
+{
+ // Behaviour is set but ignored
+ UNIMPLEMENTED();
+ mState.swapBehavior = behavior;
+}
+
+void Surface::setFixedWidth(EGLint width)
+{
+ mFixedWidth = width;
+ mImplementation->setFixedWidth(width);
+}
+
+void Surface::setFixedHeight(EGLint height)
+{
+ mFixedHeight = height;
+ mImplementation->setFixedHeight(height);
+}
+
+const Config *Surface::getConfig() const
+{
+ return mState.config;
+}
+
+EGLint Surface::getPixelAspectRatio() const
+{
+ return mPixelAspectRatio;
+}
+
+EGLenum Surface::getRenderBuffer() const
+{
+ return mRenderBuffer;
+}
+
+EGLenum Surface::getSwapBehavior() const
+{
+ return mState.swapBehavior;
+}
+
+TextureFormat Surface::getTextureFormat() const
+{
+ return mTextureFormat;
+}
+
+EGLenum Surface::getTextureTarget() const
+{
+ return mTextureTarget;
+}
+
+bool Surface::getLargestPbuffer() const
+{
+ return mLargestPbuffer;
+}
+
+EGLenum Surface::getGLColorspace() const
+{
+ return mGLColorspace;
+}
+
+EGLenum Surface::getVGAlphaFormat() const
+{
+ return mVGAlphaFormat;
+}
+
+EGLenum Surface::getVGColorspace() const
+{
+ return mVGColorspace;
+}
+
+bool Surface::getMipmapTexture() const
+{
+ return mMipmapTexture;
+}
+
+EGLint Surface::getMipmapLevel() const
+{
+ return mMipmapLevel;
+}
+
+EGLint Surface::getHorizontalResolution() const
+{
+ return mHorizontalResolution;
+}
+
+EGLint Surface::getVerticalResolution() const
+{
+ return mVerticalResolution;
+}
+
+EGLenum Surface::getMultisampleResolve() const
+{
+ return mMultisampleResolve;
+}
+
+EGLint Surface::isFixedSize() const
+{
+ return mFixedSize;
+}
+
+EGLint Surface::getWidth() const
+{
+ return mFixedSize ? static_cast<EGLint>(mFixedWidth) : mImplementation->getWidth();
+}
+
+EGLint Surface::getHeight() const
+{
+ return mFixedSize ? static_cast<EGLint>(mFixedHeight) : mImplementation->getHeight();
+}
+
+egl::Error Surface::getUserWidth(const egl::Display *display, EGLint *value) const
+{
+ if (mFixedSize)
+ {
+ *value = static_cast<EGLint>(mFixedWidth);
+ return NoError();
+ }
+ else
+ {
+ return mImplementation->getUserWidth(display, value);
+ }
+}
+
+egl::Error Surface::getUserHeight(const egl::Display *display, EGLint *value) const
+{
+ if (mFixedSize)
+ {
+ *value = static_cast<EGLint>(mFixedHeight);
+ return NoError();
+ }
+ else
+ {
+ return mImplementation->getUserHeight(display, value);
+ }
+}
+
+Error Surface::bindTexImage(gl::Context *context, gl::Texture *texture, EGLint buffer)
+{
+ ASSERT(!mTexture);
+ ANGLE_TRY(mImplementation->bindTexImage(context, texture, buffer));
+
+ if (texture->bindTexImageFromSurface(context, this) == angle::Result::Stop)
+ {
+ return Error(EGL_BAD_SURFACE);
+ }
+ mTexture = texture;
+ addRef();
+
+ return NoError();
+}
+
+Error Surface::releaseTexImage(const gl::Context *context, EGLint buffer)
+{
+ ASSERT(context);
+
+ ANGLE_TRY(mImplementation->releaseTexImage(context, buffer));
+
+ ASSERT(mTexture);
+ ANGLE_TRY(ResultToEGL(mTexture->releaseTexImageFromSurface(context)));
+
+ return releaseTexImageFromTexture(context);
+}
+
+Error Surface::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
+{
+ return mImplementation->getSyncValues(ust, msc, sbc);
+}
+
+Error Surface::getMscRate(EGLint *numerator, EGLint *denominator)
+{
+ return mImplementation->getMscRate(numerator, denominator);
+}
+
+Error Surface::releaseTexImageFromTexture(const gl::Context *context)
+{
+ ASSERT(mTexture);
+ mTexture = nullptr;
+ return releaseRef(context->getDisplay());
+}
+
+gl::Extents Surface::getAttachmentSize(const gl::ImageIndex & /*target*/) const
+{
+ return gl::Extents(getWidth(), getHeight(), 1);
+}
+
+gl::Format Surface::getAttachmentFormat(GLenum binding, const gl::ImageIndex &target) const
+{
+ return (binding == GL_BACK ? mColorFormat : mDSFormat);
+}
+
+GLsizei Surface::getAttachmentSamples(const gl::ImageIndex &target) const
+{
+ return getConfig()->samples;
+}
+
+bool Surface::isRenderable(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex) const
+{
+ return true;
+}
+
+bool Surface::isYUV() const
+{
+ // EGL_EXT_yuv_surface is not implemented.
+ return false;
+}
+
+bool Surface::isCreatedWithAHB() const
+{
+ return false;
+}
+
+GLuint Surface::getId() const
+{
+ return mSerialId;
+}
+
+Error Surface::getBufferAgeImpl(const gl::Context *context, EGLint *age) const
+{
+ // When EGL_BUFFER_PRESERVED, the previous frame contents are copied to
+ // current frame, so the buffer age is always 1.
+ if (mState.swapBehavior == EGL_BUFFER_PRESERVED)
+ {
+ if (age != nullptr)
+ {
+ *age = 1;
+ }
+ return egl::NoError();
+ }
+ return mImplementation->getBufferAge(context, age);
+}
+
+Error Surface::getBufferAge(const gl::Context *context, EGLint *age)
+{
+ Error err = getBufferAgeImpl(context, age);
+ if (!err.isError())
+ {
+ mBufferAgeQueriedSinceLastSwap = true;
+ }
+ return err;
+}
+
+gl::InitState Surface::initState(GLenum binding, const gl::ImageIndex & /*imageIndex*/) const
+{
+ switch (binding)
+ {
+ case GL_BACK:
+ return mColorInitState;
+ case GL_DEPTH:
+ case GL_STENCIL:
+ return mDepthStencilInitState;
+ default:
+ UNREACHABLE();
+ return gl::InitState::Initialized;
+ }
+}
+
+void Surface::setInitState(GLenum binding,
+ const gl::ImageIndex & /*imageIndex*/,
+ gl::InitState initState)
+{
+ switch (binding)
+ {
+ case GL_BACK:
+ mColorInitState = initState;
+ break;
+ case GL_DEPTH:
+ case GL_STENCIL:
+ mDepthStencilInitState = initState;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void Surface::setTimestampsEnabled(bool enabled)
+{
+ mImplementation->setTimestampsEnabled(enabled);
+ mState.timestampsEnabled = enabled;
+}
+
+bool Surface::isTimestampsEnabled() const
+{
+ return mState.timestampsEnabled;
+}
+
+Error Surface::setAutoRefreshEnabled(bool enabled)
+{
+ ANGLE_TRY(mImplementation->setAutoRefreshEnabled(enabled));
+ mState.autoRefreshEnabled = enabled;
+ return NoError();
+}
+
+bool Surface::hasProtectedContent() const
+{
+ return mState.hasProtectedContent();
+}
+
+const SupportedCompositorTiming &Surface::getSupportedCompositorTimings() const
+{
+ return mState.supportedCompositorTimings;
+}
+
+Error Surface::getCompositorTiming(EGLint numTimestamps,
+ const EGLint *names,
+ EGLnsecsANDROID *values) const
+{
+ return mImplementation->getCompositorTiming(numTimestamps, names, values);
+}
+
+Error Surface::getNextFrameId(EGLuint64KHR *frameId) const
+{
+ return mImplementation->getNextFrameId(frameId);
+}
+
+const SupportedTimestamps &Surface::getSupportedTimestamps() const
+{
+ return mState.supportedTimestamps;
+}
+
+Error Surface::getFrameTimestamps(EGLuint64KHR frameId,
+ EGLint numTimestamps,
+ const EGLint *timestamps,
+ EGLnsecsANDROID *values) const
+{
+ return mImplementation->getFrameTimestamps(frameId, numTimestamps, timestamps, values);
+}
+
+void Surface::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
+{
+ ASSERT(index == kSurfaceImplSubjectIndex);
+ switch (message)
+ {
+ case angle::SubjectMessage::SubjectChanged:
+ onStateChange(angle::SubjectMessage::ContentsChanged);
+ break;
+ case angle::SubjectMessage::SurfaceChanged:
+ onStateChange(angle::SubjectMessage::SurfaceChanged);
+ break;
+ case angle::SubjectMessage::SwapchainImageChanged:
+ onStateChange(angle::SubjectMessage::SwapchainImageChanged);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+Error Surface::setRenderBuffer(EGLint renderBuffer)
+{
+ ANGLE_TRY(mImplementation->setRenderBuffer(renderBuffer));
+ mRenderBuffer = renderBuffer;
+ return NoError();
+}
+
+bool Surface::isLocked() const
+{
+ return (mLockBufferPtr != nullptr);
+}
+
+EGLint Surface::getBitmapPitch() const
+{
+ return mLockBufferPitch;
+}
+
+EGLint Surface::getBitmapOrigin() const
+{
+ return mImplementation->origin();
+}
+
+EGLint Surface::getRedOffset() const
+{
+ const gl::InternalFormat &format = *mColorFormat.info;
+ if (gl::IsBGRAFormat(format.internalFormat))
+ {
+ return format.blueBits + format.greenBits;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+EGLint Surface::getGreenOffset() const
+{
+ const gl::InternalFormat &format = *mColorFormat.info;
+ if (gl::IsBGRAFormat(format.internalFormat))
+ {
+ return format.blueBits;
+ }
+ else
+ {
+ return format.redBits;
+ }
+}
+
+EGLint Surface::getBlueOffset() const
+{
+ const gl::InternalFormat &format = *mColorFormat.info;
+ if (gl::IsBGRAFormat(format.internalFormat))
+ {
+ return 0;
+ }
+ else
+ {
+ return format.redBits + format.greenBits;
+ }
+}
+
+EGLint Surface::getAlphaOffset() const
+{
+ const gl::InternalFormat &format = *mColorFormat.info;
+ if (format.isLUMA())
+ {
+ return format.luminanceBits; // Luma always first, alpha optional
+ }
+ // For RGBA/BGRA alpha is last
+ return format.blueBits + format.greenBits + format.redBits;
+}
+
+EGLint Surface::getLuminanceOffset() const
+{
+ return 0;
+}
+
+EGLint Surface::getBitmapPixelSize() const
+{
+ constexpr EGLint kBitsPerByte = 8;
+ const gl::InternalFormat &format = *mColorFormat.info;
+ return (format.pixelBytes * kBitsPerByte);
+}
+
+EGLAttribKHR Surface::getBitmapPointer() const
+{
+ return static_cast<EGLAttribKHR>((intptr_t)mLockBufferPtr);
+}
+
+egl::Error Surface::lockSurfaceKHR(const egl::Display *display, const AttributeMap &attributes)
+{
+ EGLint lockBufferUsageHint = attributes.getAsInt(
+ EGL_LOCK_USAGE_HINT_KHR, (EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR));
+
+ bool preservePixels = ((attributes.getAsInt(EGL_MAP_PRESERVE_PIXELS_KHR, false) == EGL_TRUE) ||
+ (mState.swapBehavior == EGL_BUFFER_PRESERVED));
+
+ return mImplementation->lockSurface(display, lockBufferUsageHint, preservePixels,
+ &mLockBufferPtr, &mLockBufferPitch);
+}
+
+egl::Error Surface::unlockSurfaceKHR(const egl::Display *display)
+{
+ mLockBufferPtr = nullptr;
+ mLockBufferPitch = 0;
+ return mImplementation->unlockSurface(display, true);
+}
+
+WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
+ const egl::Config *config,
+ EGLNativeWindowType window,
+ const AttributeMap &attribs,
+ bool robustResourceInit)
+ : Surface(EGL_WINDOW_BIT, implFactory->getNextSurfaceID(), config, attribs, robustResourceInit)
+{
+ mImplementation = implFactory->createWindowSurface(mState, window, attribs);
+}
+
+void Surface::setDamageRegion(const EGLint *rects, EGLint n_rects)
+{
+ mIsDamageRegionSet = true;
+}
+
+WindowSurface::~WindowSurface() {}
+
+PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ const AttributeMap &attribs,
+ bool robustResourceInit)
+ : Surface(EGL_PBUFFER_BIT, implFactory->getNextSurfaceID(), config, attribs, robustResourceInit)
+{
+ mImplementation = implFactory->createPbufferSurface(mState, attribs);
+}
+
+PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs,
+ bool robustResourceInit)
+ : Surface(EGL_PBUFFER_BIT,
+ implFactory->getNextSurfaceID(),
+ config,
+ attribs,
+ robustResourceInit,
+ buftype)
+{
+ mImplementation =
+ implFactory->createPbufferFromClientBuffer(mState, buftype, clientBuffer, attribs);
+}
+
+PbufferSurface::~PbufferSurface() {}
+
+PixmapSurface::PixmapSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ NativePixmapType nativePixmap,
+ const AttributeMap &attribs,
+ bool robustResourceInit)
+ : Surface(EGL_PIXMAP_BIT, implFactory->getNextSurfaceID(), config, attribs, robustResourceInit)
+{
+ mImplementation = implFactory->createPixmapSurface(mState, nativePixmap, attribs);
+}
+
+PixmapSurface::~PixmapSurface() {}
+
+// SurfaceDeleter implementation.
+
+SurfaceDeleter::SurfaceDeleter(const Display *display) : mDisplay(display) {}
+
+SurfaceDeleter::~SurfaceDeleter() {}
+
+void SurfaceDeleter::operator()(Surface *surface)
+{
+ ANGLE_SWALLOW_ERR(surface->onDestroy(mDisplay));
+}
+
+} // namespace egl
diff --git a/gfx/angle/checkout/src/libANGLE/Surface.h b/gfx/angle/checkout/src/libANGLE/Surface.h
new file mode 100644
index 0000000000..862d2f57b2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Surface.h
@@ -0,0 +1,388 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Surface.h: Defines the egl::Surface class, representing a drawing surface
+// such as the client area of a window, including any back buffers.
+// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
+
+#ifndef LIBANGLE_SURFACE_H_
+#define LIBANGLE_SURFACE_H_
+
+#include <memory>
+
+#include <EGL/egl.h>
+
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/SurfaceImpl.h"
+
+namespace gl
+{
+class Context;
+class Framebuffer;
+class Texture;
+} // namespace gl
+
+namespace rx
+{
+class EGLImplFactory;
+}
+
+namespace egl
+{
+class Display;
+struct Config;
+
+using SupportedCompositorTiming = angle::PackedEnumBitSet<CompositorTiming>;
+using SupportedTimestamps = angle::PackedEnumBitSet<Timestamp>;
+
+struct SurfaceState final : private angle::NonCopyable
+{
+ SurfaceState(const egl::Config *configIn, const AttributeMap &attributesIn);
+ ~SurfaceState();
+
+ bool isRobustResourceInitEnabled() const;
+ bool hasProtectedContent() const;
+ EGLint getPreferredSwapInterval() const;
+
+ EGLLabelKHR label;
+ const egl::Config *config;
+ AttributeMap attributes;
+
+ bool timestampsEnabled;
+ bool autoRefreshEnabled;
+ SupportedCompositorTiming supportedCompositorTimings;
+ SupportedTimestamps supportedTimestamps;
+ bool directComposition;
+ EGLenum swapBehavior;
+};
+
+class Surface : public LabeledObject, public gl::FramebufferAttachmentObject
+{
+ public:
+ rx::SurfaceImpl *getImplementation() const { return mImplementation; }
+
+ void setLabel(EGLLabelKHR label) override;
+ EGLLabelKHR getLabel() const override;
+
+ EGLint getType() const;
+
+ Error initialize(const Display *display);
+ Error makeCurrent(const gl::Context *context);
+ Error unMakeCurrent(const gl::Context *context);
+ Error prepareSwap(const gl::Context *context);
+ Error swap(const gl::Context *context);
+ Error swapWithDamage(const gl::Context *context, const EGLint *rects, EGLint n_rects);
+ Error swapWithFrameToken(const gl::Context *context, EGLFrameTokenANGLE frameToken);
+ Error postSubBuffer(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height);
+ Error setPresentationTime(EGLnsecsANDROID time);
+ Error querySurfacePointerANGLE(EGLint attribute, void **value);
+ Error bindTexImage(gl::Context *context, gl::Texture *texture, EGLint buffer);
+ Error releaseTexImage(const gl::Context *context, EGLint buffer);
+
+ Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc);
+ Error getMscRate(EGLint *numerator, EGLint *denominator);
+
+ EGLint isPostSubBufferSupported() const;
+
+ void setSwapInterval(EGLint interval);
+ Error onDestroy(const Display *display);
+
+ void setMipmapLevel(EGLint level);
+ void setMultisampleResolve(EGLenum resolve);
+ void setSwapBehavior(EGLenum behavior);
+
+ void setFixedWidth(EGLint width);
+ void setFixedHeight(EGLint height);
+
+ const Config *getConfig() const;
+
+ // width and height can change with client window resizing
+ EGLint getWidth() const;
+ EGLint getHeight() const;
+ // Note: windows cannot be resized on Android. The approach requires
+ // calling vkGetPhysicalDeviceSurfaceCapabilitiesKHR. However, that is
+ // expensive; and there are troublesome timing issues for other parts of
+ // ANGLE (which cause test failures and crashes). Therefore, a
+ // special-Android-only path is created just for the querying of EGL_WIDTH
+ // and EGL_HEIGHT.
+ // https://issuetracker.google.com/issues/153329980
+ egl::Error getUserWidth(const egl::Display *display, EGLint *value) const;
+ egl::Error getUserHeight(const egl::Display *display, EGLint *value) const;
+ EGLint getPixelAspectRatio() const;
+ EGLenum getRenderBuffer() const;
+ EGLenum getSwapBehavior() const;
+ TextureFormat getTextureFormat() const;
+ EGLenum getTextureTarget() const;
+ bool getLargestPbuffer() const;
+ EGLenum getGLColorspace() const;
+ EGLenum getVGAlphaFormat() const;
+ EGLenum getVGColorspace() const;
+ bool getMipmapTexture() const;
+ EGLint getMipmapLevel() const;
+ EGLint getHorizontalResolution() const;
+ EGLint getVerticalResolution() const;
+ EGLenum getMultisampleResolve() const;
+ bool hasProtectedContent() const override;
+
+ // For lock surface buffer
+ EGLint getBitmapPitch() const;
+ EGLint getBitmapOrigin() const;
+ EGLint getRedOffset() const;
+ EGLint getGreenOffset() const;
+ EGLint getBlueOffset() const;
+ EGLint getAlphaOffset() const;
+ EGLint getLuminanceOffset() const;
+ EGLint getBitmapPixelSize() const;
+ EGLAttribKHR getBitmapPointer() const;
+ egl::Error lockSurfaceKHR(const egl::Display *display, const AttributeMap &attributes);
+ egl::Error unlockSurfaceKHR(const egl::Display *display);
+
+ bool isLocked() const;
+ bool isCurrentOnAnyContext() const { return mIsCurrentOnAnyContext; }
+
+ gl::Texture *getBoundTexture() const { return mTexture; }
+
+ EGLint isFixedSize() const;
+
+ // FramebufferAttachmentObject implementation
+ gl::Extents getAttachmentSize(const gl::ImageIndex &imageIndex) const override;
+ gl::Format getAttachmentFormat(GLenum binding, const gl::ImageIndex &imageIndex) const override;
+ GLsizei getAttachmentSamples(const gl::ImageIndex &imageIndex) const override;
+ bool isRenderable(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex) const override;
+ bool isYUV() const override;
+ bool isCreatedWithAHB() const override;
+
+ void onAttach(const gl::Context *context, rx::Serial framebufferSerial) override {}
+ void onDetach(const gl::Context *context, rx::Serial framebufferSerial) override {}
+ GLuint getId() const override;
+
+ EGLint getOrientation() const { return mOrientation; }
+
+ bool directComposition() const { return mState.directComposition; }
+
+ gl::InitState initState(GLenum binding, const gl::ImageIndex &imageIndex) const override;
+ void setInitState(GLenum binding,
+ const gl::ImageIndex &imageIndex,
+ gl::InitState initState) override;
+
+ bool isRobustResourceInitEnabled() const { return mRobustResourceInitialization; }
+
+ const gl::Format &getBindTexImageFormat() const { return mColorFormat; }
+
+ // EGL_ANDROID_get_frame_timestamps entry points
+ void setTimestampsEnabled(bool enabled);
+ bool isTimestampsEnabled() const;
+
+ // EGL_ANDROID_front_buffer_auto_refresh entry points
+ Error setAutoRefreshEnabled(bool enabled);
+
+ const SupportedCompositorTiming &getSupportedCompositorTimings() const;
+ Error getCompositorTiming(EGLint numTimestamps,
+ const EGLint *names,
+ EGLnsecsANDROID *values) const;
+
+ Error getNextFrameId(EGLuint64KHR *frameId) const;
+ const SupportedTimestamps &getSupportedTimestamps() const;
+ Error getFrameTimestamps(EGLuint64KHR frameId,
+ EGLint numTimestamps,
+ const EGLint *timestamps,
+ EGLnsecsANDROID *values) const;
+
+ // Returns the offset into the texture backing the surface if specified via texture offset
+ // attributes (see EGL_ANGLE_d3d_texture_client_buffer extension). Returns zero offset
+ // otherwise.
+ const gl::Offset &getTextureOffset() const { return mTextureOffset; }
+
+ Error getBufferAge(const gl::Context *context, EGLint *age);
+
+ Error setRenderBuffer(EGLint renderBuffer);
+
+ bool bufferAgeQueriedSinceLastSwap() const { return mBufferAgeQueriedSinceLastSwap; }
+ void setDamageRegion(const EGLint *rects, EGLint n_rects);
+ bool isDamageRegionSet() const { return mIsDamageRegionSet; }
+
+ void addRef() { mRefCount++; }
+ void release()
+ {
+ ASSERT(mRefCount > 0);
+ mRefCount--;
+ }
+
+ protected:
+ Surface(EGLint surfaceType,
+ GLuint serialId,
+ const egl::Config *config,
+ const AttributeMap &attributes,
+ bool forceRobustResourceInit,
+ EGLenum buftype = EGL_NONE);
+ ~Surface() override;
+ rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
+
+ // ANGLE-only method, used internally
+ friend class gl::Texture;
+ Error releaseTexImageFromTexture(const gl::Context *context);
+
+ SurfaceState mState;
+ rx::SurfaceImpl *mImplementation;
+ int mRefCount;
+ bool mDestroyed;
+
+ EGLint mType;
+ EGLenum mBuftype;
+
+ bool mPostSubBufferRequested;
+
+ bool mLargestPbuffer;
+ EGLenum mGLColorspace;
+ EGLenum mVGAlphaFormat;
+ EGLenum mVGColorspace;
+ bool mMipmapTexture;
+ EGLint mMipmapLevel;
+ EGLint mHorizontalResolution;
+ EGLint mVerticalResolution;
+ EGLenum mMultisampleResolve;
+
+ bool mFixedSize;
+ size_t mFixedWidth;
+ size_t mFixedHeight;
+
+ bool mRobustResourceInitialization;
+
+ TextureFormat mTextureFormat;
+ EGLenum mTextureTarget;
+
+ EGLint mPixelAspectRatio; // Display aspect ratio
+ EGLenum mRenderBuffer; // Render buffer
+
+ EGLint mOrientation;
+
+ // We don't use a binding pointer here. We don't ever want to own an orphaned texture. If a
+ // Texture is deleted the Surface is unbound in onDestroy.
+ gl::Texture *mTexture;
+
+ gl::Format mColorFormat;
+ gl::Format mDSFormat;
+
+ gl::Offset mTextureOffset;
+
+ bool mIsCurrentOnAnyContext; // The surface is current to a context/client API
+ uint8_t *mLockBufferPtr; // Memory owned by backend.
+ EGLint mLockBufferPitch;
+
+ bool mBufferAgeQueriedSinceLastSwap;
+ bool mIsDamageRegionSet;
+
+ private:
+ Error getBufferAgeImpl(const gl::Context *context, EGLint *age) const;
+
+ Error destroyImpl(const Display *display);
+
+ void postSwap(const gl::Context *context);
+ Error releaseRef(const Display *display);
+
+ // ObserverInterface implementation.
+ void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
+
+ gl::InitState mColorInitState;
+ gl::InitState mDepthStencilInitState;
+ angle::ObserverBinding mImplObserverBinding;
+
+ GLuint mSerialId;
+};
+
+class WindowSurface final : public Surface
+{
+ public:
+ WindowSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ EGLNativeWindowType window,
+ const AttributeMap &attribs,
+ bool robustResourceInit);
+ ~WindowSurface() override;
+};
+
+class PbufferSurface final : public Surface
+{
+ public:
+ PbufferSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ const AttributeMap &attribs,
+ bool robustResourceInit);
+ PbufferSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const AttributeMap &attribs,
+ bool robustResourceInit);
+
+ protected:
+ ~PbufferSurface() override;
+};
+
+class PixmapSurface final : public Surface
+{
+ public:
+ PixmapSurface(rx::EGLImplFactory *implFactory,
+ const Config *config,
+ NativePixmapType nativePixmap,
+ const AttributeMap &attribs,
+ bool robustResourceInit);
+
+ protected:
+ ~PixmapSurface() override;
+};
+
+class [[nodiscard]] ScopedSurfaceRef
+{
+ public:
+ ScopedSurfaceRef(Surface *surface) : mSurface(surface)
+ {
+ if (mSurface)
+ {
+ mSurface->addRef();
+ }
+ }
+ ~ScopedSurfaceRef()
+ {
+ if (mSurface)
+ {
+ mSurface->release();
+ }
+ }
+
+ private:
+ Surface *const mSurface;
+};
+
+class SurfaceDeleter final
+{
+ public:
+ SurfaceDeleter(const Display *display);
+ ~SurfaceDeleter();
+ void operator()(Surface *surface);
+
+ private:
+ const Display *mDisplay;
+};
+
+using SurfacePointer = std::unique_ptr<Surface, SurfaceDeleter>;
+
+} // namespace egl
+
+#endif // LIBANGLE_SURFACE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Texture.cpp b/gfx/angle/checkout/src/libANGLE/Texture.cpp
new file mode 100644
index 0000000000..89930d1c29
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Texture.cpp
@@ -0,0 +1,2494 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Texture.cpp: Implements the gl::Texture class. [OpenGL ES 2.0.24] section 3.7 page 63.
+
+#include "libANGLE/Texture.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/TextureImpl.h"
+
+namespace gl
+{
+
+namespace
+{
+constexpr angle::SubjectIndex kBufferSubjectIndex = 2;
+static_assert(kBufferSubjectIndex != rx::kTextureImageImplObserverMessageIndex, "Index collision");
+static_assert(kBufferSubjectIndex != rx::kTextureImageSiblingMessageIndex, "Index collision");
+
+bool IsPointSampled(const SamplerState &samplerState)
+{
+ return (samplerState.getMagFilter() == GL_NEAREST &&
+ (samplerState.getMinFilter() == GL_NEAREST ||
+ samplerState.getMinFilter() == GL_NEAREST_MIPMAP_NEAREST));
+}
+
+size_t GetImageDescIndex(TextureTarget target, size_t level)
+{
+ return IsCubeMapFaceTarget(target) ? (level * 6 + CubeMapTextureTargetToFaceIndex(target))
+ : level;
+}
+
+InitState DetermineInitState(const Context *context, Buffer *unpackBuffer, const uint8_t *pixels)
+{
+ // Can happen in tests.
+ if (!context || !context->isRobustResourceInitEnabled())
+ {
+ return InitState::Initialized;
+ }
+
+ return (!pixels && !unpackBuffer) ? InitState::MayNeedInit : InitState::Initialized;
+}
+} // namespace
+
+GLenum ConvertToNearestFilterMode(GLenum filterMode)
+{
+ switch (filterMode)
+ {
+ case GL_LINEAR:
+ return GL_NEAREST;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ return GL_NEAREST_MIPMAP_NEAREST;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ return GL_NEAREST_MIPMAP_LINEAR;
+ default:
+ return filterMode;
+ }
+}
+
+GLenum ConvertToNearestMipFilterMode(GLenum filterMode)
+{
+ switch (filterMode)
+ {
+ case GL_LINEAR_MIPMAP_LINEAR:
+ return GL_LINEAR_MIPMAP_NEAREST;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ return GL_NEAREST_MIPMAP_NEAREST;
+ default:
+ return filterMode;
+ }
+}
+
+bool IsMipmapSupported(const TextureType &type)
+{
+ if (type == TextureType::_2DMultisample || type == TextureType::Buffer)
+ {
+ return false;
+ }
+ return true;
+}
+
+SwizzleState::SwizzleState()
+ : swizzleRed(GL_RED), swizzleGreen(GL_GREEN), swizzleBlue(GL_BLUE), swizzleAlpha(GL_ALPHA)
+{}
+
+SwizzleState::SwizzleState(GLenum red, GLenum green, GLenum blue, GLenum alpha)
+ : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha)
+{}
+
+bool SwizzleState::swizzleRequired() const
+{
+ return swizzleRed != GL_RED || swizzleGreen != GL_GREEN || swizzleBlue != GL_BLUE ||
+ swizzleAlpha != GL_ALPHA;
+}
+
+bool SwizzleState::operator==(const SwizzleState &other) const
+{
+ return swizzleRed == other.swizzleRed && swizzleGreen == other.swizzleGreen &&
+ swizzleBlue == other.swizzleBlue && swizzleAlpha == other.swizzleAlpha;
+}
+
+bool SwizzleState::operator!=(const SwizzleState &other) const
+{
+ return !(*this == other);
+}
+
+TextureState::TextureState(TextureType type)
+ : mType(type),
+ mSamplerState(SamplerState::CreateDefaultForTarget(type)),
+ mSrgbOverride(SrgbOverride::Default),
+ mBaseLevel(0),
+ mMaxLevel(kInitialMaxLevel),
+ mDepthStencilTextureMode(GL_DEPTH_COMPONENT),
+ mHasBeenBoundAsImage(false),
+ mIs3DAndHasBeenBoundAs2DImage(false),
+ mHasBeenBoundAsAttachment(false),
+ mImmutableFormat(false),
+ mImmutableLevels(0),
+ mUsage(GL_NONE),
+ mHasProtectedContent(false),
+ mImageDescs((IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1) * (type == TextureType::CubeMap ? 6 : 1)),
+ mCropRect(0, 0, 0, 0),
+ mGenerateMipmapHint(GL_FALSE),
+ mInitState(InitState::Initialized),
+ mCachedSamplerFormat(SamplerFormat::InvalidEnum),
+ mCachedSamplerCompareMode(GL_NONE),
+ mCachedSamplerFormatValid(false)
+{}
+
+TextureState::~TextureState() {}
+
+bool TextureState::swizzleRequired() const
+{
+ return mSwizzleState.swizzleRequired();
+}
+
+GLuint TextureState::getEffectiveBaseLevel() const
+{
+ if (mImmutableFormat)
+ {
+ // GLES 3.0.4 section 3.8.10
+ return std::min(mBaseLevel, mImmutableLevels - 1);
+ }
+ // Some classes use the effective base level to index arrays with level data. By clamping the
+ // effective base level to max levels these arrays need just one extra item to store properties
+ // that should be returned for all out-of-range base level values, instead of needing special
+ // handling for out-of-range base levels.
+ return std::min(mBaseLevel, static_cast<GLuint>(IMPLEMENTATION_MAX_TEXTURE_LEVELS));
+}
+
+GLuint TextureState::getEffectiveMaxLevel() const
+{
+ if (mImmutableFormat)
+ {
+ // GLES 3.0.4 section 3.8.10
+ GLuint clampedMaxLevel = std::max(mMaxLevel, getEffectiveBaseLevel());
+ clampedMaxLevel = std::min(clampedMaxLevel, mImmutableLevels - 1);
+ return clampedMaxLevel;
+ }
+ return mMaxLevel;
+}
+
+GLuint TextureState::getMipmapMaxLevel() const
+{
+ const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
+ GLuint expectedMipLevels = 0;
+ if (mType == TextureType::_3D)
+ {
+ const int maxDim = std::max(std::max(baseImageDesc.size.width, baseImageDesc.size.height),
+ baseImageDesc.size.depth);
+ expectedMipLevels = static_cast<GLuint>(log2(maxDim));
+ }
+ else
+ {
+ expectedMipLevels = static_cast<GLuint>(
+ log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)));
+ }
+
+ return std::min<GLuint>(getEffectiveBaseLevel() + expectedMipLevels, getEffectiveMaxLevel());
+}
+
+bool TextureState::setBaseLevel(GLuint baseLevel)
+{
+ if (mBaseLevel != baseLevel)
+ {
+ mBaseLevel = baseLevel;
+ return true;
+ }
+ return false;
+}
+
+bool TextureState::setMaxLevel(GLuint maxLevel)
+{
+ if (mMaxLevel != maxLevel)
+ {
+ mMaxLevel = maxLevel;
+ return true;
+ }
+
+ return false;
+}
+
+// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+// According to [OpenGL ES 3.0.5] section 3.8.13 Texture Completeness page 160 any
+// per-level checks begin at the base-level.
+// For OpenGL ES2 the base level is always zero.
+bool TextureState::isCubeComplete() const
+{
+ ASSERT(mType == TextureType::CubeMap);
+
+ angle::EnumIterator<TextureTarget> face = kCubeMapTextureTargetMin;
+ const ImageDesc &baseImageDesc = getImageDesc(*face, getEffectiveBaseLevel());
+ if (baseImageDesc.size.width == 0 || baseImageDesc.size.width != baseImageDesc.size.height)
+ {
+ return false;
+ }
+
+ ++face;
+
+ for (; face != kAfterCubeMapTextureTargetMax; ++face)
+ {
+ const ImageDesc &faceImageDesc = getImageDesc(*face, getEffectiveBaseLevel());
+ if (faceImageDesc.size.width != baseImageDesc.size.width ||
+ faceImageDesc.size.height != baseImageDesc.size.height ||
+ !Format::SameSized(faceImageDesc.format, baseImageDesc.format))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+const ImageDesc &TextureState::getBaseLevelDesc() const
+{
+ ASSERT(mType != TextureType::CubeMap || isCubeComplete());
+ return getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
+}
+
+const ImageDesc &TextureState::getLevelZeroDesc() const
+{
+ ASSERT(mType != TextureType::CubeMap || isCubeComplete());
+ return getImageDesc(getBaseImageTarget(), 0);
+}
+
+void TextureState::setCrop(const Rectangle &rect)
+{
+ mCropRect = rect;
+}
+
+const Rectangle &TextureState::getCrop() const
+{
+ return mCropRect;
+}
+
+void TextureState::setGenerateMipmapHint(GLenum hint)
+{
+ mGenerateMipmapHint = hint;
+}
+
+GLenum TextureState::getGenerateMipmapHint() const
+{
+ return mGenerateMipmapHint;
+}
+
+SamplerFormat TextureState::computeRequiredSamplerFormat(const SamplerState &samplerState) const
+{
+ const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
+ if ((baseImageDesc.format.info->format == GL_DEPTH_COMPONENT ||
+ baseImageDesc.format.info->format == GL_DEPTH_STENCIL) &&
+ samplerState.getCompareMode() != GL_NONE)
+ {
+ return SamplerFormat::Shadow;
+ }
+ else
+ {
+ switch (baseImageDesc.format.info->componentType)
+ {
+ case GL_UNSIGNED_NORMALIZED:
+ case GL_SIGNED_NORMALIZED:
+ case GL_FLOAT:
+ return SamplerFormat::Float;
+ case GL_INT:
+ return SamplerFormat::Signed;
+ case GL_UNSIGNED_INT:
+ return SamplerFormat::Unsigned;
+ default:
+ return SamplerFormat::InvalidEnum;
+ }
+ }
+}
+
+bool TextureState::computeSamplerCompleteness(const SamplerState &samplerState,
+ const State &state) const
+{
+ // Buffer textures cannot be incomplete.
+ if (mType == TextureType::Buffer)
+ {
+ return true;
+ }
+
+ // Check for all non-format-based completeness rules
+ if (!computeSamplerCompletenessForCopyImage(samplerState, state))
+ {
+ return false;
+ }
+
+ const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
+
+ // According to es 3.1 spec, texture is justified as incomplete if sized internalformat is
+ // unfilterable(table 20.11) and filter is not GL_NEAREST(8.16). The default value of minFilter
+ // is NEAREST_MIPMAP_LINEAR and magFilter is LINEAR(table 20.11,). For multismaple texture,
+ // filter state of multisample texture is ignored(11.1.3.3). So it shouldn't be judged as
+ // incomplete texture. So, we ignore filtering for multisample texture completeness here.
+ if (!IsMultisampled(mType) &&
+ !baseImageDesc.format.info->filterSupport(state.getClientVersion(),
+ state.getExtensions()) &&
+ !IsPointSampled(samplerState))
+ {
+ return false;
+ }
+
+ // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
+ // The internalformat specified for the texture arrays is a sized internal depth or
+ // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
+ // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
+ // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
+ if (!IsMultisampled(mType) && baseImageDesc.format.info->depthBits > 0 &&
+ state.getClientMajorVersion() >= 3)
+ {
+ // Note: we restrict this validation to sized types. For the OES_depth_textures
+ // extension, due to some underspecification problems, we must allow linear filtering
+ // for legacy compatibility with WebGL 1.
+ // See http://crbug.com/649200
+ if (samplerState.getCompareMode() == GL_NONE && baseImageDesc.format.info->sized)
+ {
+ if ((samplerState.getMinFilter() != GL_NEAREST &&
+ samplerState.getMinFilter() != GL_NEAREST_MIPMAP_NEAREST) ||
+ samplerState.getMagFilter() != GL_NEAREST)
+ {
+ return false;
+ }
+ }
+ }
+
+ // OpenGLES 3.1 spec section 8.16 states that a texture is not mipmap complete if:
+ // The internalformat specified for the texture is DEPTH_STENCIL format, the value of
+ // DEPTH_STENCIL_TEXTURE_MODE is STENCIL_INDEX, and either the magnification filter is
+ // not NEAREST or the minification filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
+ // However, the ES 3.1 spec differs from the statement above, because it is incorrect.
+ // See the issue at https://github.com/KhronosGroup/OpenGL-API/issues/33.
+ // For multismaple texture, filter state of multisample texture is ignored(11.1.3.3).
+ // So it shouldn't be judged as incomplete texture. So, we ignore filtering for multisample
+ // texture completeness here.
+ if (!IsMultisampled(mType) && baseImageDesc.format.info->depthBits > 0 &&
+ mDepthStencilTextureMode == GL_STENCIL_INDEX)
+ {
+ if ((samplerState.getMinFilter() != GL_NEAREST &&
+ samplerState.getMinFilter() != GL_NEAREST_MIPMAP_NEAREST) ||
+ samplerState.getMagFilter() != GL_NEAREST)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// CopyImageSubData has more lax rules for texture completeness: format-based completeness rules are
+// ignored, so a texture can still be considered complete even if it violates format-specific
+// conditions
+bool TextureState::computeSamplerCompletenessForCopyImage(const SamplerState &samplerState,
+ const State &state) const
+{
+ // Buffer textures cannot be incomplete.
+ if (mType == TextureType::Buffer)
+ {
+ return true;
+ }
+
+ if (!mImmutableFormat && mBaseLevel > mMaxLevel)
+ {
+ return false;
+ }
+ const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
+ if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 ||
+ baseImageDesc.size.depth == 0)
+ {
+ return false;
+ }
+ // The cases where the texture is incomplete because base level is out of range should be
+ // handled by the above condition.
+ ASSERT(mBaseLevel < IMPLEMENTATION_MAX_TEXTURE_LEVELS || mImmutableFormat);
+
+ if (mType == TextureType::CubeMap && baseImageDesc.size.width != baseImageDesc.size.height)
+ {
+ return false;
+ }
+
+ bool npotSupport = state.getExtensions().textureNpotOES || state.getClientMajorVersion() >= 3;
+ if (!npotSupport)
+ {
+ if ((samplerState.getWrapS() != GL_CLAMP_TO_EDGE &&
+ samplerState.getWrapS() != GL_CLAMP_TO_BORDER && !isPow2(baseImageDesc.size.width)) ||
+ (samplerState.getWrapT() != GL_CLAMP_TO_EDGE &&
+ samplerState.getWrapT() != GL_CLAMP_TO_BORDER && !isPow2(baseImageDesc.size.height)))
+ {
+ return false;
+ }
+ }
+
+ if (IsMipmapSupported(mType) && IsMipmapFiltered(samplerState.getMinFilter()))
+ {
+ if (!npotSupport)
+ {
+ if (!isPow2(baseImageDesc.size.width) || !isPow2(baseImageDesc.size.height))
+ {
+ return false;
+ }
+ }
+
+ if (!computeMipmapCompleteness())
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (mType == TextureType::CubeMap && !isCubeComplete())
+ {
+ return false;
+ }
+ }
+
+ // From GL_OES_EGL_image_external_essl3: If state is present in a sampler object bound to a
+ // texture unit that would have been rejected by a call to TexParameter* for the texture bound
+ // to that unit, the behavior of the implementation is as if the texture were incomplete. For
+ // example, if TEXTURE_WRAP_S or TEXTURE_WRAP_T is set to anything but CLAMP_TO_EDGE on the
+ // sampler object bound to a texture unit and the texture bound to that unit is an external
+ // texture and EXT_EGL_image_external_wrap_modes is not enabled, the texture will be considered
+ // incomplete.
+ // Sampler object state which does not affect sampling for the type of texture bound
+ // to a texture unit, such as TEXTURE_WRAP_R for an external texture, does not affect
+ // completeness.
+ if (mType == TextureType::External)
+ {
+ if (!state.getExtensions().EGLImageExternalWrapModesEXT)
+ {
+ if (samplerState.getWrapS() != GL_CLAMP_TO_EDGE ||
+ samplerState.getWrapT() != GL_CLAMP_TO_EDGE)
+ {
+ return false;
+ }
+ }
+
+ if (samplerState.getMinFilter() != GL_LINEAR && samplerState.getMinFilter() != GL_NEAREST)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool TextureState::computeMipmapCompleteness() const
+{
+ const GLuint maxLevel = getMipmapMaxLevel();
+
+ for (GLuint level = getEffectiveBaseLevel(); level <= maxLevel; level++)
+ {
+ if (mType == TextureType::CubeMap)
+ {
+ for (TextureTarget face : AllCubeFaceTextureTargets())
+ {
+ if (!computeLevelCompleteness(face, level))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ if (!computeLevelCompleteness(NonCubeTextureTypeToTarget(mType), level))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool TextureState::computeLevelCompleteness(TextureTarget target, size_t level) const
+{
+ ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+
+ if (mImmutableFormat)
+ {
+ return true;
+ }
+
+ const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), getEffectiveBaseLevel());
+ if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 ||
+ baseImageDesc.size.depth == 0)
+ {
+ return false;
+ }
+
+ const ImageDesc &levelImageDesc = getImageDesc(target, level);
+ if (levelImageDesc.size.width == 0 || levelImageDesc.size.height == 0 ||
+ levelImageDesc.size.depth == 0)
+ {
+ return false;
+ }
+
+ if (!Format::SameSized(levelImageDesc.format, baseImageDesc.format))
+ {
+ return false;
+ }
+
+ ASSERT(level >= getEffectiveBaseLevel());
+ const size_t relativeLevel = level - getEffectiveBaseLevel();
+ if (levelImageDesc.size.width != std::max(1, baseImageDesc.size.width >> relativeLevel))
+ {
+ return false;
+ }
+
+ if (levelImageDesc.size.height != std::max(1, baseImageDesc.size.height >> relativeLevel))
+ {
+ return false;
+ }
+
+ if (mType == TextureType::_3D)
+ {
+ if (levelImageDesc.size.depth != std::max(1, baseImageDesc.size.depth >> relativeLevel))
+ {
+ return false;
+ }
+ }
+ else if (IsArrayTextureType(mType))
+ {
+ if (levelImageDesc.size.depth != baseImageDesc.size.depth)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+TextureTarget TextureState::getBaseImageTarget() const
+{
+ return mType == TextureType::CubeMap ? kCubeMapTextureTargetMin
+ : NonCubeTextureTypeToTarget(mType);
+}
+
+GLuint TextureState::getEnabledLevelCount() const
+{
+ GLuint levelCount = 0;
+ const GLuint baseLevel = getEffectiveBaseLevel();
+ const GLuint maxLevel = std::min(getEffectiveMaxLevel(), getMipmapMaxLevel());
+
+ // The mip chain will have either one or more sequential levels, or max levels,
+ // but not a sparse one.
+ Optional<Extents> expectedSize;
+ for (size_t enabledLevel = baseLevel; enabledLevel <= maxLevel; ++enabledLevel, ++levelCount)
+ {
+ // Note: for cube textures, we only check the first face.
+ TextureTarget target = TextureTypeToTarget(mType, 0);
+ size_t descIndex = GetImageDescIndex(target, enabledLevel);
+ const Extents &levelSize = mImageDescs[descIndex].size;
+
+ if (levelSize.empty())
+ {
+ break;
+ }
+ if (expectedSize.valid())
+ {
+ Extents newSize = expectedSize.value();
+ newSize.width = std::max(1, newSize.width >> 1);
+ newSize.height = std::max(1, newSize.height >> 1);
+
+ if (!IsArrayTextureType(mType))
+ {
+ newSize.depth = std::max(1, newSize.depth >> 1);
+ }
+
+ if (newSize != levelSize)
+ {
+ break;
+ }
+ }
+ expectedSize = levelSize;
+ }
+
+ return levelCount;
+}
+
+ImageDesc::ImageDesc()
+ : ImageDesc(Extents(0, 0, 0), Format::Invalid(), 0, GL_TRUE, InitState::Initialized)
+{}
+
+ImageDesc::ImageDesc(const Extents &size, const Format &format, const InitState initState)
+ : size(size), format(format), samples(0), fixedSampleLocations(GL_TRUE), initState(initState)
+{}
+
+ImageDesc::ImageDesc(const Extents &size,
+ const Format &format,
+ const GLsizei samples,
+ const bool fixedSampleLocations,
+ const InitState initState)
+ : size(size),
+ format(format),
+ samples(samples),
+ fixedSampleLocations(fixedSampleLocations),
+ initState(initState)
+{}
+
+GLint ImageDesc::getMemorySize() const
+{
+ // Assume allocated size is around width * height * depth * samples * pixelBytes
+ angle::CheckedNumeric<GLint> levelSize = 1;
+ levelSize *= format.info->pixelBytes;
+ levelSize *= size.width;
+ levelSize *= size.height;
+ levelSize *= size.depth;
+ levelSize *= std::max(samples, 1);
+ return levelSize.ValueOrDefault(std::numeric_limits<GLint>::max());
+}
+
+const ImageDesc &TextureState::getImageDesc(TextureTarget target, size_t level) const
+{
+ size_t descIndex = GetImageDescIndex(target, level);
+ ASSERT(descIndex < mImageDescs.size());
+ return mImageDescs[descIndex];
+}
+
+void TextureState::setImageDesc(TextureTarget target, size_t level, const ImageDesc &desc)
+{
+ size_t descIndex = GetImageDescIndex(target, level);
+ ASSERT(descIndex < mImageDescs.size());
+ mImageDescs[descIndex] = desc;
+ if (desc.initState == InitState::MayNeedInit)
+ {
+ mInitState = InitState::MayNeedInit;
+ }
+ else
+ {
+ // Scan for any uninitialized images. If there are none, set the init state of the entire
+ // texture to initialized. The cost of the scan is only paid after doing image
+ // initialization which is already very expensive.
+ bool allImagesInitialized = true;
+
+ for (const ImageDesc &initDesc : mImageDescs)
+ {
+ if (initDesc.initState == InitState::MayNeedInit)
+ {
+ allImagesInitialized = false;
+ break;
+ }
+ }
+
+ if (allImagesInitialized)
+ {
+ mInitState = InitState::Initialized;
+ }
+ }
+}
+
+// Note that an ImageIndex that represents an entire level of a cube map corresponds to 6
+// ImageDescs, so if the cube map is cube complete, we return the ImageDesc of the first cube
+// face, and we don't allow using this function when the cube map is not cube complete.
+const ImageDesc &TextureState::getImageDesc(const ImageIndex &imageIndex) const
+{
+ if (imageIndex.isEntireLevelCubeMap())
+ {
+ ASSERT(isCubeComplete());
+ const GLint levelIndex = imageIndex.getLevelIndex();
+ return getImageDesc(kCubeMapTextureTargetMin, levelIndex);
+ }
+
+ return getImageDesc(imageIndex.getTarget(), imageIndex.getLevelIndex());
+}
+
+void TextureState::setImageDescChain(GLuint baseLevel,
+ GLuint maxLevel,
+ Extents baseSize,
+ const Format &format,
+ InitState initState)
+{
+ for (GLuint level = baseLevel; level <= maxLevel; level++)
+ {
+ int relativeLevel = (level - baseLevel);
+ Extents levelSize(std::max<int>(baseSize.width >> relativeLevel, 1),
+ std::max<int>(baseSize.height >> relativeLevel, 1),
+ (IsArrayTextureType(mType))
+ ? baseSize.depth
+ : std::max<int>(baseSize.depth >> relativeLevel, 1));
+ ImageDesc levelInfo(levelSize, format, initState);
+
+ if (mType == TextureType::CubeMap)
+ {
+ for (TextureTarget face : AllCubeFaceTextureTargets())
+ {
+ setImageDesc(face, level, levelInfo);
+ }
+ }
+ else
+ {
+ setImageDesc(NonCubeTextureTypeToTarget(mType), level, levelInfo);
+ }
+ }
+}
+
+void TextureState::setImageDescChainMultisample(Extents baseSize,
+ const Format &format,
+ GLsizei samples,
+ bool fixedSampleLocations,
+ InitState initState)
+{
+ ASSERT(mType == TextureType::_2DMultisample || mType == TextureType::_2DMultisampleArray);
+ ImageDesc levelInfo(baseSize, format, samples, fixedSampleLocations, initState);
+ setImageDesc(NonCubeTextureTypeToTarget(mType), 0, levelInfo);
+}
+
+void TextureState::clearImageDesc(TextureTarget target, size_t level)
+{
+ setImageDesc(target, level, ImageDesc());
+}
+
+void TextureState::clearImageDescs()
+{
+ for (size_t descIndex = 0; descIndex < mImageDescs.size(); descIndex++)
+ {
+ mImageDescs[descIndex] = ImageDesc();
+ }
+}
+
+Texture::Texture(rx::GLImplFactory *factory, TextureID id, TextureType type)
+ : RefCountObject(factory->generateSerial(), id),
+ mState(type),
+ mTexture(factory->createTexture(mState)),
+ mImplObserver(this, rx::kTextureImageImplObserverMessageIndex),
+ mBufferObserver(this, kBufferSubjectIndex),
+ mBoundSurface(nullptr),
+ mBoundStream(nullptr)
+{
+ mImplObserver.bind(mTexture);
+
+ // Initially assume the implementation is dirty.
+ mDirtyBits.set(DIRTY_BIT_IMPLEMENTATION);
+}
+
+void Texture::onDestroy(const Context *context)
+{
+ if (mBoundSurface)
+ {
+ ANGLE_SWALLOW_ERR(mBoundSurface->releaseTexImage(context, EGL_BACK_BUFFER));
+ mBoundSurface = nullptr;
+ }
+ if (mBoundStream)
+ {
+ mBoundStream->releaseTextures();
+ mBoundStream = nullptr;
+ }
+
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ (void)orphanImages(context, &releaseImage);
+
+ mState.mBuffer.set(context, nullptr, 0, 0);
+
+ if (mTexture)
+ {
+ mTexture->onDestroy(context);
+ }
+}
+
+Texture::~Texture()
+{
+ SafeDelete(mTexture);
+}
+
+angle::Result Texture::setLabel(const Context *context, const std::string &label)
+{
+ mState.mLabel = label;
+ return mTexture->onLabelUpdate(context);
+}
+
+const std::string &Texture::getLabel() const
+{
+ return mState.mLabel;
+}
+
+void Texture::setSwizzleRed(const Context *context, GLenum swizzleRed)
+{
+ if (mState.mSwizzleState.swizzleRed != swizzleRed)
+ {
+ mState.mSwizzleState.swizzleRed = swizzleRed;
+ signalDirtyState(DIRTY_BIT_SWIZZLE_RED);
+ }
+}
+
+GLenum Texture::getSwizzleRed() const
+{
+ return mState.mSwizzleState.swizzleRed;
+}
+
+void Texture::setSwizzleGreen(const Context *context, GLenum swizzleGreen)
+{
+ if (mState.mSwizzleState.swizzleGreen != swizzleGreen)
+ {
+ mState.mSwizzleState.swizzleGreen = swizzleGreen;
+ signalDirtyState(DIRTY_BIT_SWIZZLE_GREEN);
+ }
+}
+
+GLenum Texture::getSwizzleGreen() const
+{
+ return mState.mSwizzleState.swizzleGreen;
+}
+
+void Texture::setSwizzleBlue(const Context *context, GLenum swizzleBlue)
+{
+ if (mState.mSwizzleState.swizzleBlue != swizzleBlue)
+ {
+ mState.mSwizzleState.swizzleBlue = swizzleBlue;
+ signalDirtyState(DIRTY_BIT_SWIZZLE_BLUE);
+ }
+}
+
+GLenum Texture::getSwizzleBlue() const
+{
+ return mState.mSwizzleState.swizzleBlue;
+}
+
+void Texture::setSwizzleAlpha(const Context *context, GLenum swizzleAlpha)
+{
+ if (mState.mSwizzleState.swizzleAlpha != swizzleAlpha)
+ {
+ mState.mSwizzleState.swizzleAlpha = swizzleAlpha;
+ signalDirtyState(DIRTY_BIT_SWIZZLE_ALPHA);
+ }
+}
+
+GLenum Texture::getSwizzleAlpha() const
+{
+ return mState.mSwizzleState.swizzleAlpha;
+}
+
+void Texture::setMinFilter(const Context *context, GLenum minFilter)
+{
+ if (mState.mSamplerState.setMinFilter(minFilter))
+ {
+ signalDirtyState(DIRTY_BIT_MIN_FILTER);
+ }
+}
+
+GLenum Texture::getMinFilter() const
+{
+ return mState.mSamplerState.getMinFilter();
+}
+
+void Texture::setMagFilter(const Context *context, GLenum magFilter)
+{
+ if (mState.mSamplerState.setMagFilter(magFilter))
+ {
+ signalDirtyState(DIRTY_BIT_MAG_FILTER);
+ }
+}
+
+GLenum Texture::getMagFilter() const
+{
+ return mState.mSamplerState.getMagFilter();
+}
+
+void Texture::setWrapS(const Context *context, GLenum wrapS)
+{
+ if (mState.mSamplerState.setWrapS(wrapS))
+ {
+ signalDirtyState(DIRTY_BIT_WRAP_S);
+ }
+}
+
+GLenum Texture::getWrapS() const
+{
+ return mState.mSamplerState.getWrapS();
+}
+
+void Texture::setWrapT(const Context *context, GLenum wrapT)
+{
+ if (mState.mSamplerState.getWrapT() == wrapT)
+ return;
+ if (mState.mSamplerState.setWrapT(wrapT))
+ {
+ signalDirtyState(DIRTY_BIT_WRAP_T);
+ }
+}
+
+GLenum Texture::getWrapT() const
+{
+ return mState.mSamplerState.getWrapT();
+}
+
+void Texture::setWrapR(const Context *context, GLenum wrapR)
+{
+ if (mState.mSamplerState.setWrapR(wrapR))
+ {
+ signalDirtyState(DIRTY_BIT_WRAP_R);
+ }
+}
+
+GLenum Texture::getWrapR() const
+{
+ return mState.mSamplerState.getWrapR();
+}
+
+void Texture::setMaxAnisotropy(const Context *context, float maxAnisotropy)
+{
+ if (mState.mSamplerState.setMaxAnisotropy(maxAnisotropy))
+ {
+ signalDirtyState(DIRTY_BIT_MAX_ANISOTROPY);
+ }
+}
+
+float Texture::getMaxAnisotropy() const
+{
+ return mState.mSamplerState.getMaxAnisotropy();
+}
+
+void Texture::setMinLod(const Context *context, GLfloat minLod)
+{
+ if (mState.mSamplerState.setMinLod(minLod))
+ {
+ signalDirtyState(DIRTY_BIT_MIN_LOD);
+ }
+}
+
+GLfloat Texture::getMinLod() const
+{
+ return mState.mSamplerState.getMinLod();
+}
+
+void Texture::setMaxLod(const Context *context, GLfloat maxLod)
+{
+ if (mState.mSamplerState.setMaxLod(maxLod))
+ {
+ signalDirtyState(DIRTY_BIT_MAX_LOD);
+ }
+}
+
+GLfloat Texture::getMaxLod() const
+{
+ return mState.mSamplerState.getMaxLod();
+}
+
+void Texture::setCompareMode(const Context *context, GLenum compareMode)
+{
+ if (mState.mSamplerState.setCompareMode(compareMode))
+ {
+ signalDirtyState(DIRTY_BIT_COMPARE_MODE);
+ }
+}
+
+GLenum Texture::getCompareMode() const
+{
+ return mState.mSamplerState.getCompareMode();
+}
+
+void Texture::setCompareFunc(const Context *context, GLenum compareFunc)
+{
+ if (mState.mSamplerState.setCompareFunc(compareFunc))
+ {
+ signalDirtyState(DIRTY_BIT_COMPARE_FUNC);
+ }
+}
+
+GLenum Texture::getCompareFunc() const
+{
+ return mState.mSamplerState.getCompareFunc();
+}
+
+void Texture::setSRGBDecode(const Context *context, GLenum sRGBDecode)
+{
+ if (mState.mSamplerState.setSRGBDecode(sRGBDecode))
+ {
+ signalDirtyState(DIRTY_BIT_SRGB_DECODE);
+ }
+}
+
+GLenum Texture::getSRGBDecode() const
+{
+ return mState.mSamplerState.getSRGBDecode();
+}
+
+void Texture::setSRGBOverride(const Context *context, GLenum sRGBOverride)
+{
+ SrgbOverride oldOverride = mState.mSrgbOverride;
+ mState.mSrgbOverride = (sRGBOverride == GL_SRGB) ? SrgbOverride::SRGB : SrgbOverride::Default;
+ if (mState.mSrgbOverride != oldOverride)
+ {
+ signalDirtyState(DIRTY_BIT_SRGB_OVERRIDE);
+ }
+}
+
+GLenum Texture::getSRGBOverride() const
+{
+ return (mState.mSrgbOverride == SrgbOverride::SRGB) ? GL_SRGB : GL_NONE;
+}
+
+const SamplerState &Texture::getSamplerState() const
+{
+ return mState.mSamplerState;
+}
+
+angle::Result Texture::setBaseLevel(const Context *context, GLuint baseLevel)
+{
+ if (mState.setBaseLevel(baseLevel))
+ {
+ ANGLE_TRY(mTexture->setBaseLevel(context, mState.getEffectiveBaseLevel()));
+ signalDirtyState(DIRTY_BIT_BASE_LEVEL);
+ }
+
+ return angle::Result::Continue;
+}
+
+GLuint Texture::getBaseLevel() const
+{
+ return mState.mBaseLevel;
+}
+
+void Texture::setMaxLevel(const Context *context, GLuint maxLevel)
+{
+ if (mState.setMaxLevel(maxLevel))
+ {
+ signalDirtyState(DIRTY_BIT_MAX_LEVEL);
+ }
+}
+
+GLuint Texture::getMaxLevel() const
+{
+ return mState.mMaxLevel;
+}
+
+void Texture::setDepthStencilTextureMode(const Context *context, GLenum mode)
+{
+ if (mState.mDepthStencilTextureMode != mode)
+ {
+ mState.mDepthStencilTextureMode = mode;
+ signalDirtyState(DIRTY_BIT_DEPTH_STENCIL_TEXTURE_MODE);
+ }
+}
+
+GLenum Texture::getDepthStencilTextureMode() const
+{
+ return mState.mDepthStencilTextureMode;
+}
+
+bool Texture::getImmutableFormat() const
+{
+ return mState.mImmutableFormat;
+}
+
+GLuint Texture::getImmutableLevels() const
+{
+ return mState.mImmutableLevels;
+}
+
+void Texture::setUsage(const Context *context, GLenum usage)
+{
+ mState.mUsage = usage;
+ signalDirtyState(DIRTY_BIT_USAGE);
+}
+
+GLenum Texture::getUsage() const
+{
+ return mState.mUsage;
+}
+
+void Texture::setProtectedContent(Context *context, bool hasProtectedContent)
+{
+ mState.mHasProtectedContent = hasProtectedContent;
+}
+
+bool Texture::hasProtectedContent() const
+{
+ return mState.mHasProtectedContent;
+}
+
+const TextureState &Texture::getTextureState() const
+{
+ return mState;
+}
+
+const Extents &Texture::getExtents(TextureTarget target, size_t level) const
+{
+ ASSERT(TextureTargetToType(target) == mState.mType);
+ return mState.getImageDesc(target, level).size;
+}
+
+size_t Texture::getWidth(TextureTarget target, size_t level) const
+{
+ ASSERT(TextureTargetToType(target) == mState.mType);
+ return mState.getImageDesc(target, level).size.width;
+}
+
+size_t Texture::getHeight(TextureTarget target, size_t level) const
+{
+ ASSERT(TextureTargetToType(target) == mState.mType);
+ return mState.getImageDesc(target, level).size.height;
+}
+
+size_t Texture::getDepth(TextureTarget target, size_t level) const
+{
+ ASSERT(TextureTargetToType(target) == mState.mType);
+ return mState.getImageDesc(target, level).size.depth;
+}
+
+const Format &Texture::getFormat(TextureTarget target, size_t level) const
+{
+ ASSERT(TextureTargetToType(target) == mState.mType);
+ return mState.getImageDesc(target, level).format;
+}
+
+GLsizei Texture::getSamples(TextureTarget target, size_t level) const
+{
+ ASSERT(TextureTargetToType(target) == mState.mType);
+ return mState.getImageDesc(target, level).samples;
+}
+
+bool Texture::getFixedSampleLocations(TextureTarget target, size_t level) const
+{
+ ASSERT(TextureTargetToType(target) == mState.mType);
+ return mState.getImageDesc(target, level).fixedSampleLocations;
+}
+
+GLuint Texture::getMipmapMaxLevel() const
+{
+ return mState.getMipmapMaxLevel();
+}
+
+bool Texture::isMipmapComplete() const
+{
+ return mState.computeMipmapCompleteness();
+}
+
+egl::Surface *Texture::getBoundSurface() const
+{
+ return mBoundSurface;
+}
+
+egl::Stream *Texture::getBoundStream() const
+{
+ return mBoundStream;
+}
+
+GLint Texture::getMemorySize() const
+{
+ GLint implSize = mTexture->getMemorySize();
+ if (implSize > 0)
+ {
+ return implSize;
+ }
+
+ angle::CheckedNumeric<GLint> size = 0;
+ for (const ImageDesc &imageDesc : mState.mImageDescs)
+ {
+ size += imageDesc.getMemorySize();
+ }
+ return size.ValueOrDefault(std::numeric_limits<GLint>::max());
+}
+
+GLint Texture::getLevelMemorySize(TextureTarget target, GLint level) const
+{
+ GLint implSize = mTexture->getLevelMemorySize(target, level);
+ if (implSize > 0)
+ {
+ return implSize;
+ }
+
+ return mState.getImageDesc(target, level).getMemorySize();
+}
+
+void Texture::signalDirtyStorage(InitState initState)
+{
+ mState.mInitState = initState;
+ invalidateCompletenessCache();
+ mState.mCachedSamplerFormatValid = false;
+ onStateChange(angle::SubjectMessage::SubjectChanged);
+}
+
+void Texture::signalDirtyState(size_t dirtyBit)
+{
+ mDirtyBits.set(dirtyBit);
+ invalidateCompletenessCache();
+ mState.mCachedSamplerFormatValid = false;
+
+ if (dirtyBit == DIRTY_BIT_BASE_LEVEL || dirtyBit == DIRTY_BIT_MAX_LEVEL)
+ {
+ onStateChange(angle::SubjectMessage::SubjectChanged);
+ }
+ else
+ {
+ onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
+ }
+}
+
+angle::Result Texture::setImage(Context *context,
+ const PixelUnpackState &unpackState,
+ Buffer *unpackBuffer,
+ TextureTarget target,
+ GLint level,
+ GLenum internalFormat,
+ const Extents &size,
+ GLenum format,
+ GLenum type,
+ const uint8_t *pixels)
+{
+ ASSERT(TextureTargetToType(target) == mState.mType);
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ ANGLE_TRY(releaseTexImageInternal(context));
+
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ ANGLE_TRY(orphanImages(context, &releaseImage));
+
+ ImageIndex index = ImageIndex::MakeFromTarget(target, level, size.depth);
+
+ ANGLE_TRY(mTexture->setImage(context, index, internalFormat, size, format, type, unpackState,
+ unpackBuffer, pixels));
+
+ InitState initState = DetermineInitState(context, unpackBuffer, pixels);
+ mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat, type), initState));
+
+ ANGLE_TRY(handleMipmapGenerationHint(context, level));
+
+ signalDirtyStorage(initState);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::setSubImage(Context *context,
+ const PixelUnpackState &unpackState,
+ Buffer *unpackBuffer,
+ TextureTarget target,
+ GLint level,
+ const Box &area,
+ GLenum format,
+ GLenum type,
+ const uint8_t *pixels)
+{
+ ASSERT(TextureTargetToType(target) == mState.mType);
+
+ ImageIndex index = ImageIndex::MakeFromTarget(target, level, area.depth);
+ ANGLE_TRY(ensureSubImageInitialized(context, index, area));
+
+ ANGLE_TRY(mTexture->setSubImage(context, index, area, format, type, unpackState, unpackBuffer,
+ pixels));
+
+ ANGLE_TRY(handleMipmapGenerationHint(context, level));
+
+ onStateChange(angle::SubjectMessage::ContentsChanged);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::setCompressedImage(Context *context,
+ const PixelUnpackState &unpackState,
+ TextureTarget target,
+ GLint level,
+ GLenum internalFormat,
+ const Extents &size,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ASSERT(TextureTargetToType(target) == mState.mType);
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ ANGLE_TRY(releaseTexImageInternal(context));
+
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ ANGLE_TRY(orphanImages(context, &releaseImage));
+
+ ImageIndex index = ImageIndex::MakeFromTarget(target, level, size.depth);
+
+ ANGLE_TRY(mTexture->setCompressedImage(context, index, internalFormat, size, unpackState,
+ imageSize, pixels));
+
+ Buffer *unpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
+
+ InitState initState = DetermineInitState(context, unpackBuffer, pixels);
+ mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat), initState));
+ signalDirtyStorage(initState);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::setCompressedSubImage(const Context *context,
+ const PixelUnpackState &unpackState,
+ TextureTarget target,
+ GLint level,
+ const Box &area,
+ GLenum format,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ASSERT(TextureTargetToType(target) == mState.mType);
+
+ ImageIndex index = ImageIndex::MakeFromTarget(target, level, area.depth);
+ ANGLE_TRY(ensureSubImageInitialized(context, index, area));
+
+ ANGLE_TRY(mTexture->setCompressedSubImage(context, index, area, format, unpackState, imageSize,
+ pixels));
+
+ onStateChange(angle::SubjectMessage::ContentsChanged);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::copyImage(Context *context,
+ TextureTarget target,
+ GLint level,
+ const Rectangle &sourceArea,
+ GLenum internalFormat,
+ Framebuffer *source)
+{
+ ASSERT(TextureTargetToType(target) == mState.mType);
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ ANGLE_TRY(releaseTexImageInternal(context));
+
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ ANGLE_TRY(orphanImages(context, &releaseImage));
+
+ ImageIndex index = ImageIndex::MakeFromTarget(target, level, 1);
+
+ const InternalFormat &internalFormatInfo =
+ GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
+
+ // Most if not all renderers clip these copies to the size of the source framebuffer, leaving
+ // other pixels untouched. For safety in robust resource initialization, assume that that
+ // clipping is going to occur when computing the region for which to ensure initialization. If
+ // the copy lies entirely off the source framebuffer, initialize as though a zero-size box is
+ // going to be set during the copy operation.
+ Box destBox;
+ bool forceCopySubImage = false;
+ if (context->isRobustResourceInitEnabled())
+ {
+ const FramebufferAttachment *sourceReadAttachment = source->getReadColorAttachment();
+ Extents fbSize = sourceReadAttachment->getSize();
+ // Force using copySubImage when the source area is out of bounds AND
+ // we're not copying to and from the same texture
+ forceCopySubImage = ((sourceArea.x < 0) || (sourceArea.y < 0) ||
+ ((sourceArea.x + sourceArea.width) > fbSize.width) ||
+ ((sourceArea.y + sourceArea.height) > fbSize.height)) &&
+ (sourceReadAttachment->getResource() != this);
+ Rectangle clippedArea;
+ if (ClipRectangle(sourceArea, Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
+ {
+ const Offset clippedOffset(clippedArea.x - sourceArea.x, clippedArea.y - sourceArea.y,
+ 0);
+ destBox = Box(clippedOffset.x, clippedOffset.y, clippedOffset.z, clippedArea.width,
+ clippedArea.height, 1);
+ }
+ }
+
+ InitState initState = DetermineInitState(context, nullptr, nullptr);
+
+ // If we need to initialize the destination texture we split the call into a create call,
+ // an initializeContents call, and then a copySubImage call. This ensures the destination
+ // texture exists before we try to clear it.
+ Extents size(sourceArea.width, sourceArea.height, 1);
+ if (forceCopySubImage || doesSubImageNeedInit(context, index, destBox))
+ {
+ ANGLE_TRY(mTexture->setImage(context, index, internalFormat, size,
+ internalFormatInfo.format, internalFormatInfo.type,
+ PixelUnpackState(), nullptr, nullptr));
+ mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormatInfo), initState));
+ ANGLE_TRY(ensureSubImageInitialized(context, index, destBox));
+ ANGLE_TRY(mTexture->copySubImage(context, index, Offset(), sourceArea, source));
+ }
+ else
+ {
+ ANGLE_TRY(mTexture->copyImage(context, index, sourceArea, internalFormat, source));
+ }
+
+ mState.setImageDesc(target, level,
+ ImageDesc(size, Format(internalFormatInfo), InitState::Initialized));
+
+ ANGLE_TRY(handleMipmapGenerationHint(context, level));
+
+ // Because this could affect the texture storage we might need to init other layers/levels.
+ signalDirtyStorage(initState);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::copySubImage(Context *context,
+ const ImageIndex &index,
+ const Offset &destOffset,
+ const Rectangle &sourceArea,
+ Framebuffer *source)
+{
+ ASSERT(TextureTargetToType(index.getTarget()) == mState.mType);
+
+ // Most if not all renderers clip these copies to the size of the source framebuffer, leaving
+ // other pixels untouched. For safety in robust resource initialization, assume that that
+ // clipping is going to occur when computing the region for which to ensure initialization. If
+ // the copy lies entirely off the source framebuffer, initialize as though a zero-size box is
+ // going to be set during the copy operation. Note that this assumes that
+ // ensureSubImageInitialized ensures initialization of the entire destination texture, and not
+ // just a sub-region.
+ Box destBox;
+ if (context->isRobustResourceInitEnabled())
+ {
+ Extents fbSize = source->getReadColorAttachment()->getSize();
+ Rectangle clippedArea;
+ if (ClipRectangle(sourceArea, Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
+ {
+ const Offset clippedOffset(destOffset.x + clippedArea.x - sourceArea.x,
+ destOffset.y + clippedArea.y - sourceArea.y, 0);
+ destBox = Box(clippedOffset.x, clippedOffset.y, clippedOffset.z, clippedArea.width,
+ clippedArea.height, 1);
+ }
+ }
+
+ ANGLE_TRY(ensureSubImageInitialized(context, index, destBox));
+
+ ANGLE_TRY(mTexture->copySubImage(context, index, destOffset, sourceArea, source));
+ ANGLE_TRY(handleMipmapGenerationHint(context, index.getLevelIndex()));
+
+ onStateChange(angle::SubjectMessage::ContentsChanged);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::copyRenderbufferSubData(Context *context,
+ const gl::Renderbuffer *srcBuffer,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth)
+{
+ ANGLE_TRY(mTexture->copyRenderbufferSubData(context, srcBuffer, srcLevel, srcX, srcY, srcZ,
+ dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight,
+ srcDepth));
+
+ signalDirtyStorage(InitState::Initialized);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::copyTextureSubData(Context *context,
+ const gl::Texture *srcTexture,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth)
+{
+ ANGLE_TRY(mTexture->copyTextureSubData(context, srcTexture, srcLevel, srcX, srcY, srcZ,
+ dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight,
+ srcDepth));
+
+ signalDirtyStorage(InitState::Initialized);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::copyTexture(Context *context,
+ TextureTarget target,
+ GLint level,
+ GLenum internalFormat,
+ GLenum type,
+ GLint sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ Texture *source)
+{
+ ASSERT(TextureTargetToType(target) == mState.mType);
+ ASSERT(source->getType() != TextureType::CubeMap);
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ ANGLE_TRY(releaseTexImageInternal(context));
+
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ ANGLE_TRY(orphanImages(context, &releaseImage));
+
+ // Initialize source texture.
+ // Note: we don't have a way to notify which portions of the image changed currently.
+ ANGLE_TRY(source->ensureInitialized(context));
+
+ ImageIndex index = ImageIndex::MakeFromTarget(target, level, ImageIndex::kEntireLevel);
+
+ ANGLE_TRY(mTexture->copyTexture(context, index, internalFormat, type, sourceLevel, unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha, source));
+
+ const auto &sourceDesc =
+ source->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), sourceLevel);
+ const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
+ mState.setImageDesc(
+ target, level,
+ ImageDesc(sourceDesc.size, Format(internalFormatInfo), InitState::Initialized));
+
+ signalDirtyStorage(InitState::Initialized);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::copySubTexture(const Context *context,
+ TextureTarget target,
+ GLint level,
+ const Offset &destOffset,
+ GLint sourceLevel,
+ const Box &sourceBox,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ Texture *source)
+{
+ ASSERT(TextureTargetToType(target) == mState.mType);
+
+ // Ensure source is initialized.
+ ANGLE_TRY(source->ensureInitialized(context));
+
+ Box destBox(destOffset.x, destOffset.y, destOffset.z, sourceBox.width, sourceBox.height,
+ sourceBox.depth);
+ ImageIndex index = ImageIndex::MakeFromTarget(target, level, sourceBox.depth);
+ ANGLE_TRY(ensureSubImageInitialized(context, index, destBox));
+
+ ANGLE_TRY(mTexture->copySubTexture(context, index, destOffset, sourceLevel, sourceBox,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
+ source));
+
+ onStateChange(angle::SubjectMessage::ContentsChanged);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::copyCompressedTexture(Context *context, const Texture *source)
+{
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ ANGLE_TRY(releaseTexImageInternal(context));
+
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ ANGLE_TRY(orphanImages(context, &releaseImage));
+
+ ANGLE_TRY(mTexture->copyCompressedTexture(context, source));
+
+ ASSERT(source->getType() != TextureType::CubeMap && getType() != TextureType::CubeMap);
+ const auto &sourceDesc =
+ source->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), 0);
+ mState.setImageDesc(NonCubeTextureTypeToTarget(getType()), 0, sourceDesc);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::setStorage(Context *context,
+ TextureType type,
+ GLsizei levels,
+ GLenum internalFormat,
+ const Extents &size)
+{
+ ASSERT(type == mState.mType);
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ ANGLE_TRY(releaseTexImageInternal(context));
+
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ ANGLE_TRY(orphanImages(context, &releaseImage));
+
+ mState.mImmutableFormat = true;
+ mState.mImmutableLevels = static_cast<GLuint>(levels);
+ mState.clearImageDescs();
+ InitState initState = DetermineInitState(context, nullptr, nullptr);
+ mState.setImageDescChain(0, static_cast<GLuint>(levels - 1), size, Format(internalFormat),
+ initState);
+
+ ANGLE_TRY(mTexture->setStorage(context, type, levels, internalFormat, size));
+
+ // Changing the texture to immutable can trigger a change in the base and max levels:
+ // GLES 3.0.4 section 3.8.10 pg 158:
+ // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
+ // clamped to the range[levelbase;levels].
+ mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
+ mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);
+
+ signalDirtyStorage(initState);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::setImageExternal(Context *context,
+ TextureTarget target,
+ GLint level,
+ GLenum internalFormat,
+ const Extents &size,
+ GLenum format,
+ GLenum type)
+{
+ ASSERT(TextureTargetToType(target) == mState.mType);
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ ANGLE_TRY(releaseTexImageInternal(context));
+
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ ANGLE_TRY(orphanImages(context, &releaseImage));
+
+ ImageIndex index = ImageIndex::MakeFromTarget(target, level, size.depth);
+
+ ANGLE_TRY(mTexture->setImageExternal(context, index, internalFormat, size, format, type));
+
+ InitState initState = InitState::Initialized;
+ mState.setImageDesc(target, level, ImageDesc(size, Format(internalFormat, type), initState));
+
+ ANGLE_TRY(handleMipmapGenerationHint(context, level));
+
+ signalDirtyStorage(initState);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::setStorageMultisample(Context *context,
+ TextureType type,
+ GLsizei samplesIn,
+ GLint internalFormat,
+ const Extents &size,
+ bool fixedSampleLocations)
+{
+ ASSERT(type == mState.mType);
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ ANGLE_TRY(releaseTexImageInternal(context));
+
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ ANGLE_TRY(orphanImages(context, &releaseImage));
+
+ // Potentially adjust "samples" to a supported value
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
+ GLsizei samples = formatCaps.getNearestSamples(samplesIn);
+
+ mState.mImmutableFormat = true;
+ mState.mImmutableLevels = static_cast<GLuint>(1);
+ mState.clearImageDescs();
+ InitState initState = DetermineInitState(context, nullptr, nullptr);
+ mState.setImageDescChainMultisample(size, Format(internalFormat), samples, fixedSampleLocations,
+ initState);
+
+ ANGLE_TRY(mTexture->setStorageMultisample(context, type, samples, internalFormat, size,
+ fixedSampleLocations));
+ signalDirtyStorage(initState);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::setStorageExternalMemory(Context *context,
+ TextureType type,
+ GLsizei levels,
+ GLenum internalFormat,
+ const Extents &size,
+ MemoryObject *memoryObject,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext)
+{
+ ASSERT(type == mState.mType);
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ ANGLE_TRY(releaseTexImageInternal(context));
+
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ ANGLE_TRY(orphanImages(context, &releaseImage));
+
+ ANGLE_TRY(mTexture->setStorageExternalMemory(context, type, levels, internalFormat, size,
+ memoryObject, offset, createFlags, usageFlags,
+ imageCreateInfoPNext));
+
+ mState.mImmutableFormat = true;
+ mState.mImmutableLevels = static_cast<GLuint>(levels);
+ mState.clearImageDescs();
+ mState.setImageDescChain(0, static_cast<GLuint>(levels - 1), size, Format(internalFormat),
+ InitState::Initialized);
+
+ // Changing the texture to immutable can trigger a change in the base and max levels:
+ // GLES 3.0.4 section 3.8.10 pg 158:
+ // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
+ // clamped to the range[levelbase;levels].
+ mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
+ mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);
+
+ signalDirtyStorage(InitState::Initialized);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::generateMipmap(Context *context)
+{
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ ANGLE_TRY(releaseTexImageInternal(context));
+
+ // EGL_KHR_gl_image states that images are only orphaned when generating mipmaps if the texture
+ // is not mip complete.
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ if (!isMipmapComplete())
+ {
+ ANGLE_TRY(orphanImages(context, &releaseImage));
+ }
+
+ const GLuint baseLevel = mState.getEffectiveBaseLevel();
+ const GLuint maxLevel = mState.getMipmapMaxLevel();
+
+ if (maxLevel <= baseLevel)
+ {
+ return angle::Result::Continue;
+ }
+
+ // If any dimension is zero, this is a no-op:
+ //
+ // > Otherwise, if level_base is not defined, or if any dimension is zero, all mipmap levels are
+ // > left unchanged. This is not an error.
+ const ImageDesc &baseImageInfo = mState.getImageDesc(mState.getBaseImageTarget(), baseLevel);
+ if (baseImageInfo.size.empty())
+ {
+ return angle::Result::Continue;
+ }
+
+ // Clear the base image(s) immediately if needed
+ if (context->isRobustResourceInitEnabled())
+ {
+ ImageIndexIterator it =
+ ImageIndexIterator::MakeGeneric(mState.mType, baseLevel, baseLevel + 1,
+ ImageIndex::kEntireLevel, ImageIndex::kEntireLevel);
+ while (it.hasNext())
+ {
+ const ImageIndex index = it.next();
+ const ImageDesc &desc = mState.getImageDesc(index.getTarget(), index.getLevelIndex());
+
+ if (desc.initState == InitState::MayNeedInit)
+ {
+ ANGLE_TRY(initializeContents(context, GL_NONE, index));
+ }
+ }
+ }
+
+ ANGLE_TRY(syncState(context, Command::GenerateMipmap));
+ ANGLE_TRY(mTexture->generateMipmap(context));
+
+ // Propagate the format and size of the base mip to the smaller ones. Cube maps are guaranteed
+ // to have faces of the same size and format so any faces can be picked.
+ mState.setImageDescChain(baseLevel, maxLevel, baseImageInfo.size, baseImageInfo.format,
+ InitState::Initialized);
+
+ signalDirtyStorage(InitState::Initialized);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::bindTexImageFromSurface(Context *context, egl::Surface *surface)
+{
+ ASSERT(surface);
+
+ if (mBoundSurface)
+ {
+ ANGLE_TRY(releaseTexImageFromSurface(context));
+ }
+
+ mBoundSurface = surface;
+
+ // Set the image info to the size and format of the surface
+ ASSERT(mState.mType == TextureType::_2D || mState.mType == TextureType::Rectangle);
+ Extents size(surface->getWidth(), surface->getHeight(), 1);
+ ImageDesc desc(size, surface->getBindTexImageFormat(), InitState::Initialized);
+ mState.setImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0, desc);
+ mState.mHasProtectedContent = surface->hasProtectedContent();
+
+ ANGLE_TRY(mTexture->bindTexImage(context, surface));
+
+ signalDirtyStorage(InitState::Initialized);
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::releaseTexImageFromSurface(const Context *context)
+{
+ ASSERT(mBoundSurface);
+ mBoundSurface = nullptr;
+ ANGLE_TRY(mTexture->releaseTexImage(context));
+
+ // Erase the image info for level 0
+ ASSERT(mState.mType == TextureType::_2D || mState.mType == TextureType::Rectangle);
+ mState.clearImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0);
+ mState.mHasProtectedContent = false;
+ signalDirtyStorage(InitState::Initialized);
+ return angle::Result::Continue;
+}
+
+void Texture::bindStream(egl::Stream *stream)
+{
+ ASSERT(stream);
+
+ // It should not be possible to bind a texture already bound to another stream
+ ASSERT(mBoundStream == nullptr);
+
+ mBoundStream = stream;
+
+ ASSERT(mState.mType == TextureType::External);
+}
+
+void Texture::releaseStream()
+{
+ ASSERT(mBoundStream);
+ mBoundStream = nullptr;
+}
+
+angle::Result Texture::acquireImageFromStream(const Context *context,
+ const egl::Stream::GLTextureDescription &desc)
+{
+ ASSERT(mBoundStream != nullptr);
+ ANGLE_TRY(mTexture->setImageExternal(context, mState.mType, mBoundStream, desc));
+
+ Extents size(desc.width, desc.height, 1);
+ mState.setImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0,
+ ImageDesc(size, Format(desc.internalFormat), InitState::Initialized));
+ signalDirtyStorage(InitState::Initialized);
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::releaseImageFromStream(const Context *context)
+{
+ ASSERT(mBoundStream != nullptr);
+ ANGLE_TRY(mTexture->setImageExternal(context, mState.mType, nullptr,
+ egl::Stream::GLTextureDescription()));
+
+ // Set to incomplete
+ mState.clearImageDesc(NonCubeTextureTypeToTarget(mState.mType), 0);
+ signalDirtyStorage(InitState::Initialized);
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::releaseTexImageInternal(Context *context)
+{
+ if (mBoundSurface)
+ {
+ // Notify the surface
+ egl::Error eglErr = mBoundSurface->releaseTexImageFromTexture(context);
+ // TODO(jmadill): Remove this once refactor is complete. http://anglebug.com/3041
+ if (eglErr.isError())
+ {
+ context->handleError(GL_INVALID_OPERATION, "Error releasing tex image from texture",
+ __FILE__, ANGLE_FUNCTION, __LINE__);
+ }
+
+ // Then, call the same method as from the surface
+ ANGLE_TRY(releaseTexImageFromSurface(context));
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::setEGLImageTargetImpl(Context *context,
+ TextureType type,
+ GLuint levels,
+ egl::Image *imageTarget)
+{
+ ASSERT(type == mState.mType);
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ ANGLE_TRY(releaseTexImageInternal(context));
+
+ egl::RefCountObjectReleaser<egl::Image> releaseImage;
+ ANGLE_TRY(orphanImages(context, &releaseImage));
+
+ setTargetImage(context, imageTarget);
+
+ auto initState = imageTarget->sourceInitState();
+
+ mState.clearImageDescs();
+ mState.setImageDescChain(0, levels - 1, imageTarget->getExtents(), imageTarget->getFormat(),
+ initState);
+ mState.mHasProtectedContent = imageTarget->hasProtectedContent();
+
+ ANGLE_TRY(mTexture->setEGLImageTarget(context, type, imageTarget));
+
+ signalDirtyStorage(initState);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::setEGLImageTarget(Context *context,
+ TextureType type,
+ egl::Image *imageTarget)
+{
+ ASSERT(type == TextureType::_2D || type == TextureType::External ||
+ type == TextureType::_2DArray);
+
+ return setEGLImageTargetImpl(context, type, 1u, imageTarget);
+}
+
+angle::Result Texture::setStorageEGLImageTarget(Context *context,
+ TextureType type,
+ egl::Image *imageTarget,
+ const GLint *attrib_list)
+{
+ ASSERT(type == TextureType::External || type == TextureType::_3D || type == TextureType::_2D ||
+ type == TextureType::_2DArray || type == TextureType::CubeMap ||
+ type == TextureType::CubeMapArray);
+
+ ANGLE_TRY(setEGLImageTargetImpl(context, type, imageTarget->getLevelCount(), imageTarget));
+
+ mState.mImmutableLevels = imageTarget->getLevelCount();
+ mState.mImmutableFormat = true;
+
+ // Changing the texture to immutable can trigger a change in the base and max levels:
+ // GLES 3.0.4 section 3.8.10 pg 158:
+ // "For immutable-format textures, levelbase is clamped to the range[0;levels],levelmax is then
+ // clamped to the range[levelbase;levels].
+ mDirtyBits.set(DIRTY_BIT_BASE_LEVEL);
+ mDirtyBits.set(DIRTY_BIT_MAX_LEVEL);
+
+ return angle::Result::Continue;
+}
+
+Extents Texture::getAttachmentSize(const ImageIndex &imageIndex) const
+{
+ // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
+ // we only allow querying ImageDesc on a complete cube map, and this ImageDesc is exactly the
+ // one that belongs to the first face of the cube map.
+ if (imageIndex.isEntireLevelCubeMap())
+ {
+ // A cube map texture is cube complete if the following conditions all hold true:
+ // - The levelbase arrays of each of the six texture images making up the cube map have
+ // identical, positive, and square dimensions.
+ if (!mState.isCubeComplete())
+ {
+ return Extents();
+ }
+ }
+
+ return mState.getImageDesc(imageIndex).size;
+}
+
+Format Texture::getAttachmentFormat(GLenum /*binding*/, const ImageIndex &imageIndex) const
+{
+ // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
+ // we only allow querying ImageDesc on a complete cube map, and this ImageDesc is exactly the
+ // one that belongs to the first face of the cube map.
+ if (imageIndex.isEntireLevelCubeMap())
+ {
+ // A cube map texture is cube complete if the following conditions all hold true:
+ // - The levelbase arrays were each specified with the same effective internal format.
+ if (!mState.isCubeComplete())
+ {
+ return Format::Invalid();
+ }
+ }
+ return mState.getImageDesc(imageIndex).format;
+}
+
+GLsizei Texture::getAttachmentSamples(const ImageIndex &imageIndex) const
+{
+ // We do not allow querying TextureTarget by an ImageIndex that represents an entire level of a
+ // cube map (See comments in function TextureTypeToTarget() in ImageIndex.cpp).
+ if (imageIndex.isEntireLevelCubeMap())
+ {
+ return 0;
+ }
+
+ return getSamples(imageIndex.getTarget(), imageIndex.getLevelIndex());
+}
+
+bool Texture::isRenderable(const Context *context,
+ GLenum binding,
+ const ImageIndex &imageIndex) const
+{
+ if (isEGLImageTarget())
+ {
+ return ImageSibling::isRenderable(context, binding, imageIndex);
+ }
+
+ // Surfaces bound to textures are always renderable. This avoids issues with surfaces with ES3+
+ // formats not being renderable when bound to textures in ES2 contexts.
+ if (mBoundSurface)
+ {
+ return true;
+ }
+
+ return getAttachmentFormat(binding, imageIndex)
+ .info->textureAttachmentSupport(context->getClientVersion(), context->getExtensions());
+}
+
+bool Texture::getAttachmentFixedSampleLocations(const ImageIndex &imageIndex) const
+{
+ // We do not allow querying TextureTarget by an ImageIndex that represents an entire level of a
+ // cube map (See comments in function TextureTypeToTarget() in ImageIndex.cpp).
+ if (imageIndex.isEntireLevelCubeMap())
+ {
+ return true;
+ }
+
+ // ES3.1 (section 9.4) requires that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS should be
+ // the same for all attached textures.
+ return getFixedSampleLocations(imageIndex.getTarget(), imageIndex.getLevelIndex());
+}
+
+void Texture::setBorderColor(const Context *context, const ColorGeneric &color)
+{
+ mState.mSamplerState.setBorderColor(color);
+ signalDirtyState(DIRTY_BIT_BORDER_COLOR);
+}
+
+const ColorGeneric &Texture::getBorderColor() const
+{
+ return mState.mSamplerState.getBorderColor();
+}
+
+GLint Texture::getRequiredTextureImageUnits(const Context *context) const
+{
+ // Only external texture types can return non-1.
+ if (mState.mType != TextureType::External)
+ {
+ return 1;
+ }
+
+ return mTexture->getRequiredExternalTextureImageUnits(context);
+}
+
+void Texture::setCrop(const Rectangle &rect)
+{
+ mState.setCrop(rect);
+}
+
+const Rectangle &Texture::getCrop() const
+{
+ return mState.getCrop();
+}
+
+void Texture::setGenerateMipmapHint(GLenum hint)
+{
+ mState.setGenerateMipmapHint(hint);
+}
+
+GLenum Texture::getGenerateMipmapHint() const
+{
+ return mState.getGenerateMipmapHint();
+}
+
+angle::Result Texture::setBuffer(const gl::Context *context,
+ gl::Buffer *buffer,
+ GLenum internalFormat)
+{
+ // Use 0 to indicate that the size is taken from whatever size the buffer has when the texture
+ // buffer is used.
+ return setBufferRange(context, buffer, internalFormat, 0, 0);
+}
+
+angle::Result Texture::setBufferRange(const gl::Context *context,
+ gl::Buffer *buffer,
+ GLenum internalFormat,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ mState.mImmutableFormat = true;
+ mState.mBuffer.set(context, buffer, offset, size);
+ ANGLE_TRY(mTexture->setBuffer(context, internalFormat));
+
+ mState.clearImageDescs();
+ if (buffer == nullptr)
+ {
+ mBufferObserver.reset();
+ InitState initState = DetermineInitState(context, nullptr, nullptr);
+ signalDirtyStorage(initState);
+ return angle::Result::Continue;
+ }
+
+ size = GetBoundBufferAvailableSize(mState.mBuffer);
+
+ mState.mImmutableLevels = static_cast<GLuint>(1);
+ InternalFormat internalFormatInfo = GetSizedInternalFormatInfo(internalFormat);
+ Format format(internalFormat);
+ Extents extents(static_cast<GLuint>(size / internalFormatInfo.pixelBytes), 1, 1);
+ InitState initState = buffer->initState();
+ mState.setImageDesc(TextureTarget::Buffer, 0, ImageDesc(extents, format, initState));
+
+ signalDirtyStorage(initState);
+
+ // Observe modifications to the buffer, so that extents can be updated.
+ mBufferObserver.bind(buffer);
+
+ return angle::Result::Continue;
+}
+
+const OffsetBindingPointer<Buffer> &Texture::getBuffer() const
+{
+ return mState.mBuffer;
+}
+
+void Texture::onAttach(const Context *context, rx::Serial framebufferSerial)
+{
+ addRef();
+
+ // Duplicates allowed for multiple attachment points. See the comment in the header.
+ mBoundFramebufferSerials.push_back(framebufferSerial);
+
+ if (!mState.mHasBeenBoundAsAttachment)
+ {
+ mDirtyBits.set(DIRTY_BIT_BOUND_AS_ATTACHMENT);
+ mState.mHasBeenBoundAsAttachment = true;
+ }
+}
+
+void Texture::onDetach(const Context *context, rx::Serial framebufferSerial)
+{
+ // Erase first instance. If there are multiple bindings, leave the others.
+ ASSERT(isBoundToFramebuffer(framebufferSerial));
+ mBoundFramebufferSerials.remove_and_permute(framebufferSerial);
+
+ release(context);
+}
+
+GLuint Texture::getId() const
+{
+ return id().value;
+}
+
+GLuint Texture::getNativeID() const
+{
+ return mTexture->getNativeID();
+}
+
+angle::Result Texture::syncState(const Context *context, Command source)
+{
+ ASSERT(hasAnyDirtyBit() || source == Command::GenerateMipmap);
+ ANGLE_TRY(mTexture->syncState(context, mDirtyBits, source));
+ mDirtyBits.reset();
+ mState.mInitState = InitState::Initialized;
+ return angle::Result::Continue;
+}
+
+rx::FramebufferAttachmentObjectImpl *Texture::getAttachmentImpl() const
+{
+ return mTexture;
+}
+
+bool Texture::isSamplerComplete(const Context *context, const Sampler *optionalSampler)
+{
+ const auto &samplerState =
+ optionalSampler ? optionalSampler->getSamplerState() : mState.mSamplerState;
+ const auto &contextState = context->getState();
+
+ if (contextState.getContextID() != mCompletenessCache.context ||
+ !mCompletenessCache.samplerState.sameCompleteness(samplerState))
+ {
+ mCompletenessCache.context = context->getState().getContextID();
+ mCompletenessCache.samplerState = samplerState;
+ mCompletenessCache.samplerComplete =
+ mState.computeSamplerCompleteness(samplerState, contextState);
+ }
+
+ return mCompletenessCache.samplerComplete;
+}
+
+// CopyImageSubData requires that we ignore format-based completeness rules
+bool Texture::isSamplerCompleteForCopyImage(const Context *context,
+ const Sampler *optionalSampler) const
+{
+ const gl::SamplerState &samplerState =
+ optionalSampler ? optionalSampler->getSamplerState() : mState.mSamplerState;
+ const gl::State &contextState = context->getState();
+ return mState.computeSamplerCompletenessForCopyImage(samplerState, contextState);
+}
+
+Texture::SamplerCompletenessCache::SamplerCompletenessCache()
+ : context({0}), samplerState(), samplerComplete(false)
+{}
+
+void Texture::invalidateCompletenessCache() const
+{
+ mCompletenessCache.context = {0};
+}
+
+angle::Result Texture::ensureInitialized(const Context *context)
+{
+ if (!context->isRobustResourceInitEnabled() || mState.mInitState == InitState::Initialized)
+ {
+ return angle::Result::Continue;
+ }
+
+ bool anyDirty = false;
+
+ ImageIndexIterator it =
+ ImageIndexIterator::MakeGeneric(mState.mType, 0, IMPLEMENTATION_MAX_TEXTURE_LEVELS + 1,
+ ImageIndex::kEntireLevel, ImageIndex::kEntireLevel);
+ while (it.hasNext())
+ {
+ const ImageIndex index = it.next();
+ ImageDesc &desc =
+ mState.mImageDescs[GetImageDescIndex(index.getTarget(), index.getLevelIndex())];
+ if (desc.initState == InitState::MayNeedInit && !desc.size.empty())
+ {
+ ASSERT(mState.mInitState == InitState::MayNeedInit);
+ ANGLE_TRY(initializeContents(context, GL_NONE, index));
+ desc.initState = InitState::Initialized;
+ anyDirty = true;
+ }
+ }
+ if (anyDirty)
+ {
+ signalDirtyStorage(InitState::Initialized);
+ }
+ mState.mInitState = InitState::Initialized;
+
+ return angle::Result::Continue;
+}
+
+InitState Texture::initState(GLenum /*binding*/, const ImageIndex &imageIndex) const
+{
+ // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
+ // we need to check all the related ImageDescs.
+ if (imageIndex.isEntireLevelCubeMap())
+ {
+ const GLint levelIndex = imageIndex.getLevelIndex();
+ for (TextureTarget cubeFaceTarget : AllCubeFaceTextureTargets())
+ {
+ if (mState.getImageDesc(cubeFaceTarget, levelIndex).initState == InitState::MayNeedInit)
+ {
+ return InitState::MayNeedInit;
+ }
+ }
+ return InitState::Initialized;
+ }
+
+ return mState.getImageDesc(imageIndex).initState;
+}
+
+void Texture::setInitState(GLenum binding, const ImageIndex &imageIndex, InitState initState)
+{
+ // As an ImageIndex that represents an entire level of a cube map corresponds to 6 ImageDescs,
+ // we need to update all the related ImageDescs.
+ if (imageIndex.isEntireLevelCubeMap())
+ {
+ const GLint levelIndex = imageIndex.getLevelIndex();
+ for (TextureTarget cubeFaceTarget : AllCubeFaceTextureTargets())
+ {
+ setInitState(binding, ImageIndex::MakeCubeMapFace(cubeFaceTarget, levelIndex),
+ initState);
+ }
+ }
+ else
+ {
+ ImageDesc newDesc = mState.getImageDesc(imageIndex);
+ newDesc.initState = initState;
+ mState.setImageDesc(imageIndex.getTarget(), imageIndex.getLevelIndex(), newDesc);
+ }
+}
+
+void Texture::setInitState(InitState initState)
+{
+ for (ImageDesc &imageDesc : mState.mImageDescs)
+ {
+ // Only modify defined images, undefined images will remain in the initialized state
+ if (!imageDesc.size.empty())
+ {
+ imageDesc.initState = initState;
+ }
+ }
+ mState.mInitState = initState;
+}
+
+bool Texture::doesSubImageNeedInit(const Context *context,
+ const ImageIndex &imageIndex,
+ const Box &area) const
+{
+ if (!context->isRobustResourceInitEnabled() || mState.mInitState == InitState::Initialized)
+ {
+ return false;
+ }
+
+ // Pre-initialize the texture contents if necessary.
+ const ImageDesc &desc = mState.getImageDesc(imageIndex);
+ if (desc.initState != InitState::MayNeedInit)
+ {
+ return false;
+ }
+
+ ASSERT(mState.mInitState == InitState::MayNeedInit);
+ return !area.coversSameExtent(desc.size);
+}
+
+angle::Result Texture::ensureSubImageInitialized(const Context *context,
+ const ImageIndex &imageIndex,
+ const Box &area)
+{
+ if (doesSubImageNeedInit(context, imageIndex, area))
+ {
+ // NOTE: do not optimize this to only initialize the passed area of the texture, or the
+ // initialization logic in copySubImage will be incorrect.
+ ANGLE_TRY(initializeContents(context, GL_NONE, imageIndex));
+ }
+ // Note: binding is ignored for textures.
+ setInitState(GL_NONE, imageIndex, InitState::Initialized);
+ return angle::Result::Continue;
+}
+
+angle::Result Texture::handleMipmapGenerationHint(Context *context, int level)
+{
+ if (getGenerateMipmapHint() == GL_TRUE && level == 0)
+ {
+ ANGLE_TRY(generateMipmap(context));
+ }
+
+ return angle::Result::Continue;
+}
+
+void Texture::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
+{
+ switch (message)
+ {
+ case angle::SubjectMessage::ContentsChanged:
+ if (index != kBufferSubjectIndex)
+ {
+ // ContentsChange originates from TextureStorage11::resolveAndReleaseTexture
+ // which resolves the underlying multisampled texture if it exists and so
+ // Texture will signal dirty storage to invalidate its own cache and the
+ // attached framebuffer's cache.
+ signalDirtyStorage(InitState::Initialized);
+ }
+ break;
+ case angle::SubjectMessage::DirtyBitsFlagged:
+ signalDirtyState(DIRTY_BIT_IMPLEMENTATION);
+
+ // Notify siblings that we are dirty.
+ if (index == rx::kTextureImageImplObserverMessageIndex)
+ {
+ notifySiblings(message);
+ }
+ break;
+ case angle::SubjectMessage::SubjectChanged:
+ mState.mInitState = InitState::MayNeedInit;
+ signalDirtyState(DIRTY_BIT_IMPLEMENTATION);
+ onStateChange(angle::SubjectMessage::ContentsChanged);
+
+ // Notify siblings that we are dirty.
+ if (index == rx::kTextureImageImplObserverMessageIndex)
+ {
+ notifySiblings(message);
+ }
+ else if (index == kBufferSubjectIndex)
+ {
+ const gl::Buffer *buffer = mState.mBuffer.get();
+ ASSERT(buffer != nullptr);
+
+ // Update cached image desc based on buffer size.
+ GLsizeiptr size = GetBoundBufferAvailableSize(mState.mBuffer);
+
+ ImageDesc desc = mState.getImageDesc(TextureTarget::Buffer, 0);
+ const GLuint pixelBytes = desc.format.info->pixelBytes;
+ desc.size.width = static_cast<GLuint>(size / pixelBytes);
+
+ mState.setImageDesc(TextureTarget::Buffer, 0, desc);
+ }
+ break;
+ case angle::SubjectMessage::StorageReleased:
+ // When the TextureStorage is released, it needs to update the
+ // RenderTargetCache of the Framebuffer attaching this Texture.
+ // This is currently only for D3D back-end. See http://crbug.com/1234829
+ if (index == rx::kTextureImageImplObserverMessageIndex)
+ {
+ onStateChange(angle::SubjectMessage::StorageReleased);
+ }
+ break;
+ case angle::SubjectMessage::SubjectMapped:
+ case angle::SubjectMessage::SubjectUnmapped:
+ case angle::SubjectMessage::BindingChanged:
+ ASSERT(index == kBufferSubjectIndex);
+ break;
+ case angle::SubjectMessage::InitializationComplete:
+ ASSERT(index == rx::kTextureImageImplObserverMessageIndex);
+ setInitState(InitState::Initialized);
+ break;
+ case angle::SubjectMessage::InternalMemoryAllocationChanged:
+ // Need to mark the texture dirty to give the back end a chance to handle the new
+ // buffer. For example, the Vulkan back end needs to create a new buffer view that
+ // points to the newly allocated buffer and update the texture descriptor set.
+ signalDirtyState(DIRTY_BIT_IMPLEMENTATION);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+GLenum Texture::getImplementationColorReadFormat(const Context *context) const
+{
+ return mTexture->getColorReadFormat(context);
+}
+
+GLenum Texture::getImplementationColorReadType(const Context *context) const
+{
+ return mTexture->getColorReadType(context);
+}
+
+bool Texture::isCompressedFormatEmulated(const Context *context,
+ TextureTarget target,
+ GLint level) const
+{
+ if (!getFormat(target, level).info->compressed)
+ {
+ // If it isn't compressed, the remaining logic won't work
+ return false;
+ }
+
+ GLenum implFormat = getImplementationColorReadFormat(context);
+
+ // Check against the list of formats used to emulate compressed textures
+ return IsEmulatedCompressedFormat(implFormat);
+}
+
+angle::Result Texture::getTexImage(const Context *context,
+ const PixelPackState &packState,
+ Buffer *packBuffer,
+ TextureTarget target,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ void *pixels)
+{
+ // No-op if the image level is empty.
+ if (getExtents(target, level).empty())
+ {
+ return angle::Result::Continue;
+ }
+
+ return mTexture->getTexImage(context, packState, packBuffer, target, level, format, type,
+ pixels);
+}
+
+angle::Result Texture::getCompressedTexImage(const Context *context,
+ const PixelPackState &packState,
+ Buffer *packBuffer,
+ TextureTarget target,
+ GLint level,
+ void *pixels)
+{
+ // No-op if the image level is empty.
+ if (getExtents(target, level).empty())
+ {
+ return angle::Result::Continue;
+ }
+
+ return mTexture->getCompressedTexImage(context, packState, packBuffer, target, level, pixels);
+}
+
+void Texture::onBindAsImageTexture()
+{
+ if (!mState.mHasBeenBoundAsImage)
+ {
+ mDirtyBits.set(DIRTY_BIT_BOUND_AS_IMAGE);
+ mState.mHasBeenBoundAsImage = true;
+ }
+}
+
+void Texture::onBind3DTextureAs2DImage()
+{
+ if (!mState.mIs3DAndHasBeenBoundAs2DImage)
+ {
+ mDirtyBits.set(DIRTY_BIT_BOUND_AS_IMAGE);
+ mState.mIs3DAndHasBeenBoundAs2DImage = true;
+ }
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Texture.h b/gfx/angle/checkout/src/libANGLE/Texture.h
new file mode 100644
index 0000000000..757f1a2e7e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Texture.h
@@ -0,0 +1,738 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Texture.h: Defines the gl::Texture class [OpenGL ES 2.0.24] section 3.7 page 63.
+
+#ifndef LIBANGLE_TEXTURE_H_
+#define LIBANGLE_TEXTURE_H_
+
+#include <map>
+#include <vector>
+
+#include "angle_gl.h"
+#include "common/Optional.h"
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Observer.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+
+namespace egl
+{
+class Surface;
+class Stream;
+} // namespace egl
+
+namespace rx
+{
+class GLImplFactory;
+class TextureImpl;
+class TextureGL;
+} // namespace rx
+
+namespace gl
+{
+class Framebuffer;
+class MemoryObject;
+class Sampler;
+class State;
+class Texture;
+
+constexpr GLuint kInitialMaxLevel = 1000;
+
+bool IsMipmapFiltered(GLenum minFilterMode);
+
+// Convert a given filter mode to nearest filtering.
+GLenum ConvertToNearestFilterMode(GLenum filterMode);
+
+// Convert a given filter mode to nearest mip filtering.
+GLenum ConvertToNearestMipFilterMode(GLenum filterMode);
+
+struct ImageDesc final
+{
+ ImageDesc();
+ ImageDesc(const Extents &size, const Format &format, const InitState initState);
+ ImageDesc(const Extents &size,
+ const Format &format,
+ const GLsizei samples,
+ const bool fixedSampleLocations,
+ const InitState initState);
+
+ ImageDesc(const ImageDesc &other) = default;
+ ImageDesc &operator=(const ImageDesc &other) = default;
+
+ GLint getMemorySize() const;
+
+ Extents size;
+ Format format;
+ GLsizei samples;
+ bool fixedSampleLocations;
+
+ // Needed for robust resource initialization.
+ InitState initState;
+};
+
+struct SwizzleState final
+{
+ SwizzleState();
+ SwizzleState(GLenum red, GLenum green, GLenum blue, GLenum alpha);
+ SwizzleState(const SwizzleState &other) = default;
+ SwizzleState &operator=(const SwizzleState &other) = default;
+
+ bool swizzleRequired() const;
+
+ bool operator==(const SwizzleState &other) const;
+ bool operator!=(const SwizzleState &other) const;
+
+ GLenum swizzleRed;
+ GLenum swizzleGreen;
+ GLenum swizzleBlue;
+ GLenum swizzleAlpha;
+};
+
+// State from Table 6.9 (state per texture object) in the OpenGL ES 3.0.2 spec.
+class TextureState final : private angle::NonCopyable
+{
+ public:
+ TextureState(TextureType type);
+ ~TextureState();
+
+ bool swizzleRequired() const;
+ GLuint getEffectiveBaseLevel() const;
+ GLuint getEffectiveMaxLevel() const;
+
+ // Returns the value called "q" in the GLES 3.0.4 spec section 3.8.10.
+ GLuint getMipmapMaxLevel() const;
+
+ // Returns true if base level changed.
+ bool setBaseLevel(GLuint baseLevel);
+ GLuint getBaseLevel() const { return mBaseLevel; }
+ bool setMaxLevel(GLuint maxLevel);
+ GLuint getMaxLevel() const { return mMaxLevel; }
+
+ bool isCubeComplete() const;
+
+ ANGLE_INLINE bool compatibleWithSamplerFormatForWebGL(SamplerFormat format,
+ const SamplerState &samplerState) const
+ {
+ if (!mCachedSamplerFormatValid ||
+ mCachedSamplerCompareMode != samplerState.getCompareMode())
+ {
+ mCachedSamplerFormat = computeRequiredSamplerFormat(samplerState);
+ mCachedSamplerCompareMode = samplerState.getCompareMode();
+ mCachedSamplerFormatValid = true;
+ }
+ // Incomplete textures are compatible with any sampler format.
+ return mCachedSamplerFormat == SamplerFormat::InvalidEnum || format == mCachedSamplerFormat;
+ }
+
+ const ImageDesc &getImageDesc(TextureTarget target, size_t level) const;
+ const ImageDesc &getImageDesc(const ImageIndex &imageIndex) const;
+
+ TextureType getType() const { return mType; }
+ const SwizzleState &getSwizzleState() const { return mSwizzleState; }
+ const SamplerState &getSamplerState() const { return mSamplerState; }
+ GLenum getUsage() const { return mUsage; }
+ bool hasProtectedContent() const { return mHasProtectedContent; }
+ GLenum getDepthStencilTextureMode() const { return mDepthStencilTextureMode; }
+ bool isStencilMode() const { return mDepthStencilTextureMode == GL_STENCIL_INDEX; }
+
+ bool hasBeenBoundAsImage() const { return mHasBeenBoundAsImage; }
+ bool is3DTextureAndHasBeenBoundAs2DImage() const { return mIs3DAndHasBeenBoundAs2DImage; }
+ bool hasBeenBoundAsAttachment() const { return mHasBeenBoundAsAttachment; }
+
+ gl::SrgbOverride getSRGBOverride() const { return mSrgbOverride; }
+
+ // Returns the desc of the base level. Only valid for cube-complete/mip-complete textures.
+ const ImageDesc &getBaseLevelDesc() const;
+ const ImageDesc &getLevelZeroDesc() const;
+
+ // GLES1 emulation: For GL_OES_draw_texture
+ void setCrop(const Rectangle &rect);
+ const Rectangle &getCrop() const;
+
+ // GLES1 emulation: Auto-mipmap generation is a texparameter
+ void setGenerateMipmapHint(GLenum hint);
+ GLenum getGenerateMipmapHint() const;
+
+ // Return the enabled mipmap level count.
+ GLuint getEnabledLevelCount() const;
+
+ bool getImmutableFormat() const { return mImmutableFormat; }
+ GLuint getImmutableLevels() const { return mImmutableLevels; }
+
+ const std::vector<ImageDesc> &getImageDescs() const { return mImageDescs; }
+
+ InitState getInitState() const { return mInitState; }
+
+ const OffsetBindingPointer<Buffer> &getBuffer() const { return mBuffer; }
+
+ const std::string &getLabel() const { return mLabel; }
+
+ private:
+ // Texture needs access to the ImageDesc functions.
+ friend class Texture;
+ friend bool operator==(const TextureState &a, const TextureState &b);
+
+ bool computeSamplerCompleteness(const SamplerState &samplerState, const State &state) const;
+ bool computeSamplerCompletenessForCopyImage(const SamplerState &samplerState,
+ const State &state) const;
+
+ bool computeMipmapCompleteness() const;
+ bool computeLevelCompleteness(TextureTarget target, size_t level) const;
+ SamplerFormat computeRequiredSamplerFormat(const SamplerState &samplerState) const;
+
+ TextureTarget getBaseImageTarget() const;
+
+ void setImageDesc(TextureTarget target, size_t level, const ImageDesc &desc);
+ void setImageDescChain(GLuint baselevel,
+ GLuint maxLevel,
+ Extents baseSize,
+ const Format &format,
+ InitState initState);
+ void setImageDescChainMultisample(Extents baseSize,
+ const Format &format,
+ GLsizei samples,
+ bool fixedSampleLocations,
+ InitState initState);
+
+ void clearImageDesc(TextureTarget target, size_t level);
+ void clearImageDescs();
+
+ const TextureType mType;
+
+ SwizzleState mSwizzleState;
+
+ SamplerState mSamplerState;
+
+ SrgbOverride mSrgbOverride;
+
+ GLuint mBaseLevel;
+ GLuint mMaxLevel;
+
+ GLenum mDepthStencilTextureMode;
+
+ bool mHasBeenBoundAsImage;
+ bool mIs3DAndHasBeenBoundAs2DImage;
+ bool mHasBeenBoundAsAttachment;
+
+ bool mImmutableFormat;
+ GLuint mImmutableLevels;
+
+ // From GL_ANGLE_texture_usage
+ GLenum mUsage;
+
+ // GL_EXT_protected_textures
+ bool mHasProtectedContent;
+
+ std::vector<ImageDesc> mImageDescs;
+
+ // GLES1 emulation: Texture crop rectangle
+ // For GL_OES_draw_texture
+ Rectangle mCropRect;
+
+ // GLES1 emulation: Generate-mipmap hint per texture
+ GLenum mGenerateMipmapHint;
+
+ // GL_OES_texture_buffer / GLES3.2
+ OffsetBindingPointer<Buffer> mBuffer;
+
+ InitState mInitState;
+
+ mutable SamplerFormat mCachedSamplerFormat;
+ mutable GLenum mCachedSamplerCompareMode;
+ mutable bool mCachedSamplerFormatValid;
+ std::string mLabel;
+};
+
+bool operator==(const TextureState &a, const TextureState &b);
+bool operator!=(const TextureState &a, const TextureState &b);
+
+class Texture final : public RefCountObject<TextureID>,
+ public egl::ImageSibling,
+ public LabeledObject
+{
+ public:
+ Texture(rx::GLImplFactory *factory, TextureID id, TextureType type);
+ ~Texture() override;
+
+ void onDestroy(const Context *context) override;
+
+ angle::Result setLabel(const Context *context, const std::string &label) override;
+
+ const std::string &getLabel() const override;
+
+ TextureType getType() const { return mState.mType; }
+
+ void setSwizzleRed(const Context *context, GLenum swizzleRed);
+ GLenum getSwizzleRed() const;
+
+ void setSwizzleGreen(const Context *context, GLenum swizzleGreen);
+ GLenum getSwizzleGreen() const;
+
+ void setSwizzleBlue(const Context *context, GLenum swizzleBlue);
+ GLenum getSwizzleBlue() const;
+
+ void setSwizzleAlpha(const Context *context, GLenum swizzleAlpha);
+ GLenum getSwizzleAlpha() const;
+
+ void setMinFilter(const Context *context, GLenum minFilter);
+ GLenum getMinFilter() const;
+
+ void setMagFilter(const Context *context, GLenum magFilter);
+ GLenum getMagFilter() const;
+
+ void setWrapS(const Context *context, GLenum wrapS);
+ GLenum getWrapS() const;
+
+ void setWrapT(const Context *context, GLenum wrapT);
+ GLenum getWrapT() const;
+
+ void setWrapR(const Context *context, GLenum wrapR);
+ GLenum getWrapR() const;
+
+ void setMaxAnisotropy(const Context *context, float maxAnisotropy);
+ float getMaxAnisotropy() const;
+
+ void setMinLod(const Context *context, GLfloat minLod);
+ GLfloat getMinLod() const;
+
+ void setMaxLod(const Context *context, GLfloat maxLod);
+ GLfloat getMaxLod() const;
+
+ void setCompareMode(const Context *context, GLenum compareMode);
+ GLenum getCompareMode() const;
+
+ void setCompareFunc(const Context *context, GLenum compareFunc);
+ GLenum getCompareFunc() const;
+
+ void setSRGBDecode(const Context *context, GLenum sRGBDecode);
+ GLenum getSRGBDecode() const;
+
+ void setSRGBOverride(const Context *context, GLenum sRGBOverride);
+ GLenum getSRGBOverride() const;
+
+ const SamplerState &getSamplerState() const;
+
+ angle::Result setBaseLevel(const Context *context, GLuint baseLevel);
+ GLuint getBaseLevel() const;
+
+ void setMaxLevel(const Context *context, GLuint maxLevel);
+ GLuint getMaxLevel() const;
+
+ void setDepthStencilTextureMode(const Context *context, GLenum mode);
+ GLenum getDepthStencilTextureMode() const;
+
+ bool getImmutableFormat() const;
+
+ GLuint getImmutableLevels() const;
+
+ void setUsage(const Context *context, GLenum usage);
+ GLenum getUsage() const;
+
+ void setProtectedContent(Context *context, bool hasProtectedContent);
+ bool hasProtectedContent() const override;
+
+ const TextureState &getState() const { return mState; }
+
+ void setBorderColor(const Context *context, const ColorGeneric &color);
+ const ColorGeneric &getBorderColor() const;
+
+ angle::Result setBuffer(const Context *context, gl::Buffer *buffer, GLenum internalFormat);
+ angle::Result setBufferRange(const Context *context,
+ gl::Buffer *buffer,
+ GLenum internalFormat,
+ GLintptr offset,
+ GLsizeiptr size);
+ const OffsetBindingPointer<Buffer> &getBuffer() const;
+
+ GLint getRequiredTextureImageUnits(const Context *context) const;
+
+ const TextureState &getTextureState() const;
+
+ const Extents &getExtents(TextureTarget target, size_t level) const;
+ size_t getWidth(TextureTarget target, size_t level) const;
+ size_t getHeight(TextureTarget target, size_t level) const;
+ size_t getDepth(TextureTarget target, size_t level) const;
+ GLsizei getSamples(TextureTarget target, size_t level) const;
+ bool getFixedSampleLocations(TextureTarget target, size_t level) const;
+ const Format &getFormat(TextureTarget target, size_t level) const;
+
+ // Returns the value called "q" in the GLES 3.0.4 spec section 3.8.10.
+ GLuint getMipmapMaxLevel() const;
+
+ bool isMipmapComplete() const;
+
+ angle::Result setImage(Context *context,
+ const PixelUnpackState &unpackState,
+ Buffer *unpackBuffer,
+ TextureTarget target,
+ GLint level,
+ GLenum internalFormat,
+ const Extents &size,
+ GLenum format,
+ GLenum type,
+ const uint8_t *pixels);
+ angle::Result setSubImage(Context *context,
+ const PixelUnpackState &unpackState,
+ Buffer *unpackBuffer,
+ TextureTarget target,
+ GLint level,
+ const Box &area,
+ GLenum format,
+ GLenum type,
+ const uint8_t *pixels);
+
+ angle::Result setCompressedImage(Context *context,
+ const PixelUnpackState &unpackState,
+ TextureTarget target,
+ GLint level,
+ GLenum internalFormat,
+ const Extents &size,
+ size_t imageSize,
+ const uint8_t *pixels);
+ angle::Result setCompressedSubImage(const Context *context,
+ const PixelUnpackState &unpackState,
+ TextureTarget target,
+ GLint level,
+ const Box &area,
+ GLenum format,
+ size_t imageSize,
+ const uint8_t *pixels);
+
+ angle::Result copyImage(Context *context,
+ TextureTarget target,
+ GLint level,
+ const Rectangle &sourceArea,
+ GLenum internalFormat,
+ Framebuffer *source);
+ angle::Result copySubImage(Context *context,
+ const ImageIndex &index,
+ const Offset &destOffset,
+ const Rectangle &sourceArea,
+ Framebuffer *source);
+
+ angle::Result copyRenderbufferSubData(Context *context,
+ const gl::Renderbuffer *srcBuffer,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth);
+
+ angle::Result copyTextureSubData(Context *context,
+ const gl::Texture *srcTexture,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth);
+
+ angle::Result copyTexture(Context *context,
+ TextureTarget target,
+ GLint level,
+ GLenum internalFormat,
+ GLenum type,
+ GLint sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ Texture *source);
+ angle::Result copySubTexture(const Context *context,
+ TextureTarget target,
+ GLint level,
+ const Offset &destOffset,
+ GLint sourceLevel,
+ const Box &sourceBox,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ Texture *source);
+ angle::Result copyCompressedTexture(Context *context, const Texture *source);
+
+ angle::Result setStorage(Context *context,
+ TextureType type,
+ GLsizei levels,
+ GLenum internalFormat,
+ const Extents &size);
+
+ angle::Result setStorageMultisample(Context *context,
+ TextureType type,
+ GLsizei samplesIn,
+ GLint internalformat,
+ const Extents &size,
+ bool fixedSampleLocations);
+
+ angle::Result setStorageExternalMemory(Context *context,
+ TextureType type,
+ GLsizei levels,
+ GLenum internalFormat,
+ const Extents &size,
+ MemoryObject *memoryObject,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext);
+
+ angle::Result setImageExternal(Context *context,
+ TextureTarget target,
+ GLint level,
+ GLenum internalFormat,
+ const Extents &size,
+ GLenum format,
+ GLenum type);
+
+ angle::Result setEGLImageTarget(Context *context, TextureType type, egl::Image *imageTarget);
+
+ angle::Result setStorageEGLImageTarget(Context *context,
+ TextureType type,
+ egl::Image *image,
+ const GLint *attrib_list);
+
+ angle::Result generateMipmap(Context *context);
+
+ void onBindAsImageTexture();
+ void onBind3DTextureAs2DImage();
+
+ egl::Surface *getBoundSurface() const;
+ egl::Stream *getBoundStream() const;
+
+ GLint getMemorySize() const;
+ GLint getLevelMemorySize(TextureTarget target, GLint level) const;
+
+ void signalDirtyStorage(InitState initState);
+
+ bool isSamplerComplete(const Context *context, const Sampler *optionalSampler);
+ bool isSamplerCompleteForCopyImage(const Context *context,
+ const Sampler *optionalSampler) const;
+
+ GLenum getImplementationColorReadFormat(const Context *context) const;
+ GLenum getImplementationColorReadType(const Context *context) const;
+
+ bool isCompressedFormatEmulated(const Context *context,
+ TextureTarget target,
+ GLint level) const;
+
+ // We pass the pack buffer and state explicitly so they can be overridden during capture.
+ angle::Result getTexImage(const Context *context,
+ const PixelPackState &packState,
+ Buffer *packBuffer,
+ TextureTarget target,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ void *pixels);
+
+ angle::Result getCompressedTexImage(const Context *context,
+ const PixelPackState &packState,
+ Buffer *packBuffer,
+ TextureTarget target,
+ GLint level,
+ void *pixels);
+
+ rx::TextureImpl *getImplementation() const { return mTexture; }
+
+ // FramebufferAttachmentObject implementation
+ Extents getAttachmentSize(const ImageIndex &imageIndex) const override;
+ Format getAttachmentFormat(GLenum binding, const ImageIndex &imageIndex) const override;
+ GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const override;
+ bool isRenderable(const Context *context,
+ GLenum binding,
+ const ImageIndex &imageIndex) const override;
+
+ bool getAttachmentFixedSampleLocations(const ImageIndex &imageIndex) const;
+
+ // GLES1 emulation
+ void setCrop(const Rectangle &rect);
+ const Rectangle &getCrop() const;
+ void setGenerateMipmapHint(GLenum generate);
+ GLenum getGenerateMipmapHint() const;
+
+ void onAttach(const Context *context, rx::Serial framebufferSerial) override;
+ void onDetach(const Context *context, rx::Serial framebufferSerial) override;
+
+ // Used specifically for FramebufferAttachmentObject.
+ GLuint getId() const override;
+
+ GLuint getNativeID() const;
+
+ // Needed for robust resource init.
+ angle::Result ensureInitialized(const Context *context);
+ InitState initState(GLenum binding, const ImageIndex &imageIndex) const override;
+ InitState initState() const { return mState.mInitState; }
+ void setInitState(GLenum binding, const ImageIndex &imageIndex, InitState initState) override;
+ void setInitState(InitState initState);
+
+ bool isBoundToFramebuffer(rx::Serial framebufferSerial) const
+ {
+ for (size_t index = 0; index < mBoundFramebufferSerials.size(); ++index)
+ {
+ if (mBoundFramebufferSerials[index] == framebufferSerial)
+ return true;
+ }
+
+ return false;
+ }
+
+ bool isDepthOrStencil() const
+ {
+ return mState.getBaseLevelDesc().format.info->isDepthOrStencil();
+ }
+
+ enum DirtyBitType
+ {
+ // Sampler state
+ DIRTY_BIT_MIN_FILTER,
+ DIRTY_BIT_MAG_FILTER,
+ DIRTY_BIT_WRAP_S,
+ DIRTY_BIT_WRAP_T,
+ DIRTY_BIT_WRAP_R,
+ DIRTY_BIT_MAX_ANISOTROPY,
+ DIRTY_BIT_MIN_LOD,
+ DIRTY_BIT_MAX_LOD,
+ DIRTY_BIT_COMPARE_MODE,
+ DIRTY_BIT_COMPARE_FUNC,
+ DIRTY_BIT_SRGB_DECODE,
+ DIRTY_BIT_SRGB_OVERRIDE,
+ DIRTY_BIT_BORDER_COLOR,
+
+ // Texture state
+ DIRTY_BIT_SWIZZLE_RED,
+ DIRTY_BIT_SWIZZLE_GREEN,
+ DIRTY_BIT_SWIZZLE_BLUE,
+ DIRTY_BIT_SWIZZLE_ALPHA,
+ DIRTY_BIT_BASE_LEVEL,
+ DIRTY_BIT_MAX_LEVEL,
+ DIRTY_BIT_DEPTH_STENCIL_TEXTURE_MODE,
+
+ // Image state
+ DIRTY_BIT_BOUND_AS_IMAGE,
+ DIRTY_BIT_BOUND_AS_ATTACHMENT,
+
+ // Misc
+ DIRTY_BIT_USAGE,
+ DIRTY_BIT_IMPLEMENTATION,
+
+ DIRTY_BIT_COUNT,
+ };
+ using DirtyBits = angle::BitSet<DIRTY_BIT_COUNT>;
+
+ angle::Result syncState(const Context *context, Command source);
+ bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+ bool hasAnyDirtyBitExcludingBoundAsAttachmentBit() const
+ {
+ static constexpr DirtyBits kBoundAsAttachment = DirtyBits({DIRTY_BIT_BOUND_AS_ATTACHMENT});
+ return mDirtyBits.any() && mDirtyBits != kBoundAsAttachment;
+ }
+
+ // ObserverInterface implementation.
+ void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
+
+ private:
+ rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
+
+ // ANGLE-only method, used internally
+ friend class egl::Surface;
+ angle::Result bindTexImageFromSurface(Context *context, egl::Surface *surface);
+ angle::Result releaseTexImageFromSurface(const Context *context);
+
+ // ANGLE-only methods, used internally
+ friend class egl::Stream;
+ void bindStream(egl::Stream *stream);
+ void releaseStream();
+ angle::Result acquireImageFromStream(const Context *context,
+ const egl::Stream::GLTextureDescription &desc);
+ angle::Result releaseImageFromStream(const Context *context);
+
+ void invalidateCompletenessCache() const;
+ angle::Result releaseTexImageInternal(Context *context);
+
+ bool doesSubImageNeedInit(const Context *context,
+ const ImageIndex &imageIndex,
+ const Box &area) const;
+ angle::Result ensureSubImageInitialized(const Context *context,
+ const ImageIndex &imageIndex,
+ const Box &area);
+
+ angle::Result handleMipmapGenerationHint(Context *context, int level);
+
+ angle::Result setEGLImageTargetImpl(Context *context,
+ TextureType type,
+ GLuint levels,
+ egl::Image *imageTarget);
+
+ void signalDirtyState(size_t dirtyBit);
+
+ TextureState mState;
+ DirtyBits mDirtyBits;
+ rx::TextureImpl *mTexture;
+ angle::ObserverBinding mImplObserver;
+ // For EXT_texture_buffer, observes buffer changes.
+ angle::ObserverBinding mBufferObserver;
+
+ egl::Surface *mBoundSurface;
+ egl::Stream *mBoundStream;
+
+ // We track all the serials of the Framebuffers this texture is attached to. Note that this
+ // allows duplicates because different ranges of a Texture can be bound to the same Framebuffer.
+ // For the purposes of depth-stencil loops, a simple "isBound" check works fine. For color
+ // attachment Feedback Loop checks we then need to check further to see when a Texture is bound
+ // to mulitple bindings that the bindings don't overlap.
+ static constexpr uint32_t kFastFramebufferSerialCount = 8;
+ angle::FastVector<rx::Serial, kFastFramebufferSerialCount> mBoundFramebufferSerials;
+
+ struct SamplerCompletenessCache
+ {
+ SamplerCompletenessCache();
+
+ // Context used to generate this cache entry
+ ContextID context;
+
+ // All values that affect sampler completeness that are not stored within
+ // the texture itself
+ SamplerState samplerState;
+
+ // Result of the sampler completeness with the above parameters
+ bool samplerComplete;
+ };
+
+ mutable SamplerCompletenessCache mCompletenessCache;
+};
+
+inline bool operator==(const TextureState &a, const TextureState &b)
+{
+ return a.mSwizzleState == b.mSwizzleState && a.mSamplerState == b.mSamplerState &&
+ a.mBaseLevel == b.mBaseLevel && a.mMaxLevel == b.mMaxLevel &&
+ a.mImmutableFormat == b.mImmutableFormat && a.mImmutableLevels == b.mImmutableLevels &&
+ a.mUsage == b.mUsage;
+}
+
+inline bool operator!=(const TextureState &a, const TextureState &b)
+{
+ return !(a == b);
+}
+} // namespace gl
+
+#endif // LIBANGLE_TEXTURE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Thread.cpp b/gfx/angle/checkout/src/libANGLE/Thread.cpp
new file mode 100644
index 0000000000..7f5f65fa3c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Thread.cpp
@@ -0,0 +1,168 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Thread.cpp : Defines the Thread class which represents a global EGL thread.
+
+#include "libANGLE/Thread.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Error.h"
+
+namespace angle
+{
+#if defined(ANGLE_USE_ANDROID_TLS_SLOT)
+bool gUseAndroidOpenGLTlsSlot;
+#endif
+
+void PthreadKeyDestructorCallback(void *ptr)
+{
+ egl::Thread *thread = static_cast<egl::Thread *>(ptr);
+ ASSERT(thread);
+
+ egl::Display::EglDisplaySet displays = egl::Display::GetEglDisplaySet();
+ for (egl::Display *display : displays)
+ {
+ ASSERT(display);
+ // Perform necessary cleanup.
+ display->threadCleanup(thread);
+ }
+}
+} // namespace angle
+
+namespace egl
+{
+namespace
+{
+Debug *sDebug = nullptr;
+} // namespace
+
+Thread::Thread()
+ : mLabel(nullptr),
+ mError(EGL_SUCCESS),
+ mAPI(EGL_OPENGL_ES_API),
+ mContext(static_cast<gl::Context *>(EGL_NO_CONTEXT))
+{}
+
+void Thread::setLabel(EGLLabelKHR label)
+{
+ mLabel = label;
+}
+
+EGLLabelKHR Thread::getLabel() const
+{
+ return mLabel;
+}
+
+void Thread::setSuccess()
+{
+ mError = EGL_SUCCESS;
+}
+
+void Thread::setError(EGLint error,
+ const char *command,
+ const LabeledObject *object,
+ const char *message)
+{
+ mError = error;
+ if (error != EGL_SUCCESS && message)
+ {
+ EnsureDebugAllocated();
+ sDebug->insertMessage(error, command, ErrorCodeToMessageType(error), getLabel(),
+ object ? object->getLabel() : nullptr, message);
+ }
+}
+
+void Thread::setError(const Error &error, const char *command, const LabeledObject *object)
+{
+ mError = error.getCode();
+ if (error.isError() && !error.getMessage().empty())
+ {
+ EnsureDebugAllocated();
+ sDebug->insertMessage(error.getCode(), command, ErrorCodeToMessageType(error.getCode()),
+ getLabel(), object ? object->getLabel() : nullptr,
+ error.getMessage());
+ }
+}
+
+EGLint Thread::getError() const
+{
+ return mError;
+}
+
+void Thread::setAPI(EGLenum api)
+{
+ mAPI = api;
+}
+
+EGLenum Thread::getAPI() const
+{
+ return mAPI;
+}
+
+void Thread::setCurrent(gl::Context *context)
+{
+ mContext = context;
+ if (mContext)
+ {
+ ASSERT(mContext->getDisplay());
+ mContext->getDisplay()->addActiveThread(this);
+ }
+}
+
+Surface *Thread::getCurrentDrawSurface() const
+{
+ if (mContext)
+ {
+ return mContext->getCurrentDrawSurface();
+ }
+ return nullptr;
+}
+
+Surface *Thread::getCurrentReadSurface() const
+{
+ if (mContext)
+ {
+ return mContext->getCurrentReadSurface();
+ }
+ return nullptr;
+}
+
+gl::Context *Thread::getContext() const
+{
+ return mContext;
+}
+
+Display *Thread::getDisplay() const
+{
+ if (mContext)
+ {
+ return mContext->getDisplay();
+ }
+ return nullptr;
+}
+
+void EnsureDebugAllocated()
+{
+ // All EGL calls use a global lock, this is thread safe
+ if (sDebug == nullptr)
+ {
+ sDebug = new Debug();
+ }
+}
+
+void DeallocateDebug()
+{
+ SafeDelete(sDebug);
+}
+
+Debug *GetDebug()
+{
+ EnsureDebugAllocated();
+ return sDebug;
+}
+} // namespace egl
diff --git a/gfx/angle/checkout/src/libANGLE/Thread.h b/gfx/angle/checkout/src/libANGLE/Thread.h
new file mode 100644
index 0000000000..415c09bf37
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Thread.h
@@ -0,0 +1,80 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Thread.h : Defines the Thread class which represents a global EGL thread.
+
+#ifndef LIBANGLE_THREAD_H_
+#define LIBANGLE_THREAD_H_
+
+#include <EGL/egl.h>
+
+#include "libANGLE/Debug.h"
+
+#include <atomic>
+
+namespace angle
+{
+#if defined(ANGLE_USE_ANDROID_TLS_SLOT)
+extern bool gUseAndroidOpenGLTlsSlot;
+#endif
+
+void PthreadKeyDestructorCallback(void *ptr);
+} // namespace angle
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace egl
+{
+class Error;
+class Debug;
+class Display;
+class Surface;
+
+class Thread : public LabeledObject
+{
+ public:
+ Thread();
+
+ void setLabel(EGLLabelKHR label) override;
+ EGLLabelKHR getLabel() const override;
+
+ void setSuccess();
+
+ void setError(EGLint error,
+ const char *command,
+ const LabeledObject *object,
+ const char *message);
+
+ // TODO: Remove egl::Error. http://anglebug.com/3041
+ void setError(const Error &error, const char *command, const LabeledObject *object);
+ EGLint getError() const;
+
+ void setAPI(EGLenum api);
+ EGLenum getAPI() const;
+
+ void setCurrent(gl::Context *context);
+ Surface *getCurrentDrawSurface() const;
+ Surface *getCurrentReadSurface() const;
+ gl::Context *getContext() const;
+ Display *getDisplay() const;
+
+ private:
+ EGLLabelKHR mLabel;
+ EGLint mError;
+ EGLenum mAPI;
+ gl::Context *mContext;
+};
+
+void EnsureDebugAllocated();
+void DeallocateDebug();
+Debug *GetDebug();
+
+} // namespace egl
+
+#endif // LIBANGLE_THREAD_H_
diff --git a/gfx/angle/checkout/src/libANGLE/TransformFeedback.cpp b/gfx/angle/checkout/src/libANGLE/TransformFeedback.cpp
new file mode 100644
index 0000000000..af1875ac50
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/TransformFeedback.cpp
@@ -0,0 +1,347 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "libANGLE/TransformFeedback.h"
+
+#include "common/mathutil.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/State.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+
+#include <limits>
+
+namespace gl
+{
+
+angle::CheckedNumeric<GLsizeiptr> GetVerticesNeededForDraw(PrimitiveMode primitiveMode,
+ GLsizei count,
+ GLsizei primcount)
+{
+ if (count < 0 || primcount < 0)
+ {
+ return 0;
+ }
+ // Transform feedback only outputs complete primitives, so we need to round down to the nearest
+ // complete primitive before multiplying by the number of instances.
+ angle::CheckedNumeric<GLsizeiptr> checkedCount = count;
+ angle::CheckedNumeric<GLsizeiptr> checkedPrimcount = primcount;
+ switch (primitiveMode)
+ {
+ case PrimitiveMode::Triangles:
+ return checkedPrimcount * (checkedCount - checkedCount % 3);
+ case PrimitiveMode::Lines:
+ return checkedPrimcount * (checkedCount - checkedCount % 2);
+ case PrimitiveMode::Points:
+ return checkedPrimcount * checkedCount;
+ default:
+ UNREACHABLE();
+ return checkedPrimcount * checkedCount;
+ }
+}
+
+TransformFeedbackState::TransformFeedbackState(size_t maxIndexedBuffers)
+ : mLabel(),
+ mActive(false),
+ mPrimitiveMode(PrimitiveMode::InvalidEnum),
+ mPaused(false),
+ mVerticesDrawn(0),
+ mVertexCapacity(0),
+ mProgram(nullptr),
+ mIndexedBuffers(maxIndexedBuffers)
+{}
+
+TransformFeedbackState::~TransformFeedbackState() {}
+
+const OffsetBindingPointer<Buffer> &TransformFeedbackState::getIndexedBuffer(size_t idx) const
+{
+ return mIndexedBuffers[idx];
+}
+
+const std::vector<OffsetBindingPointer<Buffer>> &TransformFeedbackState::getIndexedBuffers() const
+{
+ return mIndexedBuffers;
+}
+
+GLsizeiptr TransformFeedbackState::getPrimitivesDrawn() const
+{
+ switch (mPrimitiveMode)
+ {
+ case gl::PrimitiveMode::Points:
+ return mVerticesDrawn;
+ case gl::PrimitiveMode::Lines:
+ return mVerticesDrawn / 2;
+ case gl::PrimitiveMode::Triangles:
+ return mVerticesDrawn / 3;
+ default:
+ return 0;
+ }
+}
+
+TransformFeedback::TransformFeedback(rx::GLImplFactory *implFactory,
+ TransformFeedbackID id,
+ const Caps &caps)
+ : RefCountObject(implFactory->generateSerial(), id),
+ mState(caps.maxTransformFeedbackSeparateAttributes),
+ mImplementation(implFactory->createTransformFeedback(mState))
+{
+ ASSERT(mImplementation != nullptr);
+}
+
+void TransformFeedback::onDestroy(const Context *context)
+{
+ ASSERT(!context || !context->isCurrentTransformFeedback(this));
+ if (mState.mProgram)
+ {
+ mState.mProgram->release(context);
+ mState.mProgram = nullptr;
+ }
+
+ ASSERT(!mState.mProgram);
+ for (size_t i = 0; i < mState.mIndexedBuffers.size(); i++)
+ {
+ mState.mIndexedBuffers[i].set(context, nullptr, 0, 0);
+ }
+
+ if (mImplementation)
+ {
+ mImplementation->onDestroy(context);
+ }
+}
+
+TransformFeedback::~TransformFeedback()
+{
+ SafeDelete(mImplementation);
+}
+
+angle::Result TransformFeedback::setLabel(const Context *context, const std::string &label)
+{
+ mState.mLabel = label;
+
+ if (mImplementation)
+ {
+ return mImplementation->onLabelUpdate(context);
+ }
+ return angle::Result::Continue;
+}
+
+const std::string &TransformFeedback::getLabel() const
+{
+ return mState.mLabel;
+}
+
+angle::Result TransformFeedback::begin(const Context *context,
+ PrimitiveMode primitiveMode,
+ Program *program)
+{
+ // TODO: http://anglebug.com/5486: This method should take in as parameter a
+ // ProgramExecutable instead of a Program.
+
+ ANGLE_TRY(mImplementation->begin(context, primitiveMode));
+ mState.mActive = true;
+ mState.mPrimitiveMode = primitiveMode;
+ mState.mPaused = false;
+ mState.mVerticesDrawn = 0;
+ bindProgram(context, program);
+
+ // In one of the angle_unittests - "TransformFeedbackTest.SideEffectsOfStartAndStop"
+ // there is a code path where <context> is a nullptr, account for that possiblity.
+ const ProgramExecutable *programExecutable =
+ context ? context->getState().getLinkedProgramExecutable(context) : nullptr;
+ if (programExecutable)
+ {
+ // Compute the number of vertices we can draw before overflowing the bound buffers.
+ auto strides = programExecutable->getTransformFeedbackStrides();
+ ASSERT(strides.size() <= mState.mIndexedBuffers.size() && !strides.empty());
+ GLsizeiptr minCapacity = std::numeric_limits<GLsizeiptr>::max();
+ for (size_t index = 0; index < strides.size(); index++)
+ {
+ GLsizeiptr capacity =
+ GetBoundBufferAvailableSize(mState.mIndexedBuffers[index]) / strides[index];
+ minCapacity = std::min(minCapacity, capacity);
+ }
+ mState.mVertexCapacity = minCapacity;
+ }
+ else
+ {
+ mState.mVertexCapacity = 0;
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result TransformFeedback::end(const Context *context)
+{
+ ANGLE_TRY(mImplementation->end(context));
+ mState.mActive = false;
+ mState.mPrimitiveMode = PrimitiveMode::InvalidEnum;
+ mState.mPaused = false;
+ mState.mVerticesDrawn = 0;
+ mState.mVertexCapacity = 0;
+ if (mState.mProgram)
+ {
+ mState.mProgram->release(context);
+ mState.mProgram = nullptr;
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result TransformFeedback::pause(const Context *context)
+{
+ ANGLE_TRY(mImplementation->pause(context));
+ mState.mPaused = true;
+ return angle::Result::Continue;
+}
+
+angle::Result TransformFeedback::resume(const Context *context)
+{
+ ANGLE_TRY(mImplementation->resume(context));
+ mState.mPaused = false;
+ return angle::Result::Continue;
+}
+
+bool TransformFeedback::isPaused() const
+{
+ return mState.mPaused;
+}
+
+PrimitiveMode TransformFeedback::getPrimitiveMode() const
+{
+ return mState.mPrimitiveMode;
+}
+
+bool TransformFeedback::checkBufferSpaceForDraw(GLsizei count, GLsizei primcount) const
+{
+ auto vertices =
+ mState.mVerticesDrawn + GetVerticesNeededForDraw(mState.mPrimitiveMode, count, primcount);
+ return vertices.IsValid() && vertices.ValueOrDie() <= mState.mVertexCapacity;
+}
+
+void TransformFeedback::onVerticesDrawn(const Context *context, GLsizei count, GLsizei primcount)
+{
+ ASSERT(mState.mActive && !mState.mPaused);
+ // All draws should be validated with checkBufferSpaceForDraw so ValueOrDie should never fail.
+ mState.mVerticesDrawn =
+ (mState.mVerticesDrawn + GetVerticesNeededForDraw(mState.mPrimitiveMode, count, primcount))
+ .ValueOrDie();
+
+ for (auto &buffer : mState.mIndexedBuffers)
+ {
+ if (buffer.get() != nullptr)
+ {
+ buffer->onDataChanged();
+ }
+ }
+}
+
+void TransformFeedback::bindProgram(const Context *context, Program *program)
+{
+ if (mState.mProgram != program)
+ {
+ if (mState.mProgram != nullptr)
+ {
+ mState.mProgram->release(context);
+ }
+ mState.mProgram = program;
+ if (mState.mProgram != nullptr)
+ {
+ mState.mProgram->addRef();
+ }
+ }
+}
+
+bool TransformFeedback::hasBoundProgram(ShaderProgramID program) const
+{
+ return mState.mProgram != nullptr && mState.mProgram->id().value == program.value;
+}
+
+angle::Result TransformFeedback::detachBuffer(const Context *context, BufferID bufferID)
+{
+ bool isBound = context->isCurrentTransformFeedback(this);
+ for (size_t index = 0; index < mState.mIndexedBuffers.size(); index++)
+ {
+ if (mState.mIndexedBuffers[index].id() == bufferID)
+ {
+ if (isBound)
+ {
+ mState.mIndexedBuffers[index]->onTFBindingChanged(context, false, true);
+ }
+ mState.mIndexedBuffers[index].set(context, nullptr, 0, 0);
+ ANGLE_TRY(
+ mImplementation->bindIndexedBuffer(context, index, mState.mIndexedBuffers[index]));
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TransformFeedback::bindIndexedBuffer(const Context *context,
+ size_t index,
+ Buffer *buffer,
+ size_t offset,
+ size_t size)
+{
+ ASSERT(index < mState.mIndexedBuffers.size());
+ bool isBound = context && context->isCurrentTransformFeedback(this);
+ if (isBound && mState.mIndexedBuffers[index].get())
+ {
+ mState.mIndexedBuffers[index]->onTFBindingChanged(context, false, true);
+ }
+ mState.mIndexedBuffers[index].set(context, buffer, offset, size);
+ if (isBound && buffer)
+ {
+ buffer->onTFBindingChanged(context, true, true);
+ }
+
+ return mImplementation->bindIndexedBuffer(context, index, mState.mIndexedBuffers[index]);
+}
+
+const OffsetBindingPointer<Buffer> &TransformFeedback::getIndexedBuffer(size_t index) const
+{
+ ASSERT(index < mState.mIndexedBuffers.size());
+ return mState.mIndexedBuffers[index];
+}
+
+size_t TransformFeedback::getIndexedBufferCount() const
+{
+ return mState.mIndexedBuffers.size();
+}
+
+bool TransformFeedback::buffersBoundForOtherUseInWebGL() const
+{
+ for (auto &buffer : mState.mIndexedBuffers)
+ {
+ if (buffer.get() && buffer->hasWebGLXFBBindingConflict(true))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+rx::TransformFeedbackImpl *TransformFeedback::getImplementation() const
+{
+ return mImplementation;
+}
+
+void TransformFeedback::onBindingChanged(const Context *context, bool bound)
+{
+ for (auto &buffer : mState.mIndexedBuffers)
+ {
+ if (buffer.get())
+ {
+ buffer->onTFBindingChanged(context, bound, true);
+ }
+ }
+}
+
+const std::vector<OffsetBindingPointer<Buffer>> &TransformFeedback::getIndexedBuffers() const
+{
+ return mState.mIndexedBuffers;
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/TransformFeedback.h b/gfx/angle/checkout/src/libANGLE/TransformFeedback.h
new file mode 100644
index 0000000000..e55d0054c1
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/TransformFeedback.h
@@ -0,0 +1,120 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef LIBANGLE_TRANSFORM_FEEDBACK_H_
+#define LIBANGLE_TRANSFORM_FEEDBACK_H_
+
+#include "libANGLE/RefCountObject.h"
+
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/Debug.h"
+
+#include "angle_gl.h"
+
+namespace rx
+{
+class GLImplFactory;
+class TransformFeedbackImpl;
+class TransformFeedbackGL;
+} // namespace rx
+
+namespace gl
+{
+class Buffer;
+struct Caps;
+class Context;
+class Program;
+
+class TransformFeedbackState final : angle::NonCopyable
+{
+ public:
+ TransformFeedbackState(size_t maxIndexedBuffers);
+ ~TransformFeedbackState();
+
+ const OffsetBindingPointer<Buffer> &getIndexedBuffer(size_t idx) const;
+ const std::vector<OffsetBindingPointer<Buffer>> &getIndexedBuffers() const;
+ const Program *getBoundProgram() const { return mProgram; }
+ GLsizeiptr getVerticesDrawn() const { return mVerticesDrawn; }
+ GLsizeiptr getPrimitivesDrawn() const;
+
+ private:
+ friend class TransformFeedback;
+
+ std::string mLabel;
+
+ bool mActive;
+ PrimitiveMode mPrimitiveMode;
+ bool mPaused;
+ GLsizeiptr mVerticesDrawn;
+ GLsizeiptr mVertexCapacity;
+
+ Program *mProgram;
+
+ std::vector<OffsetBindingPointer<Buffer>> mIndexedBuffers;
+};
+
+class TransformFeedback final : public RefCountObject<TransformFeedbackID>, public LabeledObject
+{
+ public:
+ TransformFeedback(rx::GLImplFactory *implFactory, TransformFeedbackID id, const Caps &caps);
+ ~TransformFeedback() override;
+ void onDestroy(const Context *context) override;
+
+ angle::Result setLabel(const Context *context, const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ angle::Result begin(const Context *context, PrimitiveMode primitiveMode, Program *program);
+ angle::Result end(const Context *context);
+ angle::Result pause(const Context *context);
+ angle::Result resume(const Context *context);
+
+ bool isActive() const { return mState.mActive; }
+
+ bool isPaused() const;
+ PrimitiveMode getPrimitiveMode() const;
+ // Validates that the vertices produced by a draw call will fit in the bound transform feedback
+ // buffers.
+ bool checkBufferSpaceForDraw(GLsizei count, GLsizei primcount) const;
+ // This must be called after each draw call when transform feedback is enabled to keep track of
+ // how many vertices have been written to the buffers. This information is needed by
+ // checkBufferSpaceForDraw because each draw call appends vertices to the buffers starting just
+ // after the last vertex of the previous draw call.
+ void onVerticesDrawn(const Context *context, GLsizei count, GLsizei primcount);
+
+ bool hasBoundProgram(ShaderProgramID program) const;
+
+ angle::Result bindIndexedBuffer(const Context *context,
+ size_t index,
+ Buffer *buffer,
+ size_t offset,
+ size_t size);
+ const OffsetBindingPointer<Buffer> &getIndexedBuffer(size_t index) const;
+ size_t getIndexedBufferCount() const;
+ const std::vector<OffsetBindingPointer<Buffer>> &getIndexedBuffers() const;
+
+ GLsizeiptr getVerticesDrawn() const { return mState.getVerticesDrawn(); }
+ GLsizeiptr getPrimitivesDrawn() const { return mState.getPrimitivesDrawn(); }
+
+ // Returns true if any buffer bound to this object is also bound to another target.
+ bool buffersBoundForOtherUseInWebGL() const;
+
+ angle::Result detachBuffer(const Context *context, BufferID bufferID);
+
+ rx::TransformFeedbackImpl *getImplementation() const;
+
+ void onBindingChanged(const Context *context, bool bound);
+
+ private:
+ void bindProgram(const Context *context, Program *program);
+
+ TransformFeedbackState mState;
+ rx::TransformFeedbackImpl *mImplementation;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_TRANSFORM_FEEDBACK_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Uniform.cpp b/gfx/angle/checkout/src/libANGLE/Uniform.cpp
new file mode 100644
index 0000000000..d41ed5698a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Uniform.cpp
@@ -0,0 +1,179 @@
+//
+// Copyright 2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "libANGLE/Uniform.h"
+
+#include <cstring>
+
+namespace gl
+{
+
+ActiveVariable::ActiveVariable() {}
+
+ActiveVariable::~ActiveVariable() {}
+
+ActiveVariable::ActiveVariable(const ActiveVariable &rhs) = default;
+ActiveVariable &ActiveVariable::operator=(const ActiveVariable &rhs) = default;
+
+void ActiveVariable::setActive(ShaderType shaderType, bool used)
+{
+ ASSERT(shaderType != ShaderType::InvalidEnum);
+ mActiveUseBits.set(shaderType, used);
+}
+
+void ActiveVariable::unionReferencesWith(const ActiveVariable &other)
+{
+ mActiveUseBits |= other.mActiveUseBits;
+}
+
+ShaderType ActiveVariable::getFirstShaderTypeWhereActive() const
+{
+ return static_cast<ShaderType>(ScanForward(mActiveUseBits.bits()));
+}
+
+GLuint ActiveVariable::activeShaderCount() const
+{
+ return static_cast<GLuint>(mActiveUseBits.count());
+}
+
+LinkedUniform::LinkedUniform()
+ : typeInfo(nullptr),
+ bufferIndex(-1),
+ blockInfo(sh::kDefaultBlockMemberInfo),
+ outerArrayOffset(0)
+{}
+
+LinkedUniform::LinkedUniform(GLenum typeIn,
+ GLenum precisionIn,
+ const std::string &nameIn,
+ const std::vector<unsigned int> &arraySizesIn,
+ const int bindingIn,
+ const int offsetIn,
+ const int locationIn,
+ const int bufferIndexIn,
+ const sh::BlockMemberInfo &blockInfoIn)
+ : typeInfo(&GetUniformTypeInfo(typeIn)),
+ bufferIndex(bufferIndexIn),
+ blockInfo(blockInfoIn),
+ outerArrayOffset(0)
+{
+ type = typeIn;
+ precision = precisionIn;
+ name = nameIn;
+ arraySizes = arraySizesIn;
+ binding = bindingIn;
+ offset = offsetIn;
+ location = locationIn;
+ ASSERT(!isArrayOfArrays());
+ ASSERT(!isArray() || !isStruct());
+}
+
+LinkedUniform::LinkedUniform(const sh::ShaderVariable &uniform)
+ : sh::ShaderVariable(uniform),
+ typeInfo(&GetUniformTypeInfo(type)),
+ bufferIndex(-1),
+ blockInfo(sh::kDefaultBlockMemberInfo)
+{
+ ASSERT(!isArrayOfArrays());
+ ASSERT(!isArray() || !isStruct());
+}
+
+LinkedUniform::LinkedUniform(const LinkedUniform &uniform)
+ : sh::ShaderVariable(uniform),
+ ActiveVariable(uniform),
+ typeInfo(uniform.typeInfo),
+ bufferIndex(uniform.bufferIndex),
+ blockInfo(uniform.blockInfo),
+ outerArraySizes(uniform.outerArraySizes),
+ outerArrayOffset(uniform.outerArrayOffset)
+{}
+
+LinkedUniform &LinkedUniform::operator=(const LinkedUniform &uniform)
+{
+ sh::ShaderVariable::operator=(uniform);
+ ActiveVariable::operator =(uniform);
+ typeInfo = uniform.typeInfo;
+ bufferIndex = uniform.bufferIndex;
+ blockInfo = uniform.blockInfo;
+ outerArraySizes = uniform.outerArraySizes;
+ outerArrayOffset = uniform.outerArrayOffset;
+ return *this;
+}
+
+LinkedUniform::~LinkedUniform() {}
+
+BufferVariable::BufferVariable()
+ : bufferIndex(-1), blockInfo(sh::kDefaultBlockMemberInfo), topLevelArraySize(-1)
+{}
+
+BufferVariable::BufferVariable(GLenum typeIn,
+ GLenum precisionIn,
+ const std::string &nameIn,
+ const std::vector<unsigned int> &arraySizesIn,
+ const int bufferIndexIn,
+ const sh::BlockMemberInfo &blockInfoIn)
+ : bufferIndex(bufferIndexIn), blockInfo(blockInfoIn), topLevelArraySize(-1)
+{
+ type = typeIn;
+ precision = precisionIn;
+ name = nameIn;
+ arraySizes = arraySizesIn;
+}
+
+BufferVariable::~BufferVariable() {}
+
+ShaderVariableBuffer::ShaderVariableBuffer() : binding(0), dataSize(0) {}
+
+ShaderVariableBuffer::ShaderVariableBuffer(const ShaderVariableBuffer &other) = default;
+
+ShaderVariableBuffer::~ShaderVariableBuffer() {}
+
+int ShaderVariableBuffer::numActiveVariables() const
+{
+ return static_cast<int>(memberIndexes.size());
+}
+
+InterfaceBlock::InterfaceBlock() : isArray(false), arrayElement(0) {}
+
+InterfaceBlock::InterfaceBlock(const std::string &nameIn,
+ const std::string &mappedNameIn,
+ bool isArrayIn,
+ unsigned int arrayElementIn,
+ unsigned int firstFieldArraySizeIn,
+ int bindingIn)
+ : name(nameIn),
+ mappedName(mappedNameIn),
+ isArray(isArrayIn),
+ arrayElement(arrayElementIn),
+ firstFieldArraySize(firstFieldArraySizeIn)
+{
+ binding = bindingIn;
+}
+
+std::string InterfaceBlock::nameWithArrayIndex() const
+{
+ std::stringstream fullNameStr;
+ fullNameStr << name;
+ if (isArray)
+ {
+ fullNameStr << "[" << arrayElement << "]";
+ }
+
+ return fullNameStr.str();
+}
+
+std::string InterfaceBlock::mappedNameWithArrayIndex() const
+{
+ std::stringstream fullNameStr;
+ fullNameStr << mappedName;
+ if (isArray)
+ {
+ fullNameStr << "[" << arrayElement << "]";
+ }
+
+ return fullNameStr.str();
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/Uniform.h b/gfx/angle/checkout/src/libANGLE/Uniform.h
new file mode 100644
index 0000000000..5c15906779
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Uniform.h
@@ -0,0 +1,138 @@
+//
+// Copyright 2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef LIBANGLE_UNIFORM_H_
+#define LIBANGLE_UNIFORM_H_
+
+#include <string>
+#include <vector>
+
+#include "angle_gl.h"
+#include "common/MemoryBuffer.h"
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "compiler/translator/blocklayout.h"
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+struct UniformTypeInfo;
+
+struct ActiveVariable
+{
+ ActiveVariable();
+ ActiveVariable(const ActiveVariable &rhs);
+ virtual ~ActiveVariable();
+
+ ActiveVariable &operator=(const ActiveVariable &rhs);
+
+ ShaderType getFirstShaderTypeWhereActive() const;
+ void setActive(ShaderType shaderType, bool used);
+ void unionReferencesWith(const ActiveVariable &other);
+ bool isActive(ShaderType shaderType) const
+ {
+ ASSERT(shaderType != ShaderType::InvalidEnum);
+ return mActiveUseBits[shaderType];
+ }
+ ShaderBitSet activeShaders() const { return mActiveUseBits; }
+ GLuint activeShaderCount() const;
+
+ private:
+ ShaderBitSet mActiveUseBits;
+};
+
+// Helper struct representing a single shader uniform
+struct LinkedUniform : public sh::ShaderVariable, public ActiveVariable
+{
+ LinkedUniform();
+ LinkedUniform(GLenum type,
+ GLenum precision,
+ const std::string &name,
+ const std::vector<unsigned int> &arraySizes,
+ const int binding,
+ const int offset,
+ const int location,
+ const int bufferIndex,
+ const sh::BlockMemberInfo &blockInfo);
+ LinkedUniform(const sh::ShaderVariable &uniform);
+ LinkedUniform(const LinkedUniform &uniform);
+ LinkedUniform &operator=(const LinkedUniform &uniform);
+ ~LinkedUniform() override;
+
+ bool isSampler() const { return typeInfo->isSampler; }
+ bool isImage() const { return typeInfo->isImageType; }
+ bool isAtomicCounter() const { return IsAtomicCounterType(type); }
+ bool isInDefaultBlock() const { return bufferIndex == -1; }
+ bool isField() const { return name.find('.') != std::string::npos; }
+ size_t getElementSize() const { return typeInfo->externalSize; }
+ size_t getElementComponents() const { return typeInfo->componentCount; }
+
+ const UniformTypeInfo *typeInfo;
+
+ // Identifies the containing buffer backed resource -- interface block or atomic counter buffer.
+ int bufferIndex;
+ sh::BlockMemberInfo blockInfo;
+ std::vector<unsigned int> outerArraySizes;
+ unsigned int outerArrayOffset;
+};
+
+struct BufferVariable : public sh::ShaderVariable, public ActiveVariable
+{
+ BufferVariable();
+ BufferVariable(GLenum type,
+ GLenum precision,
+ const std::string &name,
+ const std::vector<unsigned int> &arraySizes,
+ const int bufferIndex,
+ const sh::BlockMemberInfo &blockInfo);
+ ~BufferVariable() override;
+
+ int bufferIndex;
+ sh::BlockMemberInfo blockInfo;
+
+ int topLevelArraySize;
+};
+
+// Parent struct for atomic counter, uniform block, and shader storage block buffer, which all
+// contain a group of shader variables, and have a GL buffer backed.
+struct ShaderVariableBuffer : public ActiveVariable
+{
+ ShaderVariableBuffer();
+ ShaderVariableBuffer(const ShaderVariableBuffer &other);
+ ~ShaderVariableBuffer() override;
+ int numActiveVariables() const;
+
+ int binding;
+ unsigned int dataSize;
+ std::vector<unsigned int> memberIndexes;
+};
+
+using AtomicCounterBuffer = ShaderVariableBuffer;
+
+// Helper struct representing a single shader interface block
+struct InterfaceBlock : public ShaderVariableBuffer
+{
+ InterfaceBlock();
+ InterfaceBlock(const std::string &nameIn,
+ const std::string &mappedNameIn,
+ bool isArrayIn,
+ unsigned int arrayElementIn,
+ unsigned int firstFieldArraySizeIn,
+ int bindingIn);
+
+ std::string nameWithArrayIndex() const;
+ std::string mappedNameWithArrayIndex() const;
+
+ std::string name;
+ std::string mappedName;
+ bool isArray;
+ unsigned int arrayElement;
+ unsigned int firstFieldArraySize;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_UNIFORM_H_
diff --git a/gfx/angle/checkout/src/libANGLE/VaryingPacking.cpp b/gfx/angle/checkout/src/libANGLE/VaryingPacking.cpp
new file mode 100644
index 0000000000..7dbb0cc2b8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/VaryingPacking.cpp
@@ -0,0 +1,1152 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// VaryingPacking:
+// Class which describes a mapping from varyings to registers, according
+// to the spec, or using custom packing algorithms. We also keep a register
+// allocation list for the D3D renderer.
+//
+
+#include "libANGLE/VaryingPacking.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/ProgramExecutable.h"
+#include "libANGLE/Shader.h"
+
+namespace gl
+{
+
+namespace
+{
+
+// true if varying x has a higher priority in packing than y
+bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y)
+{
+ // If the PackedVarying 'x' or 'y' to be compared is an array element for transform feedback,
+ // this clones an equivalent non-array shader variable 'vx' or 'vy' for actual comparison
+ // instead. For I/O block arrays, the array index is used in the comparison.
+ sh::ShaderVariable vx, vy;
+ const sh::ShaderVariable *px, *py;
+
+ px = &x.varying();
+ py = &y.varying();
+
+ if (x.isTransformFeedbackArrayElement())
+ {
+ vx = *px;
+ vx.arraySizes.clear();
+ px = &vx;
+ }
+
+ if (y.isTransformFeedbackArrayElement())
+ {
+ vy = *py;
+ vy.arraySizes.clear();
+ py = &vy;
+ }
+
+ // Make sure struct fields end up together.
+ if (x.isStructField() != y.isStructField())
+ {
+ return x.isStructField();
+ }
+
+ if (x.isStructField())
+ {
+ ASSERT(y.isStructField());
+
+ if (x.getParentStructName() != y.getParentStructName())
+ {
+ return x.getParentStructName() < y.getParentStructName();
+ }
+ }
+
+ // For I/O block fields, order first by array index:
+ if (!x.isTransformFeedbackArrayElement() && !y.isTransformFeedbackArrayElement())
+ {
+ if (x.arrayIndex != y.arrayIndex)
+ {
+ return x.arrayIndex < y.arrayIndex;
+ }
+ }
+
+ // Then order by field index
+ if (x.fieldIndex != y.fieldIndex)
+ {
+ return x.fieldIndex < y.fieldIndex;
+ }
+
+ // Then order by secondary field index
+ if (x.secondaryFieldIndex != y.secondaryFieldIndex)
+ {
+ return x.secondaryFieldIndex < y.secondaryFieldIndex;
+ }
+
+ // Otherwise order by variable
+ return gl::CompareShaderVar(*px, *py);
+}
+
+bool InterfaceVariablesMatch(const sh::ShaderVariable &front, const sh::ShaderVariable &back)
+{
+ // Matching ruels from 7.4.1 Shader Interface Matching from the GLES 3.2 spec:
+ // - the two variables match in name, type, and qualification; or
+ // - the two variables are declared with the same location qualifier and match in type and
+ // qualification. Note that we use a more permissive check here thanks to front-end validation.
+ if (back.location != -1 && back.location == front.location)
+ {
+ return true;
+ }
+
+ if (front.isShaderIOBlock != back.isShaderIOBlock)
+ {
+ return false;
+ }
+
+ // Compare names, or if shader I/O blocks, block names.
+ const std::string &backName = back.isShaderIOBlock ? back.structOrBlockName : back.name;
+ const std::string &frontName = front.isShaderIOBlock ? front.structOrBlockName : front.name;
+ return backName == frontName;
+}
+
+GLint GetMaxShaderInputVectors(const Caps &caps, ShaderType shaderStage)
+{
+ switch (shaderStage)
+ {
+ case ShaderType::TessControl:
+ return caps.maxTessControlInputComponents / 4;
+ case ShaderType::TessEvaluation:
+ return caps.maxTessEvaluationInputComponents / 4;
+ case ShaderType::Geometry:
+ return caps.maxGeometryInputComponents / 4;
+ case ShaderType::Fragment:
+ return caps.maxFragmentInputComponents / 4;
+ default:
+ return std::numeric_limits<GLint>::max();
+ }
+}
+
+GLint GetMaxShaderOutputVectors(const Caps &caps, ShaderType shaderStage)
+{
+ switch (shaderStage)
+ {
+ case ShaderType::Vertex:
+ return caps.maxVertexOutputComponents / 4;
+ case ShaderType::TessControl:
+ return caps.maxTessControlOutputComponents / 4;
+ case ShaderType::TessEvaluation:
+ return caps.maxTessEvaluationOutputComponents / 4;
+ case ShaderType::Geometry:
+ return caps.maxGeometryOutputComponents / 4;
+ default:
+ return std::numeric_limits<GLint>::max();
+ }
+}
+
+bool ShouldSkipPackedVarying(const sh::ShaderVariable &varying, PackMode packMode)
+{
+ // Don't pack gl_Position. Also don't count gl_PointSize for D3D9.
+ return varying.name == "gl_Position" ||
+ (varying.name == "gl_PointSize" && packMode == PackMode::ANGLE_NON_CONFORMANT_D3D9);
+}
+
+std::vector<unsigned int> StripVaryingArrayDimension(const sh::ShaderVariable *frontVarying,
+ ShaderType frontShaderStage,
+ const sh::ShaderVariable *backVarying,
+ ShaderType backShaderStage,
+ bool isStructField)
+{
+ // "Geometry shader inputs, tessellation control shader inputs and outputs, and tessellation
+ // evaluation inputs all have an additional level of arrayness relative to other shader inputs
+ // and outputs. This outer array level is removed from the type before considering how many
+ // locations the type consumes."
+
+ if (backVarying && backVarying->isArray() && !backVarying->isPatch && !isStructField &&
+ (backShaderStage == ShaderType::Geometry || backShaderStage == ShaderType::TessEvaluation ||
+ backShaderStage == ShaderType::TessControl))
+ {
+ std::vector<unsigned int> arr = backVarying->arraySizes;
+ arr.pop_back();
+ return arr;
+ }
+
+ if (frontVarying && frontVarying->isArray() && !frontVarying->isPatch && !isStructField &&
+ frontShaderStage == ShaderType::TessControl)
+ {
+ std::vector<unsigned int> arr = frontVarying->arraySizes;
+ arr.pop_back();
+ return arr;
+ }
+
+ return frontVarying ? frontVarying->arraySizes : backVarying->arraySizes;
+}
+} // anonymous namespace
+
+// Implementation of VaryingInShaderRef
+VaryingInShaderRef::VaryingInShaderRef(ShaderType stageIn, const sh::ShaderVariable *varyingIn)
+ : varying(varyingIn), stage(stageIn)
+{}
+
+VaryingInShaderRef::~VaryingInShaderRef() = default;
+
+VaryingInShaderRef::VaryingInShaderRef(VaryingInShaderRef &&other)
+ : varying(other.varying),
+ stage(other.stage),
+ parentStructName(std::move(other.parentStructName)),
+ parentStructMappedName(std::move(other.parentStructMappedName))
+{}
+
+VaryingInShaderRef &VaryingInShaderRef::operator=(VaryingInShaderRef &&other)
+{
+ std::swap(varying, other.varying);
+ std::swap(stage, other.stage);
+ std::swap(parentStructName, other.parentStructName);
+ std::swap(parentStructMappedName, other.parentStructMappedName);
+
+ return *this;
+}
+
+// Implementation of PackedVarying
+PackedVarying::PackedVarying(VaryingInShaderRef &&frontVaryingIn,
+ VaryingInShaderRef &&backVaryingIn,
+ sh::InterpolationType interpolationIn)
+ : PackedVarying(std::move(frontVaryingIn),
+ std::move(backVaryingIn),
+ interpolationIn,
+ GL_INVALID_INDEX,
+ 0,
+ 0)
+{}
+
+PackedVarying::PackedVarying(VaryingInShaderRef &&frontVaryingIn,
+ VaryingInShaderRef &&backVaryingIn,
+ sh::InterpolationType interpolationIn,
+ GLuint arrayIndexIn,
+ GLuint fieldIndexIn,
+ GLuint secondaryFieldIndexIn)
+ : frontVarying(std::move(frontVaryingIn)),
+ backVarying(std::move(backVaryingIn)),
+ interpolation(interpolationIn),
+ arrayIndex(arrayIndexIn),
+ isTransformFeedback(false),
+ fieldIndex(fieldIndexIn),
+ secondaryFieldIndex(secondaryFieldIndexIn)
+{}
+
+PackedVarying::~PackedVarying() = default;
+
+PackedVarying::PackedVarying(PackedVarying &&other)
+ : frontVarying(std::move(other.frontVarying)),
+ backVarying(std::move(other.backVarying)),
+ interpolation(other.interpolation),
+ arrayIndex(other.arrayIndex),
+ isTransformFeedback(other.isTransformFeedback),
+ fieldIndex(other.fieldIndex),
+ secondaryFieldIndex(other.secondaryFieldIndex)
+{}
+
+PackedVarying &PackedVarying::operator=(PackedVarying &&other)
+{
+ std::swap(frontVarying, other.frontVarying);
+ std::swap(backVarying, other.backVarying);
+ std::swap(interpolation, other.interpolation);
+ std::swap(arrayIndex, other.arrayIndex);
+ std::swap(isTransformFeedback, other.isTransformFeedback);
+ std::swap(fieldIndex, other.fieldIndex);
+ std::swap(secondaryFieldIndex, other.secondaryFieldIndex);
+
+ return *this;
+}
+
+unsigned int PackedVarying::getBasicTypeElementCount() const
+{
+ // "Geometry shader inputs, tessellation control shader inputs and outputs, and tessellation
+ // evaluation inputs all have an additional level of arrayness relative to other shader inputs
+ // and outputs. This outer array level is removed from the type before considering how many
+ // locations the type consumes."
+ std::vector<unsigned int> arr =
+ StripVaryingArrayDimension(frontVarying.varying, frontVarying.stage, backVarying.varying,
+ backVarying.stage, isStructField());
+ return arr.empty() ? 1u : arr.back();
+}
+
+// Implementation of VaryingPacking
+VaryingPacking::VaryingPacking() = default;
+
+VaryingPacking::~VaryingPacking() = default;
+
+void VaryingPacking::reset()
+{
+ clearRegisterMap();
+ mRegisterList.clear();
+ mPackedVaryings.clear();
+
+ for (std::vector<std::string> &inactiveVaryingMappedNames : mInactiveVaryingMappedNames)
+ {
+ inactiveVaryingMappedNames.clear();
+ }
+
+ for (std::vector<std::string> &activeBuiltIns : mActiveOutputBuiltIns)
+ {
+ activeBuiltIns.clear();
+ }
+}
+
+void VaryingPacking::clearRegisterMap()
+{
+ std::fill(mRegisterMap.begin(), mRegisterMap.end(), Register());
+}
+
+// Packs varyings into generic varying registers, using the algorithm from
+// See [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
+// Also [OpenGL ES Shading Language 3.00 rev. 4] Section 11 page 119
+// Returns false if unsuccessful.
+bool VaryingPacking::packVaryingIntoRegisterMap(PackMode packMode,
+ const PackedVarying &packedVarying)
+{
+ const sh::ShaderVariable &varying = packedVarying.varying();
+
+ // "Non - square matrices of type matCxR consume the same space as a square matrix of type matN
+ // where N is the greater of C and R."
+ // Here we are a bit more conservative and allow packing non-square matrices more tightly.
+ // Make sure we use transposed matrix types to count registers correctly.
+ ASSERT(!varying.isStruct());
+ GLenum transposedType = gl::TransposeMatrixType(varying.type);
+ unsigned int varyingRows = gl::VariableRowCount(transposedType);
+ unsigned int varyingColumns = gl::VariableColumnCount(transposedType);
+
+ // Special pack mode for D3D9. Each varying takes a full register, no sharing.
+ // TODO(jmadill): Implement more sophisticated component packing in D3D9.
+ if (packMode == PackMode::ANGLE_NON_CONFORMANT_D3D9)
+ {
+ varyingColumns = 4;
+ }
+
+ // "Variables of type mat2 occupies 2 complete rows."
+ // For non-WebGL contexts, we allow mat2 to occupy only two columns per row.
+ else if (packMode == PackMode::WEBGL_STRICT && varying.type == GL_FLOAT_MAT2)
+ {
+ varyingColumns = 4;
+ }
+
+ // "Arrays of size N are assumed to take N times the size of the base type"
+ // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
+ // structures, so we may use getBasicTypeElementCount().
+ const unsigned int elementCount = packedVarying.getBasicTypeElementCount();
+ varyingRows *= (packedVarying.isTransformFeedbackArrayElement() ? 1 : elementCount);
+
+ unsigned int maxVaryingVectors = static_cast<unsigned int>(mRegisterMap.size());
+
+ // Fail if we are packing a single over-large varying.
+ if (varyingRows > maxVaryingVectors)
+ {
+ return false;
+ }
+
+ // "For 2, 3 and 4 component variables packing is started using the 1st column of the 1st row.
+ // Variables are then allocated to successive rows, aligning them to the 1st column."
+ if (varyingColumns >= 2 && varyingColumns <= 4)
+ {
+ for (unsigned int row = 0; row <= maxVaryingVectors - varyingRows; ++row)
+ {
+ if (isRegisterRangeFree(row, 0, varyingRows, varyingColumns))
+ {
+ insertVaryingIntoRegisterMap(row, 0, varyingColumns, packedVarying);
+ return true;
+ }
+ }
+
+ // "For 2 component variables, when there are no spare rows, the strategy is switched to
+ // using the highest numbered row and the lowest numbered column where the variable will
+ // fit."
+ if (varyingColumns == 2)
+ {
+ for (unsigned int r = maxVaryingVectors - varyingRows + 1; r-- >= 1;)
+ {
+ if (isRegisterRangeFree(r, 2, varyingRows, 2))
+ {
+ insertVaryingIntoRegisterMap(r, 2, varyingColumns, packedVarying);
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ // "1 component variables have their own packing rule. They are packed in order of size, largest
+ // first. Each variable is placed in the column that leaves the least amount of space in the
+ // column and aligned to the lowest available rows within that column."
+ ASSERT(varyingColumns == 1);
+ unsigned int contiguousSpace[4] = {0};
+ unsigned int bestContiguousSpace[4] = {0};
+ unsigned int totalSpace[4] = {0};
+
+ for (unsigned int row = 0; row < maxVaryingVectors; ++row)
+ {
+ for (unsigned int column = 0; column < 4; ++column)
+ {
+ if (mRegisterMap[row][column])
+ {
+ contiguousSpace[column] = 0;
+ }
+ else
+ {
+ contiguousSpace[column]++;
+ totalSpace[column]++;
+
+ if (contiguousSpace[column] > bestContiguousSpace[column])
+ {
+ bestContiguousSpace[column] = contiguousSpace[column];
+ }
+ }
+ }
+ }
+
+ unsigned int bestColumn = 0;
+ for (unsigned int column = 1; column < 4; ++column)
+ {
+ if (bestContiguousSpace[column] >= varyingRows &&
+ (bestContiguousSpace[bestColumn] < varyingRows ||
+ totalSpace[column] < totalSpace[bestColumn]))
+ {
+ bestColumn = column;
+ }
+ }
+
+ if (bestContiguousSpace[bestColumn] >= varyingRows)
+ {
+ for (unsigned int row = 0; row < maxVaryingVectors; row++)
+ {
+ if (isRegisterRangeFree(row, bestColumn, varyingRows, 1))
+ {
+ for (unsigned int arrayIndex = 0; arrayIndex < varyingRows; ++arrayIndex)
+ {
+ // If varyingRows > 1, it must be an array.
+ PackedVaryingRegister registerInfo;
+ registerInfo.packedVarying = &packedVarying;
+ registerInfo.registerRow = row + arrayIndex;
+ registerInfo.registerColumn = bestColumn;
+ registerInfo.varyingArrayIndex =
+ (packedVarying.isTransformFeedbackArrayElement() ? packedVarying.arrayIndex
+ : arrayIndex);
+ registerInfo.varyingRowIndex = 0;
+ // Do not record register info for builtins.
+ // TODO(jmadill): Clean this up.
+ if (!varying.isBuiltIn())
+ {
+ mRegisterList.push_back(registerInfo);
+ }
+ mRegisterMap[row + arrayIndex][bestColumn] = true;
+ }
+ break;
+ }
+ }
+ return true;
+ }
+
+ return false;
+}
+
+bool VaryingPacking::isRegisterRangeFree(unsigned int registerRow,
+ unsigned int registerColumn,
+ unsigned int varyingRows,
+ unsigned int varyingColumns) const
+{
+ for (unsigned int row = 0; row < varyingRows; ++row)
+ {
+ ASSERT(registerRow + row < mRegisterMap.size());
+ for (unsigned int column = 0; column < varyingColumns; ++column)
+ {
+ ASSERT(registerColumn + column < 4);
+ if (mRegisterMap[registerRow + row][registerColumn + column])
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void VaryingPacking::insertVaryingIntoRegisterMap(unsigned int registerRow,
+ unsigned int registerColumn,
+ unsigned int varyingColumns,
+ const PackedVarying &packedVarying)
+{
+ unsigned int varyingRows = 0;
+
+ const sh::ShaderVariable &varying = packedVarying.varying();
+ ASSERT(!varying.isStruct());
+ GLenum transposedType = gl::TransposeMatrixType(varying.type);
+ varyingRows = gl::VariableRowCount(transposedType);
+
+ PackedVaryingRegister registerInfo;
+ registerInfo.packedVarying = &packedVarying;
+ registerInfo.registerColumn = registerColumn;
+
+ // GLSL ES 3.10 section 4.3.6: Output variables cannot be arrays of arrays or arrays of
+ // structures, so we may use getBasicTypeElementCount().
+ const unsigned int arrayElementCount = packedVarying.getBasicTypeElementCount();
+ for (unsigned int arrayElement = 0; arrayElement < arrayElementCount; ++arrayElement)
+ {
+ if (packedVarying.isTransformFeedbackArrayElement() &&
+ arrayElement != packedVarying.arrayIndex)
+ {
+ continue;
+ }
+ for (unsigned int varyingRow = 0; varyingRow < varyingRows; ++varyingRow)
+ {
+ registerInfo.registerRow = registerRow + (arrayElement * varyingRows) + varyingRow;
+ registerInfo.varyingRowIndex = varyingRow;
+ registerInfo.varyingArrayIndex = arrayElement;
+ // Do not record register info for builtins.
+ // TODO(jmadill): Clean this up.
+ if (!varying.isBuiltIn())
+ {
+ mRegisterList.push_back(registerInfo);
+ }
+
+ for (unsigned int columnIndex = 0; columnIndex < varyingColumns; ++columnIndex)
+ {
+ mRegisterMap[registerInfo.registerRow][registerColumn + columnIndex] = true;
+ }
+ }
+ }
+}
+
+void VaryingPacking::collectUserVarying(const ProgramVaryingRef &ref,
+ VaryingUniqueFullNames *uniqueFullNames)
+{
+ const sh::ShaderVariable *input = ref.frontShader;
+ const sh::ShaderVariable *output = ref.backShader;
+
+ // Will get the vertex shader interpolation by default.
+ sh::InterpolationType interpolation = input ? input->interpolation : output->interpolation;
+
+ VaryingInShaderRef frontVarying(ref.frontShaderStage, input);
+ VaryingInShaderRef backVarying(ref.backShaderStage, output);
+
+ mPackedVaryings.emplace_back(std::move(frontVarying), std::move(backVarying), interpolation);
+ if (input && !input->isBuiltIn())
+ {
+ (*uniqueFullNames)[ref.frontShaderStage].insert(
+ mPackedVaryings.back().fullName(ref.frontShaderStage));
+ }
+ if (output && !output->isBuiltIn())
+ {
+ (*uniqueFullNames)[ref.backShaderStage].insert(
+ mPackedVaryings.back().fullName(ref.backShaderStage));
+ }
+}
+
+void VaryingPacking::collectUserVaryingField(const ProgramVaryingRef &ref,
+ GLuint arrayIndex,
+ GLuint fieldIndex,
+ GLuint secondaryFieldIndex,
+ VaryingUniqueFullNames *uniqueFullNames)
+{
+ const sh::ShaderVariable *input = ref.frontShader;
+ const sh::ShaderVariable *output = ref.backShader;
+
+ // Will get the vertex shader interpolation by default.
+ sh::InterpolationType interpolation = input ? input->interpolation : output->interpolation;
+
+ const sh::ShaderVariable *frontField = input ? &input->fields[fieldIndex] : nullptr;
+ const sh::ShaderVariable *backField = output ? &output->fields[fieldIndex] : nullptr;
+
+ if (secondaryFieldIndex != GL_INVALID_INDEX)
+ {
+ frontField = frontField ? &frontField->fields[secondaryFieldIndex] : nullptr;
+ backField = backField ? &backField->fields[secondaryFieldIndex] : nullptr;
+ }
+
+ VaryingInShaderRef frontVarying(ref.frontShaderStage, frontField);
+ VaryingInShaderRef backVarying(ref.backShaderStage, backField);
+
+ if (input)
+ {
+ if (frontField->isShaderIOBlock)
+ {
+ frontVarying.parentStructName = input->structOrBlockName;
+ frontVarying.parentStructMappedName = input->mappedStructOrBlockName;
+ }
+ else
+ {
+ ASSERT(!frontField->isStruct() && !frontField->isArray());
+ frontVarying.parentStructName = input->name;
+ frontVarying.parentStructMappedName = input->mappedName;
+ }
+ }
+ if (output)
+ {
+ if (backField->isShaderIOBlock)
+ {
+ backVarying.parentStructName = output->structOrBlockName;
+ backVarying.parentStructMappedName = output->mappedStructOrBlockName;
+ }
+ else
+ {
+ ASSERT(!backField->isStruct() && !backField->isArray());
+ backVarying.parentStructName = output->name;
+ backVarying.parentStructMappedName = output->mappedName;
+ }
+ }
+
+ mPackedVaryings.emplace_back(std::move(frontVarying), std::move(backVarying), interpolation,
+ arrayIndex, fieldIndex,
+ secondaryFieldIndex == GL_INVALID_INDEX ? 0 : secondaryFieldIndex);
+
+ if (input)
+ {
+ (*uniqueFullNames)[ref.frontShaderStage].insert(
+ mPackedVaryings.back().fullName(ref.frontShaderStage));
+ }
+ if (output)
+ {
+ (*uniqueFullNames)[ref.backShaderStage].insert(
+ mPackedVaryings.back().fullName(ref.backShaderStage));
+ }
+}
+
+void VaryingPacking::collectUserVaryingTF(const ProgramVaryingRef &ref, size_t subscript)
+{
+ const sh::ShaderVariable *input = ref.frontShader;
+
+ VaryingInShaderRef frontVarying(ref.frontShaderStage, input);
+ VaryingInShaderRef backVarying(ref.backShaderStage, nullptr);
+
+ mPackedVaryings.emplace_back(std::move(frontVarying), std::move(backVarying),
+ input->interpolation);
+ mPackedVaryings.back().arrayIndex = static_cast<GLuint>(subscript);
+ mPackedVaryings.back().isTransformFeedback = true;
+}
+
+void VaryingPacking::collectUserVaryingFieldTF(const ProgramVaryingRef &ref,
+ const sh::ShaderVariable &field,
+ GLuint fieldIndex,
+ GLuint secondaryFieldIndex)
+{
+ const sh::ShaderVariable *input = ref.frontShader;
+
+ const sh::ShaderVariable *frontField = &field;
+ if (secondaryFieldIndex != GL_INVALID_INDEX)
+ {
+ frontField = &frontField->fields[secondaryFieldIndex];
+ }
+
+ VaryingInShaderRef frontVarying(ref.frontShaderStage, frontField);
+ VaryingInShaderRef backVarying(ref.backShaderStage, nullptr);
+
+ if (frontField->isShaderIOBlock)
+ {
+ frontVarying.parentStructName = input->structOrBlockName;
+ frontVarying.parentStructMappedName = input->mappedStructOrBlockName;
+ }
+ else
+ {
+ ASSERT(!frontField->isStruct() && !frontField->isArray());
+ frontVarying.parentStructName = input->name;
+ frontVarying.parentStructMappedName = input->mappedName;
+ }
+
+ mPackedVaryings.emplace_back(std::move(frontVarying), std::move(backVarying),
+ input->interpolation, GL_INVALID_INDEX, fieldIndex,
+ secondaryFieldIndex == GL_INVALID_INDEX ? 0 : secondaryFieldIndex);
+}
+
+void VaryingPacking::collectVarying(const sh::ShaderVariable &varying,
+ const ProgramVaryingRef &ref,
+ PackMode packMode,
+ VaryingUniqueFullNames *uniqueFullNames)
+{
+ const sh::ShaderVariable *input = ref.frontShader;
+ const sh::ShaderVariable *output = ref.backShader;
+
+ if (varying.isStruct())
+ {
+ std::vector<unsigned int> arraySizes = StripVaryingArrayDimension(
+ ref.frontShader, ref.frontShaderStage, ref.backShader, ref.backShaderStage, false);
+ const bool isArray = !arraySizes.empty();
+ const GLuint arraySize = isArray ? arraySizes[0] : 1;
+
+ for (GLuint arrayIndex = 0; arrayIndex < arraySize; ++arrayIndex)
+ {
+ const GLuint effectiveArrayIndex = isArray ? arrayIndex : GL_INVALID_INDEX;
+ for (GLuint fieldIndex = 0; fieldIndex < varying.fields.size(); ++fieldIndex)
+ {
+ const sh::ShaderVariable &fieldVarying = varying.fields[fieldIndex];
+ if (ShouldSkipPackedVarying(fieldVarying, packMode))
+ {
+ continue;
+ }
+
+ if (fieldVarying.isStruct())
+ {
+ if (fieldVarying.isArray())
+ {
+ unsigned int structFieldArraySize = fieldVarying.arraySizes[0];
+ for (unsigned int fieldArrayIndex = 0;
+ fieldArrayIndex < structFieldArraySize; ++fieldArrayIndex)
+ {
+ for (GLuint nestedIndex = 0; nestedIndex < fieldVarying.fields.size();
+ nestedIndex++)
+ {
+ collectUserVaryingField(ref, effectiveArrayIndex, fieldIndex,
+ nestedIndex, uniqueFullNames);
+ }
+ }
+ }
+ else
+ {
+ for (GLuint nestedIndex = 0; nestedIndex < fieldVarying.fields.size();
+ nestedIndex++)
+ {
+ collectUserVaryingField(ref, effectiveArrayIndex, fieldIndex,
+ nestedIndex, uniqueFullNames);
+ }
+ }
+ }
+ else
+ {
+ collectUserVaryingField(ref, effectiveArrayIndex, fieldIndex, GL_INVALID_INDEX,
+ uniqueFullNames);
+ }
+ }
+ }
+ if (input)
+ {
+ (*uniqueFullNames)[ref.frontShaderStage].insert(input->name);
+ if (input->isShaderIOBlock)
+ {
+ (*uniqueFullNames)[ref.frontShaderStage].insert(input->structOrBlockName);
+ }
+ }
+ if (output)
+ {
+ (*uniqueFullNames)[ref.backShaderStage].insert(output->name);
+ }
+ }
+ else
+ {
+ collectUserVarying(ref, uniqueFullNames);
+ }
+}
+
+void VaryingPacking::collectTFVarying(const std::string &tfVarying,
+ const ProgramVaryingRef &ref,
+ VaryingUniqueFullNames *uniqueFullNames)
+{
+ const sh::ShaderVariable *input = ref.frontShader;
+
+ std::vector<unsigned int> subscripts;
+ std::string baseName = ParseResourceName(tfVarying, &subscripts);
+
+ // Already packed as active varying.
+ if ((*uniqueFullNames)[ref.frontShaderStage].count(tfVarying) > 0 ||
+ (*uniqueFullNames)[ref.frontShaderStage].count(baseName) > 0 ||
+ (input->isShaderIOBlock &&
+ (*uniqueFullNames)[ref.frontShaderStage].count(input->structOrBlockName) > 0))
+ {
+ return;
+ }
+
+ if (input->isStruct())
+ {
+ GLuint fieldIndex = 0;
+ const sh::ShaderVariable *field = input->findField(tfVarying, &fieldIndex);
+ if (field != nullptr)
+ {
+ ASSERT(input->isShaderIOBlock || (!field->isStruct() && !field->isArray()));
+
+ // If it's an I/O block whose member is being captured, pack every member of the
+ // block. Currently, we pack either all or none of an I/O block.
+ if (input->isShaderIOBlock)
+ {
+ for (fieldIndex = 0; fieldIndex < input->fields.size(); ++fieldIndex)
+ {
+ if (input->fields[fieldIndex].isStruct())
+ {
+
+ for (GLuint nestedIndex = 0;
+ nestedIndex < input->fields[fieldIndex].fields.size(); nestedIndex++)
+ {
+ collectUserVaryingFieldTF(ref, input->fields[fieldIndex], fieldIndex,
+ nestedIndex);
+ }
+ }
+ else
+ {
+ collectUserVaryingFieldTF(ref, input->fields[fieldIndex], fieldIndex,
+ GL_INVALID_INDEX);
+ }
+ }
+
+ (*uniqueFullNames)[ref.frontShaderStage].insert(input->structOrBlockName);
+ }
+ else
+ {
+ collectUserVaryingFieldTF(ref, *field, fieldIndex, GL_INVALID_INDEX);
+ }
+ (*uniqueFullNames)[ref.frontShaderStage].insert(tfVarying);
+ (*uniqueFullNames)[ref.frontShaderStage].insert(input->name);
+ }
+ }
+ // Array as a whole and array element conflict has already been checked in
+ // linkValidateTransformFeedback.
+ else if (baseName == input->name)
+ {
+ size_t subscript = GL_INVALID_INDEX;
+ if (!subscripts.empty())
+ {
+ subscript = subscripts.back();
+ }
+
+ // only pack varyings that are not builtins.
+ if (tfVarying.compare(0, 3, "gl_") != 0)
+ {
+ collectUserVaryingTF(ref, subscript);
+ (*uniqueFullNames)[ref.frontShaderStage].insert(tfVarying);
+ }
+ }
+}
+
+bool VaryingPacking::collectAndPackUserVaryings(gl::InfoLog &infoLog,
+ GLint maxVaryingVectors,
+ PackMode packMode,
+ ShaderType frontShaderStage,
+ ShaderType backShaderStage,
+ const ProgramMergedVaryings &mergedVaryings,
+ const std::vector<std::string> &tfVaryings,
+ const bool isSeparableProgram)
+{
+ VaryingUniqueFullNames uniqueFullNames;
+
+ reset();
+
+ for (const ProgramVaryingRef &ref : mergedVaryings)
+ {
+ const sh::ShaderVariable *input = ref.frontShader;
+ const sh::ShaderVariable *output = ref.backShader;
+
+ if ((input && ref.frontShaderStage != frontShaderStage) ||
+ (output && ref.backShaderStage != backShaderStage))
+ {
+ continue;
+ }
+
+ const bool isActiveBuiltInInput = input && input->isBuiltIn() && input->active;
+ const bool isActiveBuiltInOutput = output && output->isBuiltIn() && output->active;
+
+ // Keep track of output builtins that are used by the shader, such as gl_Position,
+ // gl_PointSize etc.
+ if (isActiveBuiltInInput)
+ {
+ mActiveOutputBuiltIns[ref.frontShaderStage].push_back(input->name);
+ // Keep track of members of builtins, such as gl_out[].gl_Position, too.
+ for (sh::ShaderVariable field : input->fields)
+ {
+ mActiveOutputBuiltIns[ref.frontShaderStage].push_back(field.name);
+ }
+ }
+
+ // Only pack statically used varyings that have a matched input or output, plus special
+ // builtins. Note that we pack all statically used user-defined varyings even if they are
+ // not active. GLES specs are a bit vague on whether it's allowed to only pack active
+ // varyings, though GLES 3.1 spec section 11.1.2.1 says that "device-dependent
+ // optimizations" may be used to make vertex shader outputs fit.
+ //
+ // When separable programs are linked, varyings at the separable program's boundary are
+ // treated as active. See section 7.4.1 in
+ // https://www.khronos.org/registry/OpenGL/specs/es/3.2/es_spec_3.2.pdf
+ bool matchedInputOutputStaticUse = (input && output && output->staticUse);
+ bool activeBuiltIn = (isActiveBuiltInInput || isActiveBuiltInOutput);
+
+ // Output variable in TCS can be read as input in another invocation by barrier.
+ // See section 11.2.1.2.4 Tessellation Control Shader Execution Order in OpenGL ES 3.2.
+ bool staticUseInTCS =
+ (input && input->staticUse && ref.frontShaderStage == ShaderType::TessControl);
+
+ // Separable program requirements
+ bool separableActiveInput = (input && (input->active || !output));
+ bool separableActiveOutput = (output && (output->active || !input));
+ bool separableActiveVarying =
+ (isSeparableProgram && (separableActiveInput || separableActiveOutput));
+
+ if (matchedInputOutputStaticUse || activeBuiltIn || separableActiveVarying ||
+ staticUseInTCS)
+ {
+ const sh::ShaderVariable *varying = output ? output : input;
+
+ if (!ShouldSkipPackedVarying(*varying, packMode))
+ {
+ collectVarying(*varying, ref, packMode, &uniqueFullNames);
+ continue;
+ }
+ }
+
+ // If the varying is not used in the input, we know it is inactive, unless it's a separable
+ // program, in which case the input shader may not exist in this program.
+ if (!input && !isSeparableProgram)
+ {
+ if (!output->isBuiltIn())
+ {
+ mInactiveVaryingMappedNames[ref.backShaderStage].push_back(output->mappedName);
+ if (output->isShaderIOBlock)
+ {
+ mInactiveVaryingMappedNames[ref.backShaderStage].push_back(
+ output->mappedStructOrBlockName);
+ }
+ }
+ continue;
+ }
+
+ // Keep Transform FB varyings in the merged list always.
+ for (const std::string &tfVarying : tfVaryings)
+ {
+ collectTFVarying(tfVarying, ref, &uniqueFullNames);
+ }
+
+ if (input && !input->isBuiltIn() &&
+ uniqueFullNames[ref.frontShaderStage].count(input->name) == 0)
+ {
+ mInactiveVaryingMappedNames[ref.frontShaderStage].push_back(input->mappedName);
+ if (input->isShaderIOBlock)
+ {
+ mInactiveVaryingMappedNames[ref.frontShaderStage].push_back(
+ input->mappedStructOrBlockName);
+ }
+ }
+ if (output && !output->isBuiltIn() &&
+ uniqueFullNames[ref.backShaderStage].count(output->name) == 0)
+ {
+ mInactiveVaryingMappedNames[ref.backShaderStage].push_back(output->mappedName);
+ if (output->isShaderIOBlock)
+ {
+ mInactiveVaryingMappedNames[ref.backShaderStage].push_back(
+ output->mappedStructOrBlockName);
+ }
+ }
+ }
+
+ std::sort(mPackedVaryings.begin(), mPackedVaryings.end(), ComparePackedVarying);
+
+ return packUserVaryings(infoLog, maxVaryingVectors, packMode, mPackedVaryings);
+}
+
+// See comment on packVarying.
+bool VaryingPacking::packUserVaryings(gl::InfoLog &infoLog,
+ GLint maxVaryingVectors,
+ PackMode packMode,
+ const std::vector<PackedVarying> &packedVaryings)
+{
+ clearRegisterMap();
+ mRegisterMap.resize(maxVaryingVectors);
+
+ // "Variables are packed into the registers one at a time so that they each occupy a contiguous
+ // subrectangle. No splitting of variables is permitted."
+ for (const PackedVarying &packedVarying : packedVaryings)
+ {
+ if (!packVaryingIntoRegisterMap(packMode, packedVarying))
+ {
+ ShaderType eitherStage = packedVarying.frontVarying.varying
+ ? packedVarying.frontVarying.stage
+ : packedVarying.backVarying.stage;
+ infoLog << "Could not pack varying " << packedVarying.fullName(eitherStage);
+
+ // TODO(jmadill): Implement more sophisticated component packing in D3D9.
+ if (packMode == PackMode::ANGLE_NON_CONFORMANT_D3D9)
+ {
+ infoLog << "Note: Additional non-conformant packing restrictions are enforced on "
+ "D3D9.";
+ }
+
+ return false;
+ }
+ }
+
+ // Sort the packed register list
+ std::sort(mRegisterList.begin(), mRegisterList.end());
+
+ return true;
+}
+
+// ProgramVaryingPacking implementation.
+ProgramVaryingPacking::ProgramVaryingPacking() = default;
+
+ProgramVaryingPacking::~ProgramVaryingPacking() = default;
+
+const VaryingPacking &ProgramVaryingPacking::getInputPacking(ShaderType backShaderStage) const
+{
+ ShaderType frontShaderStage = mBackToFrontStageMap[backShaderStage];
+
+ // If there's a missing shader stage, return the compute shader packing which is always empty.
+ if (frontShaderStage == ShaderType::InvalidEnum)
+ {
+ ASSERT(mVaryingPackings[ShaderType::Compute].getMaxSemanticIndex() == 0);
+ return mVaryingPackings[ShaderType::Compute];
+ }
+
+ return mVaryingPackings[frontShaderStage];
+}
+
+const VaryingPacking &ProgramVaryingPacking::getOutputPacking(ShaderType frontShaderStage) const
+{
+ return mVaryingPackings[frontShaderStage];
+}
+
+bool ProgramVaryingPacking::collectAndPackUserVaryings(InfoLog &infoLog,
+ const Caps &caps,
+ PackMode packMode,
+ const ShaderBitSet &activeShadersMask,
+ const ProgramMergedVaryings &mergedVaryings,
+ const std::vector<std::string> &tfVaryings,
+ bool isSeparableProgram)
+{
+ mBackToFrontStageMap.fill(ShaderType::InvalidEnum);
+
+ ShaderBitSet activeShaders = activeShadersMask;
+
+ ASSERT(activeShaders.any());
+ ShaderType frontShaderStage = activeShaders.first();
+ activeShaders[frontShaderStage] = false;
+
+ // Special case for start-after-vertex.
+ if (frontShaderStage != ShaderType::Vertex)
+ {
+ ShaderType emulatedFrontShaderStage = ShaderType::Vertex;
+ ShaderType backShaderStage = frontShaderStage;
+
+ if (!mVaryingPackings[emulatedFrontShaderStage].collectAndPackUserVaryings(
+ infoLog, GetMaxShaderInputVectors(caps, backShaderStage), packMode,
+ ShaderType::InvalidEnum, backShaderStage, mergedVaryings, tfVaryings,
+ isSeparableProgram))
+ {
+ return false;
+ }
+ mBackToFrontStageMap[backShaderStage] = emulatedFrontShaderStage;
+ }
+
+ // Process input/output shader pairs.
+ for (ShaderType backShaderStage : activeShaders)
+ {
+ GLint maxVaryingVectors;
+ if (frontShaderStage == ShaderType::Vertex && backShaderStage == ShaderType::Fragment)
+ {
+ maxVaryingVectors = caps.maxVaryingVectors;
+ }
+ else
+ {
+ GLint outputVaryingsMax = GetMaxShaderOutputVectors(caps, frontShaderStage);
+ GLint inputVaryingsMax = GetMaxShaderInputVectors(caps, backShaderStage);
+ maxVaryingVectors = std::min(inputVaryingsMax, outputVaryingsMax);
+ }
+
+ ASSERT(maxVaryingVectors > 0 && maxVaryingVectors < std::numeric_limits<GLint>::max());
+
+ if (!mVaryingPackings[frontShaderStage].collectAndPackUserVaryings(
+ infoLog, maxVaryingVectors, packMode, frontShaderStage, backShaderStage,
+ mergedVaryings, tfVaryings, isSeparableProgram))
+ {
+ return false;
+ }
+
+ mBackToFrontStageMap[backShaderStage] = frontShaderStage;
+ frontShaderStage = backShaderStage;
+ }
+
+ // Special case for stop-before-fragment.
+ if (frontShaderStage != ShaderType::Fragment)
+ {
+ if (!mVaryingPackings[frontShaderStage].collectAndPackUserVaryings(
+ infoLog, GetMaxShaderOutputVectors(caps, frontShaderStage), packMode,
+ frontShaderStage, ShaderType::InvalidEnum, mergedVaryings, tfVaryings,
+ isSeparableProgram))
+ {
+ return false;
+ }
+
+ ShaderType emulatedBackShaderStage = ShaderType::Fragment;
+ mBackToFrontStageMap[emulatedBackShaderStage] = frontShaderStage;
+ }
+
+ return true;
+}
+
+ProgramMergedVaryings GetMergedVaryingsFromLinkingVariables(
+ const LinkingVariables &linkingVariables)
+{
+ ShaderType frontShaderType = ShaderType::InvalidEnum;
+ ProgramMergedVaryings merged;
+
+ for (ShaderType backShaderType : kAllGraphicsShaderTypes)
+ {
+ if (!linkingVariables.isShaderStageUsedBitset[backShaderType])
+ {
+ continue;
+ }
+ const std::vector<sh::ShaderVariable> &backShaderOutputVaryings =
+ linkingVariables.outputVaryings[backShaderType];
+ const std::vector<sh::ShaderVariable> &backShaderInputVaryings =
+ linkingVariables.inputVaryings[backShaderType];
+
+ // Add outputs. These are always unmatched since we walk shader stages sequentially.
+ for (const sh::ShaderVariable &frontVarying : backShaderOutputVaryings)
+ {
+ ProgramVaryingRef ref;
+ ref.frontShader = &frontVarying;
+ ref.frontShaderStage = backShaderType;
+ merged.push_back(ref);
+ }
+
+ if (frontShaderType == ShaderType::InvalidEnum)
+ {
+ // If this is our first shader stage, and not a VS, we might have unmatched inputs.
+ for (const sh::ShaderVariable &backVarying : backShaderInputVaryings)
+ {
+ ProgramVaryingRef ref;
+ ref.backShader = &backVarying;
+ ref.backShaderStage = backShaderType;
+ merged.push_back(ref);
+ }
+ }
+ else
+ {
+ // Match inputs with the prior shader stage outputs.
+ for (const sh::ShaderVariable &backVarying : backShaderInputVaryings)
+ {
+ bool found = false;
+ for (ProgramVaryingRef &ref : merged)
+ {
+ if (ref.frontShader && ref.frontShaderStage == frontShaderType &&
+ InterfaceVariablesMatch(*ref.frontShader, backVarying))
+ {
+ ASSERT(ref.backShader == nullptr);
+
+ ref.backShader = &backVarying;
+ ref.backShaderStage = backShaderType;
+ found = true;
+ break;
+ }
+ }
+
+ // Some outputs are never matched, e.g. some builtin variables.
+ if (!found)
+ {
+ ProgramVaryingRef ref;
+ ref.backShader = &backVarying;
+ ref.backShaderStage = backShaderType;
+ merged.push_back(ref);
+ }
+ }
+ }
+
+ // Save the current back shader to use as the next front shader.
+ frontShaderType = backShaderType;
+ }
+
+ return merged;
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/VaryingPacking.h b/gfx/angle/checkout/src/libANGLE/VaryingPacking.h
new file mode 100644
index 0000000000..3edb9326be
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/VaryingPacking.h
@@ -0,0 +1,329 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// VaryingPacking:
+// Class which describes a mapping from varyings to registers, according
+// to the spec, or using custom packing algorithms. We also keep a register
+// allocation list for the D3D renderer.
+//
+
+#ifndef LIBANGLE_VARYINGPACKING_H_
+#define LIBANGLE_VARYINGPACKING_H_
+
+#include <GLSLANG/ShaderVars.h>
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+
+#include <map>
+
+namespace gl
+{
+class InfoLog;
+class ProgramExecutable;
+struct Caps;
+struct LinkingVariables;
+struct ProgramVaryingRef;
+
+using ProgramMergedVaryings = std::vector<ProgramVaryingRef>;
+
+// A varying can have different names between stages if matched by the location layout qualifier.
+// Additionally, same name varyings could still be of two identical struct types with different
+// names. This struct contains information on the varying in one of the two stages. PackedVarying
+// will thus contain two copies of this along with common information, such as interpolation or
+// field index.
+struct VaryingInShaderRef : angle::NonCopyable
+{
+ VaryingInShaderRef(ShaderType stageIn, const sh::ShaderVariable *varyingIn);
+ VaryingInShaderRef(VaryingInShaderRef &&other);
+ ~VaryingInShaderRef();
+
+ VaryingInShaderRef &operator=(VaryingInShaderRef &&other);
+
+ const sh::ShaderVariable *varying;
+
+ ShaderType stage;
+
+ // Struct name
+ std::string parentStructName;
+ std::string parentStructMappedName;
+};
+
+struct PackedVarying : angle::NonCopyable
+{
+ // Throughout this file, the "front" stage refers to the stage that outputs the varying, and the
+ // "back" stage refers to the stage that takes the varying as input. Note that this struct
+ // contains linked varyings, which means both front and back stage varyings are valid, except
+ // for the following which may have only one valid stage.
+ //
+ // - transform-feedback-captured varyings
+ // - builtins
+ // - separable program stages,
+ //
+ PackedVarying(VaryingInShaderRef &&frontVaryingIn,
+ VaryingInShaderRef &&backVaryingIn,
+ sh::InterpolationType interpolationIn);
+ PackedVarying(VaryingInShaderRef &&frontVaryingIn,
+ VaryingInShaderRef &&backVaryingIn,
+ sh::InterpolationType interpolationIn,
+ GLuint arrayIndexIn,
+ GLuint fieldIndexIn,
+ GLuint secondaryFieldIndexIn);
+ PackedVarying(PackedVarying &&other);
+ ~PackedVarying();
+
+ PackedVarying &operator=(PackedVarying &&other);
+
+ bool isStructField() const
+ {
+ return frontVarying.varying ? !frontVarying.parentStructName.empty()
+ : !backVarying.parentStructName.empty();
+ }
+
+ bool isTransformFeedbackArrayElement() const
+ {
+ return isTransformFeedback && arrayIndex != GL_INVALID_INDEX;
+ }
+
+ // Return either front or back varying, whichever is available. Only used when the name of the
+ // varying is not important, but only the type is interesting.
+ const sh::ShaderVariable &varying() const
+ {
+ return frontVarying.varying ? *frontVarying.varying : *backVarying.varying;
+ }
+
+ const std::string &getParentStructName() const
+ {
+ ASSERT(isStructField());
+ return frontVarying.varying ? frontVarying.parentStructName : backVarying.parentStructName;
+ }
+
+ std::string fullName(ShaderType stage) const
+ {
+ ASSERT(stage == frontVarying.stage || stage == backVarying.stage);
+ const VaryingInShaderRef &varying =
+ stage == frontVarying.stage ? frontVarying : backVarying;
+
+ std::stringstream fullNameStr;
+ if (isStructField())
+ {
+ fullNameStr << varying.parentStructName << ".";
+ }
+
+ fullNameStr << varying.varying->name;
+ if (arrayIndex != GL_INVALID_INDEX)
+ {
+ fullNameStr << "[" << arrayIndex << "]";
+ }
+ return fullNameStr.str();
+ }
+
+ // Transform feedback varyings can be only referenced in the VS.
+ bool vertexOnly() const
+ {
+ return frontVarying.stage == ShaderType::Vertex && backVarying.varying == nullptr;
+ }
+
+ // Special handling for GS/TS array inputs.
+ unsigned int getBasicTypeElementCount() const;
+
+ VaryingInShaderRef frontVarying;
+ VaryingInShaderRef backVarying;
+
+ // Cached so we can store sh::ShaderVariable to point to varying fields.
+ sh::InterpolationType interpolation;
+
+ // Used by varyings that are captured with transform feedback, xor arrays of shader I/O blocks,
+ // distinguished by isTransformFeedback;
+ GLuint arrayIndex;
+ bool isTransformFeedback;
+
+ // Field index in the struct. In Vulkan, this is used to assign a
+ // struct-typed varying location to the location of its first field.
+ GLuint fieldIndex;
+ GLuint secondaryFieldIndex;
+};
+
+struct PackedVaryingRegister final
+{
+ PackedVaryingRegister()
+ : packedVarying(nullptr),
+ varyingArrayIndex(0),
+ varyingRowIndex(0),
+ registerRow(0),
+ registerColumn(0)
+ {}
+
+ PackedVaryingRegister(const PackedVaryingRegister &) = default;
+ PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default;
+
+ bool operator<(const PackedVaryingRegister &other) const
+ {
+ return sortOrder() < other.sortOrder();
+ }
+
+ unsigned int sortOrder() const
+ {
+ // TODO(jmadill): Handle interpolation types
+ return registerRow * 4 + registerColumn;
+ }
+
+ std::string tfVaryingName() const
+ {
+ return packedVarying->fullName(packedVarying->frontVarying.stage);
+ }
+
+ // Index to the array of varyings.
+ const PackedVarying *packedVarying;
+
+ // The array element of the packed varying.
+ unsigned int varyingArrayIndex;
+
+ // The row of the array element of the packed varying.
+ unsigned int varyingRowIndex;
+
+ // The register row to which we've assigned this packed varying.
+ unsigned int registerRow;
+
+ // The column of the register row into which we've packed this varying.
+ unsigned int registerColumn;
+};
+
+// Supported packing modes:
+enum class PackMode
+{
+ // We treat mat2 arrays as taking two full rows.
+ WEBGL_STRICT,
+
+ // We allow mat2 to take a 2x2 chunk.
+ ANGLE_RELAXED,
+
+ // Each varying takes a separate register. No register sharing.
+ ANGLE_NON_CONFORMANT_D3D9,
+};
+
+class VaryingPacking final : angle::NonCopyable
+{
+ public:
+ VaryingPacking();
+ ~VaryingPacking();
+
+ [[nodiscard]] bool collectAndPackUserVaryings(InfoLog &infoLog,
+ GLint maxVaryingVectors,
+ PackMode packMode,
+ ShaderType frontShaderStage,
+ ShaderType backShaderStage,
+ const ProgramMergedVaryings &mergedVaryings,
+ const std::vector<std::string> &tfVaryings,
+ const bool isSeparableProgram);
+
+ struct Register
+ {
+ Register() { data[0] = data[1] = data[2] = data[3] = false; }
+
+ bool &operator[](unsigned int index) { return data[index]; }
+ bool operator[](unsigned int index) const { return data[index]; }
+
+ bool data[4];
+ };
+
+ Register &operator[](unsigned int index) { return mRegisterMap[index]; }
+ const Register &operator[](unsigned int index) const { return mRegisterMap[index]; }
+
+ const std::vector<PackedVaryingRegister> &getRegisterList() const { return mRegisterList; }
+ unsigned int getMaxSemanticIndex() const
+ {
+ return static_cast<unsigned int>(mRegisterList.size());
+ }
+
+ const ShaderMap<std::vector<std::string>> &getInactiveVaryingMappedNames() const
+ {
+ return mInactiveVaryingMappedNames;
+ }
+
+ const ShaderMap<std::vector<std::string>> &getActiveOutputBuiltInNames() const
+ {
+ return mActiveOutputBuiltIns;
+ }
+
+ void reset();
+
+ private:
+ using VaryingUniqueFullNames = ShaderMap<std::set<std::string>>;
+
+ // Register map functions.
+ bool packUserVaryings(InfoLog &infoLog,
+ GLint maxVaryingVectors,
+ PackMode packMode,
+ const std::vector<PackedVarying> &packedVaryings);
+ bool packVaryingIntoRegisterMap(PackMode packMode, const PackedVarying &packedVarying);
+ bool isRegisterRangeFree(unsigned int registerRow,
+ unsigned int registerColumn,
+ unsigned int varyingRows,
+ unsigned int varyingColumns) const;
+ void insertVaryingIntoRegisterMap(unsigned int registerRow,
+ unsigned int registerColumn,
+ unsigned int varyingColumns,
+ const PackedVarying &packedVarying);
+ void clearRegisterMap();
+
+ // Collection functions.
+ void collectUserVarying(const ProgramVaryingRef &ref, VaryingUniqueFullNames *uniqueFullNames);
+ void collectUserVaryingField(const ProgramVaryingRef &ref,
+ GLuint arrayIndex,
+ GLuint fieldIndex,
+ GLuint secondaryFieldIndex,
+ VaryingUniqueFullNames *uniqueFullNames);
+ void collectUserVaryingTF(const ProgramVaryingRef &ref, size_t subscript);
+ void collectUserVaryingFieldTF(const ProgramVaryingRef &ref,
+ const sh::ShaderVariable &field,
+ GLuint fieldIndex,
+ GLuint secondaryFieldIndex);
+ void collectVarying(const sh::ShaderVariable &varying,
+ const ProgramVaryingRef &ref,
+ PackMode packMode,
+ VaryingUniqueFullNames *uniqueFullNames);
+ void collectTFVarying(const std::string &tfVarying,
+ const ProgramVaryingRef &ref,
+ VaryingUniqueFullNames *uniqueFullNames);
+
+ std::vector<Register> mRegisterMap;
+ std::vector<PackedVaryingRegister> mRegisterList;
+ std::vector<PackedVarying> mPackedVaryings;
+ ShaderMap<std::vector<std::string>> mInactiveVaryingMappedNames;
+ ShaderMap<std::vector<std::string>> mActiveOutputBuiltIns;
+};
+
+class ProgramVaryingPacking final : angle::NonCopyable
+{
+ public:
+ ProgramVaryingPacking();
+ ~ProgramVaryingPacking();
+
+ const VaryingPacking &getInputPacking(ShaderType backShaderStage) const;
+ const VaryingPacking &getOutputPacking(ShaderType frontShaderStage) const;
+
+ [[nodiscard]] bool collectAndPackUserVaryings(InfoLog &infoLog,
+ const Caps &caps,
+ PackMode packMode,
+ const ShaderBitSet &activeShadersMask,
+ const ProgramMergedVaryings &mergedVaryings,
+ const std::vector<std::string> &tfVaryings,
+ bool isSeparableProgram);
+
+ private:
+ // Indexed by the front shader.
+ ShaderMap<VaryingPacking> mVaryingPackings;
+
+ // Looks up the front stage from the back stage.
+ ShaderMap<ShaderType> mBackToFrontStageMap;
+};
+
+ProgramMergedVaryings GetMergedVaryingsFromLinkingVariables(
+ const LinkingVariables &linkingVariables);
+} // namespace gl
+
+#endif // LIBANGLE_VARYINGPACKING_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Version.h b/gfx/angle/checkout/src/libANGLE/Version.h
new file mode 100644
index 0000000000..0d3b502d21
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Version.h
@@ -0,0 +1,34 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Version.h: Encapsulation of a GL version.
+
+#ifndef LIBANGLE_VERSION_H_
+#define LIBANGLE_VERSION_H_
+
+namespace gl
+{
+
+struct Version
+{
+ constexpr Version();
+ constexpr Version(unsigned int major, unsigned int minor);
+
+ unsigned int major;
+ unsigned int minor;
+};
+
+bool operator==(const Version &a, const Version &b);
+bool operator!=(const Version &a, const Version &b);
+bool operator>=(const Version &a, const Version &b);
+bool operator<=(const Version &a, const Version &b);
+bool operator<(const Version &a, const Version &b);
+bool operator>(const Version &a, const Version &b);
+} // namespace gl
+
+#include "Version.inc"
+
+#endif // LIBANGLE_VERSION_H_
diff --git a/gfx/angle/checkout/src/libANGLE/Version.inc b/gfx/angle/checkout/src/libANGLE/Version.inc
new file mode 100644
index 0000000000..a2bab8dc1f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/Version.inc
@@ -0,0 +1,59 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Version.inc: Encapsulation of a GL version.
+
+#include <tuple>
+
+namespace gl
+{
+
+constexpr Version::Version()
+ : Version(0, 0)
+{
+}
+
+// Avoid conflicts with linux system defines
+#undef major
+#undef minor
+
+constexpr Version::Version(unsigned int major_, unsigned int minor_)
+ : major(major_),
+ minor(minor_)
+{
+}
+
+inline bool operator==(const Version &a, const Version &b)
+{
+ return std::tie(a.major, a.minor) == std::tie(b.major, b.minor);
+}
+
+inline bool operator!=(const Version &a, const Version &b)
+{
+ return std::tie(a.major, a.minor) != std::tie(b.major, b.minor);
+}
+
+inline bool operator>=(const Version &a, const Version &b)
+{
+ return std::tie(a.major, a.minor) >= std::tie(b.major, b.minor);
+}
+
+inline bool operator<=(const Version &a, const Version &b)
+{
+ return std::tie(a.major, a.minor) <= std::tie(b.major, b.minor);
+}
+
+inline bool operator<(const Version &a, const Version &b)
+{
+ return std::tie(a.major, a.minor) < std::tie(b.major, b.minor);
+}
+
+inline bool operator>(const Version &a, const Version &b)
+{
+ return std::tie(a.major, a.minor) > std::tie(b.major, b.minor);
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/VertexArray.cpp b/gfx/angle/checkout/src/libANGLE/VertexArray.cpp
new file mode 100644
index 0000000000..2a9bcd7cc0
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/VertexArray.cpp
@@ -0,0 +1,906 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Implementation of the state class for mananging GLES 3 Vertex Array Objects.
+//
+
+#include "libANGLE/VertexArray.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/BufferImpl.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+#include "libANGLE/renderer/VertexArrayImpl.h"
+
+namespace gl
+{
+namespace
+{
+constexpr size_t kMaxObserverCountToTriggerUnobserve = 20;
+
+bool IsElementArrayBufferSubjectIndex(angle::SubjectIndex subjectIndex)
+{
+ return (subjectIndex == kElementArrayBufferIndex);
+}
+} // namespace
+
+// VertexArrayState implementation.
+VertexArrayState::VertexArrayState(VertexArray *vertexArray,
+ size_t maxAttribs,
+ size_t maxAttribBindings)
+ : mElementArrayBuffer(vertexArray, kElementArrayBufferIndex)
+{
+ ASSERT(maxAttribs <= maxAttribBindings);
+
+ for (size_t i = 0; i < maxAttribs; i++)
+ {
+ mVertexAttributes.emplace_back(static_cast<GLuint>(i));
+ mVertexBindings.emplace_back(static_cast<GLuint>(i));
+ }
+
+ // Initially all attributes start as "client" with no buffer bound.
+ mClientMemoryAttribsMask.set();
+}
+
+VertexArrayState::~VertexArrayState() {}
+
+bool VertexArrayState::hasEnabledNullPointerClientArray() const
+{
+ return (mNullPointerClientMemoryAttribsMask & mEnabledAttributesMask).any();
+}
+
+AttributesMask VertexArrayState::getBindingToAttributesMask(GLuint bindingIndex) const
+{
+ ASSERT(bindingIndex < mVertexBindings.size());
+ return mVertexBindings[bindingIndex].getBoundAttributesMask();
+}
+
+// Set an attribute using a new binding.
+void VertexArrayState::setAttribBinding(const Context *context,
+ size_t attribIndex,
+ GLuint newBindingIndex)
+{
+ ASSERT(attribIndex < mVertexAttributes.size() && newBindingIndex < mVertexBindings.size());
+
+ VertexAttribute &attrib = mVertexAttributes[attribIndex];
+
+ // Update the binding-attribute map.
+ const GLuint oldBindingIndex = attrib.bindingIndex;
+ ASSERT(oldBindingIndex != newBindingIndex);
+
+ VertexBinding &oldBinding = mVertexBindings[oldBindingIndex];
+ VertexBinding &newBinding = mVertexBindings[newBindingIndex];
+
+ ASSERT(oldBinding.getBoundAttributesMask().test(attribIndex) &&
+ !newBinding.getBoundAttributesMask().test(attribIndex));
+
+ oldBinding.resetBoundAttribute(attribIndex);
+ newBinding.setBoundAttribute(attribIndex);
+
+ // Set the attribute using the new binding.
+ attrib.bindingIndex = newBindingIndex;
+
+ if (context->isBufferAccessValidationEnabled())
+ {
+ attrib.updateCachedElementLimit(newBinding);
+ }
+
+ bool isMapped = newBinding.getBuffer().get() && newBinding.getBuffer()->isMapped();
+ mCachedMappedArrayBuffers.set(attribIndex, isMapped);
+ mEnabledAttributesMask.set(attribIndex, attrib.enabled);
+ updateCachedMutableOrNonPersistentArrayBuffers(attribIndex);
+ mCachedInvalidMappedArrayBuffer = mCachedMappedArrayBuffers & mEnabledAttributesMask &
+ mCachedMutableOrImpersistentArrayBuffers;
+}
+
+void VertexArrayState::updateCachedMutableOrNonPersistentArrayBuffers(size_t index)
+{
+ const VertexBinding &vertexBinding = mVertexBindings[index];
+ const BindingPointer<Buffer> &buffer = vertexBinding.getBuffer();
+ bool isMutableOrImpersistentArrayBuffer =
+ buffer.get() &&
+ (!buffer->isImmutable() || (buffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) == 0);
+ mCachedMutableOrImpersistentArrayBuffers.set(index, isMutableOrImpersistentArrayBuffer);
+}
+
+// VertexArray implementation.
+VertexArray::VertexArray(rx::GLImplFactory *factory,
+ VertexArrayID id,
+ size_t maxAttribs,
+ size_t maxAttribBindings)
+ : mId(id),
+ mState(this, maxAttribs, maxAttribBindings),
+ mVertexArray(factory->createVertexArray(mState)),
+ mBufferAccessValidationEnabled(false),
+ mContentsObservers(this)
+{
+ for (size_t attribIndex = 0; attribIndex < maxAttribBindings; ++attribIndex)
+ {
+ mArrayBufferObserverBindings.emplace_back(this, attribIndex);
+ }
+
+ mVertexArray->setContentsObservers(&mContentsObservers);
+}
+
+void VertexArray::onDestroy(const Context *context)
+{
+ bool isBound = context->isCurrentVertexArray(this);
+ for (uint32_t bindingIndex = 0; bindingIndex < mState.mVertexBindings.size(); ++bindingIndex)
+ {
+ VertexBinding &binding = mState.mVertexBindings[bindingIndex];
+ Buffer *buffer = binding.getBuffer().get();
+ if (isBound)
+ {
+ if (buffer)
+ {
+ buffer->onNonTFBindingChanged(-1);
+ }
+ }
+ if (buffer)
+ {
+ // Note: the non-contents observer is unbound in the ObserverBinding destructor.
+ buffer->removeContentsObserver(this, bindingIndex);
+ }
+ binding.setBuffer(context, nullptr);
+ }
+ if (mState.mElementArrayBuffer.get())
+ {
+ if (isBound)
+ {
+ mState.mElementArrayBuffer->onNonTFBindingChanged(-1);
+ }
+ mState.mElementArrayBuffer->removeContentsObserver(this, kElementArrayBufferIndex);
+ }
+ mState.mElementArrayBuffer.bind(context, nullptr);
+
+ // If mDirtyObserverBindingBits is set, it means we have removed it from the buffer's observer
+ // list. We should unassign subject to avoid assertion.
+ for (size_t bindingIndex : mDirtyObserverBindingBits)
+ {
+ angle::ObserverBinding *observer = &mArrayBufferObserverBindings[bindingIndex];
+ observer->assignSubject(nullptr);
+ }
+
+ mVertexArray->destroy(context);
+ SafeDelete(mVertexArray);
+ delete this;
+}
+
+VertexArray::~VertexArray()
+{
+ ASSERT(!mVertexArray);
+}
+
+angle::Result VertexArray::setLabel(const Context *context, const std::string &label)
+{
+ mState.mLabel = label;
+
+ if (mVertexArray)
+ {
+ return mVertexArray->onLabelUpdate(context);
+ }
+ return angle::Result::Continue;
+}
+
+const std::string &VertexArray::getLabel() const
+{
+ return mState.mLabel;
+}
+
+bool VertexArray::detachBuffer(const Context *context, BufferID bufferID)
+{
+ bool isBound = context->isCurrentVertexArray(this);
+ bool anyBufferDetached = false;
+ for (uint32_t bindingIndex = 0; bindingIndex < mState.mVertexBindings.size(); ++bindingIndex)
+ {
+ VertexBinding &binding = mState.mVertexBindings[bindingIndex];
+ const BindingPointer<Buffer> &bufferBinding = binding.getBuffer();
+ if (bufferBinding.id() == bufferID)
+ {
+ if (isBound)
+ {
+ if (bufferBinding.get())
+ bufferBinding->onNonTFBindingChanged(-1);
+ }
+ bufferBinding->removeContentsObserver(this, bindingIndex);
+ binding.setBuffer(context, nullptr);
+ mArrayBufferObserverBindings[bindingIndex].reset();
+
+ if (context->getClientVersion() >= ES_3_1)
+ {
+ setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
+ }
+ else
+ {
+ static_assert(gl::MAX_VERTEX_ATTRIB_BINDINGS < 8 * sizeof(uint32_t),
+ "Not enough bits in bindingIndex");
+ // The redundant uint32_t cast here is required to avoid a warning on MSVC.
+ ASSERT(binding.getBoundAttributesMask() ==
+ AttributesMask(static_cast<uint32_t>(1 << bindingIndex)));
+ setDirtyAttribBit(bindingIndex, DIRTY_ATTRIB_POINTER);
+ }
+
+ anyBufferDetached = true;
+ mState.mClientMemoryAttribsMask |= binding.getBoundAttributesMask();
+ }
+ }
+
+ if (mState.mElementArrayBuffer.get() && mState.mElementArrayBuffer->id() == bufferID)
+ {
+ if (isBound && mState.mElementArrayBuffer.get())
+ mState.mElementArrayBuffer->onNonTFBindingChanged(-1);
+ mState.mElementArrayBuffer->removeContentsObserver(this, kElementArrayBufferIndex);
+ mState.mElementArrayBuffer.bind(context, nullptr);
+ mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
+ anyBufferDetached = true;
+ }
+
+ return anyBufferDetached;
+}
+
+const VertexAttribute &VertexArray::getVertexAttribute(size_t attribIndex) const
+{
+ ASSERT(attribIndex < getMaxAttribs());
+ return mState.mVertexAttributes[attribIndex];
+}
+
+const VertexBinding &VertexArray::getVertexBinding(size_t bindingIndex) const
+{
+ ASSERT(bindingIndex < getMaxBindings());
+ return mState.mVertexBindings[bindingIndex];
+}
+
+size_t VertexArray::GetVertexIndexFromDirtyBit(size_t dirtyBit)
+{
+ static_assert(gl::MAX_VERTEX_ATTRIBS == gl::MAX_VERTEX_ATTRIB_BINDINGS,
+ "The stride of vertex attributes should equal to that of vertex bindings.");
+ ASSERT(dirtyBit > DIRTY_BIT_ELEMENT_ARRAY_BUFFER);
+ return (dirtyBit - DIRTY_BIT_ATTRIB_0) % gl::MAX_VERTEX_ATTRIBS;
+}
+
+ANGLE_INLINE void VertexArray::setDirtyAttribBit(size_t attribIndex,
+ DirtyAttribBitType dirtyAttribBit)
+{
+ mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex);
+ mDirtyAttribBits[attribIndex].set(dirtyAttribBit);
+}
+
+ANGLE_INLINE void VertexArray::clearDirtyAttribBit(size_t attribIndex,
+ DirtyAttribBitType dirtyAttribBit)
+{
+ mDirtyAttribBits[attribIndex].set(dirtyAttribBit, false);
+ if (mDirtyAttribBits[attribIndex].any())
+ {
+ return;
+ }
+ mDirtyBits.set(DIRTY_BIT_ATTRIB_0 + attribIndex, false);
+}
+
+ANGLE_INLINE void VertexArray::setDirtyBindingBit(size_t bindingIndex,
+ DirtyBindingBitType dirtyBindingBit)
+{
+ mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
+ mDirtyBindingBits[bindingIndex].set(dirtyBindingBit);
+}
+
+ANGLE_INLINE void VertexArray::updateCachedBufferBindingSize(VertexBinding *binding)
+{
+ if (!mBufferAccessValidationEnabled)
+ return;
+
+ for (size_t boundAttribute : binding->getBoundAttributesMask())
+ {
+ mState.mVertexAttributes[boundAttribute].updateCachedElementLimit(*binding);
+ }
+}
+
+ANGLE_INLINE void VertexArray::updateCachedArrayBuffersMasks(
+ bool isMapped,
+ bool isImmutable,
+ bool isPersistent,
+ const AttributesMask &boundAttributesMask)
+{
+ if (isMapped)
+ {
+ mState.mCachedMappedArrayBuffers |= boundAttributesMask;
+ }
+ else
+ {
+ mState.mCachedMappedArrayBuffers &= ~boundAttributesMask;
+ }
+
+ if (!isImmutable || !isPersistent)
+ {
+ mState.mCachedMutableOrImpersistentArrayBuffers |= boundAttributesMask;
+ }
+ else
+ {
+ mState.mCachedMutableOrImpersistentArrayBuffers &= ~boundAttributesMask;
+ }
+
+ mState.mCachedInvalidMappedArrayBuffer = mState.mCachedMappedArrayBuffers &
+ mState.mEnabledAttributesMask &
+ mState.mCachedMutableOrImpersistentArrayBuffers;
+}
+
+ANGLE_INLINE void VertexArray::updateCachedMappedArrayBuffersBinding(const VertexBinding &binding)
+{
+ const Buffer *buffer = binding.getBuffer().get();
+ bool isMapped = buffer && buffer->isMapped();
+ bool isImmutable = buffer && buffer->isImmutable();
+ bool isPersistent = buffer && (buffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
+ return updateCachedArrayBuffersMasks(isMapped, isImmutable, isPersistent,
+ binding.getBoundAttributesMask());
+}
+
+ANGLE_INLINE void VertexArray::updateCachedTransformFeedbackBindingValidation(size_t bindingIndex,
+ const Buffer *buffer)
+{
+ const bool hasConflict = buffer && buffer->hasWebGLXFBBindingConflict(true);
+ mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, hasConflict);
+}
+
+bool VertexArray::bindVertexBufferImpl(const Context *context,
+ size_t bindingIndex,
+ Buffer *boundBuffer,
+ GLintptr offset,
+ GLsizei stride)
+{
+ ASSERT(bindingIndex < getMaxBindings());
+ ASSERT(context->isCurrentVertexArray(this));
+
+ VertexBinding *binding = &mState.mVertexBindings[bindingIndex];
+
+ Buffer *oldBuffer = binding->getBuffer().get();
+
+ const bool sameBuffer = oldBuffer == boundBuffer;
+ const bool sameStride = static_cast<GLuint>(stride) == binding->getStride();
+ const bool sameOffset = offset == binding->getOffset();
+
+ if (sameBuffer && sameStride && sameOffset)
+ {
+ return false;
+ }
+
+ angle::ObserverBinding *observer = &mArrayBufferObserverBindings[bindingIndex];
+ observer->assignSubject(boundBuffer);
+
+ // Several nullptr checks are combined here for optimization purposes.
+ if (oldBuffer)
+ {
+ oldBuffer->onNonTFBindingChanged(-1);
+ oldBuffer->removeObserver(observer);
+ oldBuffer->removeContentsObserver(this, static_cast<uint32_t>(bindingIndex));
+ oldBuffer->release(context);
+ }
+
+ binding->assignBuffer(boundBuffer);
+ binding->setOffset(offset);
+ binding->setStride(stride);
+ updateCachedBufferBindingSize(binding);
+
+ // Update client memory attribute pointers. Affects all bound attributes.
+ if (boundBuffer)
+ {
+ boundBuffer->addRef();
+ boundBuffer->onNonTFBindingChanged(1);
+ boundBuffer->addObserver(observer);
+ if (context->isWebGL())
+ {
+ mCachedTransformFeedbackConflictedBindingsMask.set(
+ bindingIndex, boundBuffer->hasWebGLXFBBindingConflict(true));
+ }
+ mState.mClientMemoryAttribsMask &= ~binding->getBoundAttributesMask();
+
+ bool isMapped = boundBuffer->isMapped() == GL_TRUE;
+ bool isImmutable = boundBuffer->isImmutable() == GL_TRUE;
+ bool isPersistent = (boundBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
+ updateCachedArrayBuffersMasks(isMapped, isImmutable, isPersistent,
+ binding->getBoundAttributesMask());
+ }
+ else
+ {
+ if (context->isWebGL())
+ {
+ mCachedTransformFeedbackConflictedBindingsMask.set(bindingIndex, false);
+ }
+ mState.mClientMemoryAttribsMask |= binding->getBoundAttributesMask();
+ updateCachedArrayBuffersMasks(false, false, false, binding->getBoundAttributesMask());
+ }
+
+ return true;
+}
+
+void VertexArray::bindVertexBuffer(const Context *context,
+ size_t bindingIndex,
+ Buffer *boundBuffer,
+ GLintptr offset,
+ GLsizei stride)
+{
+ if (bindVertexBufferImpl(context, bindingIndex, boundBuffer, offset, stride))
+ {
+ setDirtyBindingBit(bindingIndex, DIRTY_BINDING_BUFFER);
+ }
+}
+
+void VertexArray::setVertexAttribBinding(const Context *context,
+ size_t attribIndex,
+ GLuint bindingIndex)
+{
+ ASSERT(attribIndex < getMaxAttribs() && bindingIndex < getMaxBindings());
+
+ if (mState.mVertexAttributes[attribIndex].bindingIndex == bindingIndex)
+ {
+ return;
+ }
+
+ // In ES 3.0 contexts, the binding cannot change, hence the code below is unreachable.
+ ASSERT(context->getClientVersion() >= ES_3_1);
+
+ mState.setAttribBinding(context, attribIndex, bindingIndex);
+
+ setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_BINDING);
+
+ // Update client attribs mask.
+ bool hasBuffer = mState.mVertexBindings[bindingIndex].getBuffer().get() != nullptr;
+ mState.mClientMemoryAttribsMask.set(attribIndex, !hasBuffer);
+}
+
+void VertexArray::setVertexBindingDivisor(const Context *context,
+ size_t bindingIndex,
+ GLuint divisor)
+{
+ ASSERT(bindingIndex < getMaxBindings());
+
+ VertexBinding &binding = mState.mVertexBindings[bindingIndex];
+
+ if (binding.getDivisor() == divisor)
+ {
+ return;
+ }
+
+ binding.setDivisor(divisor);
+ setDirtyBindingBit(bindingIndex, DIRTY_BINDING_DIVISOR);
+
+ // Trigger updates in all bound attributes.
+ if (context->isBufferAccessValidationEnabled())
+ {
+ for (size_t attribIndex : binding.getBoundAttributesMask())
+ {
+ mState.mVertexAttributes[attribIndex].updateCachedElementLimit(binding);
+ }
+ }
+}
+
+ANGLE_INLINE bool VertexArray::setVertexAttribFormatImpl(VertexAttribute *attrib,
+ GLint size,
+ VertexAttribType type,
+ bool normalized,
+ bool pureInteger,
+ GLuint relativeOffset)
+{
+ angle::FormatID formatID = gl::GetVertexFormatID(type, normalized, size, pureInteger);
+
+ if (formatID != attrib->format->id || attrib->relativeOffset != relativeOffset)
+ {
+ attrib->relativeOffset = relativeOffset;
+ attrib->format = &angle::Format::Get(formatID);
+ return true;
+ }
+
+ return false;
+}
+
+void VertexArray::setVertexAttribFormat(size_t attribIndex,
+ GLint size,
+ VertexAttribType type,
+ bool normalized,
+ bool pureInteger,
+ GLuint relativeOffset)
+{
+ VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
+
+ ComponentType componentType = GetVertexAttributeComponentType(pureInteger, type);
+ SetComponentTypeMask(componentType, attribIndex, &mState.mVertexAttributesTypeMask);
+
+ if (setVertexAttribFormatImpl(&attrib, size, type, normalized, pureInteger, relativeOffset))
+ {
+ setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_FORMAT);
+ }
+
+ attrib.updateCachedElementLimit(mState.mVertexBindings[attrib.bindingIndex]);
+}
+
+void VertexArray::setVertexAttribDivisor(const Context *context, size_t attribIndex, GLuint divisor)
+{
+ ASSERT(attribIndex < getMaxAttribs());
+
+ setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
+ setVertexBindingDivisor(context, attribIndex, divisor);
+}
+
+void VertexArray::enableAttribute(size_t attribIndex, bool enabledState)
+{
+ ASSERT(attribIndex < getMaxAttribs());
+
+ VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
+
+ if (mState.mEnabledAttributesMask.test(attribIndex) == enabledState)
+ {
+ return;
+ }
+
+ attrib.enabled = enabledState;
+
+ // Update state cache
+ mState.mEnabledAttributesMask.set(attribIndex, enabledState);
+ bool enableChanged = (mState.mEnabledAttributesMask.test(attribIndex) !=
+ mState.mLastSyncedEnabledAttributesMask.test(attribIndex));
+
+ if (enableChanged)
+ {
+ setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
+ }
+ else
+ {
+ clearDirtyAttribBit(attribIndex, DIRTY_ATTRIB_ENABLED);
+ }
+
+ mState.updateCachedMutableOrNonPersistentArrayBuffers(attribIndex);
+ mState.mCachedInvalidMappedArrayBuffer = mState.mCachedMappedArrayBuffers &
+ mState.mEnabledAttributesMask &
+ mState.mCachedMutableOrImpersistentArrayBuffers;
+}
+
+ANGLE_INLINE void VertexArray::setVertexAttribPointerImpl(const Context *context,
+ ComponentType componentType,
+ bool pureInteger,
+ size_t attribIndex,
+ Buffer *boundBuffer,
+ GLint size,
+ VertexAttribType type,
+ bool normalized,
+ GLsizei stride,
+ const void *pointer)
+{
+ ASSERT(attribIndex < getMaxAttribs());
+
+ VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
+
+ SetComponentTypeMask(componentType, attribIndex, &mState.mVertexAttributesTypeMask);
+
+ bool attribDirty = setVertexAttribFormatImpl(&attrib, size, type, normalized, pureInteger, 0);
+
+ if (attrib.bindingIndex != attribIndex)
+ {
+ setVertexAttribBinding(context, attribIndex, static_cast<GLuint>(attribIndex));
+ }
+
+ GLsizei effectiveStride =
+ stride == 0 ? static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)) : stride;
+
+ if (attrib.vertexAttribArrayStride != static_cast<GLuint>(stride))
+ {
+ attribDirty = true;
+ }
+ attrib.vertexAttribArrayStride = stride;
+
+ // If we switch from an array buffer to a client pointer(or vice-versa), we set the whole
+ // attribute dirty. This notifies the Vulkan back-end to update all its caches.
+ const VertexBinding &binding = mState.mVertexBindings[attribIndex];
+ if ((boundBuffer == nullptr) != (binding.getBuffer().get() == nullptr))
+ {
+ attribDirty = true;
+ }
+
+ // Change of attrib.pointer is not part of attribDirty. Pointer is actually the buffer offset
+ // which is handled within bindVertexBufferImpl and reflected in bufferDirty.
+ attrib.pointer = pointer;
+ GLintptr offset = boundBuffer ? reinterpret_cast<GLintptr>(pointer) : 0;
+ const bool bufferDirty =
+ bindVertexBufferImpl(context, attribIndex, boundBuffer, offset, effectiveStride);
+
+ if (attribDirty)
+ {
+ setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER);
+ }
+ else if (bufferDirty)
+ {
+ setDirtyAttribBit(attribIndex, DIRTY_ATTRIB_POINTER_BUFFER);
+ }
+
+ mState.mNullPointerClientMemoryAttribsMask.set(attribIndex,
+ boundBuffer == nullptr && pointer == nullptr);
+}
+
+void VertexArray::setVertexAttribPointer(const Context *context,
+ size_t attribIndex,
+ gl::Buffer *boundBuffer,
+ GLint size,
+ VertexAttribType type,
+ bool normalized,
+ GLsizei stride,
+ const void *pointer)
+{
+ setVertexAttribPointerImpl(context, ComponentType::Float, false, attribIndex, boundBuffer, size,
+ type, normalized, stride, pointer);
+}
+
+void VertexArray::setVertexAttribIPointer(const Context *context,
+ size_t attribIndex,
+ gl::Buffer *boundBuffer,
+ GLint size,
+ VertexAttribType type,
+ GLsizei stride,
+ const void *pointer)
+{
+ ComponentType componentType = GetVertexAttributeComponentType(true, type);
+ setVertexAttribPointerImpl(context, componentType, true, attribIndex, boundBuffer, size, type,
+ false, stride, pointer);
+}
+
+angle::Result VertexArray::syncState(const Context *context)
+{
+ if (mDirtyBits.any())
+ {
+ mDirtyBitsGuard = mDirtyBits;
+ ANGLE_TRY(
+ mVertexArray->syncState(context, mDirtyBits, &mDirtyAttribBits, &mDirtyBindingBits));
+ mDirtyBits.reset();
+ mDirtyBitsGuard.reset();
+
+ // The dirty bits should be reset in the back-end. To simplify ASSERTs only check attrib 0.
+ ASSERT(mDirtyAttribBits[0].none());
+ ASSERT(mDirtyBindingBits[0].none());
+ mState.mLastSyncedEnabledAttributesMask = mState.mEnabledAttributesMask;
+ }
+ return angle::Result::Continue;
+}
+
+// This becomes current vertex array on the context
+void VertexArray::onBind(const Context *context)
+{
+ if (mDirtyObserverBindingBits.none())
+ {
+ return;
+ }
+
+ // This vertex array becoming current. Some of the bindings we may have removed from buffer's
+ // observer list. We need to add it back to the buffer's observer list and update dirty bits
+ // that we may have missed while we were not observing.
+ for (size_t bindingIndex : mDirtyObserverBindingBits)
+ {
+ const gl::VertexBinding &binding = mState.getVertexBindings()[bindingIndex];
+ gl::Buffer *bufferGL = binding.getBuffer().get();
+ ASSERT(bufferGL != nullptr);
+
+ bufferGL->addObserver(&mArrayBufferObserverBindings[bindingIndex]);
+ updateCachedMappedArrayBuffersBinding(mState.mVertexBindings[bindingIndex]);
+
+ // Assume both data and internal storage has been dirtied.
+ mDirtyBits.set(DIRTY_BIT_BINDING_0 + bindingIndex);
+
+ if (mBufferAccessValidationEnabled)
+ {
+ for (size_t boundAttribute :
+ mState.mVertexBindings[bindingIndex].getBoundAttributesMask())
+ {
+ mState.mVertexAttributes[boundAttribute].updateCachedElementLimit(
+ mState.mVertexBindings[bindingIndex]);
+ }
+ }
+
+ if (context->isWebGL())
+ {
+ updateCachedTransformFeedbackBindingValidation(bindingIndex, bufferGL);
+ }
+ }
+ mDirtyObserverBindingBits.reset();
+
+ onStateChange(angle::SubjectMessage::ContentsChanged);
+}
+
+// This becomes non-current vertex array on the context
+void VertexArray::onUnbind(const Context *context)
+{
+ // This vertex array becoming non-current. For performance reason, if there are too many
+ // observers in the buffer, we remove it from the buffers' observer list so that the cost of
+ // buffer sending signal to observers will be too expensive.
+ for (uint32_t bindingIndex = 0; bindingIndex < mArrayBufferObserverBindings.size();
+ ++bindingIndex)
+ {
+ const gl::VertexBinding &binding = mState.getVertexBindings()[bindingIndex];
+ gl::Buffer *bufferGL = binding.getBuffer().get();
+ if (bufferGL && bufferGL->getObserversCount() > kMaxObserverCountToTriggerUnobserve)
+ {
+ bufferGL->removeObserver(&mArrayBufferObserverBindings[bindingIndex]);
+ mDirtyObserverBindingBits.set(bindingIndex);
+ }
+ }
+}
+
+void VertexArray::onBindingChanged(const Context *context, int incr)
+{
+ // When vertex array gets unbound, we remove it from bound buffers' observer list so that when
+ // buffer changes, it wont has to loop over all these non-current vertex arrays and set dirty
+ // bit on them. To compensate for that, when we bind a vertex array, we have to check against
+ // each bound buffers and see if they have changed and needs to update vertex array's dirty bits
+ // accordingly
+ ASSERT(incr == 1 || incr == -1);
+ if (incr < 0)
+ {
+ onUnbind(context);
+ }
+ else
+ {
+ onBind(context);
+ }
+
+ if (context->isWebGL())
+ {
+ if (mState.mElementArrayBuffer.get())
+ mState.mElementArrayBuffer->onNonTFBindingChanged(incr);
+ for (auto &binding : mState.mVertexBindings)
+ {
+ binding.onContainerBindingChanged(context, incr);
+ }
+ }
+}
+
+VertexArray::DirtyBitType VertexArray::getDirtyBitFromIndex(bool contentsChanged,
+ angle::SubjectIndex index) const
+{
+ if (IsElementArrayBufferSubjectIndex(index))
+ {
+ mIndexRangeCache.invalidate();
+ return contentsChanged ? DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA
+ : DIRTY_BIT_ELEMENT_ARRAY_BUFFER;
+ }
+ else
+ {
+ // Note: this currently just gets the top-level dirty bit.
+ ASSERT(index < mArrayBufferObserverBindings.size());
+ return static_cast<DirtyBitType>(
+ (contentsChanged ? DIRTY_BIT_BUFFER_DATA_0 : DIRTY_BIT_BINDING_0) + index);
+ }
+}
+
+void VertexArray::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
+{
+ switch (message)
+ {
+ case angle::SubjectMessage::SubjectChanged:
+ if (!IsElementArrayBufferSubjectIndex(index))
+ {
+ updateCachedBufferBindingSize(&mState.mVertexBindings[index]);
+ }
+ setDependentDirtyBit(false, index);
+ break;
+
+ case angle::SubjectMessage::BindingChanged:
+ if (!IsElementArrayBufferSubjectIndex(index))
+ {
+ const Buffer *buffer = mState.mVertexBindings[index].getBuffer().get();
+ updateCachedTransformFeedbackBindingValidation(index, buffer);
+ }
+ break;
+
+ case angle::SubjectMessage::SubjectMapped:
+ if (!IsElementArrayBufferSubjectIndex(index))
+ {
+ updateCachedMappedArrayBuffersBinding(mState.mVertexBindings[index]);
+ }
+ onStateChange(angle::SubjectMessage::SubjectMapped);
+ break;
+
+ case angle::SubjectMessage::SubjectUnmapped:
+ setDependentDirtyBit(true, index);
+
+ if (!IsElementArrayBufferSubjectIndex(index))
+ {
+ updateCachedMappedArrayBuffersBinding(mState.mVertexBindings[index]);
+ }
+ onStateChange(angle::SubjectMessage::SubjectUnmapped);
+ break;
+
+ case angle::SubjectMessage::InternalMemoryAllocationChanged:
+ setDependentDirtyBit(false, index);
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void VertexArray::setDependentDirtyBit(bool contentsChanged, angle::SubjectIndex index)
+{
+ DirtyBitType dirtyBit = getDirtyBitFromIndex(contentsChanged, index);
+ ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(dirtyBit));
+ mDirtyBits.set(dirtyBit);
+ onStateChange(angle::SubjectMessage::ContentsChanged);
+}
+
+bool VertexArray::hasTransformFeedbackBindingConflict(const gl::Context *context) const
+{
+ // Fast check first.
+ if (!mCachedTransformFeedbackConflictedBindingsMask.any())
+ {
+ return false;
+ }
+
+ const AttributesMask &activeAttribues = context->getStateCache().getActiveBufferedAttribsMask();
+
+ // Slow check. We must ensure that the conflicting attributes are enabled/active.
+ for (size_t attribIndex : activeAttribues)
+ {
+ const VertexAttribute &attrib = mState.mVertexAttributes[attribIndex];
+ if (mCachedTransformFeedbackConflictedBindingsMask[attrib.bindingIndex])
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+angle::Result VertexArray::getIndexRangeImpl(const Context *context,
+ DrawElementsType type,
+ GLsizei indexCount,
+ const void *indices,
+ IndexRange *indexRangeOut) const
+{
+ Buffer *elementArrayBuffer = mState.mElementArrayBuffer.get();
+ if (!elementArrayBuffer)
+ {
+ *indexRangeOut = ComputeIndexRange(type, indices, indexCount,
+ context->getState().isPrimitiveRestartEnabled());
+ return angle::Result::Continue;
+ }
+
+ size_t offset = reinterpret_cast<uintptr_t>(indices);
+ ANGLE_TRY(elementArrayBuffer->getIndexRange(context, type, offset, indexCount,
+ context->getState().isPrimitiveRestartEnabled(),
+ indexRangeOut));
+
+ mIndexRangeCache.put(type, indexCount, offset, *indexRangeOut);
+ return angle::Result::Continue;
+}
+
+VertexArray::IndexRangeCache::IndexRangeCache() = default;
+
+void VertexArray::IndexRangeCache::put(DrawElementsType type,
+ GLsizei indexCount,
+ size_t offset,
+ const IndexRange &indexRange)
+{
+ ASSERT(type != DrawElementsType::InvalidEnum);
+
+ mTypeKey = type;
+ mIndexCountKey = indexCount;
+ mOffsetKey = offset;
+ mPayload = indexRange;
+}
+
+void VertexArray::onBufferContentsChange(uint32_t bufferIndex)
+{
+ setDependentDirtyBit(true, bufferIndex);
+}
+
+VertexArrayBufferContentsObservers::VertexArrayBufferContentsObservers(VertexArray *vertexArray)
+ : mVertexArray(vertexArray)
+{}
+
+void VertexArrayBufferContentsObservers::enableForBuffer(Buffer *buffer, uint32_t bufferIndex)
+{
+ buffer->addContentsObserver(mVertexArray, bufferIndex);
+}
+
+void VertexArrayBufferContentsObservers::disableForBuffer(Buffer *buffer, uint32_t bufferIndex)
+{
+ buffer->removeContentsObserver(mVertexArray, bufferIndex);
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/VertexArray.h b/gfx/angle/checkout/src/libANGLE/VertexArray.h
new file mode 100644
index 0000000000..16f036c86b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/VertexArray.h
@@ -0,0 +1,436 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This class contains prototypes for representing GLES 3 Vertex Array Objects:
+//
+// The buffer objects that are to be used by the vertex stage of the GL are collected
+// together to form a vertex array object. All state related to the definition of data used
+// by the vertex processor is encapsulated in a vertex array object.
+//
+
+#ifndef LIBANGLE_VERTEXARRAY_H_
+#define LIBANGLE_VERTEXARRAY_H_
+
+#include "common/Optional.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Debug.h"
+#include "libANGLE/Observer.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/VertexAttribute.h"
+
+#include <vector>
+
+namespace rx
+{
+class GLImplFactory;
+class VertexArrayImpl;
+} // namespace rx
+
+namespace gl
+{
+class Buffer;
+
+constexpr uint32_t kElementArrayBufferIndex = MAX_VERTEX_ATTRIBS;
+
+class VertexArrayState final : angle::NonCopyable
+{
+ public:
+ VertexArrayState(VertexArray *vertexArray, size_t maxAttribs, size_t maxBindings);
+ ~VertexArrayState();
+
+ const std::string &getLabel() const { return mLabel; }
+
+ Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); }
+ size_t getMaxAttribs() const { return mVertexAttributes.size(); }
+ size_t getMaxBindings() const { return mVertexBindings.size(); }
+ const AttributesMask &getEnabledAttributesMask() const { return mEnabledAttributesMask; }
+ const std::vector<VertexAttribute> &getVertexAttributes() const { return mVertexAttributes; }
+ const VertexAttribute &getVertexAttribute(size_t attribIndex) const
+ {
+ return mVertexAttributes[attribIndex];
+ }
+ const std::vector<VertexBinding> &getVertexBindings() const { return mVertexBindings; }
+ const VertexBinding &getVertexBinding(size_t bindingIndex) const
+ {
+ return mVertexBindings[bindingIndex];
+ }
+ const VertexBinding &getBindingFromAttribIndex(size_t attribIndex) const
+ {
+ return mVertexBindings[mVertexAttributes[attribIndex].bindingIndex];
+ }
+ size_t getBindingIndexFromAttribIndex(size_t attribIndex) const
+ {
+ return mVertexAttributes[attribIndex].bindingIndex;
+ }
+
+ void setAttribBinding(const Context *context, size_t attribIndex, GLuint newBindingIndex);
+
+ // Extra validation performed on the Vertex Array.
+ bool hasEnabledNullPointerClientArray() const;
+
+ // Get all the attributes in an AttributesMask that are using the given binding.
+ AttributesMask getBindingToAttributesMask(GLuint bindingIndex) const;
+
+ ComponentTypeMask getVertexAttributesTypeMask() const { return mVertexAttributesTypeMask; }
+
+ AttributesMask getClientMemoryAttribsMask() const { return mClientMemoryAttribsMask; }
+
+ gl::AttributesMask getNullPointerClientMemoryAttribsMask() const
+ {
+ return mNullPointerClientMemoryAttribsMask;
+ }
+
+ private:
+ void updateCachedMutableOrNonPersistentArrayBuffers(size_t index);
+
+ friend class VertexArray;
+ std::string mLabel;
+ std::vector<VertexAttribute> mVertexAttributes;
+ SubjectBindingPointer<Buffer> mElementArrayBuffer;
+ std::vector<VertexBinding> mVertexBindings;
+ AttributesMask mEnabledAttributesMask;
+ ComponentTypeMask mVertexAttributesTypeMask;
+ AttributesMask mLastSyncedEnabledAttributesMask;
+
+ // This is a performance optimization for buffer binding. Allows element array buffer updates.
+ friend class State;
+
+ // From the GLES 3.1 spec:
+ // When a generic attribute array is sourced from client memory, the vertex attribute binding
+ // state is ignored. Thus we don't have to worry about binding state when using client memory
+ // attribs.
+ gl::AttributesMask mClientMemoryAttribsMask;
+ gl::AttributesMask mNullPointerClientMemoryAttribsMask;
+
+ // Used for validation cache. Indexed by attribute.
+ AttributesMask mCachedMappedArrayBuffers;
+ AttributesMask mCachedMutableOrImpersistentArrayBuffers;
+ AttributesMask mCachedInvalidMappedArrayBuffer;
+};
+
+class VertexArrayBufferContentsObservers final : angle::NonCopyable
+{
+ public:
+ VertexArrayBufferContentsObservers(VertexArray *vertexArray);
+ void enableForBuffer(Buffer *buffer, uint32_t bufferIndex);
+ void disableForBuffer(Buffer *buffer, uint32_t bufferIndex);
+
+ private:
+ VertexArray *mVertexArray;
+};
+
+class VertexArray final : public angle::ObserverInterface,
+ public LabeledObject,
+ public angle::Subject
+{
+ public:
+ // Dirty bits for VertexArrays use a hierarchical design. At the top level, each attribute
+ // has a single dirty bit. Then an array of MAX_ATTRIBS dirty bits each has a dirty bit for
+ // enabled/pointer/format/binding. Bindings are handled similarly. Note that because the
+ // total number of dirty bits is 33, it will not be as fast on a 32-bit machine, which
+ // can't support the advanced 64-bit scanning intrinsics. We could consider packing the
+ // binding and attribute bits together if this becomes a problem.
+ //
+ // Special note on "DIRTY_ATTRIB_POINTER_BUFFER": this is a special case when the app
+ // calls glVertexAttribPointer but only changes a VBO and/or offset binding. This allows
+ // the Vulkan back-end to skip performing a pipeline change for performance.
+ enum DirtyBitType
+ {
+ DIRTY_BIT_ELEMENT_ARRAY_BUFFER,
+ DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA,
+
+ // Dirty bits for bindings.
+ DIRTY_BIT_BINDING_0,
+ DIRTY_BIT_BINDING_MAX = DIRTY_BIT_BINDING_0 + gl::MAX_VERTEX_ATTRIB_BINDINGS,
+
+ // We keep separate dirty bits for bound buffers whose data changed since last update.
+ DIRTY_BIT_BUFFER_DATA_0 = DIRTY_BIT_BINDING_MAX,
+ DIRTY_BIT_BUFFER_DATA_MAX = DIRTY_BIT_BUFFER_DATA_0 + gl::MAX_VERTEX_ATTRIB_BINDINGS,
+
+ // Dirty bits for attributes.
+ DIRTY_BIT_ATTRIB_0 = DIRTY_BIT_BUFFER_DATA_MAX,
+ DIRTY_BIT_ATTRIB_MAX = DIRTY_BIT_ATTRIB_0 + gl::MAX_VERTEX_ATTRIBS,
+
+ DIRTY_BIT_UNKNOWN = DIRTY_BIT_ATTRIB_MAX,
+ DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN,
+ };
+
+ // We want to keep the number of dirty bits within 64 to keep iteration times fast.
+ static_assert(DIRTY_BIT_MAX <= 64, "Too many vertex array dirty bits.");
+ // The dirty bit processing has the logic to avoid redundant processing by removing other dirty
+ // bits when it processes dirtyBits. This assertion ensures these dirty bit order matches what
+ // VertexArrayVk::syncState expects.
+ static_assert(DIRTY_BIT_BINDING_0 < DIRTY_BIT_BUFFER_DATA_0,
+ "BINDING dity bits should come before DATA.");
+ static_assert(DIRTY_BIT_BUFFER_DATA_0 < DIRTY_BIT_ATTRIB_0,
+ "DATA dity bits should come before ATTRIB.");
+
+ enum DirtyAttribBitType
+ {
+ DIRTY_ATTRIB_ENABLED,
+ DIRTY_ATTRIB_POINTER,
+ DIRTY_ATTRIB_FORMAT,
+ DIRTY_ATTRIB_BINDING,
+ DIRTY_ATTRIB_POINTER_BUFFER,
+ DIRTY_ATTRIB_UNKNOWN,
+ DIRTY_ATTRIB_MAX = DIRTY_ATTRIB_UNKNOWN,
+ };
+
+ enum DirtyBindingBitType
+ {
+ DIRTY_BINDING_BUFFER,
+ DIRTY_BINDING_DIVISOR,
+ DIRTY_BINDING_UNKNOWN,
+ DIRTY_BINDING_MAX = DIRTY_BINDING_UNKNOWN,
+ };
+
+ using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
+ using DirtyAttribBits = angle::BitSet<DIRTY_ATTRIB_MAX>;
+ using DirtyBindingBits = angle::BitSet<DIRTY_BINDING_MAX>;
+ using DirtyAttribBitsArray = std::array<DirtyAttribBits, gl::MAX_VERTEX_ATTRIBS>;
+ using DirtyBindingBitsArray = std::array<DirtyBindingBits, gl::MAX_VERTEX_ATTRIB_BINDINGS>;
+ using DirtyObserverBindingBits = angle::BitSet<gl::MAX_VERTEX_ATTRIB_BINDINGS>;
+
+ VertexArray(rx::GLImplFactory *factory,
+ VertexArrayID id,
+ size_t maxAttribs,
+ size_t maxAttribBindings);
+
+ void onDestroy(const Context *context);
+
+ VertexArrayID id() const { return mId; }
+
+ angle::Result setLabel(const Context *context, const std::string &label) override;
+ const std::string &getLabel() const override;
+
+ const VertexBinding &getVertexBinding(size_t bindingIndex) const;
+ const VertexAttribute &getVertexAttribute(size_t attribIndex) const;
+ const VertexBinding &getBindingFromAttribIndex(size_t attribIndex) const
+ {
+ return mState.getBindingFromAttribIndex(attribIndex);
+ }
+
+ // Returns true if the function finds and detaches a bound buffer.
+ bool detachBuffer(const Context *context, BufferID bufferID);
+
+ void setVertexAttribDivisor(const Context *context, size_t index, GLuint divisor);
+ void enableAttribute(size_t attribIndex, bool enabledState);
+
+ void setVertexAttribPointer(const Context *context,
+ size_t attribIndex,
+ Buffer *boundBuffer,
+ GLint size,
+ VertexAttribType type,
+ bool normalized,
+ GLsizei stride,
+ const void *pointer);
+
+ void setVertexAttribIPointer(const Context *context,
+ size_t attribIndex,
+ Buffer *boundBuffer,
+ GLint size,
+ VertexAttribType type,
+ GLsizei stride,
+ const void *pointer);
+
+ void setVertexAttribFormat(size_t attribIndex,
+ GLint size,
+ VertexAttribType type,
+ bool normalized,
+ bool pureInteger,
+ GLuint relativeOffset);
+ void bindVertexBuffer(const Context *context,
+ size_t bindingIndex,
+ Buffer *boundBuffer,
+ GLintptr offset,
+ GLsizei stride);
+ void setVertexAttribBinding(const Context *context, size_t attribIndex, GLuint bindingIndex);
+ void setVertexBindingDivisor(const Context *context, size_t bindingIndex, GLuint divisor);
+
+ Buffer *getElementArrayBuffer() const { return mState.getElementArrayBuffer(); }
+ size_t getMaxAttribs() const { return mState.getMaxAttribs(); }
+ size_t getMaxBindings() const { return mState.getMaxBindings(); }
+
+ const std::vector<VertexAttribute> &getVertexAttributes() const
+ {
+ return mState.getVertexAttributes();
+ }
+ const std::vector<VertexBinding> &getVertexBindings() const
+ {
+ return mState.getVertexBindings();
+ }
+
+ rx::VertexArrayImpl *getImplementation() const { return mVertexArray; }
+
+ const AttributesMask &getEnabledAttributesMask() const
+ {
+ return mState.getEnabledAttributesMask();
+ }
+
+ gl::AttributesMask getClientAttribsMask() const { return mState.mClientMemoryAttribsMask; }
+
+ bool hasEnabledNullPointerClientArray() const
+ {
+ return mState.hasEnabledNullPointerClientArray();
+ }
+
+ bool hasInvalidMappedArrayBuffer() const
+ {
+ return mState.mCachedInvalidMappedArrayBuffer.any();
+ }
+
+ const VertexArrayState &getState() const { return mState; }
+
+ bool isBufferAccessValidationEnabled() const { return mBufferAccessValidationEnabled; }
+
+ // Observer implementation
+ void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
+ void onBufferContentsChange(uint32_t bufferIndex);
+
+ static size_t GetVertexIndexFromDirtyBit(size_t dirtyBit);
+
+ angle::Result syncState(const Context *context);
+ bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
+
+ ComponentTypeMask getAttributesTypeMask() const { return mState.mVertexAttributesTypeMask; }
+ AttributesMask getAttributesMask() const { return mState.mEnabledAttributesMask; }
+
+ void onBindingChanged(const Context *context, int incr);
+ bool hasTransformFeedbackBindingConflict(const gl::Context *context) const;
+
+ ANGLE_INLINE angle::Result getIndexRange(const Context *context,
+ DrawElementsType type,
+ GLsizei indexCount,
+ const void *indices,
+ IndexRange *indexRangeOut) const
+ {
+ Buffer *elementArrayBuffer = mState.mElementArrayBuffer.get();
+ if (elementArrayBuffer && mIndexRangeCache.get(type, indexCount, indices, indexRangeOut))
+ {
+ return angle::Result::Continue;
+ }
+
+ return getIndexRangeImpl(context, type, indexCount, indices, indexRangeOut);
+ }
+
+ void setBufferAccessValidationEnabled(bool enabled)
+ {
+ mBufferAccessValidationEnabled = enabled;
+ }
+
+ private:
+ ~VertexArray() override;
+
+ // This is a performance optimization for buffer binding. Allows element array buffer updates.
+ friend class State;
+
+ void setDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit);
+ void setDirtyBindingBit(size_t bindingIndex, DirtyBindingBitType dirtyBindingBit);
+ void clearDirtyAttribBit(size_t attribIndex, DirtyAttribBitType dirtyAttribBit);
+
+ DirtyBitType getDirtyBitFromIndex(bool contentsChanged, angle::SubjectIndex index) const;
+ void setDependentDirtyBit(bool contentsChanged, angle::SubjectIndex index);
+
+ // These are used to optimize draw call validation.
+ void updateCachedBufferBindingSize(VertexBinding *binding);
+ void updateCachedTransformFeedbackBindingValidation(size_t bindingIndex, const Buffer *buffer);
+ void updateCachedArrayBuffersMasks(bool isMapped,
+ bool isImmutable,
+ bool isPersistent,
+ const AttributesMask &boundAttributesMask);
+ void updateCachedMappedArrayBuffersBinding(const VertexBinding &binding);
+
+ angle::Result getIndexRangeImpl(const Context *context,
+ DrawElementsType type,
+ GLsizei indexCount,
+ const void *indices,
+ IndexRange *indexRangeOut) const;
+
+ void setVertexAttribPointerImpl(const Context *context,
+ ComponentType componentType,
+ bool pureInteger,
+ size_t attribIndex,
+ Buffer *boundBuffer,
+ GLint size,
+ VertexAttribType type,
+ bool normalized,
+ GLsizei stride,
+ const void *pointer);
+
+ // These two functions return true if the state was dirty.
+ bool setVertexAttribFormatImpl(VertexAttribute *attrib,
+ GLint size,
+ VertexAttribType type,
+ bool normalized,
+ bool pureInteger,
+ GLuint relativeOffset);
+ bool bindVertexBufferImpl(const Context *context,
+ size_t bindingIndex,
+ Buffer *boundBuffer,
+ GLintptr offset,
+ GLsizei stride);
+
+ void onBind(const Context *context);
+ void onUnbind(const Context *context);
+
+ VertexArrayID mId;
+
+ VertexArrayState mState;
+ DirtyBits mDirtyBits;
+ DirtyAttribBitsArray mDirtyAttribBits;
+ DirtyBindingBitsArray mDirtyBindingBits;
+ Optional<DirtyBits> mDirtyBitsGuard;
+
+ rx::VertexArrayImpl *mVertexArray;
+
+ std::vector<angle::ObserverBinding> mArrayBufferObserverBindings;
+ // Track which observer in mArrayBufferObserverBindings is not currently been removed from
+ // subject's observer list.
+ DirtyObserverBindingBits mDirtyObserverBindingBits;
+
+ AttributesMask mCachedTransformFeedbackConflictedBindingsMask;
+
+ class IndexRangeCache final : angle::NonCopyable
+ {
+ public:
+ IndexRangeCache();
+
+ void invalidate() { mTypeKey = DrawElementsType::InvalidEnum; }
+
+ bool get(DrawElementsType type,
+ GLsizei indexCount,
+ const void *indices,
+ IndexRange *indexRangeOut)
+ {
+ size_t offset = reinterpret_cast<uintptr_t>(indices);
+ if (mTypeKey == type && mIndexCountKey == indexCount && mOffsetKey == offset)
+ {
+ *indexRangeOut = mPayload;
+ return true;
+ }
+
+ return false;
+ }
+
+ void put(DrawElementsType type,
+ GLsizei indexCount,
+ size_t offset,
+ const IndexRange &indexRange);
+
+ private:
+ DrawElementsType mTypeKey;
+ GLsizei mIndexCountKey;
+ size_t mOffsetKey;
+ IndexRange mPayload;
+ };
+
+ mutable IndexRangeCache mIndexRangeCache;
+ bool mBufferAccessValidationEnabled;
+ VertexArrayBufferContentsObservers mContentsObservers;
+};
+
+} // namespace gl
+
+#endif // LIBANGLE_VERTEXARRAY_H_
diff --git a/gfx/angle/checkout/src/libANGLE/VertexAttribute.cpp b/gfx/angle/checkout/src/libANGLE/VertexAttribute.cpp
new file mode 100644
index 0000000000..f525addbba
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/VertexAttribute.cpp
@@ -0,0 +1,170 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Implementation of the state classes for mananging GLES 3.1 Vertex Array Objects.
+//
+
+#include "libANGLE/VertexAttribute.h"
+
+namespace gl
+{
+
+// [OpenGL ES 3.1] (November 3, 2016) Section 20 Page 361
+// Table 20.2: Vertex Array Object State
+VertexBinding::VertexBinding() : VertexBinding(0) {}
+
+VertexBinding::VertexBinding(GLuint boundAttribute) : mStride(16u), mDivisor(0), mOffset(0)
+{
+ mBoundAttributesMask.set(boundAttribute);
+}
+
+VertexBinding::VertexBinding(VertexBinding &&binding)
+{
+ *this = std::move(binding);
+}
+
+VertexBinding::~VertexBinding() {}
+
+VertexBinding &VertexBinding::operator=(VertexBinding &&binding)
+{
+ if (this != &binding)
+ {
+ mStride = binding.mStride;
+ mDivisor = binding.mDivisor;
+ mOffset = binding.mOffset;
+ mBoundAttributesMask = binding.mBoundAttributesMask;
+ std::swap(binding.mBuffer, mBuffer);
+ }
+ return *this;
+}
+
+void VertexBinding::onContainerBindingChanged(const Context *context, int incr) const
+{
+ if (mBuffer.get())
+ mBuffer->onNonTFBindingChanged(incr);
+}
+
+VertexAttribute::VertexAttribute(GLuint bindingIndex)
+ : enabled(false),
+ format(&angle::Format::Get(angle::FormatID::R32G32B32A32_FLOAT)),
+ pointer(nullptr),
+ relativeOffset(0),
+ vertexAttribArrayStride(0),
+ bindingIndex(bindingIndex),
+ mCachedElementLimit(0)
+{}
+
+VertexAttribute::VertexAttribute(VertexAttribute &&attrib)
+ : enabled(attrib.enabled),
+ format(attrib.format),
+ pointer(attrib.pointer),
+ relativeOffset(attrib.relativeOffset),
+ vertexAttribArrayStride(attrib.vertexAttribArrayStride),
+ bindingIndex(attrib.bindingIndex),
+ mCachedElementLimit(attrib.mCachedElementLimit)
+{}
+
+VertexAttribute &VertexAttribute::operator=(VertexAttribute &&attrib)
+{
+ if (this != &attrib)
+ {
+ enabled = attrib.enabled;
+ format = attrib.format;
+ pointer = attrib.pointer;
+ relativeOffset = attrib.relativeOffset;
+ vertexAttribArrayStride = attrib.vertexAttribArrayStride;
+ bindingIndex = attrib.bindingIndex;
+ mCachedElementLimit = attrib.mCachedElementLimit;
+ }
+ return *this;
+}
+
+void VertexAttribute::updateCachedElementLimit(const VertexBinding &binding)
+{
+ Buffer *buffer = binding.getBuffer().get();
+ if (!buffer)
+ {
+ mCachedElementLimit = 0;
+ return;
+ }
+
+ angle::CheckedNumeric<GLint64> bufferSize(buffer->getSize());
+ angle::CheckedNumeric<GLint64> bufferOffset(binding.getOffset());
+ angle::CheckedNumeric<GLint64> attribOffset(relativeOffset);
+ angle::CheckedNumeric<GLint64> attribSize(ComputeVertexAttributeTypeSize(*this));
+
+ // (buffer.size - buffer.offset - attrib.relativeOffset - attrib.size) / binding.stride
+ angle::CheckedNumeric<GLint64> elementLimit =
+ (bufferSize - bufferOffset - attribOffset - attribSize);
+
+ // Use the special integer overflow value if there was a math error.
+ if (!elementLimit.IsValid())
+ {
+ static_assert(kIntegerOverflow < 0, "Unexpected value");
+ mCachedElementLimit = kIntegerOverflow;
+ return;
+ }
+
+ mCachedElementLimit = elementLimit.ValueOrDie();
+ if (mCachedElementLimit < 0)
+ {
+ return;
+ }
+
+ if (binding.getStride() == 0)
+ {
+ // Special case for a zero stride. If we can fit one vertex we can fit infinite vertices.
+ mCachedElementLimit = std::numeric_limits<GLint64>::max();
+ return;
+ }
+
+ angle::CheckedNumeric<GLint64> bindingStride(binding.getStride());
+ elementLimit /= bindingStride;
+
+ if (binding.getDivisor() > 0)
+ {
+ // For instanced draws, the element count is floor(instanceCount - 1) / binding.divisor.
+ angle::CheckedNumeric<GLint64> bindingDivisor(binding.getDivisor());
+ elementLimit *= bindingDivisor;
+
+ // We account for the floor() part rounding by adding a rounding constant.
+ elementLimit += bindingDivisor - 1;
+ }
+
+ mCachedElementLimit = elementLimit.ValueOrDefault(kIntegerOverflow);
+}
+
+size_t ComputeVertexAttributeStride(const VertexAttribute &attrib, const VertexBinding &binding)
+{
+ // In ES 3.1, VertexAttribPointer will store the type size in the binding stride.
+ // Hence, rendering always uses the binding's stride.
+ return attrib.enabled ? binding.getStride() : 16u;
+}
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+GLintptr ComputeVertexAttributeOffset(const VertexAttribute &attrib, const VertexBinding &binding)
+{
+ return attrib.relativeOffset + binding.getOffset();
+}
+
+size_t ComputeVertexBindingElementCount(GLuint divisor, size_t drawCount, size_t instanceCount)
+{
+ // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices.
+ //
+ // A vertex attribute with a positive divisor loads one instanced vertex for every set of
+ // non-instanced vertices, and the instanced vertex index advances once every "mDivisor"
+ // instances.
+ if (instanceCount > 0 && divisor > 0)
+ {
+ // When instanceDrawCount is not a multiple attrib.divisor, the division must round up.
+ // For instance, with 5 non-instanced vertices and a divisor equal to 3, we need 2 instanced
+ // vertices.
+ return (instanceCount + divisor - 1u) / divisor;
+ }
+
+ return drawCount;
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/VertexAttribute.h b/gfx/angle/checkout/src/libANGLE/VertexAttribute.h
new file mode 100644
index 0000000000..dd89228d2a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/VertexAttribute.h
@@ -0,0 +1,139 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Helper structures about Generic Vertex Attribute.
+//
+
+#ifndef LIBANGLE_VERTEXATTRIBUTE_H_
+#define LIBANGLE_VERTEXATTRIBUTE_H_
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/Format.h"
+
+namespace gl
+{
+class VertexArray;
+
+//
+// Implementation of Generic Vertex Attribute Bindings for ES3.1. The members are intentionally made
+// private in order to hide implementation details.
+//
+class VertexBinding final : angle::NonCopyable
+{
+ public:
+ VertexBinding();
+ explicit VertexBinding(GLuint boundAttribute);
+ VertexBinding(VertexBinding &&binding);
+ ~VertexBinding();
+ VertexBinding &operator=(VertexBinding &&binding);
+
+ GLuint getStride() const { return mStride; }
+ void setStride(GLuint strideIn) { mStride = strideIn; }
+
+ GLuint getDivisor() const { return mDivisor; }
+ void setDivisor(GLuint divisorIn) { mDivisor = divisorIn; }
+
+ GLintptr getOffset() const { return mOffset; }
+ void setOffset(GLintptr offsetIn) { mOffset = offsetIn; }
+
+ const BindingPointer<Buffer> &getBuffer() const { return mBuffer; }
+
+ ANGLE_INLINE void setBuffer(const gl::Context *context, Buffer *bufferIn)
+ {
+ mBuffer.set(context, bufferIn);
+ }
+
+ // Skips ref counting for better inlined performance.
+ ANGLE_INLINE void assignBuffer(Buffer *bufferIn) { mBuffer.assign(bufferIn); }
+
+ void onContainerBindingChanged(const Context *context, int incr) const;
+
+ const AttributesMask &getBoundAttributesMask() const { return mBoundAttributesMask; }
+
+ void setBoundAttribute(size_t index) { mBoundAttributesMask.set(index); }
+
+ void resetBoundAttribute(size_t index) { mBoundAttributesMask.reset(index); }
+
+ private:
+ GLuint mStride;
+ GLuint mDivisor;
+ GLintptr mOffset;
+
+ BindingPointer<Buffer> mBuffer;
+
+ // Mapping from this binding to all of the attributes that are using this binding.
+ AttributesMask mBoundAttributesMask;
+};
+
+//
+// Implementation of Generic Vertex Attributes for ES3.1
+//
+struct VertexAttribute final : private angle::NonCopyable
+{
+ explicit VertexAttribute(GLuint bindingIndex);
+ VertexAttribute(VertexAttribute &&attrib);
+ VertexAttribute &operator=(VertexAttribute &&attrib);
+
+ // Called from VertexArray.
+ void updateCachedElementLimit(const VertexBinding &binding);
+ GLint64 getCachedElementLimit() const { return mCachedElementLimit; }
+
+ bool enabled; // For glEnable/DisableVertexAttribArray
+ const angle::Format *format;
+
+ const void *pointer;
+ GLuint relativeOffset;
+
+ GLuint vertexAttribArrayStride; // ONLY for queries of VERTEX_ATTRIB_ARRAY_STRIDE
+ GLuint bindingIndex;
+
+ // Special value for the cached element limit on the integer overflow case.
+ static constexpr GLint64 kIntegerOverflow = std::numeric_limits<GLint64>::min();
+
+ private:
+ // This is kept in sync by the VertexArray. It is used to optimize draw call validation.
+ GLint64 mCachedElementLimit;
+};
+
+ANGLE_INLINE size_t ComputeVertexAttributeTypeSize(const VertexAttribute &attrib)
+{
+ ASSERT(attrib.format);
+ return attrib.format->pixelBytes;
+}
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+size_t ComputeVertexAttributeStride(const VertexAttribute &attrib, const VertexBinding &binding);
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+GLintptr ComputeVertexAttributeOffset(const VertexAttribute &attrib, const VertexBinding &binding);
+
+size_t ComputeVertexBindingElementCount(GLuint divisor, size_t drawCount, size_t instanceCount);
+
+struct VertexAttribCurrentValueData
+{
+ union
+ {
+ GLfloat FloatValues[4];
+ GLint IntValues[4];
+ GLuint UnsignedIntValues[4];
+ } Values;
+ VertexAttribType Type;
+
+ VertexAttribCurrentValueData();
+
+ void setFloatValues(const GLfloat floatValues[4]);
+ void setIntValues(const GLint intValues[4]);
+ void setUnsignedIntValues(const GLuint unsignedIntValues[4]);
+};
+
+bool operator==(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b);
+bool operator!=(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b);
+
+} // namespace gl
+
+#include "VertexAttribute.inc"
+
+#endif // LIBANGLE_VERTEXATTRIBUTE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/VertexAttribute.inc b/gfx/angle/checkout/src/libANGLE/VertexAttribute.inc
new file mode 100644
index 0000000000..0c98f091b9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/VertexAttribute.inc
@@ -0,0 +1,58 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// VertexAttribute.inc: Inline vertex attribute methods
+//
+
+namespace gl
+{
+
+inline VertexAttribCurrentValueData::VertexAttribCurrentValueData()
+ : Type(gl::VertexAttribType::Float)
+{
+ Values.FloatValues[0] = 0.0f;
+ Values.FloatValues[1] = 0.0f;
+ Values.FloatValues[2] = 0.0f;
+ Values.FloatValues[3] = 1.0f;
+}
+
+inline void VertexAttribCurrentValueData::setFloatValues(const GLfloat floatValues[4])
+{
+ for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++)
+ {
+ Values.FloatValues[valueIndex] = floatValues[valueIndex];
+ }
+ Type = gl::VertexAttribType::Float;
+}
+
+inline void VertexAttribCurrentValueData::setIntValues(const GLint intValues[4])
+{
+ for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++)
+ {
+ Values.IntValues[valueIndex] = intValues[valueIndex];
+ }
+ Type = gl::VertexAttribType::Int;
+}
+
+inline void VertexAttribCurrentValueData::setUnsignedIntValues(const GLuint unsignedIntValues[4])
+{
+ for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++)
+ {
+ Values.UnsignedIntValues[valueIndex] = unsignedIntValues[valueIndex];
+ }
+ Type = gl::VertexAttribType::UnsignedInt;
+}
+
+inline bool operator==(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b)
+{
+ return (a.Type == b.Type && memcmp(&a.Values, &b.Values, sizeof(VertexAttribCurrentValueData::Values)) == 0);
+}
+
+inline bool operator!=(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b)
+{
+ return !(a == b);
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/WorkerThread.cpp b/gfx/angle/checkout/src/libANGLE/WorkerThread.cpp
new file mode 100644
index 0000000000..30c454dd26
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/WorkerThread.cpp
@@ -0,0 +1,356 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// WorkerThread:
+// Task running thread for ANGLE, similar to a TaskRunner in Chromium.
+// Might be implemented differently depending on platform.
+//
+
+#include "libANGLE/WorkerThread.h"
+
+#include "libANGLE/trace.h"
+
+#if (ANGLE_DELEGATE_WORKERS == ANGLE_ENABLED) || (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+# include <condition_variable>
+# include <future>
+# include <mutex>
+# include <queue>
+# include <thread>
+#endif // (ANGLE_DELEGATE_WORKERS == ANGLE_ENABLED) || (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+
+namespace angle
+{
+
+WaitableEvent::WaitableEvent() = default;
+WaitableEvent::~WaitableEvent() = default;
+
+void WaitableEventDone::wait() {}
+
+bool WaitableEventDone::isReady()
+{
+ return true;
+}
+
+WorkerThreadPool::WorkerThreadPool() = default;
+WorkerThreadPool::~WorkerThreadPool() = default;
+
+class SingleThreadedWaitableEvent final : public WaitableEvent
+{
+ public:
+ SingleThreadedWaitableEvent() = default;
+ ~SingleThreadedWaitableEvent() override = default;
+
+ void wait() override;
+ bool isReady() override;
+};
+
+void SingleThreadedWaitableEvent::wait() {}
+
+bool SingleThreadedWaitableEvent::isReady()
+{
+ return true;
+}
+
+class SingleThreadedWorkerPool final : public WorkerThreadPool
+{
+ public:
+ std::shared_ptr<WaitableEvent> postWorkerTask(std::shared_ptr<Closure> task) override;
+ void setMaxThreads(size_t maxThreads) override;
+ bool isAsync() override;
+};
+
+// SingleThreadedWorkerPool implementation.
+std::shared_ptr<WaitableEvent> SingleThreadedWorkerPool::postWorkerTask(
+ std::shared_ptr<Closure> task)
+{
+ (*task)();
+ return std::make_shared<SingleThreadedWaitableEvent>();
+}
+
+void SingleThreadedWorkerPool::setMaxThreads(size_t maxThreads) {}
+
+bool SingleThreadedWorkerPool::isAsync()
+{
+ return false;
+}
+
+#if (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+class AsyncWaitableEvent final : public WaitableEvent
+{
+ public:
+ AsyncWaitableEvent() : mIsPending(true) {}
+ ~AsyncWaitableEvent() override = default;
+
+ void wait() override;
+ bool isReady() override;
+
+ private:
+ friend class AsyncWorkerPool;
+ void setFuture(std::future<void> &&future);
+
+ // To block wait() when the task is still in queue to be run.
+ // Also to protect the concurrent accesses from both main thread and
+ // background threads to the member fields.
+ std::mutex mMutex;
+
+ bool mIsPending;
+ std::condition_variable mCondition;
+ std::future<void> mFuture;
+};
+
+void AsyncWaitableEvent::setFuture(std::future<void> &&future)
+{
+ mFuture = std::move(future);
+}
+
+void AsyncWaitableEvent::wait()
+{
+ ANGLE_TRACE_EVENT0("gpu.angle", "AsyncWaitableEvent::wait");
+ {
+ std::unique_lock<std::mutex> lock(mMutex);
+ mCondition.wait(lock, [this] { return !mIsPending; });
+ }
+
+ ASSERT(mFuture.valid());
+ mFuture.wait();
+}
+
+bool AsyncWaitableEvent::isReady()
+{
+ std::lock_guard<std::mutex> lock(mMutex);
+ if (mIsPending)
+ {
+ return false;
+ }
+ ASSERT(mFuture.valid());
+ return mFuture.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
+}
+
+class AsyncWorkerPool final : public WorkerThreadPool
+{
+ public:
+ AsyncWorkerPool(size_t maxThreads) : mMaxThreads(maxThreads), mRunningThreads(0) {}
+ ~AsyncWorkerPool() override = default;
+
+ std::shared_ptr<WaitableEvent> postWorkerTask(std::shared_ptr<Closure> task) override;
+ void setMaxThreads(size_t maxThreads) override;
+ bool isAsync() override;
+
+ private:
+ void checkToRunPendingTasks();
+
+ // To protect the concurrent accesses from both main thread and background
+ // threads to the member fields.
+ std::mutex mMutex;
+
+ size_t mMaxThreads;
+ size_t mRunningThreads;
+ std::queue<std::pair<std::shared_ptr<AsyncWaitableEvent>, std::shared_ptr<Closure>>> mTaskQueue;
+};
+
+// AsyncWorkerPool implementation.
+std::shared_ptr<WaitableEvent> AsyncWorkerPool::postWorkerTask(std::shared_ptr<Closure> task)
+{
+ ASSERT(mMaxThreads > 0);
+
+ auto waitable = std::make_shared<AsyncWaitableEvent>();
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mTaskQueue.push(std::make_pair(waitable, task));
+ }
+ checkToRunPendingTasks();
+ return std::move(waitable);
+}
+
+void AsyncWorkerPool::setMaxThreads(size_t maxThreads)
+{
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mMaxThreads = (maxThreads == 0xFFFFFFFF ? std::thread::hardware_concurrency() : maxThreads);
+ }
+ checkToRunPendingTasks();
+}
+
+bool AsyncWorkerPool::isAsync()
+{
+ return true;
+}
+
+void AsyncWorkerPool::checkToRunPendingTasks()
+{
+ std::lock_guard<std::mutex> lock(mMutex);
+ while (mRunningThreads < mMaxThreads && !mTaskQueue.empty())
+ {
+ auto task = mTaskQueue.front();
+ mTaskQueue.pop();
+ auto waitable = task.first;
+ auto closure = task.second;
+
+ auto future = std::async(std::launch::async, [closure, this] {
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "AsyncWorkerPool::RunTask");
+ (*closure)();
+ }
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ ASSERT(mRunningThreads != 0);
+ --mRunningThreads;
+ }
+ checkToRunPendingTasks();
+ });
+
+ ++mRunningThreads;
+
+ {
+ std::lock_guard<std::mutex> waitableLock(waitable->mMutex);
+ waitable->mIsPending = false;
+ waitable->setFuture(std::move(future));
+ }
+ waitable->mCondition.notify_all();
+ }
+}
+#endif // (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+
+#if (ANGLE_DELEGATE_WORKERS == ANGLE_ENABLED)
+class DelegateWaitableEvent final : public WaitableEvent
+{
+ public:
+ DelegateWaitableEvent() = default;
+ ~DelegateWaitableEvent() override = default;
+
+ void wait() override;
+ bool isReady() override;
+
+ void markAsReady();
+
+ private:
+ // To protect the concurrent accesses from both main thread and background
+ // threads to the member fields.
+ std::mutex mMutex;
+
+ bool mIsReady = false;
+ std::condition_variable mCondition;
+};
+
+void DelegateWaitableEvent::markAsReady()
+{
+ std::lock_guard<std::mutex> lock(mMutex);
+ mIsReady = true;
+ mCondition.notify_all();
+}
+
+void DelegateWaitableEvent::wait()
+{
+ std::unique_lock<std::mutex> lock(mMutex);
+ mCondition.wait(lock, [this] { return mIsReady; });
+}
+
+bool DelegateWaitableEvent::isReady()
+{
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mIsReady;
+}
+
+class DelegateWorkerPool final : public WorkerThreadPool
+{
+ public:
+ DelegateWorkerPool() = default;
+ ~DelegateWorkerPool() override = default;
+
+ std::shared_ptr<WaitableEvent> postWorkerTask(std::shared_ptr<Closure> task) override;
+
+ void setMaxThreads(size_t maxThreads) override;
+ bool isAsync() override;
+};
+
+// A function wrapper to execute the closure and to notify the waitable
+// event after the execution.
+class DelegateWorkerTask
+{
+ public:
+ DelegateWorkerTask(std::shared_ptr<Closure> task,
+ std::shared_ptr<DelegateWaitableEvent> waitable)
+ : mTask(task), mWaitable(waitable)
+ {}
+ DelegateWorkerTask() = delete;
+ DelegateWorkerTask(DelegateWorkerTask &) = delete;
+
+ static void RunTask(void *userData)
+ {
+ DelegateWorkerTask *workerTask = static_cast<DelegateWorkerTask *>(userData);
+ (*workerTask->mTask)();
+ workerTask->mWaitable->markAsReady();
+
+ // Delete the task after its execution.
+ delete workerTask;
+ }
+
+ private:
+ ~DelegateWorkerTask() = default;
+
+ std::shared_ptr<Closure> mTask;
+ std::shared_ptr<DelegateWaitableEvent> mWaitable;
+};
+
+std::shared_ptr<WaitableEvent> DelegateWorkerPool::postWorkerTask(std::shared_ptr<Closure> task)
+{
+ auto waitable = std::make_shared<DelegateWaitableEvent>();
+
+ // The task will be deleted by DelegateWorkerTask::RunTask(...) after its execution.
+ DelegateWorkerTask *workerTask = new DelegateWorkerTask(task, waitable);
+ auto *platform = ANGLEPlatformCurrent();
+ platform->postWorkerTask(platform, DelegateWorkerTask::RunTask, workerTask);
+
+ return std::move(waitable);
+}
+
+void DelegateWorkerPool::setMaxThreads(size_t maxThreads) {}
+
+bool DelegateWorkerPool::isAsync()
+{
+ return true;
+}
+#endif
+
+// static
+std::shared_ptr<WorkerThreadPool> WorkerThreadPool::Create(bool multithreaded)
+{
+ std::shared_ptr<WorkerThreadPool> pool(nullptr);
+
+#if (ANGLE_DELEGATE_WORKERS == ANGLE_ENABLED)
+ const bool hasPostWorkerTaskImpl = ANGLEPlatformCurrent()->postWorkerTask;
+ if (hasPostWorkerTaskImpl && multithreaded)
+ {
+ pool = std::shared_ptr<WorkerThreadPool>(new DelegateWorkerPool());
+ }
+#endif
+#if (ANGLE_STD_ASYNC_WORKERS == ANGLE_ENABLED)
+ if (!pool && multithreaded)
+ {
+ pool = std::shared_ptr<WorkerThreadPool>(
+ new AsyncWorkerPool(std::thread::hardware_concurrency()));
+ }
+#endif
+ if (!pool)
+ {
+ return std::shared_ptr<WorkerThreadPool>(new SingleThreadedWorkerPool());
+ }
+ return pool;
+}
+
+// static
+std::shared_ptr<WaitableEvent> WorkerThreadPool::PostWorkerTask(
+ std::shared_ptr<WorkerThreadPool> pool,
+ std::shared_ptr<Closure> task)
+{
+ std::shared_ptr<WaitableEvent> event = pool->postWorkerTask(task);
+ if (event.get())
+ {
+ event->setWorkerThreadPool(pool);
+ }
+ return event;
+}
+
+} // namespace angle
diff --git a/gfx/angle/checkout/src/libANGLE/WorkerThread.h b/gfx/angle/checkout/src/libANGLE/WorkerThread.h
new file mode 100644
index 0000000000..6ef94fcc5b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/WorkerThread.h
@@ -0,0 +1,94 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// WorkerThread:
+// Asychronous tasks/threads for ANGLE, similar to a TaskRunner in Chromium.
+// Can be implemented as different targets, depending on platform.
+//
+
+#ifndef LIBANGLE_WORKER_THREAD_H_
+#define LIBANGLE_WORKER_THREAD_H_
+
+#include <array>
+#include <memory>
+#include <vector>
+
+#include "common/debug.h"
+#include "libANGLE/features.h"
+
+namespace angle
+{
+
+class WorkerThreadPool;
+
+// A callback function with no return value and no arguments.
+class Closure
+{
+ public:
+ virtual ~Closure() = default;
+ virtual void operator()() = 0;
+};
+
+// An event that we can wait on, useful for joining worker threads.
+class WaitableEvent : angle::NonCopyable
+{
+ public:
+ WaitableEvent();
+ virtual ~WaitableEvent();
+
+ // Waits indefinitely for the event to be signaled.
+ virtual void wait() = 0;
+
+ // Peeks whether the event is ready. If ready, wait() will not block.
+ virtual bool isReady() = 0;
+ void setWorkerThreadPool(std::shared_ptr<WorkerThreadPool> pool) { mPool = pool; }
+
+ template <size_t Count>
+ static void WaitMany(std::array<std::shared_ptr<WaitableEvent>, Count> *waitables)
+ {
+ ASSERT(Count > 0);
+ for (size_t index = 0; index < Count; ++index)
+ {
+ (*waitables)[index]->wait();
+ }
+ }
+
+ private:
+ std::shared_ptr<WorkerThreadPool> mPool;
+};
+
+// A mock waitable event.
+class WaitableEventDone final : public WaitableEvent
+{
+ public:
+ void wait() override;
+ bool isReady() override;
+};
+
+// Request WorkerThreads from the WorkerThreadPool. Each pool can keep worker threads around so
+// we avoid the costly spin up and spin down time.
+class WorkerThreadPool : angle::NonCopyable
+{
+ public:
+ WorkerThreadPool();
+ virtual ~WorkerThreadPool();
+
+ static std::shared_ptr<WorkerThreadPool> Create(bool multithreaded);
+ static std::shared_ptr<WaitableEvent> PostWorkerTask(std::shared_ptr<WorkerThreadPool> pool,
+ std::shared_ptr<Closure> task);
+
+ virtual void setMaxThreads(size_t maxThreads) = 0;
+
+ virtual bool isAsync() = 0;
+
+ private:
+ // Returns an event to wait on for the task to finish.
+ // If the pool fails to create the task, returns null.
+ virtual std::shared_ptr<WaitableEvent> postWorkerTask(std::shared_ptr<Closure> task) = 0;
+};
+
+} // namespace angle
+
+#endif // LIBANGLE_WORKER_THREAD_H_
diff --git a/gfx/angle/checkout/src/libANGLE/angletypes.cpp b/gfx/angle/checkout/src/libANGLE/angletypes.cpp
new file mode 100644
index 0000000000..19f9a25441
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/angletypes.cpp
@@ -0,0 +1,1039 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/VertexAttribute.h"
+
+#include <limits>
+
+namespace gl
+{
+namespace
+{
+bool IsStencilNoOp(GLenum stencilFunc,
+ GLenum stencilFail,
+ GLenum stencilPassDepthFail,
+ GLenum stencilPassDepthPass)
+{
+ const bool isNeverAndKeep = stencilFunc == GL_NEVER && stencilFail == GL_KEEP;
+ const bool isAlwaysAndKeepOrAllKeep = (stencilFunc == GL_ALWAYS || stencilFail == GL_KEEP) &&
+ stencilPassDepthFail == GL_KEEP &&
+ stencilPassDepthPass == GL_KEEP;
+
+ return isNeverAndKeep || isAlwaysAndKeepOrAllKeep;
+}
+
+// Calculate whether the range [outsideLow, outsideHigh] encloses the range [insideLow, insideHigh]
+bool EnclosesRange(int outsideLow, int outsideHigh, int insideLow, int insideHigh)
+{
+ return outsideLow <= insideLow && outsideHigh >= insideHigh;
+}
+
+bool IsAdvancedBlendEquation(gl::BlendEquationType blendEquation)
+{
+ return blendEquation >= gl::BlendEquationType::Multiply &&
+ blendEquation <= gl::BlendEquationType::HslLuminosity;
+}
+} // anonymous namespace
+
+RasterizerState::RasterizerState()
+{
+ memset(this, 0, sizeof(RasterizerState));
+
+ rasterizerDiscard = false;
+ cullFace = false;
+ cullMode = CullFaceMode::Back;
+ frontFace = GL_CCW;
+ polygonOffsetFill = false;
+ polygonOffsetFactor = 0.0f;
+ polygonOffsetUnits = 0.0f;
+ pointDrawMode = false;
+ multiSample = false;
+ dither = true;
+}
+
+RasterizerState::RasterizerState(const RasterizerState &other)
+{
+ memcpy(this, &other, sizeof(RasterizerState));
+}
+
+RasterizerState &RasterizerState::operator=(const RasterizerState &other)
+{
+ memcpy(this, &other, sizeof(RasterizerState));
+ return *this;
+}
+
+bool operator==(const RasterizerState &a, const RasterizerState &b)
+{
+ return memcmp(&a, &b, sizeof(RasterizerState)) == 0;
+}
+
+bool operator!=(const RasterizerState &a, const RasterizerState &b)
+{
+ return !(a == b);
+}
+
+BlendState::BlendState()
+{
+ memset(this, 0, sizeof(BlendState));
+
+ blend = false;
+ sourceBlendRGB = GL_ONE;
+ sourceBlendAlpha = GL_ONE;
+ destBlendRGB = GL_ZERO;
+ destBlendAlpha = GL_ZERO;
+ blendEquationRGB = GL_FUNC_ADD;
+ blendEquationAlpha = GL_FUNC_ADD;
+ colorMaskRed = true;
+ colorMaskGreen = true;
+ colorMaskBlue = true;
+ colorMaskAlpha = true;
+}
+
+BlendState::BlendState(const BlendState &other)
+{
+ memcpy(this, &other, sizeof(BlendState));
+}
+
+bool operator==(const BlendState &a, const BlendState &b)
+{
+ return memcmp(&a, &b, sizeof(BlendState)) == 0;
+}
+
+bool operator!=(const BlendState &a, const BlendState &b)
+{
+ return !(a == b);
+}
+
+DepthStencilState::DepthStencilState()
+{
+ memset(this, 0, sizeof(DepthStencilState));
+
+ depthTest = false;
+ depthFunc = GL_LESS;
+ depthMask = true;
+ stencilTest = false;
+ stencilFunc = GL_ALWAYS;
+ stencilMask = static_cast<GLuint>(-1);
+ stencilWritemask = static_cast<GLuint>(-1);
+ stencilBackFunc = GL_ALWAYS;
+ stencilBackMask = static_cast<GLuint>(-1);
+ stencilBackWritemask = static_cast<GLuint>(-1);
+ stencilFail = GL_KEEP;
+ stencilPassDepthFail = GL_KEEP;
+ stencilPassDepthPass = GL_KEEP;
+ stencilBackFail = GL_KEEP;
+ stencilBackPassDepthFail = GL_KEEP;
+ stencilBackPassDepthPass = GL_KEEP;
+}
+
+DepthStencilState::DepthStencilState(const DepthStencilState &other)
+{
+ memcpy(this, &other, sizeof(DepthStencilState));
+}
+
+DepthStencilState &DepthStencilState::operator=(const DepthStencilState &other)
+{
+ memcpy(this, &other, sizeof(DepthStencilState));
+ return *this;
+}
+
+bool DepthStencilState::isDepthMaskedOut() const
+{
+ return !depthMask;
+}
+
+bool DepthStencilState::isStencilMaskedOut() const
+{
+ return (stencilMask & stencilWritemask) == 0;
+}
+
+bool DepthStencilState::isStencilNoOp() const
+{
+ return isStencilMaskedOut() ||
+ IsStencilNoOp(stencilFunc, stencilFail, stencilPassDepthFail, stencilPassDepthPass);
+}
+
+bool DepthStencilState::isStencilBackNoOp() const
+{
+ const bool isStencilBackMaskedOut = (stencilBackMask & stencilBackWritemask) == 0;
+ return isStencilBackMaskedOut ||
+ IsStencilNoOp(stencilBackFunc, stencilBackFail, stencilBackPassDepthFail,
+ stencilBackPassDepthPass);
+}
+
+bool operator==(const DepthStencilState &a, const DepthStencilState &b)
+{
+ return memcmp(&a, &b, sizeof(DepthStencilState)) == 0;
+}
+
+bool operator!=(const DepthStencilState &a, const DepthStencilState &b)
+{
+ return !(a == b);
+}
+
+SamplerState::SamplerState()
+{
+ memset(this, 0, sizeof(SamplerState));
+
+ setMinFilter(GL_NEAREST_MIPMAP_LINEAR);
+ setMagFilter(GL_LINEAR);
+ setWrapS(GL_REPEAT);
+ setWrapT(GL_REPEAT);
+ setWrapR(GL_REPEAT);
+ setMaxAnisotropy(1.0f);
+ setMinLod(-1000.0f);
+ setMaxLod(1000.0f);
+ setCompareMode(GL_NONE);
+ setCompareFunc(GL_LEQUAL);
+ setSRGBDecode(GL_DECODE_EXT);
+}
+
+SamplerState::SamplerState(const SamplerState &other) = default;
+
+SamplerState &SamplerState::operator=(const SamplerState &other) = default;
+
+// static
+SamplerState SamplerState::CreateDefaultForTarget(TextureType type)
+{
+ SamplerState state;
+
+ // According to OES_EGL_image_external and ARB_texture_rectangle: For external textures, the
+ // default min filter is GL_LINEAR and the default s and t wrap modes are GL_CLAMP_TO_EDGE.
+ if (type == TextureType::External || type == TextureType::Rectangle)
+ {
+ state.mMinFilter = GL_LINEAR;
+ state.mWrapS = GL_CLAMP_TO_EDGE;
+ state.mWrapT = GL_CLAMP_TO_EDGE;
+ }
+
+ return state;
+}
+
+bool SamplerState::setMinFilter(GLenum minFilter)
+{
+ if (mMinFilter != minFilter)
+ {
+ mMinFilter = minFilter;
+ mCompleteness.typed.minFilter = static_cast<uint8_t>(FromGLenum<FilterMode>(minFilter));
+ return true;
+ }
+ return false;
+}
+
+bool SamplerState::setMagFilter(GLenum magFilter)
+{
+ if (mMagFilter != magFilter)
+ {
+ mMagFilter = magFilter;
+ mCompleteness.typed.magFilter = static_cast<uint8_t>(FromGLenum<FilterMode>(magFilter));
+ return true;
+ }
+ return false;
+}
+
+bool SamplerState::setWrapS(GLenum wrapS)
+{
+ if (mWrapS != wrapS)
+ {
+ mWrapS = wrapS;
+ mCompleteness.typed.wrapS = static_cast<uint8_t>(FromGLenum<WrapMode>(wrapS));
+ return true;
+ }
+ return false;
+}
+
+bool SamplerState::setWrapT(GLenum wrapT)
+{
+ if (mWrapT != wrapT)
+ {
+ mWrapT = wrapT;
+ updateWrapTCompareMode();
+ return true;
+ }
+ return false;
+}
+
+bool SamplerState::setWrapR(GLenum wrapR)
+{
+ if (mWrapR != wrapR)
+ {
+ mWrapR = wrapR;
+ return true;
+ }
+ return false;
+}
+
+bool SamplerState::setMaxAnisotropy(float maxAnisotropy)
+{
+ if (mMaxAnisotropy != maxAnisotropy)
+ {
+ mMaxAnisotropy = maxAnisotropy;
+ return true;
+ }
+ return false;
+}
+
+bool SamplerState::setMinLod(GLfloat minLod)
+{
+ if (mMinLod != minLod)
+ {
+ mMinLod = minLod;
+ return true;
+ }
+ return false;
+}
+
+bool SamplerState::setMaxLod(GLfloat maxLod)
+{
+ if (mMaxLod != maxLod)
+ {
+ mMaxLod = maxLod;
+ return true;
+ }
+ return false;
+}
+
+bool SamplerState::setCompareMode(GLenum compareMode)
+{
+ if (mCompareMode != compareMode)
+ {
+ mCompareMode = compareMode;
+ updateWrapTCompareMode();
+ return true;
+ }
+ return false;
+}
+
+bool SamplerState::setCompareFunc(GLenum compareFunc)
+{
+ if (mCompareFunc != compareFunc)
+ {
+ mCompareFunc = compareFunc;
+ return true;
+ }
+ return false;
+}
+
+bool SamplerState::setSRGBDecode(GLenum sRGBDecode)
+{
+ if (mSRGBDecode != sRGBDecode)
+ {
+ mSRGBDecode = sRGBDecode;
+ return true;
+ }
+ return false;
+}
+
+bool SamplerState::setBorderColor(const ColorGeneric &color)
+{
+ if (mBorderColor != color)
+ {
+ mBorderColor = color;
+ return true;
+ }
+ return false;
+}
+
+void SamplerState::updateWrapTCompareMode()
+{
+ uint8_t wrap = static_cast<uint8_t>(FromGLenum<WrapMode>(mWrapT));
+ uint8_t compare = static_cast<uint8_t>(mCompareMode == GL_NONE ? 0x10 : 0x00);
+ mCompleteness.typed.wrapTCompareMode = wrap | compare;
+}
+
+ImageUnit::ImageUnit()
+ : texture(), level(0), layered(false), layer(0), access(GL_READ_ONLY), format(GL_R32UI)
+{}
+
+ImageUnit::ImageUnit(const ImageUnit &other) = default;
+
+ImageUnit::~ImageUnit() = default;
+
+BlendStateExt::BlendStateExt(const size_t drawBufferCount)
+ : mParameterMask(FactorStorage::GetMask(drawBufferCount)),
+ mSrcColor(FactorStorage::GetReplicatedValue(BlendFactorType::One, mParameterMask)),
+ mDstColor(FactorStorage::GetReplicatedValue(BlendFactorType::Zero, mParameterMask)),
+ mSrcAlpha(FactorStorage::GetReplicatedValue(BlendFactorType::One, mParameterMask)),
+ mDstAlpha(FactorStorage::GetReplicatedValue(BlendFactorType::Zero, mParameterMask)),
+ mEquationColor(EquationStorage::GetReplicatedValue(BlendEquationType::Add, mParameterMask)),
+ mEquationAlpha(EquationStorage::GetReplicatedValue(BlendEquationType::Add, mParameterMask)),
+ mAllColorMask(
+ ColorMaskStorage::GetReplicatedValue(PackColorMask(true, true, true, true),
+ ColorMaskStorage::GetMask(drawBufferCount))),
+ mColorMask(mAllColorMask),
+ mAllEnabledMask(0xFF >> (8 - drawBufferCount)),
+ mDrawBufferCount(drawBufferCount)
+{}
+
+BlendStateExt::BlendStateExt(const BlendStateExt &other) = default;
+
+BlendStateExt &BlendStateExt::operator=(const BlendStateExt &other) = default;
+
+void BlendStateExt::setEnabled(const bool enabled)
+{
+ mEnabledMask = enabled ? mAllEnabledMask : DrawBufferMask::Zero();
+}
+
+void BlendStateExt::setEnabledIndexed(const size_t index, const bool enabled)
+{
+ ASSERT(index < mDrawBufferCount);
+ mEnabledMask.set(index, enabled);
+}
+
+BlendStateExt::ColorMaskStorage::Type BlendStateExt::expandColorMaskValue(const bool red,
+ const bool green,
+ const bool blue,
+ const bool alpha) const
+{
+ return BlendStateExt::ColorMaskStorage::GetReplicatedValue(
+ PackColorMask(red, green, blue, alpha), mAllColorMask);
+}
+
+BlendStateExt::ColorMaskStorage::Type BlendStateExt::expandColorMaskIndexed(
+ const size_t index) const
+{
+ return ColorMaskStorage::GetReplicatedValue(
+ ColorMaskStorage::GetValueIndexed(index, mColorMask), mAllColorMask);
+}
+
+void BlendStateExt::setColorMask(const bool red,
+ const bool green,
+ const bool blue,
+ const bool alpha)
+{
+ mColorMask = expandColorMaskValue(red, green, blue, alpha);
+}
+
+void BlendStateExt::setColorMaskIndexed(const size_t index, const uint8_t value)
+{
+ ASSERT(index < mDrawBufferCount);
+ ASSERT(value <= 0xF);
+ ColorMaskStorage::SetValueIndexed(index, value, &mColorMask);
+}
+
+void BlendStateExt::setColorMaskIndexed(const size_t index,
+ const bool red,
+ const bool green,
+ const bool blue,
+ const bool alpha)
+{
+ ASSERT(index < mDrawBufferCount);
+ ColorMaskStorage::SetValueIndexed(index, PackColorMask(red, green, blue, alpha), &mColorMask);
+}
+
+uint8_t BlendStateExt::getColorMaskIndexed(const size_t index) const
+{
+ ASSERT(index < mDrawBufferCount);
+ return ColorMaskStorage::GetValueIndexed(index, mColorMask);
+}
+
+void BlendStateExt::getColorMaskIndexed(const size_t index,
+ bool *red,
+ bool *green,
+ bool *blue,
+ bool *alpha) const
+{
+ ASSERT(index < mDrawBufferCount);
+ UnpackColorMask(ColorMaskStorage::GetValueIndexed(index, mColorMask), red, green, blue, alpha);
+}
+
+DrawBufferMask BlendStateExt::compareColorMask(ColorMaskStorage::Type other) const
+{
+ return ColorMaskStorage::GetDiffMask(mColorMask, other);
+}
+
+BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationValue(const GLenum mode) const
+{
+ return EquationStorage::GetReplicatedValue(FromGLenum<BlendEquationType>(mode), mParameterMask);
+}
+
+BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationValue(
+ const gl::BlendEquationType equation) const
+{
+ return EquationStorage::GetReplicatedValue(equation, mParameterMask);
+}
+
+BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationColorIndexed(
+ const size_t index) const
+{
+ return EquationStorage::GetReplicatedValue(
+ EquationStorage::GetValueIndexed(index, mEquationColor), mParameterMask);
+}
+
+BlendStateExt::EquationStorage::Type BlendStateExt::expandEquationAlphaIndexed(
+ const size_t index) const
+{
+ return EquationStorage::GetReplicatedValue(
+ EquationStorage::GetValueIndexed(index, mEquationAlpha), mParameterMask);
+}
+
+void BlendStateExt::setEquations(const GLenum modeColor, const GLenum modeAlpha)
+{
+ const gl::BlendEquationType colorEquation = FromGLenum<BlendEquationType>(modeColor);
+ const gl::BlendEquationType alphaEquation = FromGLenum<BlendEquationType>(modeAlpha);
+
+ mEquationColor = expandEquationValue(colorEquation);
+ mEquationAlpha = expandEquationValue(alphaEquation);
+
+ // Note that advanced blend equations cannot be independently set for color and alpha, so only
+ // the color equation can be checked.
+ if (IsAdvancedBlendEquation(colorEquation))
+ {
+ mUsesAdvancedBlendEquationMask = mAllEnabledMask;
+ }
+ else
+ {
+ mUsesAdvancedBlendEquationMask.reset();
+ }
+}
+
+void BlendStateExt::setEquationsIndexed(const size_t index,
+ const GLenum modeColor,
+ const GLenum modeAlpha)
+{
+ ASSERT(index < mDrawBufferCount);
+
+ const gl::BlendEquationType colorEquation = FromGLenum<BlendEquationType>(modeColor);
+ const gl::BlendEquationType alphaEquation = FromGLenum<BlendEquationType>(modeAlpha);
+
+ EquationStorage::SetValueIndexed(index, colorEquation, &mEquationColor);
+ EquationStorage::SetValueIndexed(index, alphaEquation, &mEquationAlpha);
+
+ mUsesAdvancedBlendEquationMask.set(index, IsAdvancedBlendEquation(colorEquation));
+}
+
+void BlendStateExt::setEquationsIndexed(const size_t index,
+ const size_t sourceIndex,
+ const BlendStateExt &source)
+{
+ ASSERT(index < mDrawBufferCount);
+ ASSERT(sourceIndex < source.mDrawBufferCount);
+
+ const gl::BlendEquationType colorEquation =
+ EquationStorage::GetValueIndexed(sourceIndex, source.mEquationColor);
+ const gl::BlendEquationType alphaEquation =
+ EquationStorage::GetValueIndexed(sourceIndex, source.mEquationAlpha);
+
+ EquationStorage::SetValueIndexed(index, colorEquation, &mEquationColor);
+ EquationStorage::SetValueIndexed(index, alphaEquation, &mEquationAlpha);
+
+ mUsesAdvancedBlendEquationMask.set(index, IsAdvancedBlendEquation(colorEquation));
+}
+
+GLenum BlendStateExt::getEquationColorIndexed(size_t index) const
+{
+ ASSERT(index < mDrawBufferCount);
+ return ToGLenum(EquationStorage::GetValueIndexed(index, mEquationColor));
+}
+
+GLenum BlendStateExt::getEquationAlphaIndexed(size_t index) const
+{
+ ASSERT(index < mDrawBufferCount);
+ return ToGLenum(EquationStorage::GetValueIndexed(index, mEquationAlpha));
+}
+
+DrawBufferMask BlendStateExt::compareEquations(const EquationStorage::Type color,
+ const EquationStorage::Type alpha) const
+{
+ return EquationStorage::GetDiffMask(mEquationColor, color) |
+ EquationStorage::GetDiffMask(mEquationAlpha, alpha);
+}
+
+BlendStateExt::FactorStorage::Type BlendStateExt::expandFactorValue(const GLenum func) const
+{
+ return FactorStorage::GetReplicatedValue(FromGLenum<BlendFactorType>(func), mParameterMask);
+}
+
+BlendStateExt::FactorStorage::Type BlendStateExt::expandSrcColorIndexed(const size_t index) const
+{
+ ASSERT(index < mDrawBufferCount);
+ return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mSrcColor),
+ mParameterMask);
+}
+
+BlendStateExt::FactorStorage::Type BlendStateExt::expandDstColorIndexed(const size_t index) const
+{
+ ASSERT(index < mDrawBufferCount);
+ return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mDstColor),
+ mParameterMask);
+}
+
+BlendStateExt::FactorStorage::Type BlendStateExt::expandSrcAlphaIndexed(const size_t index) const
+{
+ ASSERT(index < mDrawBufferCount);
+ return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mSrcAlpha),
+ mParameterMask);
+}
+
+BlendStateExt::FactorStorage::Type BlendStateExt::expandDstAlphaIndexed(const size_t index) const
+{
+ ASSERT(index < mDrawBufferCount);
+ return FactorStorage::GetReplicatedValue(FactorStorage::GetValueIndexed(index, mDstAlpha),
+ mParameterMask);
+}
+
+void BlendStateExt::setFactors(const GLenum srcColor,
+ const GLenum dstColor,
+ const GLenum srcAlpha,
+ const GLenum dstAlpha)
+{
+ mSrcColor = expandFactorValue(srcColor);
+ mDstColor = expandFactorValue(dstColor);
+ mSrcAlpha = expandFactorValue(srcAlpha);
+ mDstAlpha = expandFactorValue(dstAlpha);
+}
+
+void BlendStateExt::setFactorsIndexed(const size_t index,
+ const GLenum srcColor,
+ const GLenum dstColor,
+ const GLenum srcAlpha,
+ const GLenum dstAlpha)
+{
+ ASSERT(index < mDrawBufferCount);
+ FactorStorage::SetValueIndexed(index, FromGLenum<BlendFactorType>(srcColor), &mSrcColor);
+ FactorStorage::SetValueIndexed(index, FromGLenum<BlendFactorType>(dstColor), &mDstColor);
+ FactorStorage::SetValueIndexed(index, FromGLenum<BlendFactorType>(srcAlpha), &mSrcAlpha);
+ FactorStorage::SetValueIndexed(index, FromGLenum<BlendFactorType>(dstAlpha), &mDstAlpha);
+}
+
+void BlendStateExt::setFactorsIndexed(const size_t index,
+ const size_t sourceIndex,
+ const BlendStateExt &source)
+{
+ ASSERT(index < mDrawBufferCount);
+ ASSERT(sourceIndex < source.mDrawBufferCount);
+ FactorStorage::SetValueIndexed(
+ index, FactorStorage::GetValueIndexed(sourceIndex, source.mSrcColor), &mSrcColor);
+ FactorStorage::SetValueIndexed(
+ index, FactorStorage::GetValueIndexed(sourceIndex, source.mDstColor), &mDstColor);
+ FactorStorage::SetValueIndexed(
+ index, FactorStorage::GetValueIndexed(sourceIndex, source.mSrcAlpha), &mSrcAlpha);
+ FactorStorage::SetValueIndexed(
+ index, FactorStorage::GetValueIndexed(sourceIndex, source.mDstAlpha), &mDstAlpha);
+}
+
+GLenum BlendStateExt::getSrcColorIndexed(size_t index) const
+{
+ ASSERT(index < mDrawBufferCount);
+ return ToGLenum(FactorStorage::GetValueIndexed(index, mSrcColor));
+}
+
+GLenum BlendStateExt::getDstColorIndexed(size_t index) const
+{
+ ASSERT(index < mDrawBufferCount);
+ return ToGLenum(FactorStorage::GetValueIndexed(index, mDstColor));
+}
+
+GLenum BlendStateExt::getSrcAlphaIndexed(size_t index) const
+{
+ ASSERT(index < mDrawBufferCount);
+ return ToGLenum(FactorStorage::GetValueIndexed(index, mSrcAlpha));
+}
+
+GLenum BlendStateExt::getDstAlphaIndexed(size_t index) const
+{
+ ASSERT(index < mDrawBufferCount);
+ return ToGLenum(FactorStorage::GetValueIndexed(index, mDstAlpha));
+}
+
+DrawBufferMask BlendStateExt::compareFactors(const FactorStorage::Type srcColor,
+ const FactorStorage::Type dstColor,
+ const FactorStorage::Type srcAlpha,
+ const FactorStorage::Type dstAlpha) const
+{
+ return FactorStorage::GetDiffMask(mSrcColor, srcColor) |
+ FactorStorage::GetDiffMask(mDstColor, dstColor) |
+ FactorStorage::GetDiffMask(mSrcAlpha, srcAlpha) |
+ FactorStorage::GetDiffMask(mDstAlpha, dstAlpha);
+}
+
+static void MinMax(int a, int b, int *minimum, int *maximum)
+{
+ if (a < b)
+ {
+ *minimum = a;
+ *maximum = b;
+ }
+ else
+ {
+ *minimum = b;
+ *maximum = a;
+ }
+}
+
+template <>
+bool RectangleImpl<int>::empty() const
+{
+ return width == 0 && height == 0;
+}
+
+template <>
+bool RectangleImpl<float>::empty() const
+{
+ return std::abs(width) < std::numeric_limits<float>::epsilon() &&
+ std::abs(height) < std::numeric_limits<float>::epsilon();
+}
+
+bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection)
+{
+ angle::CheckedNumeric<int> sourceX2(source.x);
+ sourceX2 += source.width;
+ if (!sourceX2.IsValid())
+ {
+ return false;
+ }
+ angle::CheckedNumeric<int> sourceY2(source.y);
+ sourceY2 += source.height;
+ if (!sourceY2.IsValid())
+ {
+ return false;
+ }
+
+ int minSourceX, maxSourceX, minSourceY, maxSourceY;
+ MinMax(source.x, sourceX2.ValueOrDie(), &minSourceX, &maxSourceX);
+ MinMax(source.y, sourceY2.ValueOrDie(), &minSourceY, &maxSourceY);
+
+ angle::CheckedNumeric<int> clipX2(clip.x);
+ clipX2 += clip.width;
+ if (!clipX2.IsValid())
+ {
+ return false;
+ }
+ angle::CheckedNumeric<int> clipY2(clip.y);
+ clipY2 += clip.height;
+ if (!clipY2.IsValid())
+ {
+ return false;
+ }
+
+ int minClipX, maxClipX, minClipY, maxClipY;
+ MinMax(clip.x, clipX2.ValueOrDie(), &minClipX, &maxClipX);
+ MinMax(clip.y, clipY2.ValueOrDie(), &minClipY, &maxClipY);
+
+ if (minSourceX >= maxClipX || maxSourceX <= minClipX || minSourceY >= maxClipY ||
+ maxSourceY <= minClipY)
+ {
+ return false;
+ }
+
+ int x = std::max(minSourceX, minClipX);
+ int y = std::max(minSourceY, minClipY);
+ int width = std::min(maxSourceX, maxClipX) - x;
+ int height = std::min(maxSourceY, maxClipY) - y;
+
+ if (intersection)
+ {
+ intersection->x = x;
+ intersection->y = y;
+ intersection->width = width;
+ intersection->height = height;
+ }
+ return width != 0 && height != 0;
+}
+
+void GetEnclosingRectangle(const Rectangle &rect1, const Rectangle &rect2, Rectangle *rectUnion)
+{
+ // All callers use non-flipped framebuffer-size-clipped rectangles, so both flip and overflow
+ // are impossible.
+ ASSERT(!rect1.isReversedX() && !rect1.isReversedY());
+ ASSERT(!rect2.isReversedX() && !rect2.isReversedY());
+ ASSERT((angle::CheckedNumeric<int>(rect1.x) + rect1.width).IsValid());
+ ASSERT((angle::CheckedNumeric<int>(rect1.y) + rect1.height).IsValid());
+ ASSERT((angle::CheckedNumeric<int>(rect2.x) + rect2.width).IsValid());
+ ASSERT((angle::CheckedNumeric<int>(rect2.y) + rect2.height).IsValid());
+
+ // This function calculates a rectangle that covers both input rectangles:
+ //
+ // +---------+
+ // rect1 --> | |
+ // | +---+-----+
+ // | | | | <-- rect2
+ // +-----+---+ |
+ // | |
+ // +---------+
+ //
+ // xy0 = min(rect1.xy0, rect2.xy0)
+ // \
+ // +---------+-----+
+ // union --> | . |
+ // | + . + . . +
+ // | . . |
+ // + . . + . + |
+ // | . |
+ // +-----+---------+
+ // /
+ // xy1 = max(rect1.xy1, rect2.xy1)
+
+ int x0 = std::min(rect1.x0(), rect2.x0());
+ int y0 = std::min(rect1.y0(), rect2.y0());
+
+ int x1 = std::max(rect1.x1(), rect2.x1());
+ int y1 = std::max(rect1.y1(), rect2.y1());
+
+ rectUnion->x = x0;
+ rectUnion->y = y0;
+ rectUnion->width = x1 - x0;
+ rectUnion->height = y1 - y0;
+}
+
+void ExtendRectangle(const Rectangle &source, const Rectangle &extend, Rectangle *extended)
+{
+ // All callers use non-flipped framebuffer-size-clipped rectangles, so both flip and overflow
+ // are impossible.
+ ASSERT(!source.isReversedX() && !source.isReversedY());
+ ASSERT(!extend.isReversedX() && !extend.isReversedY());
+ ASSERT((angle::CheckedNumeric<int>(source.x) + source.width).IsValid());
+ ASSERT((angle::CheckedNumeric<int>(source.y) + source.height).IsValid());
+ ASSERT((angle::CheckedNumeric<int>(extend.x) + extend.width).IsValid());
+ ASSERT((angle::CheckedNumeric<int>(extend.y) + extend.height).IsValid());
+
+ int x0 = source.x0();
+ int x1 = source.x1();
+ int y0 = source.y0();
+ int y1 = source.y1();
+
+ const int extendX0 = extend.x0();
+ const int extendX1 = extend.x1();
+ const int extendY0 = extend.y0();
+ const int extendY1 = extend.y1();
+
+ // For each side of the rectangle, calculate whether it can be extended by the second rectangle.
+ // If so, extend it and continue for the next side with the new dimensions.
+
+ // Left: Reduce x0 if the second rectangle's vertical edge covers the source's:
+ //
+ // +--- - - - +--- - - -
+ // | |
+ // | +--------------+ +-----------------+
+ // | | source | --> | source |
+ // | +--------------+ +-----------------+
+ // | |
+ // +--- - - - +--- - - -
+ //
+ const bool enclosesHeight = EnclosesRange(extendY0, extendY1, y0, y1);
+ if (extendX0 < x0 && extendX1 >= x0 && enclosesHeight)
+ {
+ x0 = extendX0;
+ }
+
+ // Right: Increase x1 simiarly.
+ if (extendX0 <= x1 && extendX1 > x1 && enclosesHeight)
+ {
+ x1 = extendX1;
+ }
+
+ // Top: Reduce y0 if the second rectangle's horizontal edge covers the source's potentially
+ // extended edge.
+ const bool enclosesWidth = EnclosesRange(extendX0, extendX1, x0, x1);
+ if (extendY0 < y0 && extendY1 >= y0 && enclosesWidth)
+ {
+ y0 = extendY0;
+ }
+
+ // Right: Increase y1 simiarly.
+ if (extendY0 <= y1 && extendY1 > y1 && enclosesWidth)
+ {
+ y1 = extendY1;
+ }
+
+ extended->x = x0;
+ extended->y = y0;
+ extended->width = x1 - x0;
+ extended->height = y1 - y0;
+}
+
+bool Box::valid() const
+{
+ return width != 0 && height != 0 && depth != 0;
+}
+
+bool Box::operator==(const Box &other) const
+{
+ return (x == other.x && y == other.y && z == other.z && width == other.width &&
+ height == other.height && depth == other.depth);
+}
+
+bool Box::operator!=(const Box &other) const
+{
+ return !(*this == other);
+}
+
+Rectangle Box::toRect() const
+{
+ ASSERT(z == 0 && depth == 1);
+ return Rectangle(x, y, width, height);
+}
+
+bool Box::coversSameExtent(const Extents &size) const
+{
+ return x == 0 && y == 0 && z == 0 && width == size.width && height == size.height &&
+ depth == size.depth;
+}
+
+bool Box::contains(const Box &other) const
+{
+ return x <= other.x && y <= other.y && z <= other.z && x + width >= other.x + other.width &&
+ y + height >= other.y + other.height && z + depth >= other.z + other.depth;
+}
+
+size_t Box::volume() const
+{
+ return width * height * depth;
+}
+
+void Box::extend(const Box &other)
+{
+ // This extends the logic of "ExtendRectangle" to 3 dimensions
+
+ int x0 = x;
+ int x1 = x + width;
+ int y0 = y;
+ int y1 = y + height;
+ int z0 = z;
+ int z1 = z + depth;
+
+ const int otherx0 = other.x;
+ const int otherx1 = other.x + other.width;
+ const int othery0 = other.y;
+ const int othery1 = other.y + other.height;
+ const int otherz0 = other.z;
+ const int otherz1 = other.z + other.depth;
+
+ // For each side of the box, calculate whether it can be extended by the other box.
+ // If so, extend it and continue to the next side with the new dimensions.
+
+ const bool enclosesWidth = EnclosesRange(otherx0, otherx1, x0, x1);
+ const bool enclosesHeight = EnclosesRange(othery0, othery1, y0, y1);
+ const bool enclosesDepth = EnclosesRange(otherz0, otherz1, z0, z1);
+
+ // Left: Reduce x0 if the other box's Y and Z plane encloses the source
+ if (otherx0 < x0 && otherx1 >= x0 && enclosesHeight && enclosesDepth)
+ {
+ x0 = otherx0;
+ }
+
+ // Right: Increase x1 simiarly.
+ if (otherx0 <= x1 && otherx1 > x1 && enclosesHeight && enclosesDepth)
+ {
+ x1 = otherx1;
+ }
+
+ // Bottom: Reduce y0 if the other box's X and Z plane encloses the source
+ if (othery0 < y0 && othery1 >= y0 && enclosesWidth && enclosesDepth)
+ {
+ y0 = othery0;
+ }
+
+ // Top: Increase y1 simiarly.
+ if (othery0 <= y1 && othery1 > y1 && enclosesWidth && enclosesDepth)
+ {
+ y1 = othery1;
+ }
+
+ // Front: Reduce z0 if the other box's X and Y plane encloses the source
+ if (otherz0 < z0 && otherz1 >= z0 && enclosesWidth && enclosesHeight)
+ {
+ z0 = otherz0;
+ }
+
+ // Back: Increase z1 simiarly.
+ if (otherz0 <= z1 && otherz1 > z1 && enclosesWidth && enclosesHeight)
+ {
+ z1 = otherz1;
+ }
+
+ // Update member var with new dimensions
+ x = x0;
+ width = x1 - x0;
+ y = y0;
+ height = y1 - y0;
+ z = z0;
+ depth = z1 - z0;
+}
+
+bool operator==(const Offset &a, const Offset &b)
+{
+ return a.x == b.x && a.y == b.y && a.z == b.z;
+}
+
+bool operator!=(const Offset &a, const Offset &b)
+{
+ return !(a == b);
+}
+
+bool operator==(const Extents &lhs, const Extents &rhs)
+{
+ return lhs.width == rhs.width && lhs.height == rhs.height && lhs.depth == rhs.depth;
+}
+
+bool operator!=(const Extents &lhs, const Extents &rhs)
+{
+ return !(lhs == rhs);
+}
+
+bool ValidateComponentTypeMasks(unsigned long outputTypes,
+ unsigned long inputTypes,
+ unsigned long outputMask,
+ unsigned long inputMask)
+{
+ static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS <= kMaxComponentTypeMaskIndex,
+ "Output/input masks should fit into 16 bits - 1 bit per draw buffer. The "
+ "corresponding type masks should fit into 32 bits - 2 bits per draw buffer.");
+ static_assert(MAX_VERTEX_ATTRIBS <= kMaxComponentTypeMaskIndex,
+ "Output/input masks should fit into 16 bits - 1 bit per attrib. The "
+ "corresponding type masks should fit into 32 bits - 2 bits per attrib.");
+
+ // For performance reasons, draw buffer and attribute type validation is done using bit masks.
+ // We store two bits representing the type split, with the low bit in the lower 16 bits of the
+ // variable, and the high bit in the upper 16 bits of the variable. This is done so we can AND
+ // with the elswewhere used DrawBufferMask or AttributeMask.
+
+ // OR the masks with themselves, shifted 16 bits. This is to match our split type bits.
+ outputMask |= (outputMask << kMaxComponentTypeMaskIndex);
+ inputMask |= (inputMask << kMaxComponentTypeMaskIndex);
+
+ // To validate:
+ // 1. Remove any indexes that are not enabled in the input (& inputMask)
+ // 2. Remove any indexes that exist in output, but not in input (& outputMask)
+ // 3. Use == to verify equality
+ return (outputTypes & inputMask) == ((inputTypes & outputMask) & inputMask);
+}
+
+GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> &binding)
+{
+ Buffer *buffer = binding.get();
+ if (buffer == nullptr)
+ {
+ return 0;
+ }
+
+ const GLsizeiptr bufferSize = static_cast<GLsizeiptr>(buffer->getSize());
+
+ if (binding.getSize() == 0)
+ {
+ return bufferSize;
+ }
+
+ const GLintptr offset = binding.getOffset();
+ const GLsizeiptr size = binding.getSize();
+
+ ASSERT(offset >= 0 && bufferSize >= 0);
+
+ if (bufferSize <= offset)
+ {
+ return 0;
+ }
+
+ return std::min(size, bufferSize - offset);
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/angletypes.h b/gfx/angle/checkout/src/libANGLE/angletypes.h
new file mode 100644
index 0000000000..6ac65a5cf3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/angletypes.h
@@ -0,0 +1,1203 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2
+
+#ifndef LIBANGLE_ANGLETYPES_H_
+#define LIBANGLE_ANGLETYPES_H_
+
+#include "common/Color.h"
+#include "common/FixedVector.h"
+#include "common/PackedEnums.h"
+#include "common/bitset_utils.h"
+#include "common/vector_utils.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+#include <inttypes.h>
+#include <stdint.h>
+
+#include <bitset>
+#include <map>
+#include <memory>
+#include <unordered_map>
+
+namespace gl
+{
+class Buffer;
+class Texture;
+
+enum class Command
+{
+ // The Blit command carries the bitmask of which buffers are being blit. The command passed to
+ // the backends is:
+ //
+ // Blit + (Color?0x1) + (Depth?0x2) + (Stencil?0x4)
+ Blit,
+ BlitAll = Blit + 0x7,
+ Clear,
+ CopyImage,
+ Dispatch,
+ Draw,
+ GenerateMipmap,
+ Invalidate,
+ ReadPixels,
+ TexImage,
+ Other,
+};
+
+enum CommandBlitBuffer
+{
+ CommandBlitBufferColor = 0x1,
+ CommandBlitBufferDepth = 0x2,
+ CommandBlitBufferStencil = 0x4,
+};
+
+enum class InitState
+{
+ MayNeedInit,
+ Initialized,
+};
+
+template <typename T>
+struct RectangleImpl
+{
+ RectangleImpl() : x(T(0)), y(T(0)), width(T(0)), height(T(0)) {}
+ constexpr RectangleImpl(T x_in, T y_in, T width_in, T height_in)
+ : x(x_in), y(y_in), width(width_in), height(height_in)
+ {}
+ explicit constexpr RectangleImpl(const T corners[4])
+ : x(corners[0]),
+ y(corners[1]),
+ width(corners[2] - corners[0]),
+ height(corners[3] - corners[1])
+ {}
+ template <typename S>
+ explicit constexpr RectangleImpl(const RectangleImpl<S> rect)
+ : x(rect.x), y(rect.y), width(rect.width), height(rect.height)
+ {}
+
+ T x0() const { return x; }
+ T y0() const { return y; }
+ T x1() const { return x + width; }
+ T y1() const { return y + height; }
+
+ bool isReversedX() const { return width < T(0); }
+ bool isReversedY() const { return height < T(0); }
+
+ // Returns a rectangle with the same area but flipped in X, Y, neither or both.
+ RectangleImpl<T> flip(bool flipX, bool flipY) const
+ {
+ RectangleImpl flipped = *this;
+ if (flipX)
+ {
+ flipped.x = flipped.x + flipped.width;
+ flipped.width = -flipped.width;
+ }
+ if (flipY)
+ {
+ flipped.y = flipped.y + flipped.height;
+ flipped.height = -flipped.height;
+ }
+ return flipped;
+ }
+
+ // Returns a rectangle with the same area but with height and width guaranteed to be positive.
+ RectangleImpl<T> removeReversal() const { return flip(isReversedX(), isReversedY()); }
+
+ bool encloses(const RectangleImpl<T> &inside) const
+ {
+ return x0() <= inside.x0() && y0() <= inside.y0() && x1() >= inside.x1() &&
+ y1() >= inside.y1();
+ }
+
+ bool empty() const;
+
+ T x;
+ T y;
+ T width;
+ T height;
+};
+
+template <typename T>
+bool operator==(const RectangleImpl<T> &a, const RectangleImpl<T> &b);
+template <typename T>
+bool operator!=(const RectangleImpl<T> &a, const RectangleImpl<T> &b);
+
+using Rectangle = RectangleImpl<int>;
+
+enum class ClipSpaceOrigin
+{
+ LowerLeft = 0,
+ UpperLeft = 1
+};
+
+// Calculate the intersection of two rectangles. Returns false if the intersection is empty.
+[[nodiscard]] bool ClipRectangle(const Rectangle &source,
+ const Rectangle &clip,
+ Rectangle *intersection);
+// Calculate the smallest rectangle that covers both rectangles. This rectangle may cover areas
+// not covered by the two rectangles, for example in this situation:
+//
+// +--+ +----+
+// | ++-+ -> | |
+// +-++ | | |
+// +--+ +----+
+//
+void GetEnclosingRectangle(const Rectangle &rect1, const Rectangle &rect2, Rectangle *rectUnion);
+// Extend the source rectangle to cover parts (or all of) the second rectangle, in such a way that
+// no area is covered that isn't covered by both rectangles. For example:
+//
+// +--+ +--+
+// source --> | | | |
+// ++--+-+ -> | |
+// |+--+ | | |
+// +-----+ +--+
+//
+void ExtendRectangle(const Rectangle &source, const Rectangle &extend, Rectangle *extended);
+
+struct Offset
+{
+ constexpr Offset() : x(0), y(0), z(0) {}
+ constexpr Offset(int x_in, int y_in, int z_in) : x(x_in), y(y_in), z(z_in) {}
+
+ int x;
+ int y;
+ int z;
+};
+
+constexpr Offset kOffsetZero(0, 0, 0);
+
+bool operator==(const Offset &a, const Offset &b);
+bool operator!=(const Offset &a, const Offset &b);
+
+struct Extents
+{
+ Extents() : width(0), height(0), depth(0) {}
+ Extents(int width_, int height_, int depth_) : width(width_), height(height_), depth(depth_) {}
+
+ Extents(const Extents &other) = default;
+ Extents &operator=(const Extents &other) = default;
+
+ bool empty() const { return (width * height * depth) == 0; }
+
+ int width;
+ int height;
+ int depth;
+};
+
+bool operator==(const Extents &lhs, const Extents &rhs);
+bool operator!=(const Extents &lhs, const Extents &rhs);
+
+struct Box
+{
+ Box() : x(0), y(0), z(0), width(0), height(0), depth(0) {}
+ Box(int x_in, int y_in, int z_in, int width_in, int height_in, int depth_in)
+ : x(x_in), y(y_in), z(z_in), width(width_in), height(height_in), depth(depth_in)
+ {}
+ template <typename O, typename E>
+ Box(const O &offset, const E &size)
+ : x(offset.x),
+ y(offset.y),
+ z(offset.z),
+ width(size.width),
+ height(size.height),
+ depth(size.depth)
+ {}
+ bool valid() const;
+ bool operator==(const Box &other) const;
+ bool operator!=(const Box &other) const;
+ Rectangle toRect() const;
+
+ // Whether the Box has offset 0 and the same extents as argument.
+ bool coversSameExtent(const Extents &size) const;
+
+ bool contains(const Box &other) const;
+ size_t volume() const;
+ void extend(const Box &other);
+
+ int x;
+ int y;
+ int z;
+ int width;
+ int height;
+ int depth;
+};
+
+struct RasterizerState final
+{
+ // This will zero-initialize the struct, including padding.
+ RasterizerState();
+ RasterizerState(const RasterizerState &other);
+ RasterizerState &operator=(const RasterizerState &other);
+
+ bool cullFace;
+ CullFaceMode cullMode;
+ GLenum frontFace;
+
+ bool polygonOffsetFill;
+ GLfloat polygonOffsetFactor;
+ GLfloat polygonOffsetUnits;
+
+ // pointDrawMode/multiSample are only used in the D3D back-end right now.
+ bool pointDrawMode;
+ bool multiSample;
+
+ bool rasterizerDiscard;
+
+ bool dither;
+};
+
+bool operator==(const RasterizerState &a, const RasterizerState &b);
+bool operator!=(const RasterizerState &a, const RasterizerState &b);
+
+struct BlendState final
+{
+ // This will zero-initialize the struct, including padding.
+ BlendState();
+ BlendState(const BlendState &other);
+
+ bool blend;
+ GLenum sourceBlendRGB;
+ GLenum destBlendRGB;
+ GLenum sourceBlendAlpha;
+ GLenum destBlendAlpha;
+ GLenum blendEquationRGB;
+ GLenum blendEquationAlpha;
+
+ bool colorMaskRed;
+ bool colorMaskGreen;
+ bool colorMaskBlue;
+ bool colorMaskAlpha;
+};
+
+bool operator==(const BlendState &a, const BlendState &b);
+bool operator!=(const BlendState &a, const BlendState &b);
+
+struct DepthStencilState final
+{
+ // This will zero-initialize the struct, including padding.
+ DepthStencilState();
+ DepthStencilState(const DepthStencilState &other);
+ DepthStencilState &operator=(const DepthStencilState &other);
+
+ bool isDepthMaskedOut() const;
+ bool isStencilMaskedOut() const;
+ bool isStencilNoOp() const;
+ bool isStencilBackNoOp() const;
+
+ bool depthTest;
+ GLenum depthFunc;
+ bool depthMask;
+
+ bool stencilTest;
+ GLenum stencilFunc;
+ GLuint stencilMask;
+ GLenum stencilFail;
+ GLenum stencilPassDepthFail;
+ GLenum stencilPassDepthPass;
+ GLuint stencilWritemask;
+ GLenum stencilBackFunc;
+ GLuint stencilBackMask;
+ GLenum stencilBackFail;
+ GLenum stencilBackPassDepthFail;
+ GLenum stencilBackPassDepthPass;
+ GLuint stencilBackWritemask;
+};
+
+bool operator==(const DepthStencilState &a, const DepthStencilState &b);
+bool operator!=(const DepthStencilState &a, const DepthStencilState &b);
+
+// Packs a sampler state for completeness checks:
+// * minFilter: 5 values (3 bits)
+// * magFilter: 2 values (1 bit)
+// * wrapS: 3 values (2 bits)
+// * wrapT: 3 values (2 bits)
+// * compareMode: 1 bit (for == GL_NONE).
+// This makes a total of 9 bits. We can pack this easily into 32 bits:
+// * minFilter: 8 bits
+// * magFilter: 8 bits
+// * wrapS: 8 bits
+// * wrapT: 4 bits
+// * compareMode: 4 bits
+
+struct PackedSamplerCompleteness
+{
+ uint8_t minFilter;
+ uint8_t magFilter;
+ uint8_t wrapS;
+ uint8_t wrapTCompareMode;
+};
+
+static_assert(sizeof(PackedSamplerCompleteness) == sizeof(uint32_t), "Unexpected size");
+
+// State from Table 6.10 (state per sampler object)
+class SamplerState final
+{
+ public:
+ // This will zero-initialize the struct, including padding.
+ SamplerState();
+ SamplerState(const SamplerState &other);
+
+ SamplerState &operator=(const SamplerState &other);
+
+ static SamplerState CreateDefaultForTarget(TextureType type);
+
+ GLenum getMinFilter() const { return mMinFilter; }
+
+ bool setMinFilter(GLenum minFilter);
+
+ GLenum getMagFilter() const { return mMagFilter; }
+
+ bool setMagFilter(GLenum magFilter);
+
+ GLenum getWrapS() const { return mWrapS; }
+
+ bool setWrapS(GLenum wrapS);
+
+ GLenum getWrapT() const { return mWrapT; }
+
+ bool setWrapT(GLenum wrapT);
+
+ GLenum getWrapR() const { return mWrapR; }
+
+ bool setWrapR(GLenum wrapR);
+
+ float getMaxAnisotropy() const { return mMaxAnisotropy; }
+
+ bool setMaxAnisotropy(float maxAnisotropy);
+
+ GLfloat getMinLod() const { return mMinLod; }
+
+ bool setMinLod(GLfloat minLod);
+
+ GLfloat getMaxLod() const { return mMaxLod; }
+
+ bool setMaxLod(GLfloat maxLod);
+
+ GLenum getCompareMode() const { return mCompareMode; }
+
+ bool setCompareMode(GLenum compareMode);
+
+ GLenum getCompareFunc() const { return mCompareFunc; }
+
+ bool setCompareFunc(GLenum compareFunc);
+
+ GLenum getSRGBDecode() const { return mSRGBDecode; }
+
+ bool setSRGBDecode(GLenum sRGBDecode);
+
+ bool setBorderColor(const ColorGeneric &color);
+
+ const ColorGeneric &getBorderColor() const { return mBorderColor; }
+
+ bool sameCompleteness(const SamplerState &samplerState) const
+ {
+ return mCompleteness.packed == samplerState.mCompleteness.packed;
+ }
+
+ private:
+ void updateWrapTCompareMode();
+
+ GLenum mMinFilter;
+ GLenum mMagFilter;
+
+ GLenum mWrapS;
+ GLenum mWrapT;
+ GLenum mWrapR;
+
+ // From EXT_texture_filter_anisotropic
+ float mMaxAnisotropy;
+
+ GLfloat mMinLod;
+ GLfloat mMaxLod;
+
+ GLenum mCompareMode;
+ GLenum mCompareFunc;
+
+ GLenum mSRGBDecode;
+
+ ColorGeneric mBorderColor;
+
+ union Completeness
+ {
+ uint32_t packed;
+ PackedSamplerCompleteness typed;
+ };
+
+ Completeness mCompleteness;
+};
+
+bool operator==(const SamplerState &a, const SamplerState &b);
+bool operator!=(const SamplerState &a, const SamplerState &b);
+
+struct DrawArraysIndirectCommand
+{
+ GLuint count;
+ GLuint instanceCount;
+ GLuint first;
+ GLuint baseInstance;
+};
+static_assert(sizeof(DrawArraysIndirectCommand) == 16,
+ "Unexpected size of DrawArraysIndirectCommand");
+
+struct DrawElementsIndirectCommand
+{
+ GLuint count;
+ GLuint primCount;
+ GLuint firstIndex;
+ GLint baseVertex;
+ GLuint baseInstance;
+};
+static_assert(sizeof(DrawElementsIndirectCommand) == 20,
+ "Unexpected size of DrawElementsIndirectCommand");
+
+struct ImageUnit
+{
+ ImageUnit();
+ ImageUnit(const ImageUnit &other);
+ ~ImageUnit();
+
+ BindingPointer<Texture> texture;
+ GLint level;
+ GLboolean layered;
+ GLint layer;
+ GLenum access;
+ GLenum format;
+};
+
+using ImageUnitTextureTypeMap = std::map<unsigned int, gl::TextureType>;
+
+struct PixelStoreStateBase
+{
+ GLint alignment = 4;
+ GLint rowLength = 0;
+ GLint skipRows = 0;
+ GLint skipPixels = 0;
+ GLint imageHeight = 0;
+ GLint skipImages = 0;
+};
+
+struct PixelUnpackState : PixelStoreStateBase
+{};
+
+struct PixelPackState : PixelStoreStateBase
+{
+ bool reverseRowOrder = false;
+};
+
+// Used in Program and VertexArray.
+using AttributesMask = angle::BitSet<MAX_VERTEX_ATTRIBS>;
+
+// Used in Program
+using UniformBlockBindingMask = angle::BitSet<IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS>;
+
+// Used in Framebuffer / Program
+using DrawBufferMask = angle::BitSet8<IMPLEMENTATION_MAX_DRAW_BUFFERS>;
+
+class BlendStateExt final
+{
+ static_assert(IMPLEMENTATION_MAX_DRAW_BUFFERS == 8, "Only up to 8 draw buffers supported.");
+
+ public:
+ template <typename ElementType, size_t ElementCount>
+ struct StorageType final
+ {
+ static_assert(ElementCount <= 256, "ElementCount cannot exceed 256.");
+
+#if defined(ANGLE_IS_64_BIT_CPU)
+ // Always use uint64_t on 64-bit systems
+ static constexpr size_t kBits = 8;
+#else
+ static constexpr size_t kBits = ElementCount > 16 ? 8 : 4;
+#endif
+
+ using Type = typename std::conditional<kBits == 8, uint64_t, uint32_t>::type;
+
+ static constexpr Type kMaxValueMask = (kBits == 8) ? 0xFF : 0xF;
+
+ static constexpr Type GetMask(const size_t drawBuffers)
+ {
+ ASSERT(drawBuffers > 0);
+ ASSERT(drawBuffers <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
+ return static_cast<Type>(0xFFFFFFFFFFFFFFFFull >> (64 - drawBuffers * kBits));
+ }
+
+ // A multiplier that is used to replicate 4- or 8-bit value 8 times.
+ static constexpr Type kReplicator = (kBits == 8) ? 0x0101010101010101ull : 0x11111111;
+
+ // Extract packed `Bits`-bit value of index `index`. `values` variable contains up to 8
+ // packed values.
+ static constexpr ElementType GetValueIndexed(const size_t index, const Type values)
+ {
+ ASSERT(index < IMPLEMENTATION_MAX_DRAW_BUFFERS);
+
+ return static_cast<ElementType>((values >> (index * kBits)) & kMaxValueMask);
+ }
+
+ // Replicate `Bits`-bit value 8 times and mask the result.
+ static constexpr Type GetReplicatedValue(const ElementType value, const Type mask)
+ {
+ ASSERT(static_cast<size_t>(value) <= kMaxValueMask);
+ return (static_cast<size_t>(value) * kReplicator) & mask;
+ }
+
+ // Replace `Bits`-bit value of index `index` in `target` with `value`.
+ static constexpr void SetValueIndexed(const size_t index,
+ const ElementType value,
+ Type *target)
+ {
+ ASSERT(static_cast<size_t>(value) <= kMaxValueMask);
+ ASSERT(index < IMPLEMENTATION_MAX_DRAW_BUFFERS);
+
+ // Bitmask with set bits that contain the value of index `index`.
+ const Type selector = kMaxValueMask << (index * kBits);
+
+ // Shift the new `value` to its position in the packed value.
+ const Type builtValue = static_cast<Type>(value) << (index * kBits);
+
+ // Mark differing bits of `target` and `builtValue`, then flip the bits on those
+ // positions in `target`.
+ // Taken from https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge
+ *target = *target ^ ((*target ^ builtValue) & selector);
+ }
+
+ // Compare two packed sets of eight 4-bit values and return an 8-bit diff mask.
+ static constexpr DrawBufferMask GetDiffMask(const uint32_t packedValue1,
+ const uint32_t packedValue2)
+ {
+ uint32_t diff = packedValue1 ^ packedValue2;
+
+ // For each 4-bit value that is different between inputs, set the msb to 1 and other
+ // bits to 0.
+ diff = (diff | ((diff & 0x77777777) + 0x77777777)) & 0x88888888;
+
+ // By this point, `diff` looks like a...b...c...d...e...f...g...h... (dots mean zeros).
+ // To get DrawBufferMask, we need to compress this 32-bit value to 8 bits, i.e. abcdefgh
+
+ // Multiplying the lower half of `diff` by 0x249 (0x200 + 0x40 + 0x8 + 0x1) produces:
+ // ................e...f...g...h... +
+ // .............e...f...g...h...... +
+ // ..........e...f...g...h......... +
+ // .......e...f...g...h............
+ // ________________________________ =
+ // .......e..ef.efgefghfgh.gh..h...
+ // ^^^^
+ // Similar operation is applied to the upper word.
+ // This calculation could be replaced with a single PEXT instruction from BMI2 set.
+ diff = ((((diff & 0xFFFF0000) * 0x249) >> 24) & 0xF0) | (((diff * 0x249) >> 12) & 0xF);
+
+ return DrawBufferMask(static_cast<uint8_t>(diff));
+ }
+
+ // Compare two packed sets of eight 8-bit values and return an 8-bit diff mask.
+ static constexpr DrawBufferMask GetDiffMask(const uint64_t packedValue1,
+ const uint64_t packedValue2)
+ {
+ uint64_t diff = packedValue1 ^ packedValue2;
+
+ // For each 8-bit value that is different between inputs, set the msb to 1 and other
+ // bits to 0.
+ diff = (diff | ((diff & 0x7F7F7F7F7F7F7F7F) + 0x7F7F7F7F7F7F7F7F)) & 0x8080808080808080;
+
+ // By this point, `diff` looks like (dots mean zeros):
+ // a.......b.......c.......d.......e.......f.......g.......h.......
+ // To get DrawBufferMask, we need to compress this 64-bit value to 8 bits, i.e. abcdefgh
+
+ // Multiplying `diff` by 0x0002040810204081 produces:
+ // a.......b.......c.......d.......e.......f.......g.......h....... +
+ // .b.......c.......d.......e.......f.......g.......h.............. +
+ // ..c.......d.......e.......f.......g.......h..................... +
+ // ...d.......e.......f.......g.......h............................ +
+ // ....e.......f.......g.......h................................... +
+ // .....f.......g.......h.......................................... +
+ // ......g.......h................................................. +
+ // .......h........................................................
+ // ________________________________________________________________ =
+ // abcdefghbcdefgh.cdefgh..defgh...efgh....fgh.....gh......h.......
+ // ^^^^^^^^
+ // This operation could be replaced with a single PEXT instruction from BMI2 set.
+ diff = 0x0002040810204081 * diff >> 56;
+
+ return DrawBufferMask(static_cast<uint8_t>(diff));
+ }
+ };
+
+ using FactorStorage = StorageType<BlendFactorType, angle::EnumSize<BlendFactorType>()>;
+ using EquationStorage = StorageType<BlendEquationType, angle::EnumSize<BlendEquationType>()>;
+ using ColorMaskStorage = StorageType<uint8_t, 16>;
+ static_assert(std::is_same<FactorStorage::Type, uint64_t>::value &&
+ std::is_same<EquationStorage::Type, uint64_t>::value,
+ "Factor and Equation storage must be 64-bit.");
+
+ BlendStateExt(const size_t drawBuffers = 1);
+
+ BlendStateExt(const BlendStateExt &other);
+ BlendStateExt &operator=(const BlendStateExt &other);
+
+ ///////// Blending Toggle /////////
+
+ void setEnabled(const bool enabled);
+ void setEnabledIndexed(const size_t index, const bool enabled);
+
+ ///////// Color Write Mask /////////
+
+ static constexpr size_t PackColorMask(const bool red,
+ const bool green,
+ const bool blue,
+ const bool alpha)
+ {
+ return (red ? 1 : 0) | (green ? 2 : 0) | (blue ? 4 : 0) | (alpha ? 8 : 0);
+ }
+
+ static constexpr void UnpackColorMask(const size_t value,
+ bool *red,
+ bool *green,
+ bool *blue,
+ bool *alpha)
+ {
+ *red = static_cast<bool>(value & 1);
+ *green = static_cast<bool>(value & 2);
+ *blue = static_cast<bool>(value & 4);
+ *alpha = static_cast<bool>(value & 8);
+ }
+
+ ColorMaskStorage::Type expandColorMaskValue(const bool red,
+ const bool green,
+ const bool blue,
+ const bool alpha) const;
+ ColorMaskStorage::Type expandColorMaskIndexed(const size_t index) const;
+ void setColorMask(const bool red, const bool green, const bool blue, const bool alpha);
+ void setColorMaskIndexed(const size_t index, const uint8_t value);
+ void setColorMaskIndexed(const size_t index,
+ const bool red,
+ const bool green,
+ const bool blue,
+ const bool alpha);
+ uint8_t getColorMaskIndexed(const size_t index) const;
+ void getColorMaskIndexed(const size_t index,
+ bool *red,
+ bool *green,
+ bool *blue,
+ bool *alpha) const;
+ DrawBufferMask compareColorMask(ColorMaskStorage::Type other) const;
+
+ ///////// Blend Equation /////////
+
+ EquationStorage::Type expandEquationValue(const GLenum mode) const;
+ EquationStorage::Type expandEquationValue(const gl::BlendEquationType equation) const;
+ EquationStorage::Type expandEquationColorIndexed(const size_t index) const;
+ EquationStorage::Type expandEquationAlphaIndexed(const size_t index) const;
+ void setEquations(const GLenum modeColor, const GLenum modeAlpha);
+ void setEquationsIndexed(const size_t index, const GLenum modeColor, const GLenum modeAlpha);
+ void setEquationsIndexed(const size_t index,
+ const size_t otherIndex,
+ const BlendStateExt &other);
+ GLenum getEquationColorIndexed(size_t index) const;
+ GLenum getEquationAlphaIndexed(size_t index) const;
+ DrawBufferMask compareEquations(const EquationStorage::Type color,
+ const EquationStorage::Type alpha) const;
+ DrawBufferMask compareEquations(const BlendStateExt &other) const
+ {
+ return compareEquations(other.mEquationColor, other.mEquationAlpha);
+ }
+
+ ///////// Blend Factors /////////
+
+ FactorStorage::Type expandFactorValue(const GLenum func) const;
+ FactorStorage::Type expandSrcColorIndexed(const size_t index) const;
+ FactorStorage::Type expandDstColorIndexed(const size_t index) const;
+ FactorStorage::Type expandSrcAlphaIndexed(const size_t index) const;
+ FactorStorage::Type expandDstAlphaIndexed(const size_t index) const;
+ void setFactors(const GLenum srcColor,
+ const GLenum dstColor,
+ const GLenum srcAlpha,
+ const GLenum dstAlpha);
+ void setFactorsIndexed(const size_t index,
+ const GLenum srcColor,
+ const GLenum dstColor,
+ const GLenum srcAlpha,
+ const GLenum dstAlpha);
+ void setFactorsIndexed(const size_t index, const size_t otherIndex, const BlendStateExt &other);
+ GLenum getSrcColorIndexed(size_t index) const;
+ GLenum getDstColorIndexed(size_t index) const;
+ GLenum getSrcAlphaIndexed(size_t index) const;
+ GLenum getDstAlphaIndexed(size_t index) const;
+ DrawBufferMask compareFactors(const FactorStorage::Type srcColor,
+ const FactorStorage::Type dstColor,
+ const FactorStorage::Type srcAlpha,
+ const FactorStorage::Type dstAlpha) const;
+ DrawBufferMask compareFactors(const BlendStateExt &other) const
+ {
+ return compareFactors(other.mSrcColor, other.mDstColor, other.mSrcAlpha, other.mDstAlpha);
+ }
+
+ constexpr FactorStorage::Type getSrcColorBits() const { return mSrcColor; }
+ constexpr FactorStorage::Type getSrcAlphaBits() const { return mSrcAlpha; }
+ constexpr FactorStorage::Type getDstColorBits() const { return mDstColor; }
+ constexpr FactorStorage::Type getDstAlphaBits() const { return mDstAlpha; }
+
+ constexpr EquationStorage::Type getEquationColorBits() const { return mEquationColor; }
+ constexpr EquationStorage::Type getEquationAlphaBits() const { return mEquationAlpha; }
+
+ constexpr ColorMaskStorage::Type getAllColorMaskBits() const { return mAllColorMask; }
+ constexpr ColorMaskStorage::Type getColorMaskBits() const { return mColorMask; }
+
+ constexpr DrawBufferMask getAllEnabledMask() const { return mAllEnabledMask; }
+ constexpr DrawBufferMask getEnabledMask() const { return mEnabledMask; }
+
+ constexpr DrawBufferMask getUsesAdvancedBlendEquationMask() const
+ {
+ return mUsesAdvancedBlendEquationMask;
+ }
+
+ constexpr uint8_t getDrawBufferCount() const { return mDrawBufferCount; }
+
+ constexpr void setSrcColorBits(const FactorStorage::Type srcColor) { mSrcColor = srcColor; }
+ constexpr void setSrcAlphaBits(const FactorStorage::Type srcAlpha) { mSrcAlpha = srcAlpha; }
+ constexpr void setDstColorBits(const FactorStorage::Type dstColor) { mDstColor = dstColor; }
+ constexpr void setDstAlphaBits(const FactorStorage::Type dstAlpha) { mDstAlpha = dstAlpha; }
+
+ constexpr void setEquationColorBits(const EquationStorage::Type equationColor)
+ {
+ mEquationColor = equationColor;
+ }
+ constexpr void setEquationAlphaBits(const EquationStorage::Type equationAlpha)
+ {
+ mEquationAlpha = equationAlpha;
+ }
+
+ constexpr void setColorMaskBits(const ColorMaskStorage::Type colorMask)
+ {
+ mColorMask = colorMask;
+ }
+
+ constexpr void setEnabledMask(const DrawBufferMask enabledMask) { mEnabledMask = enabledMask; }
+
+ ///////// Data Members /////////
+ private:
+ uint64_t mParameterMask;
+
+ FactorStorage::Type mSrcColor;
+ FactorStorage::Type mDstColor;
+ FactorStorage::Type mSrcAlpha;
+ FactorStorage::Type mDstAlpha;
+
+ EquationStorage::Type mEquationColor;
+ EquationStorage::Type mEquationAlpha;
+
+ ColorMaskStorage::Type mAllColorMask;
+ ColorMaskStorage::Type mColorMask;
+
+ DrawBufferMask mAllEnabledMask;
+ DrawBufferMask mEnabledMask;
+
+ // Cache of whether the blend equation for each index is from KHR_blend_equation_advanced.
+ DrawBufferMask mUsesAdvancedBlendEquationMask;
+
+ uint8_t mDrawBufferCount;
+
+ [[maybe_unused]] uint32_t kUnused = 0;
+};
+
+static_assert(sizeof(BlendStateExt) == sizeof(uint64_t) +
+ (sizeof(BlendStateExt::FactorStorage::Type) * 4 +
+ sizeof(BlendStateExt::EquationStorage::Type) * 2 +
+ sizeof(BlendStateExt::ColorMaskStorage::Type) * 2 +
+ sizeof(DrawBufferMask) * 3 + sizeof(uint8_t)) +
+ sizeof(uint32_t),
+ "The BlendStateExt class must not contain gaps.");
+
+// Used in StateCache
+using StorageBuffersMask = angle::BitSet<IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
+
+template <typename T>
+using SampleMaskArray = std::array<T, IMPLEMENTATION_MAX_SAMPLE_MASK_WORDS>;
+
+template <typename T>
+using TexLevelArray = std::array<T, IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
+
+using TexLevelMask = angle::BitSet<IMPLEMENTATION_MAX_TEXTURE_LEVELS>;
+
+enum class ComponentType
+{
+ Float = 0,
+ Int = 1,
+ UnsignedInt = 2,
+ NoType = 3,
+ EnumCount = 4,
+ InvalidEnum = 4,
+};
+
+constexpr ComponentType GLenumToComponentType(GLenum componentType)
+{
+ switch (componentType)
+ {
+ case GL_FLOAT:
+ return ComponentType::Float;
+ case GL_INT:
+ return ComponentType::Int;
+ case GL_UNSIGNED_INT:
+ return ComponentType::UnsignedInt;
+ case GL_NONE:
+ return ComponentType::NoType;
+ default:
+ return ComponentType::InvalidEnum;
+ }
+}
+
+constexpr angle::PackedEnumMap<ComponentType, uint32_t> kComponentMasks = {{
+ {ComponentType::Float, 0x10001},
+ {ComponentType::Int, 0x00001},
+ {ComponentType::UnsignedInt, 0x10000},
+}};
+
+constexpr size_t kMaxComponentTypeMaskIndex = 16;
+using ComponentTypeMask = angle::BitSet<kMaxComponentTypeMaskIndex * 2>;
+
+ANGLE_INLINE void SetComponentTypeMask(ComponentType type, size_t index, ComponentTypeMask *mask)
+{
+ ASSERT(index <= kMaxComponentTypeMaskIndex);
+ *mask &= ~(0x10001 << index);
+ *mask |= kComponentMasks[type] << index;
+}
+
+ANGLE_INLINE ComponentType GetComponentTypeMask(const ComponentTypeMask &mask, size_t index)
+{
+ ASSERT(index <= kMaxComponentTypeMaskIndex);
+ uint32_t mask_bits = static_cast<uint32_t>((mask.to_ulong() >> index) & 0x10001);
+ switch (mask_bits)
+ {
+ case 0x10001:
+ return ComponentType::Float;
+ case 0x00001:
+ return ComponentType::Int;
+ case 0x10000:
+ return ComponentType::UnsignedInt;
+ default:
+ return ComponentType::InvalidEnum;
+ }
+}
+
+bool ValidateComponentTypeMasks(unsigned long outputTypes,
+ unsigned long inputTypes,
+ unsigned long outputMask,
+ unsigned long inputMask);
+
+enum class RenderToTextureImageIndex
+{
+ // The default image of the texture, where data is expected to be.
+ Default = 0,
+
+ // Intermediate multisampled images for EXT_multisampled_render_to_texture.
+ // These values must match log2(SampleCount).
+ IntermediateImage2xMultisampled = 1,
+ IntermediateImage4xMultisampled = 2,
+ IntermediateImage8xMultisampled = 3,
+ IntermediateImage16xMultisampled = 4,
+
+ // We currently only support up to 16xMSAA in backends that use this enum.
+ InvalidEnum = 5,
+ EnumCount = 5,
+};
+
+template <typename T>
+using RenderToTextureImageMap = angle::PackedEnumMap<RenderToTextureImageIndex, T>;
+
+struct ContextID
+{
+ uint32_t value;
+};
+
+inline bool operator==(ContextID lhs, ContextID rhs)
+{
+ return lhs.value == rhs.value;
+}
+
+inline bool operator!=(ContextID lhs, ContextID rhs)
+{
+ return lhs.value != rhs.value;
+}
+
+inline bool operator<(ContextID lhs, ContextID rhs)
+{
+ return lhs.value < rhs.value;
+}
+
+constexpr size_t kCubeFaceCount = 6;
+
+template <typename T>
+using TextureTypeMap = angle::PackedEnumMap<TextureType, T>;
+using TextureMap = TextureTypeMap<BindingPointer<Texture>>;
+
+// ShaderVector can contain one item per shader. It differs from ShaderMap in that the values are
+// not indexed by ShaderType.
+template <typename T>
+using ShaderVector = angle::FixedVector<T, static_cast<size_t>(ShaderType::EnumCount)>;
+
+template <typename T>
+using AttachmentArray = std::array<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
+
+template <typename T>
+using AttachmentVector = angle::FixedVector<T, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
+
+using AttachmentsMask = angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS>;
+
+template <typename T>
+using DrawBuffersArray = std::array<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
+
+template <typename T>
+using DrawBuffersVector = angle::FixedVector<T, IMPLEMENTATION_MAX_DRAW_BUFFERS>;
+
+template <typename T>
+using AttribArray = std::array<T, MAX_VERTEX_ATTRIBS>;
+
+using ActiveTextureMask = angle::BitSet<IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
+
+template <typename T>
+using ActiveTextureArray = std::array<T, IMPLEMENTATION_MAX_ACTIVE_TEXTURES>;
+
+using ActiveTextureTypeArray = ActiveTextureArray<TextureType>;
+
+template <typename T>
+using UniformBuffersArray = std::array<T, IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS>;
+template <typename T>
+using StorageBuffersArray = std::array<T, IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>;
+template <typename T>
+using AtomicCounterBuffersArray = std::array<T, IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS>;
+using AtomicCounterBufferMask = angle::BitSet<IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS>;
+template <typename T>
+using ImagesArray = std::array<T, IMPLEMENTATION_MAX_IMAGE_UNITS>;
+
+using ImageUnitMask = angle::BitSet<IMPLEMENTATION_MAX_IMAGE_UNITS>;
+
+using SupportedSampleSet = std::set<GLuint>;
+
+template <typename T>
+using TransformFeedbackBuffersArray =
+ std::array<T, gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS>;
+
+template <typename T>
+using QueryTypeMap = angle::PackedEnumMap<QueryType, T>;
+
+constexpr size_t kBarrierVectorDefaultSize = 16;
+
+template <typename T>
+using BarrierVector = angle::FastVector<T, kBarrierVectorDefaultSize>;
+
+using BufferBarrierVector = BarrierVector<Buffer *>;
+
+using SamplerBindingVector = std::vector<BindingPointer<Sampler>>;
+using BufferVector = std::vector<OffsetBindingPointer<Buffer>>;
+
+struct TextureAndLayout
+{
+ Texture *texture;
+ GLenum layout;
+};
+using TextureBarrierVector = BarrierVector<TextureAndLayout>;
+
+// OffsetBindingPointer.getSize() returns the size specified by the user, which may be larger than
+// the size of the bound buffer. This function reduces the returned size to fit the bound buffer if
+// necessary. Returns 0 if no buffer is bound or if integer overflow occurs.
+GLsizeiptr GetBoundBufferAvailableSize(const OffsetBindingPointer<Buffer> &binding);
+
+// A texture level index.
+template <typename T>
+class LevelIndexWrapper
+{
+ public:
+ LevelIndexWrapper() = default;
+ explicit constexpr LevelIndexWrapper(T levelIndex) : mLevelIndex(levelIndex) {}
+ constexpr LevelIndexWrapper(const LevelIndexWrapper &other) = default;
+ constexpr LevelIndexWrapper &operator=(const LevelIndexWrapper &other) = default;
+
+ constexpr T get() const { return mLevelIndex; }
+
+ LevelIndexWrapper &operator++()
+ {
+ ++mLevelIndex;
+ return *this;
+ }
+ constexpr bool operator<(const LevelIndexWrapper &other) const
+ {
+ return mLevelIndex < other.mLevelIndex;
+ }
+ constexpr bool operator<=(const LevelIndexWrapper &other) const
+ {
+ return mLevelIndex <= other.mLevelIndex;
+ }
+ constexpr bool operator>(const LevelIndexWrapper &other) const
+ {
+ return mLevelIndex > other.mLevelIndex;
+ }
+ constexpr bool operator>=(const LevelIndexWrapper &other) const
+ {
+ return mLevelIndex >= other.mLevelIndex;
+ }
+ constexpr bool operator==(const LevelIndexWrapper &other) const
+ {
+ return mLevelIndex == other.mLevelIndex;
+ }
+ constexpr bool operator!=(const LevelIndexWrapper &other) const
+ {
+ return mLevelIndex != other.mLevelIndex;
+ }
+ constexpr LevelIndexWrapper operator+(T other) const
+ {
+ return LevelIndexWrapper(mLevelIndex + other);
+ }
+ constexpr LevelIndexWrapper operator-(T other) const
+ {
+ return LevelIndexWrapper(mLevelIndex - other);
+ }
+ constexpr T operator-(LevelIndexWrapper other) const { return mLevelIndex - other.mLevelIndex; }
+
+ private:
+ T mLevelIndex;
+};
+
+// A GL texture level index.
+using LevelIndex = LevelIndexWrapper<GLint>;
+
+enum class MultisamplingMode
+{
+ // Regular multisampling
+ Regular = 0,
+ // GL_EXT_multisampled_render_to_texture renderbuffer/texture attachments which perform implicit
+ // resolve of multisampled data.
+ MultisampledRenderToTexture,
+};
+} // namespace gl
+
+namespace rx
+{
+// A macro that determines whether an object has a given runtime type.
+#if defined(__clang__)
+# if __has_feature(cxx_rtti)
+# define ANGLE_HAS_DYNAMIC_CAST 1
+# endif
+#elif !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) && \
+ (!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || \
+ defined(__GXX_RTTI))
+# define ANGLE_HAS_DYNAMIC_CAST 1
+#endif
+
+#ifdef ANGLE_HAS_DYNAMIC_CAST
+# define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast<type>(obj) != nullptr)
+# undef ANGLE_HAS_DYNAMIC_CAST
+#else
+# define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (obj != nullptr)
+#endif
+
+// Downcast a base implementation object (EG TextureImpl to TextureD3D)
+template <typename DestT, typename SrcT>
+inline DestT *GetAs(SrcT *src)
+{
+ ASSERT(ANGLE_HAS_DYNAMIC_TYPE(DestT *, src));
+ return static_cast<DestT *>(src);
+}
+
+template <typename DestT, typename SrcT>
+inline const DestT *GetAs(const SrcT *src)
+{
+ ASSERT(ANGLE_HAS_DYNAMIC_TYPE(const DestT *, src));
+ return static_cast<const DestT *>(src);
+}
+
+#undef ANGLE_HAS_DYNAMIC_TYPE
+
+// Downcast a GL object to an Impl (EG gl::Texture to rx::TextureD3D)
+template <typename DestT, typename SrcT>
+inline DestT *GetImplAs(SrcT *src)
+{
+ return GetAs<DestT>(src->getImplementation());
+}
+
+template <typename DestT, typename SrcT>
+inline DestT *SafeGetImplAs(SrcT *src)
+{
+ return src != nullptr ? GetAs<DestT>(src->getImplementation()) : nullptr;
+}
+
+} // namespace rx
+
+#include "angletypes.inc"
+
+namespace angle
+{
+// Zero-based for better array indexing
+enum FramebufferBinding
+{
+ FramebufferBindingRead = 0,
+ FramebufferBindingDraw,
+ FramebufferBindingSingletonMax,
+ FramebufferBindingBoth = FramebufferBindingSingletonMax,
+ FramebufferBindingMax,
+ FramebufferBindingUnknown = FramebufferBindingMax,
+};
+
+inline FramebufferBinding EnumToFramebufferBinding(GLenum enumValue)
+{
+ switch (enumValue)
+ {
+ case GL_READ_FRAMEBUFFER:
+ return FramebufferBindingRead;
+ case GL_DRAW_FRAMEBUFFER:
+ return FramebufferBindingDraw;
+ case GL_FRAMEBUFFER:
+ return FramebufferBindingBoth;
+ default:
+ UNREACHABLE();
+ return FramebufferBindingUnknown;
+ }
+}
+
+inline GLenum FramebufferBindingToEnum(FramebufferBinding binding)
+{
+ switch (binding)
+ {
+ case FramebufferBindingRead:
+ return GL_READ_FRAMEBUFFER;
+ case FramebufferBindingDraw:
+ return GL_DRAW_FRAMEBUFFER;
+ case FramebufferBindingBoth:
+ return GL_FRAMEBUFFER;
+ default:
+ UNREACHABLE();
+ return GL_NONE;
+ }
+}
+
+template <typename ObjT, typename ContextT>
+class DestroyThenDelete
+{
+ public:
+ DestroyThenDelete() = default;
+ DestroyThenDelete(const ContextT *context) : mContext(context) {}
+
+ void operator()(ObjT *obj)
+ {
+ (void)(obj->onDestroy(mContext));
+ delete obj;
+ }
+
+ private:
+ const ContextT *mContext = nullptr;
+};
+
+template <typename ObjT, typename ContextT>
+using UniqueObjectPointer = std::unique_ptr<ObjT, DestroyThenDelete<ObjT, ContextT>>;
+
+} // namespace angle
+
+namespace gl
+{
+class State;
+} // namespace gl
+
+#endif // LIBANGLE_ANGLETYPES_H_
diff --git a/gfx/angle/checkout/src/libANGLE/angletypes.inc b/gfx/angle/checkout/src/libANGLE/angletypes.inc
new file mode 100644
index 0000000000..862a3214a1
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/angletypes.inc
@@ -0,0 +1,35 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angletypes.inc : Inline definitions of some functions from angletypes.h
+
+namespace gl
+{
+
+inline bool operator==(const Rectangle &a, const Rectangle &b)
+{
+ return a.x == b.x &&
+ a.y == b.y &&
+ a.width == b.width &&
+ a.height == b.height;
+}
+
+inline bool operator!=(const Rectangle &a, const Rectangle &b)
+{
+ return !(a == b);
+}
+
+inline bool operator==(const SamplerState &a, const SamplerState &b)
+{
+ return memcmp(&a, &b, sizeof(SamplerState)) == 0;
+}
+
+inline bool operator!=(const SamplerState &a, const SamplerState &b)
+{
+ return !(a == b);
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/capture/FrameCapture.h b/gfx/angle/checkout/src/libANGLE/capture/FrameCapture.h
new file mode 100644
index 0000000000..a9b0348b6a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/FrameCapture.h
@@ -0,0 +1,1208 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FrameCapture.h:
+// ANGLE Frame capture interface.
+//
+
+#ifndef LIBANGLE_FRAME_CAPTURE_H_
+#define LIBANGLE_FRAME_CAPTURE_H_
+
+#include "common/PackedEnums.h"
+#include "common/system_utils.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/capture/frame_capture_utils_autogen.h"
+#include "libANGLE/entry_points_utils.h"
+
+namespace gl
+{
+enum class BigGLEnum;
+enum class GLESEnum;
+} // namespace gl
+
+namespace angle
+{
+
+using ParamData = std::vector<std::vector<uint8_t>>;
+struct ParamCapture : angle::NonCopyable
+{
+ ParamCapture();
+ ParamCapture(const char *nameIn, ParamType typeIn);
+ ~ParamCapture();
+
+ ParamCapture(ParamCapture &&other);
+ ParamCapture &operator=(ParamCapture &&other);
+
+ std::string name;
+ ParamType type;
+ ParamValue value;
+ gl::GLESEnum enumGroup; // only used for param type GLenum, GLboolean and GLbitfield
+ gl::BigGLEnum bigGLEnum; // only used for param type GLenum, GLboolean and GLbitfield
+ ParamData data;
+ int dataNElements = 0;
+ int arrayClientPointerIndex = -1;
+ size_t readBufferSizeBytes = 0;
+};
+
+class ParamBuffer final : angle::NonCopyable
+{
+ public:
+ ParamBuffer();
+ ~ParamBuffer();
+
+ ParamBuffer(ParamBuffer &&other);
+ ParamBuffer &operator=(ParamBuffer &&other);
+
+ template <typename T>
+ void addValueParam(const char *paramName, ParamType paramType, T paramValue);
+ template <typename T>
+ void setValueParamAtIndex(const char *paramName, ParamType paramType, T paramValue, int index);
+ template <typename T>
+ void addEnumParam(const char *paramName,
+ gl::GLESEnum enumGroup,
+ ParamType paramType,
+ T paramValue);
+ template <typename T>
+ void addEnumParam(const char *paramName,
+ gl::BigGLEnum enumGroup,
+ ParamType paramType,
+ T paramValue);
+
+ ParamCapture &getParam(const char *paramName, ParamType paramType, int index);
+ const ParamCapture &getParam(const char *paramName, ParamType paramType, int index) const;
+ ParamCapture &getParamFlexName(const char *paramName1,
+ const char *paramName2,
+ ParamType paramType,
+ int index);
+ const ParamCapture &getParamFlexName(const char *paramName1,
+ const char *paramName2,
+ ParamType paramType,
+ int index) const;
+ const ParamCapture &getReturnValue() const { return mReturnValueCapture; }
+
+ void addParam(ParamCapture &&param);
+ void addReturnValue(ParamCapture &&returnValue);
+ bool hasClientArrayData() const { return mClientArrayDataParam != -1; }
+ ParamCapture &getClientArrayPointerParameter();
+ size_t getReadBufferSize() const { return mReadBufferSize; }
+
+ const std::vector<ParamCapture> &getParamCaptures() const { return mParamCaptures; }
+
+ // These helpers allow us to track the ID of the buffer that was active when
+ // MapBufferRange was called. We'll use it during replay to track the
+ // buffer's contents, as they can be modified by the host.
+ void setMappedBufferID(gl::BufferID bufferID) { mMappedBufferID = bufferID; }
+ gl::BufferID getMappedBufferID() const { return mMappedBufferID; }
+
+ private:
+ std::vector<ParamCapture> mParamCaptures;
+ ParamCapture mReturnValueCapture;
+ int mClientArrayDataParam = -1;
+ size_t mReadBufferSize = 0;
+ gl::BufferID mMappedBufferID;
+};
+
+struct CallCapture
+{
+ CallCapture(EntryPoint entryPointIn, ParamBuffer &&paramsIn);
+ CallCapture(const std::string &customFunctionNameIn, ParamBuffer &&paramsIn);
+ ~CallCapture();
+
+ CallCapture(CallCapture &&other);
+ CallCapture &operator=(CallCapture &&other);
+
+ const char *name() const;
+
+ EntryPoint entryPoint;
+ std::string customFunctionName;
+ ParamBuffer params;
+ bool isActive = true;
+};
+
+class ReplayContext
+{
+ public:
+ ReplayContext(size_t readBufferSizebytes, const gl::AttribArray<size_t> &clientArraysSizebytes);
+ ~ReplayContext();
+
+ template <typename T>
+ T getReadBufferPointer(const ParamCapture &param)
+ {
+ ASSERT(param.readBufferSizeBytes > 0);
+ ASSERT(mReadBuffer.size() >= param.readBufferSizeBytes);
+ return reinterpret_cast<T>(mReadBuffer.data());
+ }
+ template <typename T>
+ T getAsConstPointer(const ParamCapture &param)
+ {
+ if (param.arrayClientPointerIndex != -1)
+ {
+ return reinterpret_cast<T>(mClientArraysBuffer[param.arrayClientPointerIndex].data());
+ }
+
+ if (!param.data.empty())
+ {
+ ASSERT(param.data.size() == 1);
+ return reinterpret_cast<T>(param.data[0].data());
+ }
+
+ return nullptr;
+ }
+
+ template <typename T>
+ T getAsPointerConstPointer(const ParamCapture &param)
+ {
+ static_assert(sizeof(typename std::remove_pointer<T>::type) == sizeof(uint8_t *),
+ "pointer size not match!");
+
+ ASSERT(!param.data.empty());
+ mPointersBuffer.clear();
+ mPointersBuffer.reserve(param.data.size());
+ for (const std::vector<uint8_t> &data : param.data)
+ {
+ mPointersBuffer.emplace_back(data.data());
+ }
+ return reinterpret_cast<T>(mPointersBuffer.data());
+ }
+
+ gl::AttribArray<std::vector<uint8_t>> &getClientArraysBuffer() { return mClientArraysBuffer; }
+
+ private:
+ std::vector<uint8_t> mReadBuffer;
+ std::vector<const uint8_t *> mPointersBuffer;
+ gl::AttribArray<std::vector<uint8_t>> mClientArraysBuffer;
+};
+
+// Helper to use unique IDs for each local data variable.
+class DataCounters final : angle::NonCopyable
+{
+ public:
+ DataCounters();
+ ~DataCounters();
+
+ int getAndIncrement(EntryPoint entryPoint, const std::string &paramName);
+
+ private:
+ // <CallName, ParamName>
+ using Counter = std::pair<EntryPoint, std::string>;
+ std::map<Counter, int> mData;
+};
+
+constexpr int kStringsNotFound = -1;
+class StringCounters final : angle::NonCopyable
+{
+ public:
+ StringCounters();
+ ~StringCounters();
+
+ int getStringCounter(const std::vector<std::string> &str);
+ void setStringCounter(const std::vector<std::string> &str, int &counter);
+
+ private:
+ std::map<std::vector<std::string>, int> mStringCounterMap;
+};
+
+class DataTracker final : angle::NonCopyable
+{
+ public:
+ DataTracker();
+ ~DataTracker();
+
+ DataCounters &getCounters() { return mCounters; }
+ StringCounters &getStringCounters() { return mStringCounters; }
+
+ private:
+ DataCounters mCounters;
+ StringCounters mStringCounters;
+};
+
+class ReplayWriter final : angle::NonCopyable
+{
+ public:
+ ReplayWriter();
+ ~ReplayWriter();
+
+ void setSourceFileSizeThreshold(size_t sourceFileSizeThreshold);
+ void setFilenamePattern(const std::string &pattern);
+ void setCaptureLabel(const std::string &label);
+ void setSourcePrologue(const std::string &prologue);
+ void setHeaderPrologue(const std::string &prologue);
+
+ void addPublicFunction(const std::string &functionProto,
+ const std::stringstream &headerStream,
+ const std::stringstream &bodyStream);
+ void addPrivateFunction(const std::string &functionProto,
+ const std::stringstream &headerStream,
+ const std::stringstream &bodyStream);
+ std::string getInlineVariableName(EntryPoint entryPoint, const std::string &paramName);
+
+ std::string getInlineStringSetVariableName(EntryPoint entryPoint,
+ const std::string &paramName,
+ const std::vector<std::string> &strings,
+ bool *isNewEntryOut);
+
+ void saveFrame();
+ void saveFrameIfFull();
+ void saveIndexFilesAndHeader();
+ void saveSetupFile();
+
+ std::vector<std::string> getAndResetWrittenFiles();
+
+ private:
+ static std::string GetVarName(EntryPoint entryPoint, const std::string &paramName, int counter);
+
+ void saveHeader();
+ void writeReplaySource(const std::string &filename);
+ void addWrittenFile(const std::string &filename);
+ size_t getStoredReplaySourceSize() const;
+
+ size_t mSourceFileSizeThreshold;
+ size_t mFrameIndex;
+
+ DataTracker mDataTracker;
+ std::string mFilenamePattern;
+ std::string mCaptureLabel;
+ std::string mSourcePrologue;
+ std::string mHeaderPrologue;
+
+ std::vector<std::string> mReplayHeaders;
+ std::vector<std::string> mGlobalVariableDeclarations;
+
+ std::vector<std::string> mPublicFunctionPrototypes;
+ std::vector<std::string> mPublicFunctions;
+
+ std::vector<std::string> mPrivateFunctionPrototypes;
+ std::vector<std::string> mPrivateFunctions;
+
+ std::vector<std::string> mWrittenFiles;
+};
+
+using BufferCalls = std::map<GLuint, std::vector<CallCapture>>;
+
+// true means mapped, false means unmapped
+using BufferMapStatusMap = std::map<GLuint, bool>;
+
+using FenceSyncSet = std::set<GLsync>;
+using FenceSyncCalls = std::map<GLsync, std::vector<CallCapture>>;
+
+// For default uniforms, we need to track which ones are dirty, and the series of calls to reset.
+// Each program has unique default uniforms, and each uniform has one or more locations in the
+// default buffer. For reset efficiency, we track only the uniforms dirty by location, per program.
+
+// A set of all default uniforms (per program) that were modified during the run
+using DefaultUniformLocationsSet = std::set<gl::UniformLocation>;
+using DefaultUniformLocationsPerProgramMap =
+ std::map<gl::ShaderProgramID, DefaultUniformLocationsSet>;
+
+// A map of programs which maps to locations and their reset calls
+using DefaultUniformCallsPerLocationMap = std::map<gl::UniformLocation, std::vector<CallCapture>>;
+using DefaultUniformCallsPerProgramMap =
+ std::map<gl::ShaderProgramID, DefaultUniformCallsPerLocationMap>;
+
+using DefaultUniformBaseLocationMap =
+ std::map<std::pair<gl::ShaderProgramID, gl::UniformLocation>, gl::UniformLocation>;
+
+using ResourceSet = std::set<GLuint>;
+using ResourceCalls = std::map<GLuint, std::vector<CallCapture>>;
+
+class TrackedResource final : angle::NonCopyable
+{
+ public:
+ TrackedResource();
+ ~TrackedResource();
+
+ const ResourceSet &getStartingResources() const { return mStartingResources; }
+ ResourceSet &getStartingResources() { return mStartingResources; }
+ const ResourceSet &getNewResources() const { return mNewResources; }
+ ResourceSet &getNewResources() { return mNewResources; }
+ const ResourceSet &getResourcesToRegen() const { return mResourcesToRegen; }
+ ResourceSet &getResourcesToRegen() { return mResourcesToRegen; }
+ const ResourceSet &getResourcesToRestore() const { return mResourcesToRestore; }
+ ResourceSet &getResourcesToRestore() { return mResourcesToRestore; }
+
+ void setGennedResource(GLuint id);
+ void setDeletedResource(GLuint id);
+ void setModifiedResource(GLuint id);
+ bool resourceIsGenerated(GLuint id);
+
+ ResourceCalls &getResourceRegenCalls() { return mResourceRegenCalls; }
+ ResourceCalls &getResourceRestoreCalls() { return mResourceRestoreCalls; }
+
+ private:
+ // Resource regen calls will gen a resource
+ ResourceCalls mResourceRegenCalls;
+ // Resource restore calls will restore the contents of a resource
+ ResourceCalls mResourceRestoreCalls;
+
+ // Resources created during startup
+ ResourceSet mStartingResources;
+
+ // Resources created during the run that need to be deleted
+ ResourceSet mNewResources;
+ // Resources deleted during the run that need to be recreated
+ ResourceSet mResourcesToRegen;
+ // Resources modified during the run that need to be restored
+ ResourceSet mResourcesToRestore;
+};
+
+using TrackedResourceArray =
+ std::array<TrackedResource, static_cast<uint32_t>(ResourceIDType::EnumCount)>;
+
+// Helper to track resource changes during the capture
+class ResourceTracker final : angle::NonCopyable
+{
+ public:
+ ResourceTracker();
+ ~ResourceTracker();
+
+ BufferCalls &getBufferMapCalls() { return mBufferMapCalls; }
+ BufferCalls &getBufferUnmapCalls() { return mBufferUnmapCalls; }
+
+ std::vector<CallCapture> &getBufferBindingCalls() { return mBufferBindingCalls; }
+
+ void setBufferMapped(gl::ContextID contextID, GLuint id);
+ void setBufferUnmapped(gl::ContextID contextID, GLuint id);
+
+ bool getStartingBuffersMappedCurrent(GLuint id) const;
+ bool getStartingBuffersMappedInitial(GLuint id) const;
+
+ void setStartingBufferMapped(GLuint id, bool mapped)
+ {
+ // Track the current state (which will change throughout the trace)
+ mStartingBuffersMappedCurrent[id] = mapped;
+
+ // And the initial state, to compare during frame loop reset
+ mStartingBuffersMappedInitial[id] = mapped;
+ }
+
+ void onShaderProgramAccess(gl::ShaderProgramID shaderProgramID);
+ uint32_t getMaxShaderPrograms() const { return mMaxShaderPrograms; }
+
+ FenceSyncSet &getStartingFenceSyncs() { return mStartingFenceSyncs; }
+ FenceSyncCalls &getFenceSyncRegenCalls() { return mFenceSyncRegenCalls; }
+ FenceSyncSet &getFenceSyncsToRegen() { return mFenceSyncsToRegen; }
+ void setDeletedFenceSync(GLsync sync);
+
+ DefaultUniformLocationsPerProgramMap &getDefaultUniformsToReset()
+ {
+ return mDefaultUniformsToReset;
+ }
+ DefaultUniformCallsPerLocationMap &getDefaultUniformResetCalls(gl::ShaderProgramID id)
+ {
+ return mDefaultUniformResetCalls[id];
+ }
+ void setModifiedDefaultUniform(gl::ShaderProgramID programID, gl::UniformLocation location);
+ void setDefaultUniformBaseLocation(gl::ShaderProgramID programID,
+ gl::UniformLocation location,
+ gl::UniformLocation baseLocation);
+ gl::UniformLocation getDefaultUniformBaseLocation(gl::ShaderProgramID programID,
+ gl::UniformLocation location)
+ {
+ ASSERT(mDefaultUniformBaseLocations.find({programID, location}) !=
+ mDefaultUniformBaseLocations.end());
+ return mDefaultUniformBaseLocations[{programID, location}];
+ }
+
+ TrackedResource &getTrackedResource(gl::ContextID contextID, ResourceIDType type);
+
+ void getContextIDs(std::set<gl::ContextID> &idsOut);
+
+ std::map<void *, egl::AttributeMap> &getImageToAttribTable() { return mMatchImageToAttribs; }
+
+ std::map<GLuint, void *> &getTextureIDToImageTable() { return mMatchTextureIDToImage; }
+
+ private:
+ // Buffer map calls will map a buffer with correct offset, length, and access flags
+ BufferCalls mBufferMapCalls;
+ // Buffer unmap calls will bind and unmap a given buffer
+ BufferCalls mBufferUnmapCalls;
+
+ // Buffer binding calls to restore bindings recorded during MEC
+ std::vector<CallCapture> mBufferBindingCalls;
+
+ // Whether a given buffer was mapped at the start of the trace
+ BufferMapStatusMap mStartingBuffersMappedInitial;
+ // The status of buffer mapping throughout the trace, modified with each Map/Unmap call
+ BufferMapStatusMap mStartingBuffersMappedCurrent;
+
+ // Maximum accessed shader program ID.
+ uint32_t mMaxShaderPrograms = 0;
+
+ // Fence sync objects created during MEC setup
+ FenceSyncSet mStartingFenceSyncs;
+ // Fence sync regen calls will create a fence sync objects
+ FenceSyncCalls mFenceSyncRegenCalls;
+ // Fence syncs to regen are a list of starting fence sync objects that were deleted and need to
+ // be regen'ed.
+ FenceSyncSet mFenceSyncsToRegen;
+
+ // Default uniforms that were modified during the run
+ DefaultUniformLocationsPerProgramMap mDefaultUniformsToReset;
+ // Calls per default uniform to return to original state
+ DefaultUniformCallsPerProgramMap mDefaultUniformResetCalls;
+
+ // Base location of arrayed uniforms
+ DefaultUniformBaseLocationMap mDefaultUniformBaseLocations;
+
+ // Tracked resources per context
+ TrackedResourceArray mTrackedResourcesShared;
+ std::map<gl::ContextID, TrackedResourceArray> mTrackedResourcesPerContext;
+
+ std::map<void *, egl::AttributeMap> mMatchImageToAttribs;
+ std::map<GLuint, void *> mMatchTextureIDToImage;
+};
+
+// Used by the CPP replay to filter out unnecessary code.
+using HasResourceTypeMap = angle::PackedEnumBitSet<ResourceIDType>;
+
+// Map of ResourceType to IDs and range of setup calls
+using ResourceIDToSetupCallsMap =
+ PackedEnumMap<ResourceIDType, std::map<GLuint, gl::Range<size_t>>>;
+
+// Map of buffer ID to offset and size used when mapped
+using BufferDataMap = std::map<gl::BufferID, std::pair<GLintptr, GLsizeiptr>>;
+
+// A dictionary of sources indexed by shader type.
+using ProgramSources = gl::ShaderMap<std::string>;
+
+// Maps from IDs to sources.
+using ShaderSourceMap = std::map<gl::ShaderProgramID, std::string>;
+using ProgramSourceMap = std::map<gl::ShaderProgramID, ProgramSources>;
+
+// Map from textureID to level and data
+using TextureLevels = std::map<GLint, std::vector<uint8_t>>;
+using TextureLevelDataMap = std::map<gl::TextureID, TextureLevels>;
+
+struct SurfaceParams
+{
+ gl::Extents extents;
+ egl::ColorSpace colorSpace;
+};
+
+// Map from ContextID to SurfaceParams
+using SurfaceParamsMap = std::map<gl::ContextID, SurfaceParams>;
+
+using CallVector = std::vector<std::vector<CallCapture> *>;
+
+// A map from API entry point to calls
+using CallResetMap = std::map<angle::EntryPoint, std::vector<CallCapture>>;
+
+// StateResetHelper provides a simple way to track whether an entry point has been called during the
+// trace, along with the reset calls to get it back to starting state. This is useful for things
+// that are one dimensional, like context bindings or context state.
+class StateResetHelper final : angle::NonCopyable
+{
+ public:
+ StateResetHelper();
+ ~StateResetHelper();
+
+ const std::set<angle::EntryPoint> &getDirtyEntryPoints() const { return mDirtyEntryPoints; }
+ void setEntryPointDirty(EntryPoint entryPoint) { mDirtyEntryPoints.insert(entryPoint); }
+
+ CallResetMap &getResetCalls() { return mResetCalls; }
+ const CallResetMap &getResetCalls() const { return mResetCalls; }
+
+ void setDefaultResetCalls(const gl::Context *context, angle::EntryPoint);
+
+ private:
+ // Dirty state per entry point
+ std::set<angle::EntryPoint> mDirtyEntryPoints;
+
+ // Reset calls per API entry point
+ CallResetMap mResetCalls;
+};
+
+class FrameCapture final : angle::NonCopyable
+{
+ public:
+ FrameCapture();
+ ~FrameCapture();
+
+ std::vector<CallCapture> &getSetupCalls() { return mSetupCalls; }
+ void clearSetupCalls() { mSetupCalls.clear(); }
+
+ StateResetHelper &getStateResetHelper() { return mStateResetHelper; }
+
+ void reset();
+
+ private:
+ std::vector<CallCapture> mSetupCalls;
+
+ StateResetHelper mStateResetHelper;
+};
+
+// Page range inside a coherent buffer
+struct PageRange
+{
+ PageRange(size_t start, size_t end);
+ ~PageRange();
+
+ // Relative start page
+ size_t start;
+
+ // First page after the relative end
+ size_t end;
+};
+
+// Memory address range defined by start and size
+struct AddressRange
+{
+ AddressRange();
+ AddressRange(uintptr_t start, size_t size);
+ ~AddressRange();
+
+ uintptr_t end();
+
+ uintptr_t start;
+ size_t size;
+};
+
+// Used to handle protection of buffers that overlap in pages.
+enum class PageSharingType
+{
+ NoneShared,
+ FirstShared,
+ LastShared,
+ FirstAndLastShared
+};
+
+class CoherentBuffer
+{
+ public:
+ CoherentBuffer(uintptr_t start, size_t size, size_t pageSize);
+ ~CoherentBuffer();
+
+ // Sets the a range in the buffer clean and protects a selected range
+ void protectPageRange(const PageRange &pageRange);
+
+ // Sets a page dirty state and sets it's protection
+ void setDirty(size_t relativePage, bool dirty);
+
+ // Removes protection
+ void removeProtection(PageSharingType sharingType);
+
+ bool contains(size_t page, size_t *relativePage);
+ bool isDirty();
+
+ // Returns dirty page ranges
+ std::vector<PageRange> getDirtyPageRanges();
+
+ // Calculates address range from page range
+ AddressRange getDirtyAddressRange(const PageRange &dirtyPageRange);
+ AddressRange getRange();
+
+ private:
+ // Actual buffer start and size
+ AddressRange mRange;
+
+ // Start and size of page aligned protected area
+ AddressRange mProtectionRange;
+
+ // Start and end of protection in relative pages, calculated from mProtectionRange.
+ size_t mProtectionStartPage;
+ size_t mProtectionEndPage;
+
+ size_t mPageCount;
+ size_t mPageSize;
+
+ // Clean pages are protected
+ std::vector<bool> mDirtyPages;
+};
+
+class CoherentBufferTracker final : angle::NonCopyable
+{
+ public:
+ CoherentBufferTracker();
+ ~CoherentBufferTracker();
+
+ bool isDirty(gl::BufferID id);
+ void addBuffer(gl::BufferID id, uintptr_t start, size_t size);
+ void removeBuffer(gl::BufferID id);
+ void disable();
+ void enable();
+ void onEndFrame();
+
+ private:
+ // Detect overlapping pages when removing protection
+ PageSharingType doesBufferSharePage(gl::BufferID id);
+
+ // Returns a map to found buffers and the corresponding pages for a given address.
+ // For addresses that are in a page shared by 2 buffers, 2 results are returned.
+ HashMap<std::shared_ptr<CoherentBuffer>, size_t> getBufferPagesForAddress(uintptr_t address);
+ PageFaultHandlerRangeType handleWrite(uintptr_t address);
+ bool haveBuffer(gl::BufferID id);
+
+ public:
+ std::mutex mMutex;
+ HashMap<GLuint, std::shared_ptr<CoherentBuffer>> mBuffers;
+
+ private:
+ bool mEnabled = false;
+ std::unique_ptr<PageFaultHandler> mPageFaultHandler;
+ size_t mPageSize;
+};
+
+// Shared class for any items that need to be tracked by FrameCapture across shared contexts
+class FrameCaptureShared final : angle::NonCopyable
+{
+ public:
+ FrameCaptureShared();
+ ~FrameCaptureShared();
+
+ void captureCall(const gl::Context *context, CallCapture &&call, bool isCallValid);
+ void checkForCaptureTrigger();
+ void onEndFrame(const gl::Context *context);
+ void onDestroyContext(const gl::Context *context);
+ void onMakeCurrent(const gl::Context *context, const egl::Surface *drawSurface);
+ bool enabled() const { return mEnabled; }
+
+ bool isCapturing() const;
+ void replay(gl::Context *context);
+ uint32_t getFrameCount() const;
+
+ // Returns a frame index starting from "1" as the first frame.
+ uint32_t getReplayFrameIndex() const;
+
+ void trackBufferMapping(const gl::Context *context,
+ CallCapture *call,
+ gl::BufferID id,
+ gl::Buffer *buffer,
+ GLintptr offset,
+ GLsizeiptr length,
+ bool writable,
+ bool coherent);
+
+ void trackTextureUpdate(const gl::Context *context, const CallCapture &call);
+ void trackDefaultUniformUpdate(const gl::Context *context, const CallCapture &call);
+ void trackVertexArrayUpdate(const gl::Context *context, const CallCapture &call);
+
+ const std::string &getShaderSource(gl::ShaderProgramID id) const;
+ void setShaderSource(gl::ShaderProgramID id, std::string sources);
+
+ const ProgramSources &getProgramSources(gl::ShaderProgramID id) const;
+ void setProgramSources(gl::ShaderProgramID id, ProgramSources sources);
+
+ // Load data from a previously stored texture level
+ const std::vector<uint8_t> &retrieveCachedTextureLevel(gl::TextureID id,
+ gl::TextureTarget target,
+ GLint level);
+
+ // Create new texture level data and copy the source into it
+ void copyCachedTextureLevel(const gl::Context *context,
+ gl::TextureID srcID,
+ GLint srcLevel,
+ gl::TextureID dstID,
+ GLint dstLevel,
+ const CallCapture &call);
+
+ // Create the location that should be used to cache texture level data
+ std::vector<uint8_t> &getCachedTextureLevelData(gl::Texture *texture,
+ gl::TextureTarget target,
+ GLint level,
+ EntryPoint entryPoint);
+
+ // Capture coherent buffer storages
+ void captureCoherentBufferSnapshot(const gl::Context *context, gl::BufferID bufferID);
+
+ // Remove any cached texture levels on deletion
+ void deleteCachedTextureLevelData(gl::TextureID id);
+
+ void eraseBufferDataMapEntry(const gl::BufferID bufferId)
+ {
+ const auto &bufferDataInfo = mBufferDataMap.find(bufferId);
+ if (bufferDataInfo != mBufferDataMap.end())
+ {
+ mBufferDataMap.erase(bufferDataInfo);
+ }
+ }
+
+ bool hasBufferData(gl::BufferID bufferID)
+ {
+ const auto &bufferDataInfo = mBufferDataMap.find(bufferID);
+ if (bufferDataInfo != mBufferDataMap.end())
+ {
+ return true;
+ }
+ return false;
+ }
+
+ std::pair<GLintptr, GLsizeiptr> getBufferDataOffsetAndLength(gl::BufferID bufferID)
+ {
+ const auto &bufferDataInfo = mBufferDataMap.find(bufferID);
+ ASSERT(bufferDataInfo != mBufferDataMap.end());
+ return bufferDataInfo->second;
+ }
+
+ void setCaptureActive() { mCaptureActive = true; }
+ void setCaptureInactive() { mCaptureActive = false; }
+ bool isCaptureActive() { return mCaptureActive; }
+ bool usesMidExecutionCapture() { return mCaptureStartFrame > 1; }
+
+ gl::ContextID getWindowSurfaceContextID() const { return mWindowSurfaceContextID; }
+
+ void markResourceSetupCallsInactive(std::vector<CallCapture> *setupCalls,
+ ResourceIDType type,
+ GLuint id,
+ gl::Range<size_t> range);
+
+ void updateReadBufferSize(size_t readBufferSize)
+ {
+ mReadBufferSize = std::max(mReadBufferSize, readBufferSize);
+ }
+
+ template <typename ResourceType>
+ void handleGennedResource(const gl::Context *context, ResourceType resourceID)
+ {
+ if (isCaptureActive())
+ {
+ ResourceIDType idType = GetResourceIDTypeFromType<ResourceType>::IDType;
+ TrackedResource &tracker = mResourceTracker.getTrackedResource(context->id(), idType);
+ tracker.setGennedResource(resourceID.value);
+ }
+ }
+
+ template <typename ResourceType>
+ bool resourceIsGenerated(const gl::Context *context, ResourceType resourceID)
+ {
+ ResourceIDType idType = GetResourceIDTypeFromType<ResourceType>::IDType;
+ TrackedResource &tracker = mResourceTracker.getTrackedResource(context->id(), idType);
+ return tracker.resourceIsGenerated(resourceID.value);
+ }
+
+ template <typename ResourceType>
+ void handleDeletedResource(const gl::Context *context, ResourceType resourceID)
+ {
+ if (isCaptureActive())
+ {
+ ResourceIDType idType = GetResourceIDTypeFromType<ResourceType>::IDType;
+ TrackedResource &tracker = mResourceTracker.getTrackedResource(context->id(), idType);
+ tracker.setDeletedResource(resourceID.value);
+ }
+ }
+
+ private:
+ void writeJSON(const gl::Context *context);
+ void writeCppReplayIndexFiles(const gl::Context *context, bool writeResetContextCall);
+ void writeMainContextCppReplay(const gl::Context *context,
+ const std::vector<CallCapture> &setupCalls,
+ StateResetHelper &StateResetHelper);
+
+ void captureClientArraySnapshot(const gl::Context *context,
+ size_t vertexCount,
+ size_t instanceCount);
+ void captureMappedBufferSnapshot(const gl::Context *context, const CallCapture &call);
+
+ void copyCompressedTextureData(const gl::Context *context, const CallCapture &call);
+ void captureCompressedTextureData(const gl::Context *context, const CallCapture &call);
+
+ void reset();
+ void maybeOverrideEntryPoint(const gl::Context *context,
+ CallCapture &call,
+ std::vector<CallCapture> &newCalls);
+ void maybeCapturePreCallUpdates(const gl::Context *context,
+ CallCapture &call,
+ std::vector<CallCapture> *shareGroupSetupCalls,
+ ResourceIDToSetupCallsMap *resourceIDToSetupCalls);
+ template <typename ParamValueType>
+ void maybeGenResourceOnBind(const gl::Context *context, CallCapture &call);
+ void maybeCapturePostCallUpdates(const gl::Context *context);
+ void maybeCaptureDrawArraysClientData(const gl::Context *context,
+ CallCapture &call,
+ size_t instanceCount);
+ void maybeCaptureDrawElementsClientData(const gl::Context *context,
+ CallCapture &call,
+ size_t instanceCount);
+ void maybeCaptureCoherentBuffers(const gl::Context *context);
+ void updateCopyImageSubData(CallCapture &call);
+ void overrideProgramBinary(const gl::Context *context,
+ CallCapture &call,
+ std::vector<CallCapture> &outCalls);
+ void updateResourceCountsFromParamCapture(const ParamCapture &param, ResourceIDType idType);
+ void updateResourceCountsFromCallCapture(const CallCapture &call);
+
+ void runMidExecutionCapture(const gl::Context *context);
+
+ void scanSetupCalls(const gl::Context *context, std::vector<CallCapture> &setupCalls);
+
+ static void ReplayCall(gl::Context *context,
+ ReplayContext *replayContext,
+ const CallCapture &call);
+
+ std::vector<CallCapture> mFrameCalls;
+ gl::ContextID mLastContextId;
+
+ // We save one large buffer of binary data for the whole CPP replay.
+ // This simplifies a lot of file management.
+ std::vector<uint8_t> mBinaryData;
+
+ bool mEnabled;
+ bool mSerializeStateEnabled;
+ std::string mOutDirectory;
+ std::string mCaptureLabel;
+ bool mCompression;
+ gl::AttribArray<int> mClientVertexArrayMap;
+ uint32_t mFrameIndex;
+ uint32_t mCaptureStartFrame;
+ uint32_t mCaptureEndFrame;
+ bool mIsFirstFrame = true;
+ bool mWroteIndexFile = false;
+ SurfaceParamsMap mDrawSurfaceParams;
+ gl::AttribArray<size_t> mClientArraySizes;
+ size_t mReadBufferSize;
+ HasResourceTypeMap mHasResourceType;
+ ResourceIDToSetupCallsMap mResourceIDToSetupCalls;
+ BufferDataMap mBufferDataMap;
+ bool mValidateSerializedState = false;
+ std::string mValidationExpression;
+ bool mTrimEnabled = true;
+ PackedEnumMap<ResourceIDType, uint32_t> mMaxAccessedResourceIDs;
+ CoherentBufferTracker mCoherentBufferTracker;
+
+ ResourceTracker mResourceTracker;
+ ReplayWriter mReplayWriter;
+
+ // If you don't know which frame you want to start capturing at, use the capture trigger.
+ // Initialize it to the number of frames you want to capture, and then clear the value to 0 when
+ // you reach the content you want to capture. Currently only available on Android.
+ uint32_t mCaptureTrigger;
+
+ bool mCaptureActive;
+ std::vector<uint32_t> mActiveFrameIndices;
+
+ // Cache most recently compiled and linked sources.
+ ShaderSourceMap mCachedShaderSource;
+ ProgramSourceMap mCachedProgramSources;
+
+ gl::ContextID mWindowSurfaceContextID;
+
+ std::vector<CallCapture> mShareGroupSetupCalls;
+};
+
+template <typename CaptureFuncT, typename... ArgsT>
+void CaptureCallToFrameCapture(CaptureFuncT captureFunc,
+ bool isCallValid,
+ gl::Context *context,
+ ArgsT... captureParams)
+{
+ FrameCaptureShared *frameCaptureShared = context->getShareGroup()->getFrameCaptureShared();
+ if (!frameCaptureShared->isCapturing())
+ {
+ return;
+ }
+
+ CallCapture call = captureFunc(context->getState(), isCallValid, captureParams...);
+
+ frameCaptureShared->captureCall(context, std::move(call), isCallValid);
+}
+
+template <typename T>
+void ParamBuffer::addValueParam(const char *paramName, ParamType paramType, T paramValue)
+{
+ ParamCapture capture(paramName, paramType);
+ InitParamValue(paramType, paramValue, &capture.value);
+ mParamCaptures.emplace_back(std::move(capture));
+}
+
+template <typename T>
+void ParamBuffer::setValueParamAtIndex(const char *paramName,
+ ParamType paramType,
+ T paramValue,
+ int index)
+{
+ ASSERT(mParamCaptures.size() > static_cast<size_t>(index));
+
+ ParamCapture capture(paramName, paramType);
+ InitParamValue(paramType, paramValue, &capture.value);
+ mParamCaptures[index] = std::move(capture);
+}
+
+template <typename T>
+void ParamBuffer::addEnumParam(const char *paramName,
+ gl::GLESEnum enumGroup,
+ ParamType paramType,
+ T paramValue)
+{
+ ParamCapture capture(paramName, paramType);
+ InitParamValue(paramType, paramValue, &capture.value);
+ capture.enumGroup = enumGroup;
+ mParamCaptures.emplace_back(std::move(capture));
+}
+
+template <typename T>
+void ParamBuffer::addEnumParam(const char *paramName,
+ gl::BigGLEnum enumGroup,
+ ParamType paramType,
+ T paramValue)
+{
+ ParamCapture capture(paramName, paramType);
+ InitParamValue(paramType, paramValue, &capture.value);
+ capture.bigGLEnum = enumGroup;
+ mParamCaptures.emplace_back(std::move(capture));
+}
+
+// Pointer capture helpers.
+void CaptureMemory(const void *source, size_t size, ParamCapture *paramCapture);
+void CaptureString(const GLchar *str, ParamCapture *paramCapture);
+void CaptureStringLimit(const GLchar *str, uint32_t limit, ParamCapture *paramCapture);
+void CaptureVertexPointerGLES1(const gl::State &glState,
+ gl::ClientVertexArrayType type,
+ const void *pointer,
+ ParamCapture *paramCapture);
+
+gl::Program *GetProgramForCapture(const gl::State &glState, gl::ShaderProgramID handle);
+
+// For GetIntegerv, GetFloatv, etc.
+void CaptureGetParameter(const gl::State &glState,
+ GLenum pname,
+ size_t typeSize,
+ ParamCapture *paramCapture);
+
+void CaptureGetActiveUniformBlockivParameters(const gl::State &glState,
+ gl::ShaderProgramID handle,
+ gl::UniformBlockIndex uniformBlockIndex,
+ GLenum pname,
+ ParamCapture *paramCapture);
+
+template <typename T>
+void CaptureClearBufferValue(GLenum buffer, const T *value, ParamCapture *paramCapture)
+{
+ // Per the spec, color buffers have a vec4, the rest a single value
+ uint32_t valueSize = (buffer == GL_COLOR) ? 4 : 1;
+ CaptureMemory(value, valueSize * sizeof(T), paramCapture);
+}
+
+void CaptureGenHandlesImpl(GLsizei n, GLuint *handles, ParamCapture *paramCapture);
+
+template <typename T>
+void CaptureGenHandles(GLsizei n, T *handles, ParamCapture *paramCapture)
+{
+ paramCapture->dataNElements = n;
+ CaptureGenHandlesImpl(n, reinterpret_cast<GLuint *>(handles), paramCapture);
+}
+
+template <typename T>
+void CaptureArray(T *elements, GLsizei n, ParamCapture *paramCapture)
+{
+ paramCapture->dataNElements = n;
+ CaptureMemory(elements, n * sizeof(T), paramCapture);
+}
+
+void CaptureShaderStrings(GLsizei count,
+ const GLchar *const *strings,
+ const GLint *length,
+ ParamCapture *paramCapture);
+
+template <ParamType ParamT, typename T>
+void WriteParamValueReplay(std::ostream &os, const CallCapture &call, T value);
+
+template <>
+void WriteParamValueReplay<ParamType::TGLboolean>(std::ostream &os,
+ const CallCapture &call,
+ GLboolean value);
+
+template <>
+void WriteParamValueReplay<ParamType::TGLbooleanPointer>(std::ostream &os,
+ const CallCapture &call,
+ GLboolean *value);
+
+template <>
+void WriteParamValueReplay<ParamType::TvoidConstPointer>(std::ostream &os,
+ const CallCapture &call,
+ const void *value);
+
+template <>
+void WriteParamValueReplay<ParamType::TvoidPointer>(std::ostream &os,
+ const CallCapture &call,
+ void *value);
+
+template <>
+void WriteParamValueReplay<ParamType::TGLfloatConstPointer>(std::ostream &os,
+ const CallCapture &call,
+ const GLfloat *value);
+
+template <>
+void WriteParamValueReplay<ParamType::TGLintConstPointer>(std::ostream &os,
+ const CallCapture &call,
+ const GLint *value);
+
+template <>
+void WriteParamValueReplay<ParamType::TGLsizeiPointer>(std::ostream &os,
+ const CallCapture &call,
+ GLsizei *value);
+
+template <>
+void WriteParamValueReplay<ParamType::TGLuintConstPointer>(std::ostream &os,
+ const CallCapture &call,
+ const GLuint *value);
+
+template <>
+void WriteParamValueReplay<ParamType::TGLDEBUGPROCKHR>(std::ostream &os,
+ const CallCapture &call,
+ GLDEBUGPROCKHR value);
+
+template <>
+void WriteParamValueReplay<ParamType::TGLDEBUGPROC>(std::ostream &os,
+ const CallCapture &call,
+ GLDEBUGPROC value);
+
+template <>
+void WriteParamValueReplay<ParamType::TBufferID>(std::ostream &os,
+ const CallCapture &call,
+ gl::BufferID value);
+
+template <>
+void WriteParamValueReplay<ParamType::TFenceNVID>(std::ostream &os,
+ const CallCapture &call,
+ gl::FenceNVID value);
+
+template <>
+void WriteParamValueReplay<ParamType::TFramebufferID>(std::ostream &os,
+ const CallCapture &call,
+ gl::FramebufferID value);
+
+template <>
+void WriteParamValueReplay<ParamType::TMemoryObjectID>(std::ostream &os,
+ const CallCapture &call,
+ gl::MemoryObjectID value);
+
+template <>
+void WriteParamValueReplay<ParamType::TProgramPipelineID>(std::ostream &os,
+ const CallCapture &call,
+ gl::ProgramPipelineID value);
+
+template <>
+void WriteParamValueReplay<ParamType::TQueryID>(std::ostream &os,
+ const CallCapture &call,
+ gl::QueryID value);
+
+template <>
+void WriteParamValueReplay<ParamType::TRenderbufferID>(std::ostream &os,
+ const CallCapture &call,
+ gl::RenderbufferID value);
+
+template <>
+void WriteParamValueReplay<ParamType::TSamplerID>(std::ostream &os,
+ const CallCapture &call,
+ gl::SamplerID value);
+
+template <>
+void WriteParamValueReplay<ParamType::TSemaphoreID>(std::ostream &os,
+ const CallCapture &call,
+ gl::SemaphoreID value);
+
+template <>
+void WriteParamValueReplay<ParamType::TShaderProgramID>(std::ostream &os,
+ const CallCapture &call,
+ gl::ShaderProgramID value);
+
+template <>
+void WriteParamValueReplay<ParamType::TTextureID>(std::ostream &os,
+ const CallCapture &call,
+ gl::TextureID value);
+
+template <>
+void WriteParamValueReplay<ParamType::TTransformFeedbackID>(std::ostream &os,
+ const CallCapture &call,
+ gl::TransformFeedbackID value);
+
+template <>
+void WriteParamValueReplay<ParamType::TVertexArrayID>(std::ostream &os,
+ const CallCapture &call,
+ gl::VertexArrayID value);
+
+template <>
+void WriteParamValueReplay<ParamType::TUniformLocation>(std::ostream &os,
+ const CallCapture &call,
+ gl::UniformLocation value);
+
+template <>
+void WriteParamValueReplay<ParamType::TUniformBlockIndex>(std::ostream &os,
+ const CallCapture &call,
+ gl::UniformBlockIndex value);
+
+template <>
+void WriteParamValueReplay<ParamType::TGLsync>(std::ostream &os,
+ const CallCapture &call,
+ GLsync value);
+
+template <>
+void WriteParamValueReplay<ParamType::TGLeglImageOES>(std::ostream &os,
+ const CallCapture &call,
+ GLeglImageOES value);
+
+template <>
+void WriteParamValueReplay<ParamType::TGLubyte>(std::ostream &os,
+ const CallCapture &call,
+ GLubyte value);
+
+template <>
+void WriteParamValueReplay<ParamType::TEGLContext>(std::ostream &os,
+ const CallCapture &call,
+ EGLContext value);
+
+template <>
+void WriteParamValueReplay<ParamType::TEGLDisplay>(std::ostream &os,
+ const CallCapture &call,
+ EGLContext value);
+
+template <>
+void WriteParamValueReplay<ParamType::TEGLSurface>(std::ostream &os,
+ const CallCapture &call,
+ EGLContext value);
+
+template <>
+void WriteParamValueReplay<ParamType::TEGLDEBUGPROCKHR>(std::ostream &os,
+ const CallCapture &call,
+ EGLDEBUGPROCKHR value);
+
+template <>
+void WriteParamValueReplay<ParamType::TEGLGetBlobFuncANDROID>(std::ostream &os,
+ const CallCapture &call,
+ EGLGetBlobFuncANDROID value);
+
+template <>
+void WriteParamValueReplay<ParamType::TEGLSetBlobFuncANDROID>(std::ostream &os,
+ const CallCapture &call,
+ EGLSetBlobFuncANDROID value);
+template <>
+void WriteParamValueReplay<ParamType::TEGLClientBuffer>(std::ostream &os,
+ const CallCapture &call,
+ EGLClientBuffer value);
+
+template <>
+void WriteParamValueReplay<ParamType::TEGLConfig>(std::ostream &os,
+ const CallCapture &call,
+ EGLConfig value);
+
+template <>
+void WriteParamValueReplay<ParamType::TEGLSurface>(std::ostream &os,
+ const CallCapture &call,
+ EGLSurface value);
+
+// General fallback for any unspecific type.
+template <ParamType ParamT, typename T>
+void WriteParamValueReplay(std::ostream &os, const CallCapture &call, T value)
+{
+ os << value;
+}
+} // namespace angle
+
+template <typename T>
+void CaptureTextureAndSamplerParameter_params(GLenum pname,
+ const T *param,
+ angle::ParamCapture *paramCapture)
+{
+ if (pname == GL_TEXTURE_BORDER_COLOR || pname == GL_TEXTURE_CROP_RECT_OES)
+ {
+ CaptureMemory(param, sizeof(T) * 4, paramCapture);
+ }
+ else
+ {
+ CaptureMemory(param, sizeof(T), paramCapture);
+ }
+}
+
+#endif // LIBANGLE_FRAME_CAPTURE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/capture/FrameCapture_mock.cpp b/gfx/angle/checkout/src/libANGLE/capture/FrameCapture_mock.cpp
new file mode 100644
index 0000000000..dc9e44c5bb
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/FrameCapture_mock.cpp
@@ -0,0 +1,55 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FrameCapture_mock.cpp:
+// ANGLE mock Frame capture implementation.
+//
+
+#include "libANGLE/capture/FrameCapture.h"
+
+#if ANGLE_CAPTURE_ENABLED
+# error Frame capture must be disabled to include this file.
+#endif // ANGLE_CAPTURE_ENABLED
+
+namespace angle
+{
+CallCapture::~CallCapture() {}
+ParamBuffer::~ParamBuffer() {}
+ParamCapture::~ParamCapture() {}
+ResourceTracker::ResourceTracker() {}
+ResourceTracker::~ResourceTracker() {}
+TrackedResource::TrackedResource() {}
+TrackedResource::~TrackedResource() {}
+StateResetHelper::StateResetHelper() {}
+StateResetHelper::~StateResetHelper() {}
+DataTracker::DataTracker() {}
+DataTracker::~DataTracker() {}
+DataCounters::DataCounters() {}
+DataCounters::~DataCounters() {}
+StringCounters::StringCounters() {}
+StringCounters::~StringCounters() {}
+ReplayWriter::ReplayWriter() {}
+ReplayWriter::~ReplayWriter() {}
+
+FrameCapture::FrameCapture() {}
+FrameCapture::~FrameCapture() {}
+
+FrameCaptureShared::FrameCaptureShared() : mEnabled(false) {}
+FrameCaptureShared::~FrameCaptureShared() {}
+void FrameCaptureShared::onEndFrame(const gl::Context *context) {}
+void FrameCaptureShared::onMakeCurrent(const gl::Context *context, const egl::Surface *drawSurface)
+{}
+void FrameCaptureShared::onDestroyContext(const gl::Context *context) {}
+void FrameCaptureShared::replay(gl::Context *context) {}
+const ProgramSources &FrameCaptureShared::getProgramSources(gl::ShaderProgramID id) const
+{
+ const auto &foundSources = mCachedProgramSources.find(id);
+ return foundSources->second;
+}
+void FrameCaptureShared::setProgramSources(gl::ShaderProgramID id, ProgramSources sources) {}
+
+CoherentBufferTracker::CoherentBufferTracker() {}
+CoherentBufferTracker::~CoherentBufferTracker() {}
+} // namespace angle
diff --git a/gfx/angle/checkout/src/libANGLE/capture/capture_egl.h b/gfx/angle/checkout/src/libANGLE/capture/capture_egl.h
new file mode 100644
index 0000000000..f23bc1a2ce
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/capture_egl.h
@@ -0,0 +1,69 @@
+//
+// Copyright 2022 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// capture_egl.h:
+// EGL capture functions
+//
+
+#ifndef LIBANGLE_CAPTURE_EGL_H_
+#define LIBANGLE_CAPTURE_EGL_H_
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Thread.h"
+#include "libANGLE/capture/FrameCapture.h"
+
+namespace gl
+{
+enum class GLenumGroup;
+}
+
+namespace egl
+{
+
+template <typename CaptureFuncT, typename... ArgsT>
+void CaptureCallToCaptureEGL(CaptureFuncT captureFunc, egl::Thread *thread, ArgsT... captureParams)
+{
+ gl::Context *context = thread->getContext();
+ if (!context)
+ {
+ return;
+ }
+
+ angle::FrameCaptureShared *frameCaptureShared =
+ context->getShareGroup()->getFrameCaptureShared();
+ if (!frameCaptureShared->isCapturing())
+ {
+ return;
+ }
+
+ angle::CallCapture call = captureFunc(captureParams...);
+
+ frameCaptureShared->captureCall(context, std::move(call), true);
+}
+
+angle::CallCapture CaptureCreateNativeClientBufferANDROID(const egl::AttributeMap &attribMap,
+ EGLClientBuffer eglClientBuffer);
+angle::CallCapture CaptureEGLCreateImage(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attributes,
+ egl::Image *image);
+angle::CallCapture CaptureEGLDestroyImage(egl::Display *display, egl::Image *image);
+
+angle::CallCapture CaptureEGLCreatePbufferSurface(const AttributeMap &attrib_list,
+ egl::Surface *surface);
+
+angle::CallCapture CaptureEGLDestroySurface(Display *display, Surface *surface);
+
+angle::CallCapture CaptureEGLBindTexImage(egl::Surface *surface, EGLint buffer);
+
+angle::CallCapture CaptureEGLReleaseTexImage(egl::Surface *surface, EGLint buffer);
+
+angle::CallCapture CaptureEGLMakeCurrent(Surface *drawSurface,
+ Surface *readSurface,
+ gl::Context *context);
+} // namespace egl
+
+#endif // LIBANGLE_FRAME_CAPTURE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/capture/capture_gl_1_autogen.h b/gfx/angle/checkout/src/libANGLE/capture/capture_gl_1_autogen.h
new file mode 100644
index 0000000000..7e4eea7af1
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/capture_gl_1_autogen.h
@@ -0,0 +1,2072 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// capture_gl_1_autogen.h:
+// Capture functions for the OpenGL ES Desktop GL 1.x entry points.
+
+#ifndef LIBANGLE_CAPTURE_GL_1_AUTOGEN_H_
+#define LIBANGLE_CAPTURE_GL_1_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "libANGLE/capture/FrameCapture.h"
+
+namespace gl
+{
+
+// Method Captures
+
+// GL 1.0
+angle::CallCapture CaptureAccum(const State &glState, bool isCallValid, GLenum op, GLfloat value);
+angle::CallCapture CaptureBegin(const State &glState, bool isCallValid, GLenum mode);
+angle::CallCapture CaptureBitmap(const State &glState,
+ bool isCallValid,
+ GLsizei width,
+ GLsizei height,
+ GLfloat xorig,
+ GLfloat yorig,
+ GLfloat xmove,
+ GLfloat ymove,
+ const GLubyte *bitmap);
+angle::CallCapture CaptureCallList(const State &glState, bool isCallValid, GLuint list);
+angle::CallCapture CaptureCallLists(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ GLenum type,
+ const void *lists);
+angle::CallCapture CaptureClearAccum(const State &glState,
+ bool isCallValid,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue,
+ GLfloat alpha);
+angle::CallCapture CaptureClearDepth(const State &glState, bool isCallValid, GLdouble depth);
+angle::CallCapture CaptureClearIndex(const State &glState, bool isCallValid, GLfloat c);
+angle::CallCapture CaptureClipPlane(const State &glState,
+ bool isCallValid,
+ GLenum plane,
+ const GLdouble *equation);
+angle::CallCapture CaptureColor3b(const State &glState,
+ bool isCallValid,
+ GLbyte red,
+ GLbyte green,
+ GLbyte blue);
+angle::CallCapture CaptureColor3bv(const State &glState, bool isCallValid, const GLbyte *v);
+angle::CallCapture CaptureColor3d(const State &glState,
+ bool isCallValid,
+ GLdouble red,
+ GLdouble green,
+ GLdouble blue);
+angle::CallCapture CaptureColor3dv(const State &glState, bool isCallValid, const GLdouble *v);
+angle::CallCapture CaptureColor3f(const State &glState,
+ bool isCallValid,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue);
+angle::CallCapture CaptureColor3fv(const State &glState, bool isCallValid, const GLfloat *v);
+angle::CallCapture CaptureColor3i(const State &glState,
+ bool isCallValid,
+ GLint red,
+ GLint green,
+ GLint blue);
+angle::CallCapture CaptureColor3iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureColor3s(const State &glState,
+ bool isCallValid,
+ GLshort red,
+ GLshort green,
+ GLshort blue);
+angle::CallCapture CaptureColor3sv(const State &glState, bool isCallValid, const GLshort *v);
+angle::CallCapture CaptureColor3ub(const State &glState,
+ bool isCallValid,
+ GLubyte red,
+ GLubyte green,
+ GLubyte blue);
+angle::CallCapture CaptureColor3ubv(const State &glState, bool isCallValid, const GLubyte *v);
+angle::CallCapture CaptureColor3ui(const State &glState,
+ bool isCallValid,
+ GLuint red,
+ GLuint green,
+ GLuint blue);
+angle::CallCapture CaptureColor3uiv(const State &glState, bool isCallValid, const GLuint *v);
+angle::CallCapture CaptureColor3us(const State &glState,
+ bool isCallValid,
+ GLushort red,
+ GLushort green,
+ GLushort blue);
+angle::CallCapture CaptureColor3usv(const State &glState, bool isCallValid, const GLushort *v);
+angle::CallCapture CaptureColor4b(const State &glState,
+ bool isCallValid,
+ GLbyte red,
+ GLbyte green,
+ GLbyte blue,
+ GLbyte alpha);
+angle::CallCapture CaptureColor4bv(const State &glState, bool isCallValid, const GLbyte *v);
+angle::CallCapture CaptureColor4d(const State &glState,
+ bool isCallValid,
+ GLdouble red,
+ GLdouble green,
+ GLdouble blue,
+ GLdouble alpha);
+angle::CallCapture CaptureColor4dv(const State &glState, bool isCallValid, const GLdouble *v);
+angle::CallCapture CaptureColor4fv(const State &glState, bool isCallValid, const GLfloat *v);
+angle::CallCapture CaptureColor4i(const State &glState,
+ bool isCallValid,
+ GLint red,
+ GLint green,
+ GLint blue,
+ GLint alpha);
+angle::CallCapture CaptureColor4iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureColor4s(const State &glState,
+ bool isCallValid,
+ GLshort red,
+ GLshort green,
+ GLshort blue,
+ GLshort alpha);
+angle::CallCapture CaptureColor4sv(const State &glState, bool isCallValid, const GLshort *v);
+angle::CallCapture CaptureColor4ubv(const State &glState, bool isCallValid, const GLubyte *v);
+angle::CallCapture CaptureColor4ui(const State &glState,
+ bool isCallValid,
+ GLuint red,
+ GLuint green,
+ GLuint blue,
+ GLuint alpha);
+angle::CallCapture CaptureColor4uiv(const State &glState, bool isCallValid, const GLuint *v);
+angle::CallCapture CaptureColor4us(const State &glState,
+ bool isCallValid,
+ GLushort red,
+ GLushort green,
+ GLushort blue,
+ GLushort alpha);
+angle::CallCapture CaptureColor4usv(const State &glState, bool isCallValid, const GLushort *v);
+angle::CallCapture CaptureColorMaterial(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ GLenum mode);
+angle::CallCapture CaptureCopyPixels(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum type);
+angle::CallCapture CaptureDeleteLists(const State &glState,
+ bool isCallValid,
+ GLuint list,
+ GLsizei range);
+angle::CallCapture CaptureDepthRange(const State &glState,
+ bool isCallValid,
+ GLdouble n,
+ GLdouble f);
+angle::CallCapture CaptureDrawBuffer(const State &glState, bool isCallValid, GLenum buf);
+angle::CallCapture CaptureDrawPixels(const State &glState,
+ bool isCallValid,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+angle::CallCapture CaptureEdgeFlag(const State &glState, bool isCallValid, GLboolean flag);
+angle::CallCapture CaptureEdgeFlagv(const State &glState, bool isCallValid, const GLboolean *flag);
+angle::CallCapture CaptureEnd(const State &glState, bool isCallValid);
+angle::CallCapture CaptureEndList(const State &glState, bool isCallValid);
+angle::CallCapture CaptureEvalCoord1d(const State &glState, bool isCallValid, GLdouble u);
+angle::CallCapture CaptureEvalCoord1dv(const State &glState, bool isCallValid, const GLdouble *u);
+angle::CallCapture CaptureEvalCoord1f(const State &glState, bool isCallValid, GLfloat u);
+angle::CallCapture CaptureEvalCoord1fv(const State &glState, bool isCallValid, const GLfloat *u);
+angle::CallCapture CaptureEvalCoord2d(const State &glState,
+ bool isCallValid,
+ GLdouble u,
+ GLdouble v);
+angle::CallCapture CaptureEvalCoord2dv(const State &glState, bool isCallValid, const GLdouble *u);
+angle::CallCapture CaptureEvalCoord2f(const State &glState, bool isCallValid, GLfloat u, GLfloat v);
+angle::CallCapture CaptureEvalCoord2fv(const State &glState, bool isCallValid, const GLfloat *u);
+angle::CallCapture CaptureEvalMesh1(const State &glState,
+ bool isCallValid,
+ GLenum mode,
+ GLint i1,
+ GLint i2);
+angle::CallCapture CaptureEvalMesh2(const State &glState,
+ bool isCallValid,
+ GLenum mode,
+ GLint i1,
+ GLint i2,
+ GLint j1,
+ GLint j2);
+angle::CallCapture CaptureEvalPoint1(const State &glState, bool isCallValid, GLint i);
+angle::CallCapture CaptureEvalPoint2(const State &glState, bool isCallValid, GLint i, GLint j);
+angle::CallCapture CaptureFeedbackBuffer(const State &glState,
+ bool isCallValid,
+ GLsizei size,
+ GLenum type,
+ GLfloat *buffer);
+angle::CallCapture CaptureFogi(const State &glState, bool isCallValid, GLenum pname, GLint param);
+angle::CallCapture CaptureFogiv(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLint *params);
+angle::CallCapture CaptureFrustum(const State &glState,
+ bool isCallValid,
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble zNear,
+ GLdouble zFar);
+angle::CallCapture CaptureGenLists(const State &glState,
+ bool isCallValid,
+ GLsizei range,
+ GLuint returnValue);
+angle::CallCapture CaptureGetClipPlane(const State &glState,
+ bool isCallValid,
+ GLenum plane,
+ GLdouble *equation);
+angle::CallCapture CaptureGetDoublev(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLdouble *data);
+angle::CallCapture CaptureGetLightiv(const State &glState,
+ bool isCallValid,
+ GLenum light,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetMapdv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum query,
+ GLdouble *v);
+angle::CallCapture CaptureGetMapfv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum query,
+ GLfloat *v);
+angle::CallCapture CaptureGetMapiv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum query,
+ GLint *v);
+angle::CallCapture CaptureGetMaterialiv(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetPixelMapfv(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLfloat *values);
+angle::CallCapture CaptureGetPixelMapuiv(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLuint *values);
+angle::CallCapture CaptureGetPixelMapusv(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLushort *values);
+angle::CallCapture CaptureGetPolygonStipple(const State &glState, bool isCallValid, GLubyte *mask);
+angle::CallCapture CaptureGetTexGendv(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLdouble *params);
+angle::CallCapture CaptureGetTexGenfv(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLfloat *params);
+angle::CallCapture CaptureGetTexGeniv(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetTexImage(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ void *pixels);
+angle::CallCapture CaptureIndexMask(const State &glState, bool isCallValid, GLuint mask);
+angle::CallCapture CaptureIndexd(const State &glState, bool isCallValid, GLdouble c);
+angle::CallCapture CaptureIndexdv(const State &glState, bool isCallValid, const GLdouble *c);
+angle::CallCapture CaptureIndexf(const State &glState, bool isCallValid, GLfloat c);
+angle::CallCapture CaptureIndexfv(const State &glState, bool isCallValid, const GLfloat *c);
+angle::CallCapture CaptureIndexi(const State &glState, bool isCallValid, GLint c);
+angle::CallCapture CaptureIndexiv(const State &glState, bool isCallValid, const GLint *c);
+angle::CallCapture CaptureIndexs(const State &glState, bool isCallValid, GLshort c);
+angle::CallCapture CaptureIndexsv(const State &glState, bool isCallValid, const GLshort *c);
+angle::CallCapture CaptureInitNames(const State &glState, bool isCallValid);
+angle::CallCapture CaptureIsList(const State &glState,
+ bool isCallValid,
+ GLuint list,
+ GLboolean returnValue);
+angle::CallCapture CaptureLightModeli(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLint param);
+angle::CallCapture CaptureLightModeliv(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLint *params);
+angle::CallCapture CaptureLighti(const State &glState,
+ bool isCallValid,
+ GLenum light,
+ GLenum pname,
+ GLint param);
+angle::CallCapture CaptureLightiv(const State &glState,
+ bool isCallValid,
+ GLenum light,
+ GLenum pname,
+ const GLint *params);
+angle::CallCapture CaptureLineStipple(const State &glState,
+ bool isCallValid,
+ GLint factor,
+ GLushort pattern);
+angle::CallCapture CaptureListBase(const State &glState, bool isCallValid, GLuint base);
+angle::CallCapture CaptureLoadMatrixd(const State &glState, bool isCallValid, const GLdouble *m);
+angle::CallCapture CaptureLoadName(const State &glState, bool isCallValid, GLuint name);
+angle::CallCapture CaptureMap1d(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLdouble u1,
+ GLdouble u2,
+ GLint stride,
+ GLint order,
+ const GLdouble *points);
+angle::CallCapture CaptureMap1f(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLfloat u1,
+ GLfloat u2,
+ GLint stride,
+ GLint order,
+ const GLfloat *points);
+angle::CallCapture CaptureMap2d(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLdouble u1,
+ GLdouble u2,
+ GLint ustride,
+ GLint uorder,
+ GLdouble v1,
+ GLdouble v2,
+ GLint vstride,
+ GLint vorder,
+ const GLdouble *points);
+angle::CallCapture CaptureMap2f(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLfloat u1,
+ GLfloat u2,
+ GLint ustride,
+ GLint uorder,
+ GLfloat v1,
+ GLfloat v2,
+ GLint vstride,
+ GLint vorder,
+ const GLfloat *points);
+angle::CallCapture CaptureMapGrid1d(const State &glState,
+ bool isCallValid,
+ GLint un,
+ GLdouble u1,
+ GLdouble u2);
+angle::CallCapture CaptureMapGrid1f(const State &glState,
+ bool isCallValid,
+ GLint un,
+ GLfloat u1,
+ GLfloat u2);
+angle::CallCapture CaptureMapGrid2d(const State &glState,
+ bool isCallValid,
+ GLint un,
+ GLdouble u1,
+ GLdouble u2,
+ GLint vn,
+ GLdouble v1,
+ GLdouble v2);
+angle::CallCapture CaptureMapGrid2f(const State &glState,
+ bool isCallValid,
+ GLint un,
+ GLfloat u1,
+ GLfloat u2,
+ GLint vn,
+ GLfloat v1,
+ GLfloat v2);
+angle::CallCapture CaptureMateriali(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ GLenum pname,
+ GLint param);
+angle::CallCapture CaptureMaterialiv(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ GLenum pname,
+ const GLint *params);
+angle::CallCapture CaptureMultMatrixd(const State &glState, bool isCallValid, const GLdouble *m);
+angle::CallCapture CaptureNewList(const State &glState, bool isCallValid, GLuint list, GLenum mode);
+angle::CallCapture CaptureNormal3b(const State &glState,
+ bool isCallValid,
+ GLbyte nx,
+ GLbyte ny,
+ GLbyte nz);
+angle::CallCapture CaptureNormal3bv(const State &glState, bool isCallValid, const GLbyte *v);
+angle::CallCapture CaptureNormal3d(const State &glState,
+ bool isCallValid,
+ GLdouble nx,
+ GLdouble ny,
+ GLdouble nz);
+angle::CallCapture CaptureNormal3dv(const State &glState, bool isCallValid, const GLdouble *v);
+angle::CallCapture CaptureNormal3fv(const State &glState, bool isCallValid, const GLfloat *v);
+angle::CallCapture CaptureNormal3i(const State &glState,
+ bool isCallValid,
+ GLint nx,
+ GLint ny,
+ GLint nz);
+angle::CallCapture CaptureNormal3iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureNormal3s(const State &glState,
+ bool isCallValid,
+ GLshort nx,
+ GLshort ny,
+ GLshort nz);
+angle::CallCapture CaptureNormal3sv(const State &glState, bool isCallValid, const GLshort *v);
+angle::CallCapture CaptureOrtho(const State &glState,
+ bool isCallValid,
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble zNear,
+ GLdouble zFar);
+angle::CallCapture CapturePassThrough(const State &glState, bool isCallValid, GLfloat token);
+angle::CallCapture CapturePixelMapfv(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLsizei mapsize,
+ const GLfloat *values);
+angle::CallCapture CapturePixelMapuiv(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLsizei mapsize,
+ const GLuint *values);
+angle::CallCapture CapturePixelMapusv(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLsizei mapsize,
+ const GLushort *values);
+angle::CallCapture CapturePixelStoref(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLfloat param);
+angle::CallCapture CapturePixelTransferf(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLfloat param);
+angle::CallCapture CapturePixelTransferi(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLint param);
+angle::CallCapture CapturePixelZoom(const State &glState,
+ bool isCallValid,
+ GLfloat xfactor,
+ GLfloat yfactor);
+angle::CallCapture CapturePolygonMode(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ GLenum mode);
+angle::CallCapture CapturePolygonStipple(const State &glState,
+ bool isCallValid,
+ const GLubyte *mask);
+angle::CallCapture CapturePopAttrib(const State &glState, bool isCallValid);
+angle::CallCapture CapturePopName(const State &glState, bool isCallValid);
+angle::CallCapture CapturePushAttrib(const State &glState, bool isCallValid, GLbitfield mask);
+angle::CallCapture CapturePushName(const State &glState, bool isCallValid, GLuint name);
+angle::CallCapture CaptureRasterPos2d(const State &glState,
+ bool isCallValid,
+ GLdouble x,
+ GLdouble y);
+angle::CallCapture CaptureRasterPos2dv(const State &glState, bool isCallValid, const GLdouble *v);
+angle::CallCapture CaptureRasterPos2f(const State &glState, bool isCallValid, GLfloat x, GLfloat y);
+angle::CallCapture CaptureRasterPos2fv(const State &glState, bool isCallValid, const GLfloat *v);
+angle::CallCapture CaptureRasterPos2i(const State &glState, bool isCallValid, GLint x, GLint y);
+angle::CallCapture CaptureRasterPos2iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureRasterPos2s(const State &glState, bool isCallValid, GLshort x, GLshort y);
+angle::CallCapture CaptureRasterPos2sv(const State &glState, bool isCallValid, const GLshort *v);
+angle::CallCapture CaptureRasterPos3d(const State &glState,
+ bool isCallValid,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+angle::CallCapture CaptureRasterPos3dv(const State &glState, bool isCallValid, const GLdouble *v);
+angle::CallCapture CaptureRasterPos3f(const State &glState,
+ bool isCallValid,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z);
+angle::CallCapture CaptureRasterPos3fv(const State &glState, bool isCallValid, const GLfloat *v);
+angle::CallCapture CaptureRasterPos3i(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLint z);
+angle::CallCapture CaptureRasterPos3iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureRasterPos3s(const State &glState,
+ bool isCallValid,
+ GLshort x,
+ GLshort y,
+ GLshort z);
+angle::CallCapture CaptureRasterPos3sv(const State &glState, bool isCallValid, const GLshort *v);
+angle::CallCapture CaptureRasterPos4d(const State &glState,
+ bool isCallValid,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z,
+ GLdouble w);
+angle::CallCapture CaptureRasterPos4dv(const State &glState, bool isCallValid, const GLdouble *v);
+angle::CallCapture CaptureRasterPos4f(const State &glState,
+ bool isCallValid,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w);
+angle::CallCapture CaptureRasterPos4fv(const State &glState, bool isCallValid, const GLfloat *v);
+angle::CallCapture CaptureRasterPos4i(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint w);
+angle::CallCapture CaptureRasterPos4iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureRasterPos4s(const State &glState,
+ bool isCallValid,
+ GLshort x,
+ GLshort y,
+ GLshort z,
+ GLshort w);
+angle::CallCapture CaptureRasterPos4sv(const State &glState, bool isCallValid, const GLshort *v);
+angle::CallCapture CaptureRectd(const State &glState,
+ bool isCallValid,
+ GLdouble x1,
+ GLdouble y1,
+ GLdouble x2,
+ GLdouble y2);
+angle::CallCapture CaptureRectdv(const State &glState,
+ bool isCallValid,
+ const GLdouble *v1,
+ const GLdouble *v2);
+angle::CallCapture CaptureRectf(const State &glState,
+ bool isCallValid,
+ GLfloat x1,
+ GLfloat y1,
+ GLfloat x2,
+ GLfloat y2);
+angle::CallCapture CaptureRectfv(const State &glState,
+ bool isCallValid,
+ const GLfloat *v1,
+ const GLfloat *v2);
+angle::CallCapture CaptureRecti(const State &glState,
+ bool isCallValid,
+ GLint x1,
+ GLint y1,
+ GLint x2,
+ GLint y2);
+angle::CallCapture CaptureRectiv(const State &glState,
+ bool isCallValid,
+ const GLint *v1,
+ const GLint *v2);
+angle::CallCapture CaptureRects(const State &glState,
+ bool isCallValid,
+ GLshort x1,
+ GLshort y1,
+ GLshort x2,
+ GLshort y2);
+angle::CallCapture CaptureRectsv(const State &glState,
+ bool isCallValid,
+ const GLshort *v1,
+ const GLshort *v2);
+angle::CallCapture CaptureRenderMode(const State &glState,
+ bool isCallValid,
+ GLenum mode,
+ GLint returnValue);
+angle::CallCapture CaptureRotated(const State &glState,
+ bool isCallValid,
+ GLdouble angle,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+angle::CallCapture CaptureScaled(const State &glState,
+ bool isCallValid,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+angle::CallCapture CaptureSelectBuffer(const State &glState,
+ bool isCallValid,
+ GLsizei size,
+ GLuint *buffer);
+angle::CallCapture CaptureTexCoord1d(const State &glState, bool isCallValid, GLdouble s);
+angle::CallCapture CaptureTexCoord1dv(const State &glState, bool isCallValid, const GLdouble *v);
+angle::CallCapture CaptureTexCoord1f(const State &glState, bool isCallValid, GLfloat s);
+angle::CallCapture CaptureTexCoord1fv(const State &glState, bool isCallValid, const GLfloat *v);
+angle::CallCapture CaptureTexCoord1i(const State &glState, bool isCallValid, GLint s);
+angle::CallCapture CaptureTexCoord1iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureTexCoord1s(const State &glState, bool isCallValid, GLshort s);
+angle::CallCapture CaptureTexCoord1sv(const State &glState, bool isCallValid, const GLshort *v);
+angle::CallCapture CaptureTexCoord2d(const State &glState,
+ bool isCallValid,
+ GLdouble s,
+ GLdouble t);
+angle::CallCapture CaptureTexCoord2dv(const State &glState, bool isCallValid, const GLdouble *v);
+angle::CallCapture CaptureTexCoord2f(const State &glState, bool isCallValid, GLfloat s, GLfloat t);
+angle::CallCapture CaptureTexCoord2fv(const State &glState, bool isCallValid, const GLfloat *v);
+angle::CallCapture CaptureTexCoord2i(const State &glState, bool isCallValid, GLint s, GLint t);
+angle::CallCapture CaptureTexCoord2iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureTexCoord2s(const State &glState, bool isCallValid, GLshort s, GLshort t);
+angle::CallCapture CaptureTexCoord2sv(const State &glState, bool isCallValid, const GLshort *v);
+angle::CallCapture CaptureTexCoord3d(const State &glState,
+ bool isCallValid,
+ GLdouble s,
+ GLdouble t,
+ GLdouble r);
+angle::CallCapture CaptureTexCoord3dv(const State &glState, bool isCallValid, const GLdouble *v);
+angle::CallCapture CaptureTexCoord3f(const State &glState,
+ bool isCallValid,
+ GLfloat s,
+ GLfloat t,
+ GLfloat r);
+angle::CallCapture CaptureTexCoord3fv(const State &glState, bool isCallValid, const GLfloat *v);
+angle::CallCapture CaptureTexCoord3i(const State &glState,
+ bool isCallValid,
+ GLint s,
+ GLint t,
+ GLint r);
+angle::CallCapture CaptureTexCoord3iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureTexCoord3s(const State &glState,
+ bool isCallValid,
+ GLshort s,
+ GLshort t,
+ GLshort r);
+angle::CallCapture CaptureTexCoord3sv(const State &glState, bool isCallValid, const GLshort *v);
+angle::CallCapture CaptureTexCoord4d(const State &glState,
+ bool isCallValid,
+ GLdouble s,
+ GLdouble t,
+ GLdouble r,
+ GLdouble q);
+angle::CallCapture CaptureTexCoord4dv(const State &glState, bool isCallValid, const GLdouble *v);
+angle::CallCapture CaptureTexCoord4f(const State &glState,
+ bool isCallValid,
+ GLfloat s,
+ GLfloat t,
+ GLfloat r,
+ GLfloat q);
+angle::CallCapture CaptureTexCoord4fv(const State &glState, bool isCallValid, const GLfloat *v);
+angle::CallCapture CaptureTexCoord4i(const State &glState,
+ bool isCallValid,
+ GLint s,
+ GLint t,
+ GLint r,
+ GLint q);
+angle::CallCapture CaptureTexCoord4iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureTexCoord4s(const State &glState,
+ bool isCallValid,
+ GLshort s,
+ GLshort t,
+ GLshort r,
+ GLshort q);
+angle::CallCapture CaptureTexCoord4sv(const State &glState, bool isCallValid, const GLshort *v);
+angle::CallCapture CaptureTexGend(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLdouble param);
+angle::CallCapture CaptureTexGendv(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ const GLdouble *params);
+angle::CallCapture CaptureTexGenf(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLfloat param);
+angle::CallCapture CaptureTexGenfv(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ const GLfloat *params);
+angle::CallCapture CaptureTexGeni(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLint param);
+angle::CallCapture CaptureTexGeniv(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ const GLint *params);
+angle::CallCapture CaptureTexImage1D(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+angle::CallCapture CaptureTranslated(const State &glState,
+ bool isCallValid,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+angle::CallCapture CaptureVertex2d(const State &glState, bool isCallValid, GLdouble x, GLdouble y);
+angle::CallCapture CaptureVertex2dv(const State &glState, bool isCallValid, const GLdouble *v);
+angle::CallCapture CaptureVertex2f(const State &glState, bool isCallValid, GLfloat x, GLfloat y);
+angle::CallCapture CaptureVertex2fv(const State &glState, bool isCallValid, const GLfloat *v);
+angle::CallCapture CaptureVertex2i(const State &glState, bool isCallValid, GLint x, GLint y);
+angle::CallCapture CaptureVertex2iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureVertex2s(const State &glState, bool isCallValid, GLshort x, GLshort y);
+angle::CallCapture CaptureVertex2sv(const State &glState, bool isCallValid, const GLshort *v);
+angle::CallCapture CaptureVertex3d(const State &glState,
+ bool isCallValid,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+angle::CallCapture CaptureVertex3dv(const State &glState, bool isCallValid, const GLdouble *v);
+angle::CallCapture CaptureVertex3f(const State &glState,
+ bool isCallValid,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z);
+angle::CallCapture CaptureVertex3fv(const State &glState, bool isCallValid, const GLfloat *v);
+angle::CallCapture CaptureVertex3i(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLint z);
+angle::CallCapture CaptureVertex3iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureVertex3s(const State &glState,
+ bool isCallValid,
+ GLshort x,
+ GLshort y,
+ GLshort z);
+angle::CallCapture CaptureVertex3sv(const State &glState, bool isCallValid, const GLshort *v);
+angle::CallCapture CaptureVertex4d(const State &glState,
+ bool isCallValid,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z,
+ GLdouble w);
+angle::CallCapture CaptureVertex4dv(const State &glState, bool isCallValid, const GLdouble *v);
+angle::CallCapture CaptureVertex4f(const State &glState,
+ bool isCallValid,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w);
+angle::CallCapture CaptureVertex4fv(const State &glState, bool isCallValid, const GLfloat *v);
+angle::CallCapture CaptureVertex4i(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint w);
+angle::CallCapture CaptureVertex4iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureVertex4s(const State &glState,
+ bool isCallValid,
+ GLshort x,
+ GLshort y,
+ GLshort z,
+ GLshort w);
+angle::CallCapture CaptureVertex4sv(const State &glState, bool isCallValid, const GLshort *v);
+
+// GL 1.1
+angle::CallCapture CaptureAreTexturesResident(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const GLuint *textures,
+ GLboolean *residences,
+ GLboolean returnValue);
+angle::CallCapture CaptureArrayElement(const State &glState, bool isCallValid, GLint i);
+angle::CallCapture CaptureCopyTexImage1D(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLint border);
+angle::CallCapture CaptureCopyTexSubImage1D(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint x,
+ GLint y,
+ GLsizei width);
+angle::CallCapture CaptureEdgeFlagPointer(const State &glState,
+ bool isCallValid,
+ GLsizei stride,
+ const void *pointer);
+angle::CallCapture CaptureIndexPointer(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer);
+angle::CallCapture CaptureIndexub(const State &glState, bool isCallValid, GLubyte c);
+angle::CallCapture CaptureIndexubv(const State &glState, bool isCallValid, const GLubyte *c);
+angle::CallCapture CaptureInterleavedArrays(const State &glState,
+ bool isCallValid,
+ GLenum format,
+ GLsizei stride,
+ const void *pointer);
+angle::CallCapture CapturePopClientAttrib(const State &glState, bool isCallValid);
+angle::CallCapture CapturePrioritizeTextures(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const GLuint *textures,
+ const GLfloat *priorities);
+angle::CallCapture CapturePushClientAttrib(const State &glState, bool isCallValid, GLbitfield mask);
+angle::CallCapture CaptureTexSubImage1D(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+
+// GL 1.2
+
+// GL 1.3
+angle::CallCapture CaptureCompressedTexImage1D(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLint border,
+ GLsizei imageSize,
+ const void *data);
+angle::CallCapture CaptureCompressedTexSubImage1D(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+angle::CallCapture CaptureGetCompressedTexImage(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ void *img);
+angle::CallCapture CaptureLoadTransposeMatrixd(const State &glState,
+ bool isCallValid,
+ const GLdouble *m);
+angle::CallCapture CaptureLoadTransposeMatrixf(const State &glState,
+ bool isCallValid,
+ const GLfloat *m);
+angle::CallCapture CaptureMultTransposeMatrixd(const State &glState,
+ bool isCallValid,
+ const GLdouble *m);
+angle::CallCapture CaptureMultTransposeMatrixf(const State &glState,
+ bool isCallValid,
+ const GLfloat *m);
+angle::CallCapture CaptureMultiTexCoord1d(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLdouble s);
+angle::CallCapture CaptureMultiTexCoord1dv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLdouble *v);
+angle::CallCapture CaptureMultiTexCoord1f(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLfloat s);
+angle::CallCapture CaptureMultiTexCoord1fv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLfloat *v);
+angle::CallCapture CaptureMultiTexCoord1i(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint s);
+angle::CallCapture CaptureMultiTexCoord1iv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLint *v);
+angle::CallCapture CaptureMultiTexCoord1s(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLshort s);
+angle::CallCapture CaptureMultiTexCoord1sv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLshort *v);
+angle::CallCapture CaptureMultiTexCoord2d(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLdouble s,
+ GLdouble t);
+angle::CallCapture CaptureMultiTexCoord2dv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLdouble *v);
+angle::CallCapture CaptureMultiTexCoord2f(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLfloat s,
+ GLfloat t);
+angle::CallCapture CaptureMultiTexCoord2fv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLfloat *v);
+angle::CallCapture CaptureMultiTexCoord2i(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint s,
+ GLint t);
+angle::CallCapture CaptureMultiTexCoord2iv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLint *v);
+angle::CallCapture CaptureMultiTexCoord2s(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLshort s,
+ GLshort t);
+angle::CallCapture CaptureMultiTexCoord2sv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLshort *v);
+angle::CallCapture CaptureMultiTexCoord3d(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLdouble s,
+ GLdouble t,
+ GLdouble r);
+angle::CallCapture CaptureMultiTexCoord3dv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLdouble *v);
+angle::CallCapture CaptureMultiTexCoord3f(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLfloat s,
+ GLfloat t,
+ GLfloat r);
+angle::CallCapture CaptureMultiTexCoord3fv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLfloat *v);
+angle::CallCapture CaptureMultiTexCoord3i(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint s,
+ GLint t,
+ GLint r);
+angle::CallCapture CaptureMultiTexCoord3iv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLint *v);
+angle::CallCapture CaptureMultiTexCoord3s(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLshort s,
+ GLshort t,
+ GLshort r);
+angle::CallCapture CaptureMultiTexCoord3sv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLshort *v);
+angle::CallCapture CaptureMultiTexCoord4d(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLdouble s,
+ GLdouble t,
+ GLdouble r,
+ GLdouble q);
+angle::CallCapture CaptureMultiTexCoord4dv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLdouble *v);
+angle::CallCapture CaptureMultiTexCoord4fv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLfloat *v);
+angle::CallCapture CaptureMultiTexCoord4i(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint s,
+ GLint t,
+ GLint r,
+ GLint q);
+angle::CallCapture CaptureMultiTexCoord4iv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLint *v);
+angle::CallCapture CaptureMultiTexCoord4s(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLshort s,
+ GLshort t,
+ GLshort r,
+ GLshort q);
+angle::CallCapture CaptureMultiTexCoord4sv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLshort *v);
+
+// GL 1.4
+angle::CallCapture CaptureFogCoordPointer(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer);
+angle::CallCapture CaptureFogCoordd(const State &glState, bool isCallValid, GLdouble coord);
+angle::CallCapture CaptureFogCoorddv(const State &glState, bool isCallValid, const GLdouble *coord);
+angle::CallCapture CaptureFogCoordf(const State &glState, bool isCallValid, GLfloat coord);
+angle::CallCapture CaptureFogCoordfv(const State &glState, bool isCallValid, const GLfloat *coord);
+angle::CallCapture CaptureMultiDrawArrays(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLint *first,
+ const GLsizei *count,
+ GLsizei drawcount);
+angle::CallCapture CaptureMultiDrawElements(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *count,
+ DrawElementsType typePacked,
+ const void *const *indices,
+ GLsizei drawcount);
+angle::CallCapture CapturePointParameteri(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLint param);
+angle::CallCapture CapturePointParameteriv(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLint *params);
+angle::CallCapture CaptureSecondaryColor3b(const State &glState,
+ bool isCallValid,
+ GLbyte red,
+ GLbyte green,
+ GLbyte blue);
+angle::CallCapture CaptureSecondaryColor3bv(const State &glState,
+ bool isCallValid,
+ const GLbyte *v);
+angle::CallCapture CaptureSecondaryColor3d(const State &glState,
+ bool isCallValid,
+ GLdouble red,
+ GLdouble green,
+ GLdouble blue);
+angle::CallCapture CaptureSecondaryColor3dv(const State &glState,
+ bool isCallValid,
+ const GLdouble *v);
+angle::CallCapture CaptureSecondaryColor3f(const State &glState,
+ bool isCallValid,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue);
+angle::CallCapture CaptureSecondaryColor3fv(const State &glState,
+ bool isCallValid,
+ const GLfloat *v);
+angle::CallCapture CaptureSecondaryColor3i(const State &glState,
+ bool isCallValid,
+ GLint red,
+ GLint green,
+ GLint blue);
+angle::CallCapture CaptureSecondaryColor3iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureSecondaryColor3s(const State &glState,
+ bool isCallValid,
+ GLshort red,
+ GLshort green,
+ GLshort blue);
+angle::CallCapture CaptureSecondaryColor3sv(const State &glState,
+ bool isCallValid,
+ const GLshort *v);
+angle::CallCapture CaptureSecondaryColor3ub(const State &glState,
+ bool isCallValid,
+ GLubyte red,
+ GLubyte green,
+ GLubyte blue);
+angle::CallCapture CaptureSecondaryColor3ubv(const State &glState,
+ bool isCallValid,
+ const GLubyte *v);
+angle::CallCapture CaptureSecondaryColor3ui(const State &glState,
+ bool isCallValid,
+ GLuint red,
+ GLuint green,
+ GLuint blue);
+angle::CallCapture CaptureSecondaryColor3uiv(const State &glState,
+ bool isCallValid,
+ const GLuint *v);
+angle::CallCapture CaptureSecondaryColor3us(const State &glState,
+ bool isCallValid,
+ GLushort red,
+ GLushort green,
+ GLushort blue);
+angle::CallCapture CaptureSecondaryColor3usv(const State &glState,
+ bool isCallValid,
+ const GLushort *v);
+angle::CallCapture CaptureSecondaryColorPointer(const State &glState,
+ bool isCallValid,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer);
+angle::CallCapture CaptureWindowPos2d(const State &glState,
+ bool isCallValid,
+ GLdouble x,
+ GLdouble y);
+angle::CallCapture CaptureWindowPos2dv(const State &glState, bool isCallValid, const GLdouble *v);
+angle::CallCapture CaptureWindowPos2f(const State &glState, bool isCallValid, GLfloat x, GLfloat y);
+angle::CallCapture CaptureWindowPos2fv(const State &glState, bool isCallValid, const GLfloat *v);
+angle::CallCapture CaptureWindowPos2i(const State &glState, bool isCallValid, GLint x, GLint y);
+angle::CallCapture CaptureWindowPos2iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureWindowPos2s(const State &glState, bool isCallValid, GLshort x, GLshort y);
+angle::CallCapture CaptureWindowPos2sv(const State &glState, bool isCallValid, const GLshort *v);
+angle::CallCapture CaptureWindowPos3d(const State &glState,
+ bool isCallValid,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+angle::CallCapture CaptureWindowPos3dv(const State &glState, bool isCallValid, const GLdouble *v);
+angle::CallCapture CaptureWindowPos3f(const State &glState,
+ bool isCallValid,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z);
+angle::CallCapture CaptureWindowPos3fv(const State &glState, bool isCallValid, const GLfloat *v);
+angle::CallCapture CaptureWindowPos3i(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLint z);
+angle::CallCapture CaptureWindowPos3iv(const State &glState, bool isCallValid, const GLint *v);
+angle::CallCapture CaptureWindowPos3s(const State &glState,
+ bool isCallValid,
+ GLshort x,
+ GLshort y,
+ GLshort z);
+angle::CallCapture CaptureWindowPos3sv(const State &glState, bool isCallValid, const GLshort *v);
+
+// GL 1.5
+angle::CallCapture CaptureGetBufferSubData(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr size,
+ void *data);
+angle::CallCapture CaptureGetQueryObjectiv(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureMapBuffer(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum access,
+ void *returnValue);
+
+// Parameter Captures
+
+// GL 1.0
+void CaptureBitmap_bitmap(const State &glState,
+ bool isCallValid,
+ GLsizei width,
+ GLsizei height,
+ GLfloat xorig,
+ GLfloat yorig,
+ GLfloat xmove,
+ GLfloat ymove,
+ const GLubyte *bitmap,
+ angle::ParamCapture *paramCapture);
+void CaptureCallLists_lists(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ GLenum type,
+ const void *lists,
+ angle::ParamCapture *paramCapture);
+void CaptureClipPlane_equation(const State &glState,
+ bool isCallValid,
+ GLenum plane,
+ const GLdouble *equation,
+ angle::ParamCapture *paramCapture);
+void CaptureColor3bv_v(const State &glState,
+ bool isCallValid,
+ const GLbyte *v,
+ angle::ParamCapture *paramCapture);
+void CaptureColor3dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureColor3fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureColor3iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureColor3sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureColor3ubv_v(const State &glState,
+ bool isCallValid,
+ const GLubyte *v,
+ angle::ParamCapture *paramCapture);
+void CaptureColor3uiv_v(const State &glState,
+ bool isCallValid,
+ const GLuint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureColor3usv_v(const State &glState,
+ bool isCallValid,
+ const GLushort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureColor4bv_v(const State &glState,
+ bool isCallValid,
+ const GLbyte *v,
+ angle::ParamCapture *paramCapture);
+void CaptureColor4dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureColor4fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureColor4iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureColor4sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureColor4ubv_v(const State &glState,
+ bool isCallValid,
+ const GLubyte *v,
+ angle::ParamCapture *paramCapture);
+void CaptureColor4uiv_v(const State &glState,
+ bool isCallValid,
+ const GLuint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureColor4usv_v(const State &glState,
+ bool isCallValid,
+ const GLushort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawPixels_pixels(const State &glState,
+ bool isCallValid,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureEdgeFlagv_flag(const State &glState,
+ bool isCallValid,
+ const GLboolean *flag,
+ angle::ParamCapture *paramCapture);
+void CaptureEvalCoord1dv_u(const State &glState,
+ bool isCallValid,
+ const GLdouble *u,
+ angle::ParamCapture *paramCapture);
+void CaptureEvalCoord1fv_u(const State &glState,
+ bool isCallValid,
+ const GLfloat *u,
+ angle::ParamCapture *paramCapture);
+void CaptureEvalCoord2dv_u(const State &glState,
+ bool isCallValid,
+ const GLdouble *u,
+ angle::ParamCapture *paramCapture);
+void CaptureEvalCoord2fv_u(const State &glState,
+ bool isCallValid,
+ const GLfloat *u,
+ angle::ParamCapture *paramCapture);
+void CaptureFeedbackBuffer_buffer(const State &glState,
+ bool isCallValid,
+ GLsizei size,
+ GLenum type,
+ GLfloat *buffer,
+ angle::ParamCapture *paramCapture);
+void CaptureFogiv_params(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetClipPlane_equation(const State &glState,
+ bool isCallValid,
+ GLenum plane,
+ GLdouble *equation,
+ angle::ParamCapture *paramCapture);
+void CaptureGetDoublev_data(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLdouble *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetLightiv_params(const State &glState,
+ bool isCallValid,
+ GLenum light,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetMapdv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum query,
+ GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureGetMapfv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum query,
+ GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureGetMapiv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum query,
+ GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureGetMaterialiv_params(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPixelMapfv_values(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLfloat *values,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPixelMapuiv_values(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLuint *values,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPixelMapusv_values(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLushort *values,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPolygonStipple_mask(const State &glState,
+ bool isCallValid,
+ GLubyte *mask,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexGendv_params(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLdouble *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexGenfv_params(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexGeniv_params(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexImage_pixels(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureIndexdv_c(const State &glState,
+ bool isCallValid,
+ const GLdouble *c,
+ angle::ParamCapture *paramCapture);
+void CaptureIndexfv_c(const State &glState,
+ bool isCallValid,
+ const GLfloat *c,
+ angle::ParamCapture *paramCapture);
+void CaptureIndexiv_c(const State &glState,
+ bool isCallValid,
+ const GLint *c,
+ angle::ParamCapture *paramCapture);
+void CaptureIndexsv_c(const State &glState,
+ bool isCallValid,
+ const GLshort *c,
+ angle::ParamCapture *paramCapture);
+void CaptureLightModeliv_params(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureLightiv_params(const State &glState,
+ bool isCallValid,
+ GLenum light,
+ GLenum pname,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureLoadMatrixd_m(const State &glState,
+ bool isCallValid,
+ const GLdouble *m,
+ angle::ParamCapture *paramCapture);
+void CaptureMap1d_points(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLdouble u1,
+ GLdouble u2,
+ GLint stride,
+ GLint order,
+ const GLdouble *points,
+ angle::ParamCapture *paramCapture);
+void CaptureMap1f_points(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLfloat u1,
+ GLfloat u2,
+ GLint stride,
+ GLint order,
+ const GLfloat *points,
+ angle::ParamCapture *paramCapture);
+void CaptureMap2d_points(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLdouble u1,
+ GLdouble u2,
+ GLint ustride,
+ GLint uorder,
+ GLdouble v1,
+ GLdouble v2,
+ GLint vstride,
+ GLint vorder,
+ const GLdouble *points,
+ angle::ParamCapture *paramCapture);
+void CaptureMap2f_points(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLfloat u1,
+ GLfloat u2,
+ GLint ustride,
+ GLint uorder,
+ GLfloat v1,
+ GLfloat v2,
+ GLint vstride,
+ GLint vorder,
+ const GLfloat *points,
+ angle::ParamCapture *paramCapture);
+void CaptureMaterialiv_params(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ GLenum pname,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureMultMatrixd_m(const State &glState,
+ bool isCallValid,
+ const GLdouble *m,
+ angle::ParamCapture *paramCapture);
+void CaptureNormal3bv_v(const State &glState,
+ bool isCallValid,
+ const GLbyte *v,
+ angle::ParamCapture *paramCapture);
+void CaptureNormal3dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureNormal3fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureNormal3iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureNormal3sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CapturePixelMapfv_values(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLsizei mapsize,
+ const GLfloat *values,
+ angle::ParamCapture *paramCapture);
+void CapturePixelMapuiv_values(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLsizei mapsize,
+ const GLuint *values,
+ angle::ParamCapture *paramCapture);
+void CapturePixelMapusv_values(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLsizei mapsize,
+ const GLushort *values,
+ angle::ParamCapture *paramCapture);
+void CapturePolygonStipple_mask(const State &glState,
+ bool isCallValid,
+ const GLubyte *mask,
+ angle::ParamCapture *paramCapture);
+void CaptureRasterPos2dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureRasterPos2fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureRasterPos2iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureRasterPos2sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureRasterPos3dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureRasterPos3fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureRasterPos3iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureRasterPos3sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureRasterPos4dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureRasterPos4fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureRasterPos4iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureRasterPos4sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureRectdv_v1(const State &glState,
+ bool isCallValid,
+ const GLdouble *v1,
+ const GLdouble *v2,
+ angle::ParamCapture *paramCapture);
+void CaptureRectdv_v2(const State &glState,
+ bool isCallValid,
+ const GLdouble *v1,
+ const GLdouble *v2,
+ angle::ParamCapture *paramCapture);
+void CaptureRectfv_v1(const State &glState,
+ bool isCallValid,
+ const GLfloat *v1,
+ const GLfloat *v2,
+ angle::ParamCapture *paramCapture);
+void CaptureRectfv_v2(const State &glState,
+ bool isCallValid,
+ const GLfloat *v1,
+ const GLfloat *v2,
+ angle::ParamCapture *paramCapture);
+void CaptureRectiv_v1(const State &glState,
+ bool isCallValid,
+ const GLint *v1,
+ const GLint *v2,
+ angle::ParamCapture *paramCapture);
+void CaptureRectiv_v2(const State &glState,
+ bool isCallValid,
+ const GLint *v1,
+ const GLint *v2,
+ angle::ParamCapture *paramCapture);
+void CaptureRectsv_v1(const State &glState,
+ bool isCallValid,
+ const GLshort *v1,
+ const GLshort *v2,
+ angle::ParamCapture *paramCapture);
+void CaptureRectsv_v2(const State &glState,
+ bool isCallValid,
+ const GLshort *v1,
+ const GLshort *v2,
+ angle::ParamCapture *paramCapture);
+void CaptureSelectBuffer_buffer(const State &glState,
+ bool isCallValid,
+ GLsizei size,
+ GLuint *buffer,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord1dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord1fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord1iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord1sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord2dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord2fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord2iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord2sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord3dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord3fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord3iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord3sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord4dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord4fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord4iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoord4sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureTexGendv_params(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ const GLdouble *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexGenfv_params(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ const GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexGeniv_params(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexImage1D_pixels(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureVertex2dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertex2fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertex2iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertex2sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertex3dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertex3fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertex3iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertex3sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertex4dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertex4fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertex4iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertex4sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+
+// GL 1.1
+void CaptureAreTexturesResident_textures(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const GLuint *textures,
+ GLboolean *residences,
+ angle::ParamCapture *paramCapture);
+void CaptureAreTexturesResident_residences(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const GLuint *textures,
+ GLboolean *residences,
+ angle::ParamCapture *paramCapture);
+void CaptureEdgeFlagPointer_pointer(const State &glState,
+ bool isCallValid,
+ GLsizei stride,
+ const void *pointer,
+ angle::ParamCapture *paramCapture);
+void CaptureIndexPointer_pointer(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer,
+ angle::ParamCapture *paramCapture);
+void CaptureIndexubv_c(const State &glState,
+ bool isCallValid,
+ const GLubyte *c,
+ angle::ParamCapture *paramCapture);
+void CaptureInterleavedArrays_pointer(const State &glState,
+ bool isCallValid,
+ GLenum format,
+ GLsizei stride,
+ const void *pointer,
+ angle::ParamCapture *paramCapture);
+void CapturePrioritizeTextures_textures(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const GLuint *textures,
+ const GLfloat *priorities,
+ angle::ParamCapture *paramCapture);
+void CapturePrioritizeTextures_priorities(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const GLuint *textures,
+ const GLfloat *priorities,
+ angle::ParamCapture *paramCapture);
+void CaptureTexSubImage1D_pixels(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+
+// GL 1.2
+
+// GL 1.3
+void CaptureCompressedTexImage1D_data(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLint border,
+ GLsizei imageSize,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureCompressedTexSubImage1D_data(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetCompressedTexImage_img(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ void *img,
+ angle::ParamCapture *paramCapture);
+void CaptureLoadTransposeMatrixd_m(const State &glState,
+ bool isCallValid,
+ const GLdouble *m,
+ angle::ParamCapture *paramCapture);
+void CaptureLoadTransposeMatrixf_m(const State &glState,
+ bool isCallValid,
+ const GLfloat *m,
+ angle::ParamCapture *paramCapture);
+void CaptureMultTransposeMatrixd_m(const State &glState,
+ bool isCallValid,
+ const GLdouble *m,
+ angle::ParamCapture *paramCapture);
+void CaptureMultTransposeMatrixf_m(const State &glState,
+ bool isCallValid,
+ const GLfloat *m,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord1dv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord1fv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord1iv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord1sv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord2dv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord2fv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord2iv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord2sv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord3dv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord3fv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord3iv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord3sv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord4dv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord4fv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord4iv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoord4sv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+
+// GL 1.4
+void CaptureFogCoordPointer_pointer(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer,
+ angle::ParamCapture *paramCapture);
+void CaptureFogCoorddv_coord(const State &glState,
+ bool isCallValid,
+ const GLdouble *coord,
+ angle::ParamCapture *paramCapture);
+void CaptureFogCoordfv_coord(const State &glState,
+ bool isCallValid,
+ const GLfloat *coord,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawArrays_first(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLint *first,
+ const GLsizei *count,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawArrays_count(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLint *first,
+ const GLsizei *count,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElements_count(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *count,
+ DrawElementsType typePacked,
+ const void *const *indices,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElements_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *count,
+ DrawElementsType typePacked,
+ const void *const *indices,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CapturePointParameteriv_params(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureSecondaryColor3bv_v(const State &glState,
+ bool isCallValid,
+ const GLbyte *v,
+ angle::ParamCapture *paramCapture);
+void CaptureSecondaryColor3dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureSecondaryColor3fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureSecondaryColor3iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureSecondaryColor3sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureSecondaryColor3ubv_v(const State &glState,
+ bool isCallValid,
+ const GLubyte *v,
+ angle::ParamCapture *paramCapture);
+void CaptureSecondaryColor3uiv_v(const State &glState,
+ bool isCallValid,
+ const GLuint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureSecondaryColor3usv_v(const State &glState,
+ bool isCallValid,
+ const GLushort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureSecondaryColorPointer_pointer(const State &glState,
+ bool isCallValid,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer,
+ angle::ParamCapture *paramCapture);
+void CaptureWindowPos2dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureWindowPos2fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureWindowPos2iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureWindowPos2sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureWindowPos3dv_v(const State &glState,
+ bool isCallValid,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureWindowPos3fv_v(const State &glState,
+ bool isCallValid,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureWindowPos3iv_v(const State &glState,
+ bool isCallValid,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureWindowPos3sv_v(const State &glState,
+ bool isCallValid,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+
+// GL 1.5
+void CaptureGetBufferSubData_data(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr size,
+ void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjectiv_params(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+} // namespace gl
+
+#endif // LIBANGLE_CAPTURE_GL_1_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/capture/capture_gl_2_autogen.h b/gfx/angle/checkout/src/libANGLE/capture/capture_gl_2_autogen.h
new file mode 100644
index 0000000000..5ab30a6b9a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/capture_gl_2_autogen.h
@@ -0,0 +1,266 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// capture_gl_2_autogen.h:
+// Capture functions for the OpenGL ES Desktop GL 2.x entry points.
+
+#ifndef LIBANGLE_CAPTURE_GL_2_AUTOGEN_H_
+#define LIBANGLE_CAPTURE_GL_2_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "libANGLE/capture/FrameCapture.h"
+
+namespace gl
+{
+
+// Method Captures
+
+// GL 2.0
+angle::CallCapture CaptureGetVertexAttribdv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLdouble *params);
+angle::CallCapture CaptureVertexAttrib1d(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLdouble x);
+angle::CallCapture CaptureVertexAttrib1dv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v);
+angle::CallCapture CaptureVertexAttrib1s(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLshort x);
+angle::CallCapture CaptureVertexAttrib1sv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLshort *v);
+angle::CallCapture CaptureVertexAttrib2d(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLdouble x,
+ GLdouble y);
+angle::CallCapture CaptureVertexAttrib2dv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v);
+angle::CallCapture CaptureVertexAttrib2s(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLshort x,
+ GLshort y);
+angle::CallCapture CaptureVertexAttrib2sv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLshort *v);
+angle::CallCapture CaptureVertexAttrib3d(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+angle::CallCapture CaptureVertexAttrib3dv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v);
+angle::CallCapture CaptureVertexAttrib3s(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLshort x,
+ GLshort y,
+ GLshort z);
+angle::CallCapture CaptureVertexAttrib3sv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLshort *v);
+angle::CallCapture CaptureVertexAttrib4Nbv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLbyte *v);
+angle::CallCapture CaptureVertexAttrib4Niv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLint *v);
+angle::CallCapture CaptureVertexAttrib4Nsv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLshort *v);
+angle::CallCapture CaptureVertexAttrib4Nub(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLubyte x,
+ GLubyte y,
+ GLubyte z,
+ GLubyte w);
+angle::CallCapture CaptureVertexAttrib4Nubv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLubyte *v);
+angle::CallCapture CaptureVertexAttrib4Nuiv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLuint *v);
+angle::CallCapture CaptureVertexAttrib4Nusv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLushort *v);
+angle::CallCapture CaptureVertexAttrib4bv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLbyte *v);
+angle::CallCapture CaptureVertexAttrib4d(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z,
+ GLdouble w);
+angle::CallCapture CaptureVertexAttrib4dv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v);
+angle::CallCapture CaptureVertexAttrib4iv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLint *v);
+angle::CallCapture CaptureVertexAttrib4s(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLshort x,
+ GLshort y,
+ GLshort z,
+ GLshort w);
+angle::CallCapture CaptureVertexAttrib4sv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLshort *v);
+angle::CallCapture CaptureVertexAttrib4ubv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLubyte *v);
+angle::CallCapture CaptureVertexAttrib4uiv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLuint *v);
+angle::CallCapture CaptureVertexAttrib4usv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLushort *v);
+
+// GL 2.1
+
+// Parameter Captures
+
+// GL 2.0
+void CaptureGetVertexAttribdv_params(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLdouble *params,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib1dv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib1sv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib2dv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib2sv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib3dv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib3sv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib4Nbv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLbyte *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib4Niv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib4Nsv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib4Nubv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLubyte *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib4Nuiv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLuint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib4Nusv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLushort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib4bv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLbyte *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib4dv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib4iv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib4sv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib4ubv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLubyte *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib4uiv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLuint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib4usv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLushort *v,
+ angle::ParamCapture *paramCapture);
+
+// GL 2.1
+} // namespace gl
+
+#endif // LIBANGLE_CAPTURE_GL_2_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/capture/capture_gl_3_autogen.h b/gfx/angle/checkout/src/libANGLE/capture/capture_gl_3_autogen.h
new file mode 100644
index 0000000000..b365fbec7c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/capture_gl_3_autogen.h
@@ -0,0 +1,609 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// capture_gl_3_autogen.h:
+// Capture functions for the OpenGL ES Desktop GL 3.x entry points.
+
+#ifndef LIBANGLE_CAPTURE_GL_3_AUTOGEN_H_
+#define LIBANGLE_CAPTURE_GL_3_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "libANGLE/capture/FrameCapture.h"
+
+namespace gl
+{
+
+// Method Captures
+
+// GL 3.0
+angle::CallCapture CaptureBeginConditionalRender(const State &glState,
+ bool isCallValid,
+ GLuint id,
+ GLenum mode);
+angle::CallCapture CaptureBindFragDataLocation(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint color,
+ const GLchar *name);
+angle::CallCapture CaptureClampColor(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum clamp);
+angle::CallCapture CaptureEndConditionalRender(const State &glState, bool isCallValid);
+angle::CallCapture CaptureFramebufferTexture1D(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texturePacked,
+ GLint level);
+angle::CallCapture CaptureFramebufferTexture3D(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texturePacked,
+ GLint level,
+ GLint zoffset);
+angle::CallCapture CaptureVertexAttribI1i(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLint x);
+angle::CallCapture CaptureVertexAttribI1iv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLint *v);
+angle::CallCapture CaptureVertexAttribI1ui(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLuint x);
+angle::CallCapture CaptureVertexAttribI1uiv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLuint *v);
+angle::CallCapture CaptureVertexAttribI2i(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLint x,
+ GLint y);
+angle::CallCapture CaptureVertexAttribI2iv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLint *v);
+angle::CallCapture CaptureVertexAttribI2ui(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLuint x,
+ GLuint y);
+angle::CallCapture CaptureVertexAttribI2uiv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLuint *v);
+angle::CallCapture CaptureVertexAttribI3i(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLint x,
+ GLint y,
+ GLint z);
+angle::CallCapture CaptureVertexAttribI3iv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLint *v);
+angle::CallCapture CaptureVertexAttribI3ui(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLuint x,
+ GLuint y,
+ GLuint z);
+angle::CallCapture CaptureVertexAttribI3uiv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLuint *v);
+angle::CallCapture CaptureVertexAttribI4bv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLbyte *v);
+angle::CallCapture CaptureVertexAttribI4sv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLshort *v);
+angle::CallCapture CaptureVertexAttribI4ubv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLubyte *v);
+angle::CallCapture CaptureVertexAttribI4usv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLushort *v);
+
+// GL 3.1
+angle::CallCapture CaptureGetActiveUniformName(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint uniformIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformName);
+angle::CallCapture CapturePrimitiveRestartIndex(const State &glState,
+ bool isCallValid,
+ GLuint index);
+
+// GL 3.2
+angle::CallCapture CaptureMultiDrawElementsBaseVertex(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *count,
+ DrawElementsType typePacked,
+ const void *const *indices,
+ GLsizei drawcount,
+ const GLint *basevertex);
+angle::CallCapture CaptureProvokingVertex(const State &glState,
+ bool isCallValid,
+ ProvokingVertexConvention modePacked);
+angle::CallCapture CaptureTexImage2DMultisample(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations);
+angle::CallCapture CaptureTexImage3DMultisample(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedsamplelocations);
+
+// GL 3.3
+angle::CallCapture CaptureBindFragDataLocationIndexed(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint colorNumber,
+ GLuint index,
+ const GLchar *name);
+angle::CallCapture CaptureColorP3ui(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint color);
+angle::CallCapture CaptureColorP3uiv(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *color);
+angle::CallCapture CaptureColorP4ui(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint color);
+angle::CallCapture CaptureColorP4uiv(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *color);
+angle::CallCapture CaptureGetFragDataIndex(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ const GLchar *name,
+ GLint returnValue);
+angle::CallCapture CaptureGetQueryObjecti64v(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLint64 *params);
+angle::CallCapture CaptureGetQueryObjectui64v(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLuint64 *params);
+angle::CallCapture CaptureMultiTexCoordP1ui(const State &glState,
+ bool isCallValid,
+ GLenum texture,
+ GLenum type,
+ GLuint coords);
+angle::CallCapture CaptureMultiTexCoordP1uiv(const State &glState,
+ bool isCallValid,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords);
+angle::CallCapture CaptureMultiTexCoordP2ui(const State &glState,
+ bool isCallValid,
+ GLenum texture,
+ GLenum type,
+ GLuint coords);
+angle::CallCapture CaptureMultiTexCoordP2uiv(const State &glState,
+ bool isCallValid,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords);
+angle::CallCapture CaptureMultiTexCoordP3ui(const State &glState,
+ bool isCallValid,
+ GLenum texture,
+ GLenum type,
+ GLuint coords);
+angle::CallCapture CaptureMultiTexCoordP3uiv(const State &glState,
+ bool isCallValid,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords);
+angle::CallCapture CaptureMultiTexCoordP4ui(const State &glState,
+ bool isCallValid,
+ GLenum texture,
+ GLenum type,
+ GLuint coords);
+angle::CallCapture CaptureMultiTexCoordP4uiv(const State &glState,
+ bool isCallValid,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords);
+angle::CallCapture CaptureNormalP3ui(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint coords);
+angle::CallCapture CaptureNormalP3uiv(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *coords);
+angle::CallCapture CaptureQueryCounter(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ QueryType targetPacked);
+angle::CallCapture CaptureSecondaryColorP3ui(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint color);
+angle::CallCapture CaptureSecondaryColorP3uiv(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *color);
+angle::CallCapture CaptureTexCoordP1ui(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint coords);
+angle::CallCapture CaptureTexCoordP1uiv(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *coords);
+angle::CallCapture CaptureTexCoordP2ui(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint coords);
+angle::CallCapture CaptureTexCoordP2uiv(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *coords);
+angle::CallCapture CaptureTexCoordP3ui(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint coords);
+angle::CallCapture CaptureTexCoordP3uiv(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *coords);
+angle::CallCapture CaptureTexCoordP4ui(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint coords);
+angle::CallCapture CaptureTexCoordP4uiv(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *coords);
+angle::CallCapture CaptureVertexAttribP1ui(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ GLuint value);
+angle::CallCapture CaptureVertexAttribP1uiv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value);
+angle::CallCapture CaptureVertexAttribP2ui(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ GLuint value);
+angle::CallCapture CaptureVertexAttribP2uiv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value);
+angle::CallCapture CaptureVertexAttribP3ui(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ GLuint value);
+angle::CallCapture CaptureVertexAttribP3uiv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value);
+angle::CallCapture CaptureVertexAttribP4ui(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ GLuint value);
+angle::CallCapture CaptureVertexAttribP4uiv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value);
+angle::CallCapture CaptureVertexP2ui(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint value);
+angle::CallCapture CaptureVertexP2uiv(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *value);
+angle::CallCapture CaptureVertexP3ui(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint value);
+angle::CallCapture CaptureVertexP3uiv(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *value);
+angle::CallCapture CaptureVertexP4ui(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint value);
+angle::CallCapture CaptureVertexP4uiv(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *value);
+
+// Parameter Captures
+
+// GL 3.0
+void CaptureBindFragDataLocation_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint color,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribI1iv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribI1uiv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLuint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribI2iv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribI2uiv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLuint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribI3iv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribI3uiv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLuint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribI4bv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLbyte *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribI4sv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLshort *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribI4ubv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLubyte *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribI4usv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLushort *v,
+ angle::ParamCapture *paramCapture);
+
+// GL 3.1
+void CaptureGetActiveUniformName_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint uniformIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformName,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveUniformName_uniformName(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint uniformIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformName,
+ angle::ParamCapture *paramCapture);
+
+// GL 3.2
+void CaptureMultiDrawElementsBaseVertex_count(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *count,
+ DrawElementsType typePacked,
+ const void *const *indices,
+ GLsizei drawcount,
+ const GLint *basevertex,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsBaseVertex_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *count,
+ DrawElementsType typePacked,
+ const void *const *indices,
+ GLsizei drawcount,
+ const GLint *basevertex,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsBaseVertex_basevertex(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *count,
+ DrawElementsType typePacked,
+ const void *const *indices,
+ GLsizei drawcount,
+ const GLint *basevertex,
+ angle::ParamCapture *paramCapture);
+
+// GL 3.3
+void CaptureBindFragDataLocationIndexed_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint colorNumber,
+ GLuint index,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureColorP3uiv_color(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *color,
+ angle::ParamCapture *paramCapture);
+void CaptureColorP4uiv_color(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *color,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFragDataIndex_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjecti64v_params(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLint64 *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjectui64v_params(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLuint64 *params,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoordP1uiv_coords(const State &glState,
+ bool isCallValid,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoordP2uiv_coords(const State &glState,
+ bool isCallValid,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoordP3uiv_coords(const State &glState,
+ bool isCallValid,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiTexCoordP4uiv_coords(const State &glState,
+ bool isCallValid,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords,
+ angle::ParamCapture *paramCapture);
+void CaptureNormalP3uiv_coords(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *coords,
+ angle::ParamCapture *paramCapture);
+void CaptureSecondaryColorP3uiv_color(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *color,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoordP1uiv_coords(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *coords,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoordP2uiv_coords(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *coords,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoordP3uiv_coords(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *coords,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoordP4uiv_coords(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *coords,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribP1uiv_value(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribP2uiv_value(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribP3uiv_value(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribP4uiv_value(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexP2uiv_value(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexP3uiv_value(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexP4uiv_value(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+} // namespace gl
+
+#endif // LIBANGLE_CAPTURE_GL_3_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/capture/capture_gl_4_autogen.h b/gfx/angle/checkout/src/libANGLE/capture/capture_gl_4_autogen.h
new file mode 100644
index 0000000000..495bf4cb7f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/capture_gl_4_autogen.h
@@ -0,0 +1,2524 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// capture_gl_4_autogen.h:
+// Capture functions for the OpenGL ES Desktop GL 4.x entry points.
+
+#ifndef LIBANGLE_CAPTURE_GL_4_AUTOGEN_H_
+#define LIBANGLE_CAPTURE_GL_4_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "libANGLE/capture/FrameCapture.h"
+
+namespace gl
+{
+
+// Method Captures
+
+// GL 4.0
+angle::CallCapture CaptureBeginQueryIndexed(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ QueryID idPacked);
+angle::CallCapture CaptureDrawTransformFeedback(const State &glState,
+ bool isCallValid,
+ GLenum mode,
+ TransformFeedbackID idPacked);
+angle::CallCapture CaptureDrawTransformFeedbackStream(const State &glState,
+ bool isCallValid,
+ GLenum mode,
+ TransformFeedbackID idPacked,
+ GLuint stream);
+angle::CallCapture CaptureEndQueryIndexed(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index);
+angle::CallCapture CaptureGetActiveSubroutineName(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name);
+angle::CallCapture CaptureGetActiveSubroutineUniformName(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name);
+angle::CallCapture CaptureGetActiveSubroutineUniformiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ GLuint index,
+ GLenum pname,
+ GLint *values);
+angle::CallCapture CaptureGetProgramStageiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ GLenum pname,
+ GLint *values);
+angle::CallCapture CaptureGetQueryIndexediv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetSubroutineIndex(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ const GLchar *name,
+ GLuint returnValue);
+angle::CallCapture CaptureGetSubroutineUniformLocation(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ const GLchar *name,
+ GLint returnValue);
+angle::CallCapture CaptureGetUniformSubroutineuiv(const State &glState,
+ bool isCallValid,
+ GLenum shadertype,
+ GLint location,
+ GLuint *params);
+angle::CallCapture CaptureGetUniformdv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLdouble *params);
+angle::CallCapture CapturePatchParameterfv(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLfloat *values);
+angle::CallCapture CaptureUniform1d(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLdouble x);
+angle::CallCapture CaptureUniform1dv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+angle::CallCapture CaptureUniform2d(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLdouble x,
+ GLdouble y);
+angle::CallCapture CaptureUniform2dv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+angle::CallCapture CaptureUniform3d(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+angle::CallCapture CaptureUniform3dv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+angle::CallCapture CaptureUniform4d(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z,
+ GLdouble w);
+angle::CallCapture CaptureUniform4dv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+angle::CallCapture CaptureUniformMatrix2dv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureUniformMatrix2x3dv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureUniformMatrix2x4dv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureUniformMatrix3dv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureUniformMatrix3x2dv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureUniformMatrix3x4dv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureUniformMatrix4dv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureUniformMatrix4x2dv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureUniformMatrix4x3dv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureUniformSubroutinesuiv(const State &glState,
+ bool isCallValid,
+ GLenum shadertype,
+ GLsizei count,
+ const GLuint *indices);
+
+// GL 4.1
+angle::CallCapture CaptureDepthRangeArrayv(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const GLdouble *v);
+angle::CallCapture CaptureDepthRangeIndexed(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLdouble n,
+ GLdouble f);
+angle::CallCapture CaptureGetDoublei_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLdouble *data);
+angle::CallCapture CaptureGetFloati_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLfloat *data);
+angle::CallCapture CaptureGetVertexAttribLdv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLdouble *params);
+angle::CallCapture CaptureProgramUniform1d(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLdouble v0);
+angle::CallCapture CaptureProgramUniform1dv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+angle::CallCapture CaptureProgramUniform2d(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLdouble v0,
+ GLdouble v1);
+angle::CallCapture CaptureProgramUniform2dv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+angle::CallCapture CaptureProgramUniform3d(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLdouble v0,
+ GLdouble v1,
+ GLdouble v2);
+angle::CallCapture CaptureProgramUniform3dv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+angle::CallCapture CaptureProgramUniform4d(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLdouble v0,
+ GLdouble v1,
+ GLdouble v2,
+ GLdouble v3);
+angle::CallCapture CaptureProgramUniform4dv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+angle::CallCapture CaptureProgramUniformMatrix2dv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureProgramUniformMatrix2x3dv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureProgramUniformMatrix2x4dv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureProgramUniformMatrix3dv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureProgramUniformMatrix3x2dv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureProgramUniformMatrix3x4dv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureProgramUniformMatrix4dv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureProgramUniformMatrix4x2dv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureProgramUniformMatrix4x3dv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+angle::CallCapture CaptureScissorArrayv(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const GLint *v);
+angle::CallCapture CaptureScissorIndexed(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLint left,
+ GLint bottom,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureScissorIndexedv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLint *v);
+angle::CallCapture CaptureVertexAttribL1d(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLdouble x);
+angle::CallCapture CaptureVertexAttribL1dv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v);
+angle::CallCapture CaptureVertexAttribL2d(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLdouble x,
+ GLdouble y);
+angle::CallCapture CaptureVertexAttribL2dv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v);
+angle::CallCapture CaptureVertexAttribL3d(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+angle::CallCapture CaptureVertexAttribL3dv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v);
+angle::CallCapture CaptureVertexAttribL4d(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z,
+ GLdouble w);
+angle::CallCapture CaptureVertexAttribL4dv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v);
+angle::CallCapture CaptureVertexAttribLPointer(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer);
+angle::CallCapture CaptureViewportArrayv(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const GLfloat *v);
+angle::CallCapture CaptureViewportIndexedf(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLfloat x,
+ GLfloat y,
+ GLfloat w,
+ GLfloat h);
+angle::CallCapture CaptureViewportIndexedfv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLfloat *v);
+
+// GL 4.2
+angle::CallCapture CaptureDrawArraysInstancedBaseInstance(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLint first,
+ GLsizei count,
+ GLsizei instancecount,
+ GLuint baseinstance);
+angle::CallCapture CaptureDrawElementsInstancedBaseInstance(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLuint baseinstance);
+angle::CallCapture CaptureDrawElementsInstancedBaseVertexBaseInstance(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex,
+ GLuint baseinstance);
+angle::CallCapture CaptureDrawTransformFeedbackInstanced(const State &glState,
+ bool isCallValid,
+ GLenum mode,
+ TransformFeedbackID idPacked,
+ GLsizei instancecount);
+angle::CallCapture CaptureDrawTransformFeedbackStreamInstanced(const State &glState,
+ bool isCallValid,
+ GLenum mode,
+ TransformFeedbackID idPacked,
+ GLuint stream,
+ GLsizei instancecount);
+angle::CallCapture CaptureGetActiveAtomicCounterBufferiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint bufferIndex,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureTexStorage1D(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width);
+
+// GL 4.3
+angle::CallCapture CaptureClearBufferData(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum internalformat,
+ GLenum format,
+ GLenum type,
+ const void *data);
+angle::CallCapture CaptureClearBufferSubData(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum internalformat,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLenum format,
+ GLenum type,
+ const void *data);
+angle::CallCapture CaptureGetInternalformati64v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei count,
+ GLint64 *params);
+angle::CallCapture CaptureGetProgramResourceLocationIndex(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ const GLchar *name,
+ GLint returnValue);
+angle::CallCapture CaptureInvalidateBufferData(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked);
+angle::CallCapture CaptureInvalidateBufferSubData(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr length);
+angle::CallCapture CaptureInvalidateTexImage(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level);
+angle::CallCapture CaptureInvalidateTexSubImage(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+angle::CallCapture CaptureMultiDrawArraysIndirect(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride);
+angle::CallCapture CaptureMultiDrawElementsIndirect(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ DrawElementsType typePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride);
+angle::CallCapture CaptureShaderStorageBlockBinding(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint storageBlockIndex,
+ GLuint storageBlockBinding);
+angle::CallCapture CaptureTextureView(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum target,
+ GLuint origtexture,
+ GLenum internalformat,
+ GLuint minlevel,
+ GLuint numlevels,
+ GLuint minlayer,
+ GLuint numlayers);
+angle::CallCapture CaptureVertexAttribLFormat(const State &glState,
+ bool isCallValid,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset);
+
+// GL 4.4
+angle::CallCapture CaptureBindBuffersBase(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked);
+angle::CallCapture CaptureBindBuffersRange(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ const GLintptr *offsets,
+ const GLsizeiptr *sizes);
+angle::CallCapture CaptureBindImageTextures(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const GLuint *textures);
+angle::CallCapture CaptureBindSamplers(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const GLuint *samplers);
+angle::CallCapture CaptureBindTextures(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const GLuint *textures);
+angle::CallCapture CaptureBindVertexBuffers(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ const GLintptr *offsets,
+ const GLsizei *strides);
+angle::CallCapture CaptureBufferStorage(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags);
+angle::CallCapture CaptureClearTexImage(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ const void *data);
+angle::CallCapture CaptureClearTexSubImage(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *data);
+
+// GL 4.5
+angle::CallCapture CaptureBindTextureUnit(const State &glState,
+ bool isCallValid,
+ GLuint unit,
+ TextureID texturePacked);
+angle::CallCapture CaptureBlitNamedFramebuffer(const State &glState,
+ bool isCallValid,
+ GLuint readFramebuffer,
+ GLuint drawFramebuffer,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+angle::CallCapture CaptureCheckNamedFramebufferStatus(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum target,
+ GLenum returnValue);
+angle::CallCapture CaptureClearNamedBufferData(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLenum internalformat,
+ GLenum format,
+ GLenum type,
+ const void *data);
+angle::CallCapture CaptureClearNamedBufferSubData(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLenum internalformat,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLenum format,
+ GLenum type,
+ const void *data);
+angle::CallCapture CaptureClearNamedFramebufferfi(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil);
+angle::CallCapture CaptureClearNamedFramebufferfv(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *value);
+angle::CallCapture CaptureClearNamedFramebufferiv(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *value);
+angle::CallCapture CaptureClearNamedFramebufferuiv(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *value);
+angle::CallCapture CaptureClipControl(const State &glState,
+ bool isCallValid,
+ GLenum origin,
+ GLenum depth);
+angle::CallCapture CaptureCompressedTextureSubImage1D(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+angle::CallCapture CaptureCompressedTextureSubImage2D(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+angle::CallCapture CaptureCompressedTextureSubImage3D(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+angle::CallCapture CaptureCopyNamedBufferSubData(const State &glState,
+ bool isCallValid,
+ GLuint readBuffer,
+ GLuint writeBuffer,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size);
+angle::CallCapture CaptureCopyTextureSubImage1D(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint x,
+ GLint y,
+ GLsizei width);
+angle::CallCapture CaptureCopyTextureSubImage2D(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureCopyTextureSubImage3D(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureCreateBuffers(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ BufferID *buffersPacked);
+angle::CallCapture CaptureCreateFramebuffers(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ GLuint *framebuffers);
+angle::CallCapture CaptureCreateProgramPipelines(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ GLuint *pipelines);
+angle::CallCapture CaptureCreateQueries(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei n,
+ GLuint *ids);
+angle::CallCapture CaptureCreateRenderbuffers(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ RenderbufferID *renderbuffersPacked);
+angle::CallCapture CaptureCreateSamplers(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ GLuint *samplers);
+angle::CallCapture CaptureCreateTextures(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei n,
+ GLuint *textures);
+angle::CallCapture CaptureCreateTransformFeedbacks(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ GLuint *ids);
+angle::CallCapture CaptureCreateVertexArrays(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ VertexArrayID *arraysPacked);
+angle::CallCapture CaptureDisableVertexArrayAttrib(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint index);
+angle::CallCapture CaptureEnableVertexArrayAttrib(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint index);
+angle::CallCapture CaptureFlushMappedNamedBufferRange(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr length);
+angle::CallCapture CaptureGenerateTextureMipmap(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked);
+angle::CallCapture CaptureGetCompressedTextureImage(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLsizei bufSize,
+ void *pixels);
+angle::CallCapture CaptureGetCompressedTextureSubImage(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei bufSize,
+ void *pixels);
+angle::CallCapture CaptureGetNamedBufferParameteri64v(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLenum pname,
+ GLint64 *params);
+angle::CallCapture CaptureGetNamedBufferParameteriv(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetNamedBufferPointerv(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLenum pname,
+ void **params);
+angle::CallCapture CaptureGetNamedBufferSubData(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size,
+ void *data);
+angle::CallCapture CaptureGetNamedFramebufferAttachmentParameteriv(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetNamedFramebufferParameteriv(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum pname,
+ GLint *param);
+angle::CallCapture CaptureGetNamedRenderbufferParameteriv(const State &glState,
+ bool isCallValid,
+ RenderbufferID renderbufferPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetQueryBufferObjecti64v(const State &glState,
+ bool isCallValid,
+ GLuint id,
+ BufferID bufferPacked,
+ GLenum pname,
+ GLintptr offset);
+angle::CallCapture CaptureGetQueryBufferObjectiv(const State &glState,
+ bool isCallValid,
+ GLuint id,
+ BufferID bufferPacked,
+ GLenum pname,
+ GLintptr offset);
+angle::CallCapture CaptureGetQueryBufferObjectui64v(const State &glState,
+ bool isCallValid,
+ GLuint id,
+ BufferID bufferPacked,
+ GLenum pname,
+ GLintptr offset);
+angle::CallCapture CaptureGetQueryBufferObjectuiv(const State &glState,
+ bool isCallValid,
+ GLuint id,
+ BufferID bufferPacked,
+ GLenum pname,
+ GLintptr offset);
+angle::CallCapture CaptureGetTextureImage(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *pixels);
+angle::CallCapture CaptureGetTextureLevelParameterfv(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLenum pname,
+ GLfloat *params);
+angle::CallCapture CaptureGetTextureLevelParameteriv(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetTextureParameterIiv(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetTextureParameterIuiv(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ GLuint *params);
+angle::CallCapture CaptureGetTextureParameterfv(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ GLfloat *params);
+angle::CallCapture CaptureGetTextureParameteriv(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetTextureSubImage(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *pixels);
+angle::CallCapture CaptureGetTransformFeedbacki64_v(const State &glState,
+ bool isCallValid,
+ GLuint xfb,
+ GLenum pname,
+ GLuint index,
+ GLint64 *param);
+angle::CallCapture CaptureGetTransformFeedbacki_v(const State &glState,
+ bool isCallValid,
+ GLuint xfb,
+ GLenum pname,
+ GLuint index,
+ GLint *param);
+angle::CallCapture CaptureGetTransformFeedbackiv(const State &glState,
+ bool isCallValid,
+ GLuint xfb,
+ GLenum pname,
+ GLint *param);
+angle::CallCapture CaptureGetVertexArrayIndexed64iv(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint index,
+ GLenum pname,
+ GLint64 *param);
+angle::CallCapture CaptureGetVertexArrayIndexediv(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint index,
+ GLenum pname,
+ GLint *param);
+angle::CallCapture CaptureGetVertexArrayiv(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLenum pname,
+ GLint *param);
+angle::CallCapture CaptureGetnColorTable(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *table);
+angle::CallCapture CaptureGetnCompressedTexImage(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint lod,
+ GLsizei bufSize,
+ void *pixels);
+angle::CallCapture CaptureGetnConvolutionFilter(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *image);
+angle::CallCapture CaptureGetnHistogram(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLboolean reset,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *values);
+angle::CallCapture CaptureGetnMapdv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum query,
+ GLsizei bufSize,
+ GLdouble *v);
+angle::CallCapture CaptureGetnMapfv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum query,
+ GLsizei bufSize,
+ GLfloat *v);
+angle::CallCapture CaptureGetnMapiv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum query,
+ GLsizei bufSize,
+ GLint *v);
+angle::CallCapture CaptureGetnMinmax(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLboolean reset,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *values);
+angle::CallCapture CaptureGetnPixelMapfv(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLsizei bufSize,
+ GLfloat *values);
+angle::CallCapture CaptureGetnPixelMapuiv(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLsizei bufSize,
+ GLuint *values);
+angle::CallCapture CaptureGetnPixelMapusv(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLsizei bufSize,
+ GLushort *values);
+angle::CallCapture CaptureGetnPolygonStipple(const State &glState,
+ bool isCallValid,
+ GLsizei bufSize,
+ GLubyte *pattern);
+angle::CallCapture CaptureGetnSeparableFilter(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei rowBufSize,
+ void *row,
+ GLsizei columnBufSize,
+ void *column,
+ void *span);
+angle::CallCapture CaptureGetnTexImage(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *pixels);
+angle::CallCapture CaptureGetnUniformdv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLdouble *params);
+angle::CallCapture CaptureInvalidateNamedFramebufferData(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLsizei numAttachments,
+ const GLenum *attachments);
+angle::CallCapture CaptureInvalidateNamedFramebufferSubData(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureMapNamedBuffer(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLenum access,
+ void *returnValue);
+angle::CallCapture CaptureMapNamedBufferRange(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access,
+ void *returnValue);
+angle::CallCapture CaptureNamedBufferData(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLsizeiptr size,
+ const void *data,
+ GLenum usage);
+angle::CallCapture CaptureNamedBufferStorage(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags);
+angle::CallCapture CaptureNamedBufferSubData(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data);
+angle::CallCapture CaptureNamedFramebufferDrawBuffer(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum buf);
+angle::CallCapture CaptureNamedFramebufferDrawBuffers(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLsizei n,
+ const GLenum *bufs);
+angle::CallCapture CaptureNamedFramebufferParameteri(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum pname,
+ GLint param);
+angle::CallCapture CaptureNamedFramebufferReadBuffer(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum src);
+angle::CallCapture CaptureNamedFramebufferRenderbuffer(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ RenderbufferID renderbufferPacked);
+angle::CallCapture CaptureNamedFramebufferTexture(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum attachment,
+ TextureID texturePacked,
+ GLint level);
+angle::CallCapture CaptureNamedFramebufferTextureLayer(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum attachment,
+ TextureID texturePacked,
+ GLint level,
+ GLint layer);
+angle::CallCapture CaptureNamedRenderbufferStorage(const State &glState,
+ bool isCallValid,
+ RenderbufferID renderbufferPacked,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureNamedRenderbufferStorageMultisample(const State &glState,
+ bool isCallValid,
+ RenderbufferID renderbufferPacked,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureTextureBarrier(const State &glState, bool isCallValid);
+angle::CallCapture CaptureTextureBuffer(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum internalformat,
+ BufferID bufferPacked);
+angle::CallCapture CaptureTextureBufferRange(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum internalformat,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size);
+angle::CallCapture CaptureTextureParameterIiv(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLint *params);
+angle::CallCapture CaptureTextureParameterIuiv(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLuint *params);
+angle::CallCapture CaptureTextureParameterf(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ GLfloat param);
+angle::CallCapture CaptureTextureParameterfv(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLfloat *param);
+angle::CallCapture CaptureTextureParameteri(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ GLint param);
+angle::CallCapture CaptureTextureParameteriv(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLint *param);
+angle::CallCapture CaptureTextureStorage1D(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width);
+angle::CallCapture CaptureTextureStorage2D(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureTextureStorage2DMultisample(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations);
+angle::CallCapture CaptureTextureStorage3D(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+angle::CallCapture CaptureTextureStorage3DMultisample(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedsamplelocations);
+angle::CallCapture CaptureTextureSubImage1D(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+angle::CallCapture CaptureTextureSubImage2D(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+angle::CallCapture CaptureTextureSubImage3D(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+angle::CallCapture CaptureTransformFeedbackBufferBase(const State &glState,
+ bool isCallValid,
+ GLuint xfb,
+ GLuint index,
+ BufferID bufferPacked);
+angle::CallCapture CaptureTransformFeedbackBufferRange(const State &glState,
+ bool isCallValid,
+ GLuint xfb,
+ GLuint index,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size);
+angle::CallCapture CaptureUnmapNamedBuffer(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureVertexArrayAttribBinding(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint attribindex,
+ GLuint bindingindex);
+angle::CallCapture CaptureVertexArrayAttribFormat(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLuint relativeoffset);
+angle::CallCapture CaptureVertexArrayAttribIFormat(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset);
+angle::CallCapture CaptureVertexArrayAttribLFormat(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset);
+angle::CallCapture CaptureVertexArrayBindingDivisor(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint bindingindex,
+ GLuint divisor);
+angle::CallCapture CaptureVertexArrayElementBuffer(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ BufferID bufferPacked);
+angle::CallCapture CaptureVertexArrayVertexBuffer(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint bindingindex,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizei stride);
+angle::CallCapture CaptureVertexArrayVertexBuffers(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ const GLintptr *offsets,
+ const GLsizei *strides);
+
+// GL 4.6
+angle::CallCapture CaptureMultiDrawArraysIndirectCount(const State &glState,
+ bool isCallValid,
+ GLenum mode,
+ const void *indirect,
+ GLintptr drawcount,
+ GLsizei maxdrawcount,
+ GLsizei stride);
+angle::CallCapture CaptureMultiDrawElementsIndirectCount(const State &glState,
+ bool isCallValid,
+ GLenum mode,
+ GLenum type,
+ const void *indirect,
+ GLintptr drawcount,
+ GLsizei maxdrawcount,
+ GLsizei stride);
+angle::CallCapture CapturePolygonOffsetClamp(const State &glState,
+ bool isCallValid,
+ GLfloat factor,
+ GLfloat units,
+ GLfloat clamp);
+angle::CallCapture CaptureSpecializeShader(const State &glState,
+ bool isCallValid,
+ GLuint shader,
+ const GLchar *pEntryPoint,
+ GLuint numSpecializationConstants,
+ const GLuint *pConstantIndex,
+ const GLuint *pConstantValue);
+
+// Parameter Captures
+
+// GL 4.0
+void CaptureGetActiveSubroutineName_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveSubroutineName_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveSubroutineUniformName_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveSubroutineUniformName_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveSubroutineUniformiv_values(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ GLuint index,
+ GLenum pname,
+ GLint *values,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramStageiv_values(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ GLenum pname,
+ GLint *values,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryIndexediv_params(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSubroutineIndex_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSubroutineUniformLocation_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUniformSubroutineuiv_params(const State &glState,
+ bool isCallValid,
+ GLenum shadertype,
+ GLint location,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUniformdv_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLdouble *params,
+ angle::ParamCapture *paramCapture);
+void CapturePatchParameterfv_values(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLfloat *values,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform1dv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform2dv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform3dv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform4dv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix2dv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix2x3dv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix2x4dv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix3dv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix3x2dv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix3x4dv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix4dv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix4x2dv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix4x3dv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformSubroutinesuiv_indices(const State &glState,
+ bool isCallValid,
+ GLenum shadertype,
+ GLsizei count,
+ const GLuint *indices,
+ angle::ParamCapture *paramCapture);
+
+// GL 4.1
+void CaptureDepthRangeArrayv_v(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureGetDoublei_v_data(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLdouble *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFloati_v_data(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLfloat *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribLdv_params(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLdouble *params,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform1dv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform2dv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform3dv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform4dv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix2dv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix2x3dv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix2x4dv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix3dv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix3x2dv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix3x4dv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix4dv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix4x2dv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix4x3dv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value,
+ angle::ParamCapture *paramCapture);
+void CaptureScissorArrayv_v(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureScissorIndexedv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribL1dv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribL2dv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribL3dv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribL4dv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribLPointer_pointer(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer,
+ angle::ParamCapture *paramCapture);
+void CaptureViewportArrayv_v(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureViewportIndexedfv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+
+// GL 4.2
+void CaptureDrawElementsInstancedBaseInstance_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLuint baseinstance,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawElementsInstancedBaseVertexBaseInstance_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex,
+ GLuint baseinstance,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveAtomicCounterBufferiv_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint bufferIndex,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+
+// GL 4.3
+void CaptureClearBufferData_data(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum internalformat,
+ GLenum format,
+ GLenum type,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureClearBufferSubData_data(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum internalformat,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLenum format,
+ GLenum type,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetInternalformati64v_params(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei count,
+ GLint64 *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramResourceLocationIndex_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawArraysIndirect_indirect(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsIndirect_indirect(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ DrawElementsType typePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride,
+ angle::ParamCapture *paramCapture);
+
+// GL 4.4
+void CaptureBindBuffersBase_buffersPacked(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureBindBuffersRange_buffersPacked(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ const GLintptr *offsets,
+ const GLsizeiptr *sizes,
+ angle::ParamCapture *paramCapture);
+void CaptureBindBuffersRange_offsets(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ const GLintptr *offsets,
+ const GLsizeiptr *sizes,
+ angle::ParamCapture *paramCapture);
+void CaptureBindBuffersRange_sizes(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ const GLintptr *offsets,
+ const GLsizeiptr *sizes,
+ angle::ParamCapture *paramCapture);
+void CaptureBindImageTextures_textures(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const GLuint *textures,
+ angle::ParamCapture *paramCapture);
+void CaptureBindSamplers_samplers(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const GLuint *samplers,
+ angle::ParamCapture *paramCapture);
+void CaptureBindTextures_textures(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const GLuint *textures,
+ angle::ParamCapture *paramCapture);
+void CaptureBindVertexBuffers_buffersPacked(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ const GLintptr *offsets,
+ const GLsizei *strides,
+ angle::ParamCapture *paramCapture);
+void CaptureBindVertexBuffers_offsets(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ const GLintptr *offsets,
+ const GLsizei *strides,
+ angle::ParamCapture *paramCapture);
+void CaptureBindVertexBuffers_strides(const State &glState,
+ bool isCallValid,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ const GLintptr *offsets,
+ const GLsizei *strides,
+ angle::ParamCapture *paramCapture);
+void CaptureBufferStorage_data(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags,
+ angle::ParamCapture *paramCapture);
+void CaptureClearTexImage_data(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureClearTexSubImage_data(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+
+// GL 4.5
+void CaptureClearNamedBufferData_data(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLenum internalformat,
+ GLenum format,
+ GLenum type,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureClearNamedBufferSubData_data(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLenum internalformat,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLenum format,
+ GLenum type,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureClearNamedFramebufferfv_value(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureClearNamedFramebufferiv_value(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureClearNamedFramebufferuiv_value(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureCompressedTextureSubImage1D_data(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureCompressedTextureSubImage2D_data(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureCompressedTextureSubImage3D_data(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureCreateBuffers_buffersPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ BufferID *buffersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureCreateFramebuffers_framebuffers(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ GLuint *framebuffers,
+ angle::ParamCapture *paramCapture);
+void CaptureCreateProgramPipelines_pipelines(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ GLuint *pipelines,
+ angle::ParamCapture *paramCapture);
+void CaptureCreateQueries_ids(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei n,
+ GLuint *ids,
+ angle::ParamCapture *paramCapture);
+void CaptureCreateRenderbuffers_renderbuffersPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ RenderbufferID *renderbuffersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureCreateSamplers_samplers(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ GLuint *samplers,
+ angle::ParamCapture *paramCapture);
+void CaptureCreateTextures_textures(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei n,
+ GLuint *textures,
+ angle::ParamCapture *paramCapture);
+void CaptureCreateTransformFeedbacks_ids(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ GLuint *ids,
+ angle::ParamCapture *paramCapture);
+void CaptureCreateVertexArrays_arraysPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ VertexArrayID *arraysPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGetCompressedTextureImage_pixels(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLsizei bufSize,
+ void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureGetCompressedTextureSubImage_pixels(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei bufSize,
+ void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureGetNamedBufferParameteri64v_params(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLenum pname,
+ GLint64 *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetNamedBufferParameteriv_params(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetNamedBufferPointerv_params(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLenum pname,
+ void **params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetNamedBufferSubData_data(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size,
+ void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetNamedFramebufferAttachmentParameteriv_params(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetNamedFramebufferParameteriv_param(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLenum pname,
+ GLint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureGetNamedRenderbufferParameteriv_params(const State &glState,
+ bool isCallValid,
+ RenderbufferID renderbufferPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTextureImage_pixels(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTextureLevelParameterfv_params(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLenum pname,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTextureLevelParameteriv_params(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTextureParameterIiv_params(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTextureParameterIuiv_params(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTextureParameterfv_params(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTextureParameteriv_params(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTextureSubImage_pixels(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTransformFeedbacki64_v_param(const State &glState,
+ bool isCallValid,
+ GLuint xfb,
+ GLenum pname,
+ GLuint index,
+ GLint64 *param,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTransformFeedbacki_v_param(const State &glState,
+ bool isCallValid,
+ GLuint xfb,
+ GLenum pname,
+ GLuint index,
+ GLint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTransformFeedbackiv_param(const State &glState,
+ bool isCallValid,
+ GLuint xfb,
+ GLenum pname,
+ GLint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexArrayIndexed64iv_param(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint index,
+ GLenum pname,
+ GLint64 *param,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexArrayIndexediv_param(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint index,
+ GLenum pname,
+ GLint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexArrayiv_param(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLenum pname,
+ GLint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnColorTable_table(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *table,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnCompressedTexImage_pixels(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint lod,
+ GLsizei bufSize,
+ void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnConvolutionFilter_image(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *image,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnHistogram_values(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLboolean reset,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *values,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnMapdv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum query,
+ GLsizei bufSize,
+ GLdouble *v,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnMapfv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum query,
+ GLsizei bufSize,
+ GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnMapiv_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum query,
+ GLsizei bufSize,
+ GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnMinmax_values(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLboolean reset,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *values,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnPixelMapfv_values(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLsizei bufSize,
+ GLfloat *values,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnPixelMapuiv_values(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLsizei bufSize,
+ GLuint *values,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnPixelMapusv_values(const State &glState,
+ bool isCallValid,
+ GLenum map,
+ GLsizei bufSize,
+ GLushort *values,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnPolygonStipple_pattern(const State &glState,
+ bool isCallValid,
+ GLsizei bufSize,
+ GLubyte *pattern,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnSeparableFilter_row(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei rowBufSize,
+ void *row,
+ GLsizei columnBufSize,
+ void *column,
+ void *span,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnSeparableFilter_column(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei rowBufSize,
+ void *row,
+ GLsizei columnBufSize,
+ void *column,
+ void *span,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnSeparableFilter_span(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei rowBufSize,
+ void *row,
+ GLsizei columnBufSize,
+ void *column,
+ void *span,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnTexImage_pixels(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnUniformdv_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLdouble *params,
+ angle::ParamCapture *paramCapture);
+void CaptureInvalidateNamedFramebufferData_attachments(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ angle::ParamCapture *paramCapture);
+void CaptureInvalidateNamedFramebufferSubData_attachments(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ angle::ParamCapture *paramCapture);
+void CaptureNamedBufferData_data(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLsizeiptr size,
+ const void *data,
+ GLenum usage,
+ angle::ParamCapture *paramCapture);
+void CaptureNamedBufferStorage_data(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags,
+ angle::ParamCapture *paramCapture);
+void CaptureNamedBufferSubData_data(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureNamedFramebufferDrawBuffers_bufs(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLsizei n,
+ const GLenum *bufs,
+ angle::ParamCapture *paramCapture);
+void CaptureTextureParameterIiv_params(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTextureParameterIuiv_params(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTextureParameterfv_param(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLfloat *param,
+ angle::ParamCapture *paramCapture);
+void CaptureTextureParameteriv_param(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureTextureSubImage1D_pixels(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureTextureSubImage2D_pixels(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureTextureSubImage3D_pixels(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexArrayVertexBuffers_buffersPacked(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ const GLintptr *offsets,
+ const GLsizei *strides,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexArrayVertexBuffers_offsets(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ const GLintptr *offsets,
+ const GLsizei *strides,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexArrayVertexBuffers_strides(const State &glState,
+ bool isCallValid,
+ VertexArrayID vaobjPacked,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ const GLintptr *offsets,
+ const GLsizei *strides,
+ angle::ParamCapture *paramCapture);
+
+// GL 4.6
+void CaptureMultiDrawArraysIndirectCount_indirect(const State &glState,
+ bool isCallValid,
+ GLenum mode,
+ const void *indirect,
+ GLintptr drawcount,
+ GLsizei maxdrawcount,
+ GLsizei stride,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsIndirectCount_indirect(const State &glState,
+ bool isCallValid,
+ GLenum mode,
+ GLenum type,
+ const void *indirect,
+ GLintptr drawcount,
+ GLsizei maxdrawcount,
+ GLsizei stride,
+ angle::ParamCapture *paramCapture);
+void CaptureSpecializeShader_pEntryPoint(const State &glState,
+ bool isCallValid,
+ GLuint shader,
+ const GLchar *pEntryPoint,
+ GLuint numSpecializationConstants,
+ const GLuint *pConstantIndex,
+ const GLuint *pConstantValue,
+ angle::ParamCapture *paramCapture);
+void CaptureSpecializeShader_pConstantIndex(const State &glState,
+ bool isCallValid,
+ GLuint shader,
+ const GLchar *pEntryPoint,
+ GLuint numSpecializationConstants,
+ const GLuint *pConstantIndex,
+ const GLuint *pConstantValue,
+ angle::ParamCapture *paramCapture);
+void CaptureSpecializeShader_pConstantValue(const State &glState,
+ bool isCallValid,
+ GLuint shader,
+ const GLchar *pEntryPoint,
+ GLuint numSpecializationConstants,
+ const GLuint *pConstantIndex,
+ const GLuint *pConstantValue,
+ angle::ParamCapture *paramCapture);
+} // namespace gl
+
+#endif // LIBANGLE_CAPTURE_GL_4_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/capture/capture_gles_1_0_autogen.h b/gfx/angle/checkout/src/libANGLE/capture/capture_gles_1_0_autogen.h
new file mode 100644
index 0000000000..009ddb9977
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/capture_gles_1_0_autogen.h
@@ -0,0 +1,582 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// capture_gles_1_0_autogen.h:
+// Capture functions for the OpenGL ES 1.0 entry points.
+
+#ifndef LIBANGLE_CAPTURE_GLES_1_0_AUTOGEN_H_
+#define LIBANGLE_CAPTURE_GLES_1_0_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "libANGLE/capture/FrameCapture.h"
+
+namespace gl
+{
+
+// Method Captures
+
+angle::CallCapture CaptureAlphaFunc(const State &glState,
+ bool isCallValid,
+ AlphaTestFunc funcPacked,
+ GLfloat ref);
+angle::CallCapture CaptureAlphaFuncx(const State &glState,
+ bool isCallValid,
+ AlphaTestFunc funcPacked,
+ GLfixed ref);
+angle::CallCapture CaptureClearColorx(const State &glState,
+ bool isCallValid,
+ GLfixed red,
+ GLfixed green,
+ GLfixed blue,
+ GLfixed alpha);
+angle::CallCapture CaptureClearDepthx(const State &glState, bool isCallValid, GLfixed depth);
+angle::CallCapture CaptureClientActiveTexture(const State &glState,
+ bool isCallValid,
+ GLenum texture);
+angle::CallCapture CaptureClipPlanef(const State &glState,
+ bool isCallValid,
+ GLenum p,
+ const GLfloat *eqn);
+angle::CallCapture CaptureClipPlanex(const State &glState,
+ bool isCallValid,
+ GLenum plane,
+ const GLfixed *equation);
+angle::CallCapture CaptureColor4f(const State &glState,
+ bool isCallValid,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue,
+ GLfloat alpha);
+angle::CallCapture CaptureColor4ub(const State &glState,
+ bool isCallValid,
+ GLubyte red,
+ GLubyte green,
+ GLubyte blue,
+ GLubyte alpha);
+angle::CallCapture CaptureColor4x(const State &glState,
+ bool isCallValid,
+ GLfixed red,
+ GLfixed green,
+ GLfixed blue,
+ GLfixed alpha);
+angle::CallCapture CaptureColorPointer(const State &glState,
+ bool isCallValid,
+ GLint size,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer);
+angle::CallCapture CaptureDepthRangex(const State &glState, bool isCallValid, GLfixed n, GLfixed f);
+angle::CallCapture CaptureDisableClientState(const State &glState,
+ bool isCallValid,
+ ClientVertexArrayType arrayPacked);
+angle::CallCapture CaptureEnableClientState(const State &glState,
+ bool isCallValid,
+ ClientVertexArrayType arrayPacked);
+angle::CallCapture CaptureFogf(const State &glState, bool isCallValid, GLenum pname, GLfloat param);
+angle::CallCapture CaptureFogfv(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLfloat *params);
+angle::CallCapture CaptureFogx(const State &glState, bool isCallValid, GLenum pname, GLfixed param);
+angle::CallCapture CaptureFogxv(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLfixed *param);
+angle::CallCapture CaptureFrustumf(const State &glState,
+ bool isCallValid,
+ GLfloat l,
+ GLfloat r,
+ GLfloat b,
+ GLfloat t,
+ GLfloat n,
+ GLfloat f);
+angle::CallCapture CaptureFrustumx(const State &glState,
+ bool isCallValid,
+ GLfixed l,
+ GLfixed r,
+ GLfixed b,
+ GLfixed t,
+ GLfixed n,
+ GLfixed f);
+angle::CallCapture CaptureGetClipPlanef(const State &glState,
+ bool isCallValid,
+ GLenum plane,
+ GLfloat *equation);
+angle::CallCapture CaptureGetClipPlanex(const State &glState,
+ bool isCallValid,
+ GLenum plane,
+ GLfixed *equation);
+angle::CallCapture CaptureGetFixedv(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLfixed *params);
+angle::CallCapture CaptureGetLightfv(const State &glState,
+ bool isCallValid,
+ GLenum light,
+ LightParameter pnamePacked,
+ GLfloat *params);
+angle::CallCapture CaptureGetLightxv(const State &glState,
+ bool isCallValid,
+ GLenum light,
+ LightParameter pnamePacked,
+ GLfixed *params);
+angle::CallCapture CaptureGetMaterialfv(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ GLfloat *params);
+angle::CallCapture CaptureGetMaterialxv(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ GLfixed *params);
+angle::CallCapture CaptureGetTexEnvfv(const State &glState,
+ bool isCallValid,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ GLfloat *params);
+angle::CallCapture CaptureGetTexEnviv(const State &glState,
+ bool isCallValid,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ GLint *params);
+angle::CallCapture CaptureGetTexEnvxv(const State &glState,
+ bool isCallValid,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ GLfixed *params);
+angle::CallCapture CaptureGetTexParameterxv(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLfixed *params);
+angle::CallCapture CaptureLightModelf(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLfloat param);
+angle::CallCapture CaptureLightModelfv(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLfloat *params);
+angle::CallCapture CaptureLightModelx(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLfixed param);
+angle::CallCapture CaptureLightModelxv(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLfixed *param);
+angle::CallCapture CaptureLightf(const State &glState,
+ bool isCallValid,
+ GLenum light,
+ LightParameter pnamePacked,
+ GLfloat param);
+angle::CallCapture CaptureLightfv(const State &glState,
+ bool isCallValid,
+ GLenum light,
+ LightParameter pnamePacked,
+ const GLfloat *params);
+angle::CallCapture CaptureLightx(const State &glState,
+ bool isCallValid,
+ GLenum light,
+ LightParameter pnamePacked,
+ GLfixed param);
+angle::CallCapture CaptureLightxv(const State &glState,
+ bool isCallValid,
+ GLenum light,
+ LightParameter pnamePacked,
+ const GLfixed *params);
+angle::CallCapture CaptureLineWidthx(const State &glState, bool isCallValid, GLfixed width);
+angle::CallCapture CaptureLoadIdentity(const State &glState, bool isCallValid);
+angle::CallCapture CaptureLoadMatrixf(const State &glState, bool isCallValid, const GLfloat *m);
+angle::CallCapture CaptureLoadMatrixx(const State &glState, bool isCallValid, const GLfixed *m);
+angle::CallCapture CaptureLogicOp(const State &glState,
+ bool isCallValid,
+ LogicalOperation opcodePacked);
+angle::CallCapture CaptureMaterialf(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ GLfloat param);
+angle::CallCapture CaptureMaterialfv(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ const GLfloat *params);
+angle::CallCapture CaptureMaterialx(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ GLfixed param);
+angle::CallCapture CaptureMaterialxv(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ const GLfixed *param);
+angle::CallCapture CaptureMatrixMode(const State &glState, bool isCallValid, MatrixType modePacked);
+angle::CallCapture CaptureMultMatrixf(const State &glState, bool isCallValid, const GLfloat *m);
+angle::CallCapture CaptureMultMatrixx(const State &glState, bool isCallValid, const GLfixed *m);
+angle::CallCapture CaptureMultiTexCoord4f(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLfloat s,
+ GLfloat t,
+ GLfloat r,
+ GLfloat q);
+angle::CallCapture CaptureMultiTexCoord4x(const State &glState,
+ bool isCallValid,
+ GLenum texture,
+ GLfixed s,
+ GLfixed t,
+ GLfixed r,
+ GLfixed q);
+angle::CallCapture CaptureNormal3f(const State &glState,
+ bool isCallValid,
+ GLfloat nx,
+ GLfloat ny,
+ GLfloat nz);
+angle::CallCapture CaptureNormal3x(const State &glState,
+ bool isCallValid,
+ GLfixed nx,
+ GLfixed ny,
+ GLfixed nz);
+angle::CallCapture CaptureNormalPointer(const State &glState,
+ bool isCallValid,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer);
+angle::CallCapture CaptureOrthof(const State &glState,
+ bool isCallValid,
+ GLfloat l,
+ GLfloat r,
+ GLfloat b,
+ GLfloat t,
+ GLfloat n,
+ GLfloat f);
+angle::CallCapture CaptureOrthox(const State &glState,
+ bool isCallValid,
+ GLfixed l,
+ GLfixed r,
+ GLfixed b,
+ GLfixed t,
+ GLfixed n,
+ GLfixed f);
+angle::CallCapture CapturePointParameterf(const State &glState,
+ bool isCallValid,
+ PointParameter pnamePacked,
+ GLfloat param);
+angle::CallCapture CapturePointParameterfv(const State &glState,
+ bool isCallValid,
+ PointParameter pnamePacked,
+ const GLfloat *params);
+angle::CallCapture CapturePointParameterx(const State &glState,
+ bool isCallValid,
+ PointParameter pnamePacked,
+ GLfixed param);
+angle::CallCapture CapturePointParameterxv(const State &glState,
+ bool isCallValid,
+ PointParameter pnamePacked,
+ const GLfixed *params);
+angle::CallCapture CapturePointSize(const State &glState, bool isCallValid, GLfloat size);
+angle::CallCapture CapturePointSizex(const State &glState, bool isCallValid, GLfixed size);
+angle::CallCapture CapturePolygonOffsetx(const State &glState,
+ bool isCallValid,
+ GLfixed factor,
+ GLfixed units);
+angle::CallCapture CapturePopMatrix(const State &glState, bool isCallValid);
+angle::CallCapture CapturePushMatrix(const State &glState, bool isCallValid);
+angle::CallCapture CaptureRotatef(const State &glState,
+ bool isCallValid,
+ GLfloat angle,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z);
+angle::CallCapture CaptureRotatex(const State &glState,
+ bool isCallValid,
+ GLfixed angle,
+ GLfixed x,
+ GLfixed y,
+ GLfixed z);
+angle::CallCapture CaptureSampleCoveragex(const State &glState,
+ bool isCallValid,
+ GLclampx value,
+ GLboolean invert);
+angle::CallCapture CaptureScalef(const State &glState,
+ bool isCallValid,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z);
+angle::CallCapture CaptureScalex(const State &glState,
+ bool isCallValid,
+ GLfixed x,
+ GLfixed y,
+ GLfixed z);
+angle::CallCapture CaptureShadeModel(const State &glState,
+ bool isCallValid,
+ ShadingModel modePacked);
+angle::CallCapture CaptureTexCoordPointer(const State &glState,
+ bool isCallValid,
+ GLint size,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer);
+angle::CallCapture CaptureTexEnvf(const State &glState,
+ bool isCallValid,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ GLfloat param);
+angle::CallCapture CaptureTexEnvfv(const State &glState,
+ bool isCallValid,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ const GLfloat *params);
+angle::CallCapture CaptureTexEnvi(const State &glState,
+ bool isCallValid,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ GLint param);
+angle::CallCapture CaptureTexEnviv(const State &glState,
+ bool isCallValid,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ const GLint *params);
+angle::CallCapture CaptureTexEnvx(const State &glState,
+ bool isCallValid,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ GLfixed param);
+angle::CallCapture CaptureTexEnvxv(const State &glState,
+ bool isCallValid,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ const GLfixed *params);
+angle::CallCapture CaptureTexParameterx(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLfixed param);
+angle::CallCapture CaptureTexParameterxv(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLfixed *params);
+angle::CallCapture CaptureTranslatef(const State &glState,
+ bool isCallValid,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z);
+angle::CallCapture CaptureTranslatex(const State &glState,
+ bool isCallValid,
+ GLfixed x,
+ GLfixed y,
+ GLfixed z);
+angle::CallCapture CaptureVertexPointer(const State &glState,
+ bool isCallValid,
+ GLint size,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer);
+
+// Parameter Captures
+
+void CaptureClipPlanef_eqn(const State &glState,
+ bool isCallValid,
+ GLenum p,
+ const GLfloat *eqn,
+ angle::ParamCapture *paramCapture);
+void CaptureClipPlanex_equation(const State &glState,
+ bool isCallValid,
+ GLenum plane,
+ const GLfixed *equation,
+ angle::ParamCapture *paramCapture);
+void CaptureColorPointer_pointer(const State &glState,
+ bool isCallValid,
+ GLint size,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer,
+ angle::ParamCapture *paramCapture);
+void CaptureFogfv_params(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureFogxv_param(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLfixed *param,
+ angle::ParamCapture *paramCapture);
+void CaptureGetClipPlanef_equation(const State &glState,
+ bool isCallValid,
+ GLenum plane,
+ GLfloat *equation,
+ angle::ParamCapture *paramCapture);
+void CaptureGetClipPlanex_equation(const State &glState,
+ bool isCallValid,
+ GLenum plane,
+ GLfixed *equation,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFixedv_params(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLfixed *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetLightfv_params(const State &glState,
+ bool isCallValid,
+ GLenum light,
+ LightParameter pnamePacked,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetLightxv_params(const State &glState,
+ bool isCallValid,
+ GLenum light,
+ LightParameter pnamePacked,
+ GLfixed *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetMaterialfv_params(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetMaterialxv_params(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ GLfixed *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexEnvfv_params(const State &glState,
+ bool isCallValid,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexEnviv_params(const State &glState,
+ bool isCallValid,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexEnvxv_params(const State &glState,
+ bool isCallValid,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ GLfixed *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterxv_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLfixed *params,
+ angle::ParamCapture *paramCapture);
+void CaptureLightModelfv_params(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureLightModelxv_param(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ const GLfixed *param,
+ angle::ParamCapture *paramCapture);
+void CaptureLightfv_params(const State &glState,
+ bool isCallValid,
+ GLenum light,
+ LightParameter pnamePacked,
+ const GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureLightxv_params(const State &glState,
+ bool isCallValid,
+ GLenum light,
+ LightParameter pnamePacked,
+ const GLfixed *params,
+ angle::ParamCapture *paramCapture);
+void CaptureLoadMatrixf_m(const State &glState,
+ bool isCallValid,
+ const GLfloat *m,
+ angle::ParamCapture *paramCapture);
+void CaptureLoadMatrixx_m(const State &glState,
+ bool isCallValid,
+ const GLfixed *m,
+ angle::ParamCapture *paramCapture);
+void CaptureMaterialfv_params(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ const GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureMaterialxv_param(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ const GLfixed *param,
+ angle::ParamCapture *paramCapture);
+void CaptureMultMatrixf_m(const State &glState,
+ bool isCallValid,
+ const GLfloat *m,
+ angle::ParamCapture *paramCapture);
+void CaptureMultMatrixx_m(const State &glState,
+ bool isCallValid,
+ const GLfixed *m,
+ angle::ParamCapture *paramCapture);
+void CaptureNormalPointer_pointer(const State &glState,
+ bool isCallValid,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer,
+ angle::ParamCapture *paramCapture);
+void CapturePointParameterfv_params(const State &glState,
+ bool isCallValid,
+ PointParameter pnamePacked,
+ const GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CapturePointParameterxv_params(const State &glState,
+ bool isCallValid,
+ PointParameter pnamePacked,
+ const GLfixed *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexCoordPointer_pointer(const State &glState,
+ bool isCallValid,
+ GLint size,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer,
+ angle::ParamCapture *paramCapture);
+void CaptureTexEnvfv_params(const State &glState,
+ bool isCallValid,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ const GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexEnviv_params(const State &glState,
+ bool isCallValid,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexEnvxv_params(const State &glState,
+ bool isCallValid,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ const GLfixed *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexParameterxv_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLfixed *params,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexPointer_pointer(const State &glState,
+ bool isCallValid,
+ GLint size,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer,
+ angle::ParamCapture *paramCapture);
+} // namespace gl
+
+#endif // LIBANGLE_CAPTURE_GLES_1_0_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/capture/capture_gles_2_0_autogen.h b/gfx/angle/checkout/src/libANGLE/capture/capture_gles_2_0_autogen.h
new file mode 100644
index 0000000000..d4d1d978a2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/capture_gles_2_0_autogen.h
@@ -0,0 +1,1195 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// capture_gles_2_0_autogen.h:
+// Capture functions for the OpenGL ES 2.0 entry points.
+
+#ifndef LIBANGLE_CAPTURE_GLES_2_0_AUTOGEN_H_
+#define LIBANGLE_CAPTURE_GLES_2_0_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "libANGLE/capture/FrameCapture.h"
+
+namespace gl
+{
+
+// Method Captures
+
+angle::CallCapture CaptureActiveTexture(const State &glState, bool isCallValid, GLenum texture);
+angle::CallCapture CaptureAttachShader(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ ShaderProgramID shaderPacked);
+angle::CallCapture CaptureBindAttribLocation(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ const GLchar *name);
+angle::CallCapture CaptureBindBuffer(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ BufferID bufferPacked);
+angle::CallCapture CaptureBindFramebuffer(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ FramebufferID framebufferPacked);
+angle::CallCapture CaptureBindRenderbuffer(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ RenderbufferID renderbufferPacked);
+angle::CallCapture CaptureBindTexture(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ TextureID texturePacked);
+angle::CallCapture CaptureBlendColor(const State &glState,
+ bool isCallValid,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue,
+ GLfloat alpha);
+angle::CallCapture CaptureBlendEquation(const State &glState, bool isCallValid, GLenum mode);
+angle::CallCapture CaptureBlendEquationSeparate(const State &glState,
+ bool isCallValid,
+ GLenum modeRGB,
+ GLenum modeAlpha);
+angle::CallCapture CaptureBlendFunc(const State &glState,
+ bool isCallValid,
+ GLenum sfactor,
+ GLenum dfactor);
+angle::CallCapture CaptureBlendFuncSeparate(const State &glState,
+ bool isCallValid,
+ GLenum sfactorRGB,
+ GLenum dfactorRGB,
+ GLenum sfactorAlpha,
+ GLenum dfactorAlpha);
+angle::CallCapture CaptureBufferData(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLsizeiptr size,
+ const void *data,
+ BufferUsage usagePacked);
+angle::CallCapture CaptureBufferSubData(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data);
+angle::CallCapture CaptureCheckFramebufferStatus(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum returnValue);
+angle::CallCapture CaptureClear(const State &glState, bool isCallValid, GLbitfield mask);
+angle::CallCapture CaptureClearColor(const State &glState,
+ bool isCallValid,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue,
+ GLfloat alpha);
+angle::CallCapture CaptureClearDepthf(const State &glState, bool isCallValid, GLfloat d);
+angle::CallCapture CaptureClearStencil(const State &glState, bool isCallValid, GLint s);
+angle::CallCapture CaptureColorMask(const State &glState,
+ bool isCallValid,
+ GLboolean red,
+ GLboolean green,
+ GLboolean blue,
+ GLboolean alpha);
+angle::CallCapture CaptureCompileShader(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked);
+angle::CallCapture CaptureCompressedTexImage2D(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const void *data);
+angle::CallCapture CaptureCompressedTexSubImage2D(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+angle::CallCapture CaptureCopyTexImage2D(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border);
+angle::CallCapture CaptureCopyTexSubImage2D(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureCreateProgram(const State &glState, bool isCallValid, GLuint returnValue);
+angle::CallCapture CaptureCreateShader(const State &glState,
+ bool isCallValid,
+ ShaderType typePacked,
+ GLuint returnValue);
+angle::CallCapture CaptureCullFace(const State &glState, bool isCallValid, CullFaceMode modePacked);
+angle::CallCapture CaptureDeleteBuffers(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const BufferID *buffersPacked);
+angle::CallCapture CaptureDeleteFramebuffers(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const FramebufferID *framebuffersPacked);
+angle::CallCapture CaptureDeleteProgram(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked);
+angle::CallCapture CaptureDeleteRenderbuffers(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const RenderbufferID *renderbuffersPacked);
+angle::CallCapture CaptureDeleteShader(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked);
+angle::CallCapture CaptureDeleteTextures(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const TextureID *texturesPacked);
+angle::CallCapture CaptureDepthFunc(const State &glState, bool isCallValid, GLenum func);
+angle::CallCapture CaptureDepthMask(const State &glState, bool isCallValid, GLboolean flag);
+angle::CallCapture CaptureDepthRangef(const State &glState, bool isCallValid, GLfloat n, GLfloat f);
+angle::CallCapture CaptureDetachShader(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ ShaderProgramID shaderPacked);
+angle::CallCapture CaptureDisable(const State &glState, bool isCallValid, GLenum cap);
+angle::CallCapture CaptureDisableVertexAttribArray(const State &glState,
+ bool isCallValid,
+ GLuint index);
+angle::CallCapture CaptureDrawArrays(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLint first,
+ GLsizei count);
+angle::CallCapture CaptureDrawElements(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices);
+angle::CallCapture CaptureEnable(const State &glState, bool isCallValid, GLenum cap);
+angle::CallCapture CaptureEnableVertexAttribArray(const State &glState,
+ bool isCallValid,
+ GLuint index);
+angle::CallCapture CaptureFinish(const State &glState, bool isCallValid);
+angle::CallCapture CaptureFlush(const State &glState, bool isCallValid);
+angle::CallCapture CaptureFramebufferRenderbuffer(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ RenderbufferID renderbufferPacked);
+angle::CallCapture CaptureFramebufferTexture2D(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texturePacked,
+ GLint level);
+angle::CallCapture CaptureFrontFace(const State &glState, bool isCallValid, GLenum mode);
+angle::CallCapture CaptureGenBuffers(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ BufferID *buffersPacked);
+angle::CallCapture CaptureGenFramebuffers(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ FramebufferID *framebuffersPacked);
+angle::CallCapture CaptureGenRenderbuffers(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ RenderbufferID *renderbuffersPacked);
+angle::CallCapture CaptureGenTextures(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ TextureID *texturesPacked);
+angle::CallCapture CaptureGenerateMipmap(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked);
+angle::CallCapture CaptureGetActiveAttrib(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name);
+angle::CallCapture CaptureGetActiveUniform(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name);
+angle::CallCapture CaptureGetAttachedShaders(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei maxCount,
+ GLsizei *count,
+ ShaderProgramID *shadersPacked);
+angle::CallCapture CaptureGetAttribLocation(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ const GLchar *name,
+ GLint returnValue);
+angle::CallCapture CaptureGetBooleanv(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLboolean *data);
+angle::CallCapture CaptureGetBufferParameteriv(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetError(const State &glState, bool isCallValid, GLenum returnValue);
+angle::CallCapture CaptureGetFloatv(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLfloat *data);
+angle::CallCapture CaptureGetFramebufferAttachmentParameteriv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetIntegerv(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLint *data);
+angle::CallCapture CaptureGetProgramInfoLog(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog);
+angle::CallCapture CaptureGetProgramiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetRenderbufferParameteriv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetShaderInfoLog(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog);
+angle::CallCapture CaptureGetShaderPrecisionFormat(const State &glState,
+ bool isCallValid,
+ GLenum shadertype,
+ GLenum precisiontype,
+ GLint *range,
+ GLint *precision);
+angle::CallCapture CaptureGetShaderSource(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *source);
+angle::CallCapture CaptureGetShaderiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetString(const State &glState,
+ bool isCallValid,
+ GLenum name,
+ const GLubyte *returnValue);
+angle::CallCapture CaptureGetTexParameterfv(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLfloat *params);
+angle::CallCapture CaptureGetTexParameteriv(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetUniformLocation(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ const GLchar *name,
+ GLint returnValue);
+angle::CallCapture CaptureGetUniformfv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat *params);
+angle::CallCapture CaptureGetUniformiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint *params);
+angle::CallCapture CaptureGetVertexAttribPointerv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ void **pointer);
+angle::CallCapture CaptureGetVertexAttribfv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLfloat *params);
+angle::CallCapture CaptureGetVertexAttribiv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureHint(const State &glState, bool isCallValid, GLenum target, GLenum mode);
+angle::CallCapture CaptureIsBuffer(const State &glState,
+ bool isCallValid,
+ BufferID bufferPacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureIsEnabled(const State &glState,
+ bool isCallValid,
+ GLenum cap,
+ GLboolean returnValue);
+angle::CallCapture CaptureIsFramebuffer(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureIsProgram(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureIsRenderbuffer(const State &glState,
+ bool isCallValid,
+ RenderbufferID renderbufferPacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureIsShader(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureIsTexture(const State &glState,
+ bool isCallValid,
+ TextureID texturePacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureLineWidth(const State &glState, bool isCallValid, GLfloat width);
+angle::CallCapture CaptureLinkProgram(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked);
+angle::CallCapture CapturePixelStorei(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLint param);
+angle::CallCapture CapturePolygonOffset(const State &glState,
+ bool isCallValid,
+ GLfloat factor,
+ GLfloat units);
+angle::CallCapture CaptureReadPixels(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ void *pixels);
+angle::CallCapture CaptureReleaseShaderCompiler(const State &glState, bool isCallValid);
+angle::CallCapture CaptureRenderbufferStorage(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureSampleCoverage(const State &glState,
+ bool isCallValid,
+ GLfloat value,
+ GLboolean invert);
+angle::CallCapture CaptureScissor(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureShaderBinary(const State &glState,
+ bool isCallValid,
+ GLsizei count,
+ const ShaderProgramID *shadersPacked,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length);
+angle::CallCapture CaptureShaderSource(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLsizei count,
+ const GLchar *const *string,
+ const GLint *length);
+angle::CallCapture CaptureStencilFunc(const State &glState,
+ bool isCallValid,
+ GLenum func,
+ GLint ref,
+ GLuint mask);
+angle::CallCapture CaptureStencilFuncSeparate(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ GLenum func,
+ GLint ref,
+ GLuint mask);
+angle::CallCapture CaptureStencilMask(const State &glState, bool isCallValid, GLuint mask);
+angle::CallCapture CaptureStencilMaskSeparate(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ GLuint mask);
+angle::CallCapture CaptureStencilOp(const State &glState,
+ bool isCallValid,
+ GLenum fail,
+ GLenum zfail,
+ GLenum zpass);
+angle::CallCapture CaptureStencilOpSeparate(const State &glState,
+ bool isCallValid,
+ GLenum face,
+ GLenum sfail,
+ GLenum dpfail,
+ GLenum dppass);
+angle::CallCapture CaptureTexImage2D(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+angle::CallCapture CaptureTexParameterf(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLfloat param);
+angle::CallCapture CaptureTexParameterfv(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLfloat *params);
+angle::CallCapture CaptureTexParameteri(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLint param);
+angle::CallCapture CaptureTexParameteriv(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params);
+angle::CallCapture CaptureTexSubImage2D(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+angle::CallCapture CaptureUniform1f(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLfloat v0);
+angle::CallCapture CaptureUniform1fv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+angle::CallCapture CaptureUniform1i(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLint v0);
+angle::CallCapture CaptureUniform1iv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+angle::CallCapture CaptureUniform2f(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1);
+angle::CallCapture CaptureUniform2fv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+angle::CallCapture CaptureUniform2i(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1);
+angle::CallCapture CaptureUniform2iv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+angle::CallCapture CaptureUniform3f(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2);
+angle::CallCapture CaptureUniform3fv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+angle::CallCapture CaptureUniform3i(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2);
+angle::CallCapture CaptureUniform3iv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+angle::CallCapture CaptureUniform4f(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2,
+ GLfloat v3);
+angle::CallCapture CaptureUniform4fv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+angle::CallCapture CaptureUniform4i(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2,
+ GLint v3);
+angle::CallCapture CaptureUniform4iv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+angle::CallCapture CaptureUniformMatrix2fv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureUniformMatrix3fv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureUniformMatrix4fv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureUseProgram(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked);
+angle::CallCapture CaptureValidateProgram(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked);
+angle::CallCapture CaptureVertexAttrib1f(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLfloat x);
+angle::CallCapture CaptureVertexAttrib1fv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLfloat *v);
+angle::CallCapture CaptureVertexAttrib2f(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLfloat x,
+ GLfloat y);
+angle::CallCapture CaptureVertexAttrib2fv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLfloat *v);
+angle::CallCapture CaptureVertexAttrib3f(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z);
+angle::CallCapture CaptureVertexAttrib3fv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLfloat *v);
+angle::CallCapture CaptureVertexAttrib4f(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w);
+angle::CallCapture CaptureVertexAttrib4fv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLfloat *v);
+angle::CallCapture CaptureVertexAttribPointer(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLint size,
+ VertexAttribType typePacked,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *pointer);
+angle::CallCapture CaptureViewport(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+
+// Parameter Captures
+
+void CaptureBindAttribLocation_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureBufferData_data(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLsizeiptr size,
+ const void *data,
+ BufferUsage usagePacked,
+ angle::ParamCapture *paramCapture);
+void CaptureBufferSubData_data(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureCompressedTexImage2D_data(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureCompressedTexSubImage2D_data(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteBuffers_buffersPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const BufferID *buffersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteFramebuffers_framebuffersPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const FramebufferID *framebuffersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteRenderbuffers_renderbuffersPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const RenderbufferID *renderbuffersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteTextures_texturesPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const TextureID *texturesPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawElements_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ angle::ParamCapture *paramCapture);
+void CaptureGenBuffers_buffersPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ BufferID *buffersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGenFramebuffers_framebuffersPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ FramebufferID *framebuffersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGenRenderbuffers_renderbuffersPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ RenderbufferID *renderbuffersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGenTextures_texturesPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ TextureID *texturesPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveAttrib_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveAttrib_size(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveAttrib_type(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveAttrib_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveUniform_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveUniform_size(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveUniform_type(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveUniform_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *size,
+ GLenum *type,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetAttachedShaders_count(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei maxCount,
+ GLsizei *count,
+ ShaderProgramID *shadersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGetAttachedShaders_shadersPacked(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei maxCount,
+ GLsizei *count,
+ ShaderProgramID *shadersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGetAttribLocation_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBooleanv_data(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLboolean *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBufferParameteriv_params(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFloatv_data(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLfloat *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFramebufferAttachmentParameteriv_params(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetIntegerv_data(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLint *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramInfoLog_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramInfoLog_infoLog(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramiv_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetRenderbufferParameteriv_params(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetShaderInfoLog_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetShaderInfoLog_infoLog(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetShaderPrecisionFormat_range(const State &glState,
+ bool isCallValid,
+ GLenum shadertype,
+ GLenum precisiontype,
+ GLint *range,
+ GLint *precision,
+ angle::ParamCapture *paramCapture);
+void CaptureGetShaderPrecisionFormat_precision(const State &glState,
+ bool isCallValid,
+ GLenum shadertype,
+ GLenum precisiontype,
+ GLint *range,
+ GLint *precision,
+ angle::ParamCapture *paramCapture);
+void CaptureGetShaderSource_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *source,
+ angle::ParamCapture *paramCapture);
+void CaptureGetShaderSource_source(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *source,
+ angle::ParamCapture *paramCapture);
+void CaptureGetShaderiv_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterfv_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameteriv_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUniformLocation_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUniformfv_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUniformiv_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribPointerv_pointer(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ void **pointer,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribfv_params(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribiv_params(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureReadPixels_pixels(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureShaderBinary_shadersPacked(const State &glState,
+ bool isCallValid,
+ GLsizei count,
+ const ShaderProgramID *shadersPacked,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length,
+ angle::ParamCapture *paramCapture);
+void CaptureShaderBinary_binary(const State &glState,
+ bool isCallValid,
+ GLsizei count,
+ const ShaderProgramID *shadersPacked,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length,
+ angle::ParamCapture *paramCapture);
+void CaptureShaderSource_string(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLsizei count,
+ const GLchar *const *string,
+ const GLint *length,
+ angle::ParamCapture *paramCapture);
+void CaptureShaderSource_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLsizei count,
+ const GLchar *const *string,
+ const GLint *length,
+ angle::ParamCapture *paramCapture);
+void CaptureTexImage2D_pixels(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureTexParameterfv_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexParameteriv_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexSubImage2D_pixels(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform1fv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform1iv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform2fv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform2iv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform3fv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform3iv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform4fv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform4iv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix2fv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix3fv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix4fv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib1fv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib2fv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib3fv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttrib4fv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLfloat *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribPointer_pointer(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLint size,
+ VertexAttribType typePacked,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *pointer,
+ angle::ParamCapture *paramCapture);
+} // namespace gl
+
+#endif // LIBANGLE_CAPTURE_GLES_2_0_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/capture/capture_gles_3_0_autogen.h b/gfx/angle/checkout/src/libANGLE/capture/capture_gles_3_0_autogen.h
new file mode 100644
index 0000000000..83e2f441b4
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/capture_gles_3_0_autogen.h
@@ -0,0 +1,1079 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// capture_gles_3_0_autogen.h:
+// Capture functions for the OpenGL ES 3.0 entry points.
+
+#ifndef LIBANGLE_CAPTURE_GLES_3_0_AUTOGEN_H_
+#define LIBANGLE_CAPTURE_GLES_3_0_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "libANGLE/capture/FrameCapture.h"
+
+namespace gl
+{
+
+// Method Captures
+
+angle::CallCapture CaptureBeginQuery(const State &glState,
+ bool isCallValid,
+ QueryType targetPacked,
+ QueryID idPacked);
+angle::CallCapture CaptureBeginTransformFeedback(const State &glState,
+ bool isCallValid,
+ PrimitiveMode primitiveModePacked);
+angle::CallCapture CaptureBindBufferBase(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLuint index,
+ BufferID bufferPacked);
+angle::CallCapture CaptureBindBufferRange(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLuint index,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size);
+angle::CallCapture CaptureBindSampler(const State &glState,
+ bool isCallValid,
+ GLuint unit,
+ SamplerID samplerPacked);
+angle::CallCapture CaptureBindTransformFeedback(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ TransformFeedbackID idPacked);
+angle::CallCapture CaptureBindVertexArray(const State &glState,
+ bool isCallValid,
+ VertexArrayID arrayPacked);
+angle::CallCapture CaptureBlitFramebuffer(const State &glState,
+ bool isCallValid,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+angle::CallCapture CaptureClearBufferfi(const State &glState,
+ bool isCallValid,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil);
+angle::CallCapture CaptureClearBufferfv(const State &glState,
+ bool isCallValid,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *value);
+angle::CallCapture CaptureClearBufferiv(const State &glState,
+ bool isCallValid,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *value);
+angle::CallCapture CaptureClearBufferuiv(const State &glState,
+ bool isCallValid,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *value);
+angle::CallCapture CaptureClientWaitSync(const State &glState,
+ bool isCallValid,
+ GLsync sync,
+ GLbitfield flags,
+ GLuint64 timeout,
+ GLenum returnValue);
+angle::CallCapture CaptureCompressedTexImage3D(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const void *data);
+angle::CallCapture CaptureCompressedTexSubImage3D(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+angle::CallCapture CaptureCopyBufferSubData(const State &glState,
+ bool isCallValid,
+ BufferBinding readTargetPacked,
+ BufferBinding writeTargetPacked,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size);
+angle::CallCapture CaptureCopyTexSubImage3D(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureDeleteQueries(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const QueryID *idsPacked);
+angle::CallCapture CaptureDeleteSamplers(const State &glState,
+ bool isCallValid,
+ GLsizei count,
+ const SamplerID *samplersPacked);
+angle::CallCapture CaptureDeleteSync(const State &glState, bool isCallValid, GLsync sync);
+angle::CallCapture CaptureDeleteTransformFeedbacks(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const TransformFeedbackID *idsPacked);
+angle::CallCapture CaptureDeleteVertexArrays(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const VertexArrayID *arraysPacked);
+angle::CallCapture CaptureDrawArraysInstanced(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLint first,
+ GLsizei count,
+ GLsizei instancecount);
+angle::CallCapture CaptureDrawBuffers(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const GLenum *bufs);
+angle::CallCapture CaptureDrawElementsInstanced(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount);
+angle::CallCapture CaptureDrawRangeElements(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices);
+angle::CallCapture CaptureEndQuery(const State &glState, bool isCallValid, QueryType targetPacked);
+angle::CallCapture CaptureEndTransformFeedback(const State &glState, bool isCallValid);
+angle::CallCapture CaptureFenceSync(const State &glState,
+ bool isCallValid,
+ GLenum condition,
+ GLbitfield flags,
+ GLsync returnValue);
+angle::CallCapture CaptureFlushMappedBufferRange(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLintptr offset,
+ GLsizeiptr length);
+angle::CallCapture CaptureFramebufferTextureLayer(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ TextureID texturePacked,
+ GLint level,
+ GLint layer);
+angle::CallCapture CaptureGenQueries(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ QueryID *idsPacked);
+angle::CallCapture CaptureGenSamplers(const State &glState,
+ bool isCallValid,
+ GLsizei count,
+ SamplerID *samplersPacked);
+angle::CallCapture CaptureGenTransformFeedbacks(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ TransformFeedbackID *idsPacked);
+angle::CallCapture CaptureGenVertexArrays(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ VertexArrayID *arraysPacked);
+angle::CallCapture CaptureGetActiveUniformBlockName(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformBlockIndex uniformBlockIndexPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformBlockName);
+angle::CallCapture CaptureGetActiveUniformBlockiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformBlockIndex uniformBlockIndexPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetActiveUniformsiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei uniformCount,
+ const GLuint *uniformIndices,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetBufferParameteri64v(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLint64 *params);
+angle::CallCapture CaptureGetBufferPointerv(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ void **params);
+angle::CallCapture CaptureGetFragDataLocation(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ const GLchar *name,
+ GLint returnValue);
+angle::CallCapture CaptureGetInteger64i_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLint64 *data);
+angle::CallCapture CaptureGetInteger64v(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLint64 *data);
+angle::CallCapture CaptureGetIntegeri_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLint *data);
+angle::CallCapture CaptureGetInternalformativ(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei count,
+ GLint *params);
+angle::CallCapture CaptureGetProgramBinary(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary);
+angle::CallCapture CaptureGetQueryObjectuiv(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLuint *params);
+angle::CallCapture CaptureGetQueryiv(const State &glState,
+ bool isCallValid,
+ QueryType targetPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetSamplerParameterfv(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLfloat *params);
+angle::CallCapture CaptureGetSamplerParameteriv(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetStringi(const State &glState,
+ bool isCallValid,
+ GLenum name,
+ GLuint index,
+ const GLubyte *returnValue);
+angle::CallCapture CaptureGetSynciv(const State &glState,
+ bool isCallValid,
+ GLsync sync,
+ GLenum pname,
+ GLsizei count,
+ GLsizei *length,
+ GLint *values);
+angle::CallCapture CaptureGetTransformFeedbackVarying(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name);
+angle::CallCapture CaptureGetUniformBlockIndex(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ const GLchar *uniformBlockName,
+ GLuint returnValue);
+angle::CallCapture CaptureGetUniformIndices(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei uniformCount,
+ const GLchar *const *uniformNames,
+ GLuint *uniformIndices);
+angle::CallCapture CaptureGetUniformuiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint *params);
+angle::CallCapture CaptureGetVertexAttribIiv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetVertexAttribIuiv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLuint *params);
+angle::CallCapture CaptureInvalidateFramebuffer(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments);
+angle::CallCapture CaptureInvalidateSubFramebuffer(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureIsQuery(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureIsSampler(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureIsSync(const State &glState,
+ bool isCallValid,
+ GLsync sync,
+ GLboolean returnValue);
+angle::CallCapture CaptureIsTransformFeedback(const State &glState,
+ bool isCallValid,
+ TransformFeedbackID idPacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureIsVertexArray(const State &glState,
+ bool isCallValid,
+ VertexArrayID arrayPacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureMapBufferRange(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access,
+ void *returnValue);
+angle::CallCapture CapturePauseTransformFeedback(const State &glState, bool isCallValid);
+angle::CallCapture CaptureProgramBinary(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length);
+angle::CallCapture CaptureProgramParameteri(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum pname,
+ GLint value);
+angle::CallCapture CaptureReadBuffer(const State &glState, bool isCallValid, GLenum src);
+angle::CallCapture CaptureRenderbufferStorageMultisample(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureResumeTransformFeedback(const State &glState, bool isCallValid);
+angle::CallCapture CaptureSamplerParameterf(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLfloat param);
+angle::CallCapture CaptureSamplerParameterfv(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLfloat *param);
+angle::CallCapture CaptureSamplerParameteri(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLint param);
+angle::CallCapture CaptureSamplerParameteriv(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *param);
+angle::CallCapture CaptureTexImage3D(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+angle::CallCapture CaptureTexStorage2D(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureTexStorage3D(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+angle::CallCapture CaptureTexSubImage3D(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+angle::CallCapture CaptureTransformFeedbackVaryings(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode);
+angle::CallCapture CaptureUniform1ui(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLuint v0);
+angle::CallCapture CaptureUniform1uiv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+angle::CallCapture CaptureUniform2ui(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1);
+angle::CallCapture CaptureUniform2uiv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+angle::CallCapture CaptureUniform3ui(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2);
+angle::CallCapture CaptureUniform3uiv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+angle::CallCapture CaptureUniform4ui(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3);
+angle::CallCapture CaptureUniform4uiv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+angle::CallCapture CaptureUniformBlockBinding(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformBlockIndex uniformBlockIndexPacked,
+ GLuint uniformBlockBinding);
+angle::CallCapture CaptureUniformMatrix2x3fv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureUniformMatrix2x4fv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureUniformMatrix3x2fv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureUniformMatrix3x4fv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureUniformMatrix4x2fv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureUniformMatrix4x3fv(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureUnmapBuffer(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureVertexAttribDivisor(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLuint divisor);
+angle::CallCapture CaptureVertexAttribI4i(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint w);
+angle::CallCapture CaptureVertexAttribI4iv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLint *v);
+angle::CallCapture CaptureVertexAttribI4ui(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLuint x,
+ GLuint y,
+ GLuint z,
+ GLuint w);
+angle::CallCapture CaptureVertexAttribI4uiv(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLuint *v);
+angle::CallCapture CaptureVertexAttribIPointer(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLint size,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer);
+angle::CallCapture CaptureWaitSync(const State &glState,
+ bool isCallValid,
+ GLsync sync,
+ GLbitfield flags,
+ GLuint64 timeout);
+
+// Parameter Captures
+
+void CaptureClearBufferfv_value(const State &glState,
+ bool isCallValid,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureClearBufferiv_value(const State &glState,
+ bool isCallValid,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureClearBufferuiv_value(const State &glState,
+ bool isCallValid,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureCompressedTexImage3D_data(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureCompressedTexSubImage3D_data(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteQueries_idsPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const QueryID *idsPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteSamplers_samplersPacked(const State &glState,
+ bool isCallValid,
+ GLsizei count,
+ const SamplerID *samplersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteTransformFeedbacks_idsPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const TransformFeedbackID *idsPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteVertexArrays_arraysPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const VertexArrayID *arraysPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawBuffers_bufs(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const GLenum *bufs,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawElementsInstanced_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawRangeElements_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ angle::ParamCapture *paramCapture);
+void CaptureGenQueries_idsPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ QueryID *idsPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGenSamplers_samplersPacked(const State &glState,
+ bool isCallValid,
+ GLsizei count,
+ SamplerID *samplersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGenTransformFeedbacks_idsPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ TransformFeedbackID *idsPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGenVertexArrays_arraysPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ VertexArrayID *arraysPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveUniformBlockName_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformBlockIndex uniformBlockIndexPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformBlockName,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveUniformBlockName_uniformBlockName(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformBlockIndex uniformBlockIndexPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformBlockName,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveUniformBlockiv_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformBlockIndex uniformBlockIndexPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveUniformsiv_uniformIndices(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei uniformCount,
+ const GLuint *uniformIndices,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveUniformsiv_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei uniformCount,
+ const GLuint *uniformIndices,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBufferParameteri64v_params(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLint64 *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBufferPointerv_params(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ void **params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFragDataLocation_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetInteger64i_v_data(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLint64 *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetInteger64v_data(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLint64 *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetIntegeri_v_data(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLint *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetInternalformativ_params(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei count,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramBinary_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramBinary_binaryFormat(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramBinary_binary(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjectuiv_params(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryiv_params(const State &glState,
+ bool isCallValid,
+ QueryType targetPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameterfv_params(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameteriv_params(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSynciv_length(const State &glState,
+ bool isCallValid,
+ GLsync sync,
+ GLenum pname,
+ GLsizei count,
+ GLsizei *length,
+ GLint *values,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSynciv_values(const State &glState,
+ bool isCallValid,
+ GLsync sync,
+ GLenum pname,
+ GLsizei count,
+ GLsizei *length,
+ GLint *values,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTransformFeedbackVarying_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTransformFeedbackVarying_size(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTransformFeedbackVarying_type(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTransformFeedbackVarying_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *size,
+ GLenum *type,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUniformBlockIndex_uniformBlockName(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ const GLchar *uniformBlockName,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUniformIndices_uniformNames(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei uniformCount,
+ const GLchar *const *uniformNames,
+ GLuint *uniformIndices,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUniformIndices_uniformIndices(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei uniformCount,
+ const GLchar *const *uniformNames,
+ GLuint *uniformIndices,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUniformuiv_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribIiv_params(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribIuiv_params(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureInvalidateFramebuffer_attachments(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ angle::ParamCapture *paramCapture);
+void CaptureInvalidateSubFramebuffer_attachments(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramBinary_binary(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length,
+ angle::ParamCapture *paramCapture);
+void CaptureSamplerParameterfv_param(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLfloat *param,
+ angle::ParamCapture *paramCapture);
+void CaptureSamplerParameteriv_param(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureTexImage3D_pixels(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureTexSubImage3D_pixels(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureTransformFeedbackVaryings_varyings(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform1uiv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform2uiv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform3uiv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniform4uiv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix2x3fv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix2x4fv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix3x2fv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix3x4fv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix4x2fv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureUniformMatrix4x3fv_value(const State &glState,
+ bool isCallValid,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribI4iv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribI4uiv_v(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ const GLuint *v,
+ angle::ParamCapture *paramCapture);
+void CaptureVertexAttribIPointer_pointer(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLint size,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer,
+ angle::ParamCapture *paramCapture);
+} // namespace gl
+
+#endif // LIBANGLE_CAPTURE_GLES_3_0_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/capture/capture_gles_3_1_autogen.h b/gfx/angle/checkout/src/libANGLE/capture/capture_gles_3_1_autogen.h
new file mode 100644
index 0000000000..ee594a1c79
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/capture_gles_3_1_autogen.h
@@ -0,0 +1,728 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// capture_gles_3_1_autogen.h:
+// Capture functions for the OpenGL ES 3.1 entry points.
+
+#ifndef LIBANGLE_CAPTURE_GLES_3_1_AUTOGEN_H_
+#define LIBANGLE_CAPTURE_GLES_3_1_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "libANGLE/capture/FrameCapture.h"
+
+namespace gl
+{
+
+// Method Captures
+
+angle::CallCapture CaptureActiveShaderProgram(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ ShaderProgramID programPacked);
+angle::CallCapture CaptureBindImageTexture(const State &glState,
+ bool isCallValid,
+ GLuint unit,
+ TextureID texturePacked,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format);
+angle::CallCapture CaptureBindProgramPipeline(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked);
+angle::CallCapture CaptureBindVertexBuffer(const State &glState,
+ bool isCallValid,
+ GLuint bindingindex,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizei stride);
+angle::CallCapture CaptureCreateShaderProgramv(const State &glState,
+ bool isCallValid,
+ ShaderType typePacked,
+ GLsizei count,
+ const GLchar *const *strings,
+ GLuint returnValue);
+angle::CallCapture CaptureDeleteProgramPipelines(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const ProgramPipelineID *pipelinesPacked);
+angle::CallCapture CaptureDispatchCompute(const State &glState,
+ bool isCallValid,
+ GLuint num_groups_x,
+ GLuint num_groups_y,
+ GLuint num_groups_z);
+angle::CallCapture CaptureDispatchComputeIndirect(const State &glState,
+ bool isCallValid,
+ GLintptr indirect);
+angle::CallCapture CaptureDrawArraysIndirect(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const void *indirect);
+angle::CallCapture CaptureDrawElementsIndirect(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ DrawElementsType typePacked,
+ const void *indirect);
+angle::CallCapture CaptureFramebufferParameteri(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLint param);
+angle::CallCapture CaptureGenProgramPipelines(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ ProgramPipelineID *pipelinesPacked);
+angle::CallCapture CaptureGetBooleani_v(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLboolean *data);
+angle::CallCapture CaptureGetFramebufferParameteriv(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetMultisamplefv(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLuint index,
+ GLfloat *val);
+angle::CallCapture CaptureGetProgramInterfaceiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetProgramPipelineInfoLog(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog);
+angle::CallCapture CaptureGetProgramPipelineiv(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetProgramResourceIndex(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ const GLchar *name,
+ GLuint returnValue);
+angle::CallCapture CaptureGetProgramResourceLocation(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ const GLchar *name,
+ GLint returnValue);
+angle::CallCapture CaptureGetProgramResourceName(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name);
+angle::CallCapture CaptureGetProgramResourceiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei count,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetTexLevelParameterfv(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLfloat *params);
+angle::CallCapture CaptureGetTexLevelParameteriv(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureIsProgramPipeline(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureMemoryBarrier(const State &glState,
+ bool isCallValid,
+ GLbitfield barriers);
+angle::CallCapture CaptureMemoryBarrierByRegion(const State &glState,
+ bool isCallValid,
+ GLbitfield barriers);
+angle::CallCapture CaptureProgramUniform1f(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0);
+angle::CallCapture CaptureProgramUniform1fv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniform1i(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0);
+angle::CallCapture CaptureProgramUniform1iv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+angle::CallCapture CaptureProgramUniform1ui(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0);
+angle::CallCapture CaptureProgramUniform1uiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+angle::CallCapture CaptureProgramUniform2f(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1);
+angle::CallCapture CaptureProgramUniform2fv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniform2i(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1);
+angle::CallCapture CaptureProgramUniform2iv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+angle::CallCapture CaptureProgramUniform2ui(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1);
+angle::CallCapture CaptureProgramUniform2uiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+angle::CallCapture CaptureProgramUniform3f(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2);
+angle::CallCapture CaptureProgramUniform3fv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniform3i(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2);
+angle::CallCapture CaptureProgramUniform3iv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+angle::CallCapture CaptureProgramUniform3ui(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2);
+angle::CallCapture CaptureProgramUniform3uiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+angle::CallCapture CaptureProgramUniform4f(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2,
+ GLfloat v3);
+angle::CallCapture CaptureProgramUniform4fv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniform4i(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2,
+ GLint v3);
+angle::CallCapture CaptureProgramUniform4iv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+angle::CallCapture CaptureProgramUniform4ui(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3);
+angle::CallCapture CaptureProgramUniform4uiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+angle::CallCapture CaptureProgramUniformMatrix2fv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix2x3fv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix2x4fv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix3fv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix3x2fv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix3x4fv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix4fv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix4x2fv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix4x3fv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureSampleMaski(const State &glState,
+ bool isCallValid,
+ GLuint maskNumber,
+ GLbitfield mask);
+angle::CallCapture CaptureTexStorage2DMultisample(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations);
+angle::CallCapture CaptureUseProgramStages(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ GLbitfield stages,
+ ShaderProgramID programPacked);
+angle::CallCapture CaptureValidateProgramPipeline(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked);
+angle::CallCapture CaptureVertexAttribBinding(const State &glState,
+ bool isCallValid,
+ GLuint attribindex,
+ GLuint bindingindex);
+angle::CallCapture CaptureVertexAttribFormat(const State &glState,
+ bool isCallValid,
+ GLuint attribindex,
+ GLint size,
+ VertexAttribType typePacked,
+ GLboolean normalized,
+ GLuint relativeoffset);
+angle::CallCapture CaptureVertexAttribIFormat(const State &glState,
+ bool isCallValid,
+ GLuint attribindex,
+ GLint size,
+ VertexAttribType typePacked,
+ GLuint relativeoffset);
+angle::CallCapture CaptureVertexBindingDivisor(const State &glState,
+ bool isCallValid,
+ GLuint bindingindex,
+ GLuint divisor);
+
+// Parameter Captures
+
+void CaptureCreateShaderProgramv_strings(const State &glState,
+ bool isCallValid,
+ ShaderType typePacked,
+ GLsizei count,
+ const GLchar *const *strings,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteProgramPipelines_pipelinesPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const ProgramPipelineID *pipelinesPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawArraysIndirect_indirect(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const void *indirect,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawElementsIndirect_indirect(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ DrawElementsType typePacked,
+ const void *indirect,
+ angle::ParamCapture *paramCapture);
+void CaptureGenProgramPipelines_pipelinesPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ ProgramPipelineID *pipelinesPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBooleani_v_data(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLboolean *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFramebufferParameteriv_params(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetMultisamplefv_val(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLuint index,
+ GLfloat *val,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramInterfaceiv_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramPipelineInfoLog_length(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramPipelineInfoLog_infoLog(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramPipelineiv_params(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramResourceIndex_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramResourceLocation_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramResourceName_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramResourceName_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramResourceiv_props(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei count,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramResourceiv_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei count,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramResourceiv_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei count,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexLevelParameterfv_params(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexLevelParameteriv_params(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform1fv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform1iv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform1uiv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform2fv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform2iv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform2uiv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform3fv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform3iv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform3uiv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform4fv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform4iv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform4uiv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix2fv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix2x3fv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix2x4fv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix3fv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix3x2fv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix3x4fv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix4fv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix4x2fv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix4x3fv_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+} // namespace gl
+
+#endif // LIBANGLE_CAPTURE_GLES_3_1_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/capture/capture_gles_3_2_autogen.h b/gfx/angle/checkout/src/libANGLE/capture/capture_gles_3_2_autogen.h
new file mode 100644
index 0000000000..80001a0348
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/capture_gles_3_2_autogen.h
@@ -0,0 +1,553 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// capture_gles_3_2_autogen.h:
+// Capture functions for the OpenGL ES 3.2 entry points.
+
+#ifndef LIBANGLE_CAPTURE_GLES_3_2_AUTOGEN_H_
+#define LIBANGLE_CAPTURE_GLES_3_2_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "libANGLE/capture/FrameCapture.h"
+
+namespace gl
+{
+
+// Method Captures
+
+angle::CallCapture CaptureBlendBarrier(const State &glState, bool isCallValid);
+angle::CallCapture CaptureBlendEquationSeparatei(const State &glState,
+ bool isCallValid,
+ GLuint buf,
+ GLenum modeRGB,
+ GLenum modeAlpha);
+angle::CallCapture CaptureBlendEquationi(const State &glState,
+ bool isCallValid,
+ GLuint buf,
+ GLenum mode);
+angle::CallCapture CaptureBlendFuncSeparatei(const State &glState,
+ bool isCallValid,
+ GLuint buf,
+ GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha);
+angle::CallCapture CaptureBlendFunci(const State &glState,
+ bool isCallValid,
+ GLuint buf,
+ GLenum src,
+ GLenum dst);
+angle::CallCapture CaptureColorMaski(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLboolean r,
+ GLboolean g,
+ GLboolean b,
+ GLboolean a);
+angle::CallCapture CaptureCopyImageSubData(const State &glState,
+ bool isCallValid,
+ GLuint srcName,
+ GLenum srcTarget,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLuint dstName,
+ GLenum dstTarget,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth);
+angle::CallCapture CaptureDebugMessageCallback(const State &glState,
+ bool isCallValid,
+ GLDEBUGPROC callback,
+ const void *userParam);
+angle::CallCapture CaptureDebugMessageControl(const State &glState,
+ bool isCallValid,
+ GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled);
+angle::CallCapture CaptureDebugMessageInsert(const State &glState,
+ bool isCallValid,
+ GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *buf);
+angle::CallCapture CaptureDisablei(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index);
+angle::CallCapture CaptureDrawElementsBaseVertex(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex);
+angle::CallCapture CaptureDrawElementsInstancedBaseVertex(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex);
+angle::CallCapture CaptureDrawRangeElementsBaseVertex(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex);
+angle::CallCapture CaptureEnablei(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index);
+angle::CallCapture CaptureFramebufferTexture(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ TextureID texturePacked,
+ GLint level);
+angle::CallCapture CaptureGetDebugMessageLog(const State &glState,
+ bool isCallValid,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog,
+ GLuint returnValue);
+angle::CallCapture CaptureGetGraphicsResetStatus(const State &glState,
+ bool isCallValid,
+ GLenum returnValue);
+angle::CallCapture CaptureGetObjectLabel(const State &glState,
+ bool isCallValid,
+ GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label);
+angle::CallCapture CaptureGetObjectPtrLabel(const State &glState,
+ bool isCallValid,
+ const void *ptr,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label);
+angle::CallCapture CaptureGetPointerv(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ void **params);
+angle::CallCapture CaptureGetSamplerParameterIiv(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetSamplerParameterIuiv(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLuint *params);
+angle::CallCapture CaptureGetTexParameterIiv(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetTexParameterIuiv(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLuint *params);
+angle::CallCapture CaptureGetnUniformfv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLfloat *params);
+angle::CallCapture CaptureGetnUniformiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLint *params);
+angle::CallCapture CaptureGetnUniformuiv(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLuint *params);
+angle::CallCapture CaptureIsEnabledi(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLboolean returnValue);
+angle::CallCapture CaptureMinSampleShading(const State &glState, bool isCallValid, GLfloat value);
+angle::CallCapture CaptureObjectLabel(const State &glState,
+ bool isCallValid,
+ GLenum identifier,
+ GLuint name,
+ GLsizei length,
+ const GLchar *label);
+angle::CallCapture CaptureObjectPtrLabel(const State &glState,
+ bool isCallValid,
+ const void *ptr,
+ GLsizei length,
+ const GLchar *label);
+angle::CallCapture CapturePatchParameteri(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLint value);
+angle::CallCapture CapturePopDebugGroup(const State &glState, bool isCallValid);
+angle::CallCapture CapturePrimitiveBoundingBox(const State &glState,
+ bool isCallValid,
+ GLfloat minX,
+ GLfloat minY,
+ GLfloat minZ,
+ GLfloat minW,
+ GLfloat maxX,
+ GLfloat maxY,
+ GLfloat maxZ,
+ GLfloat maxW);
+angle::CallCapture CapturePushDebugGroup(const State &glState,
+ bool isCallValid,
+ GLenum source,
+ GLuint id,
+ GLsizei length,
+ const GLchar *message);
+angle::CallCapture CaptureReadnPixels(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *data);
+angle::CallCapture CaptureSamplerParameterIiv(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *param);
+angle::CallCapture CaptureSamplerParameterIuiv(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLuint *param);
+angle::CallCapture CaptureTexBuffer(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum internalformat,
+ BufferID bufferPacked);
+angle::CallCapture CaptureTexBufferRange(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum internalformat,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size);
+angle::CallCapture CaptureTexParameterIiv(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params);
+angle::CallCapture CaptureTexParameterIuiv(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params);
+angle::CallCapture CaptureTexStorage3DMultisample(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedsamplelocations);
+
+// Parameter Captures
+
+void CaptureDebugMessageCallback_userParam(const State &glState,
+ bool isCallValid,
+ GLDEBUGPROC callback,
+ const void *userParam,
+ angle::ParamCapture *paramCapture);
+void CaptureDebugMessageControl_ids(const State &glState,
+ bool isCallValid,
+ GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled,
+ angle::ParamCapture *paramCapture);
+void CaptureDebugMessageInsert_buf(const State &glState,
+ bool isCallValid,
+ GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *buf,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawElementsBaseVertex_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawElementsInstancedBaseVertex_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawRangeElementsBaseVertex_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex,
+ angle::ParamCapture *paramCapture);
+void CaptureGetDebugMessageLog_sources(const State &glState,
+ bool isCallValid,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetDebugMessageLog_types(const State &glState,
+ bool isCallValid,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetDebugMessageLog_ids(const State &glState,
+ bool isCallValid,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetDebugMessageLog_severities(const State &glState,
+ bool isCallValid,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetDebugMessageLog_lengths(const State &glState,
+ bool isCallValid,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetDebugMessageLog_messageLog(const State &glState,
+ bool isCallValid,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetObjectLabel_length(const State &glState,
+ bool isCallValid,
+ GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureGetObjectLabel_label(const State &glState,
+ bool isCallValid,
+ GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureGetObjectPtrLabel_ptr(const State &glState,
+ bool isCallValid,
+ const void *ptr,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureGetObjectPtrLabel_length(const State &glState,
+ bool isCallValid,
+ const void *ptr,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureGetObjectPtrLabel_label(const State &glState,
+ bool isCallValid,
+ const void *ptr,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPointerv_params(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ void **params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameterIiv_params(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameterIuiv_params(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterIiv_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterIuiv_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnUniformfv_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnUniformiv_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnUniformuiv_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureObjectLabel_label(const State &glState,
+ bool isCallValid,
+ GLenum identifier,
+ GLuint name,
+ GLsizei length,
+ const GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureObjectPtrLabel_ptr(const State &glState,
+ bool isCallValid,
+ const void *ptr,
+ GLsizei length,
+ const GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureObjectPtrLabel_label(const State &glState,
+ bool isCallValid,
+ const void *ptr,
+ GLsizei length,
+ const GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CapturePushDebugGroup_message(const State &glState,
+ bool isCallValid,
+ GLenum source,
+ GLuint id,
+ GLsizei length,
+ const GLchar *message,
+ angle::ParamCapture *paramCapture);
+void CaptureReadnPixels_data(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureSamplerParameterIiv_param(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureSamplerParameterIuiv_param(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLuint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureTexParameterIiv_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexParameterIuiv_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params,
+ angle::ParamCapture *paramCapture);
+} // namespace gl
+
+#endif // LIBANGLE_CAPTURE_GLES_3_2_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/capture/capture_gles_ext_autogen.h b/gfx/angle/checkout/src/libANGLE/capture/capture_gles_ext_autogen.h
new file mode 100644
index 0000000000..03211ffeb9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/capture_gles_ext_autogen.h
@@ -0,0 +1,5231 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// capture_gles_ext_autogen.h:
+// Capture functions for the OpenGL ES extension entry points.
+
+#ifndef LIBANGLE_CAPTURE_GLES_EXT_AUTOGEN_H_
+#define LIBANGLE_CAPTURE_GLES_EXT_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "libANGLE/capture/FrameCapture.h"
+
+namespace gl
+{
+
+// Method Captures
+
+// GL_AMD_performance_monitor
+angle::CallCapture CaptureBeginPerfMonitorAMD(const State &glState,
+ bool isCallValid,
+ GLuint monitor);
+angle::CallCapture CaptureDeletePerfMonitorsAMD(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ GLuint *monitors);
+angle::CallCapture CaptureEndPerfMonitorAMD(const State &glState, bool isCallValid, GLuint monitor);
+angle::CallCapture CaptureGenPerfMonitorsAMD(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ GLuint *monitors);
+angle::CallCapture CaptureGetPerfMonitorCounterDataAMD(const State &glState,
+ bool isCallValid,
+ GLuint monitor,
+ GLenum pname,
+ GLsizei dataSize,
+ GLuint *data,
+ GLint *bytesWritten);
+angle::CallCapture CaptureGetPerfMonitorCounterInfoAMD(const State &glState,
+ bool isCallValid,
+ GLuint group,
+ GLuint counter,
+ GLenum pname,
+ void *data);
+angle::CallCapture CaptureGetPerfMonitorCounterStringAMD(const State &glState,
+ bool isCallValid,
+ GLuint group,
+ GLuint counter,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *counterString);
+angle::CallCapture CaptureGetPerfMonitorCountersAMD(const State &glState,
+ bool isCallValid,
+ GLuint group,
+ GLint *numCounters,
+ GLint *maxActiveCounters,
+ GLsizei counterSize,
+ GLuint *counters);
+angle::CallCapture CaptureGetPerfMonitorGroupStringAMD(const State &glState,
+ bool isCallValid,
+ GLuint group,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *groupString);
+angle::CallCapture CaptureGetPerfMonitorGroupsAMD(const State &glState,
+ bool isCallValid,
+ GLint *numGroups,
+ GLsizei groupsSize,
+ GLuint *groups);
+angle::CallCapture CaptureSelectPerfMonitorCountersAMD(const State &glState,
+ bool isCallValid,
+ GLuint monitor,
+ GLboolean enable,
+ GLuint group,
+ GLint numCounters,
+ GLuint *counterList);
+
+// GL_ANDROID_extension_pack_es31a
+
+// GL_ANGLE_base_vertex_base_instance
+angle::CallCapture CaptureDrawArraysInstancedBaseInstanceANGLE(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount,
+ GLuint baseInstance);
+angle::CallCapture CaptureDrawElementsInstancedBaseVertexBaseInstanceANGLE(
+ const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const GLvoid *indices,
+ GLsizei instanceCount,
+ GLint baseVertex,
+ GLuint baseInstance);
+angle::CallCapture CaptureMultiDrawArraysInstancedBaseInstanceANGLE(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ const GLuint *baseInstances,
+ GLsizei drawcount);
+angle::CallCapture CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(
+ const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount);
+
+// GL_ANGLE_copy_texture_3d
+angle::CallCapture CaptureCopyTexture3DANGLE(const State &glState,
+ bool isCallValid,
+ TextureID sourceIdPacked,
+ GLint sourceLevel,
+ TextureTarget destTargetPacked,
+ TextureID destIdPacked,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+angle::CallCapture CaptureCopySubTexture3DANGLE(const State &glState,
+ bool isCallValid,
+ TextureID sourceIdPacked,
+ GLint sourceLevel,
+ TextureTarget destTargetPacked,
+ TextureID destIdPacked,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint width,
+ GLint height,
+ GLint depth,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+
+// GL_ANGLE_depth_texture
+
+// GL_ANGLE_framebuffer_blit
+angle::CallCapture CaptureBlitFramebufferANGLE(const State &glState,
+ bool isCallValid,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+
+// GL_ANGLE_framebuffer_multisample
+angle::CallCapture CaptureRenderbufferStorageMultisampleANGLE(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+
+// GL_ANGLE_get_image
+angle::CallCapture CaptureGetTexImageANGLE(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ void *pixels);
+angle::CallCapture CaptureGetCompressedTexImageANGLE(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ void *pixels);
+angle::CallCapture CaptureGetRenderbufferImageANGLE(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ void *pixels);
+
+// GL_ANGLE_get_tex_level_parameter
+angle::CallCapture CaptureGetTexLevelParameterivANGLE(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetTexLevelParameterfvANGLE(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLfloat *params);
+
+// GL_ANGLE_instanced_arrays
+angle::CallCapture CaptureDrawArraysInstancedANGLE(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount);
+angle::CallCapture CaptureDrawElementsInstancedANGLE(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei primcount);
+angle::CallCapture CaptureVertexAttribDivisorANGLE(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLuint divisor);
+
+// GL_ANGLE_logic_op
+angle::CallCapture CaptureLogicOpANGLE(const State &glState,
+ bool isCallValid,
+ LogicalOperation opcodePacked);
+
+// GL_ANGLE_memory_object_flags
+angle::CallCapture CaptureTexStorageMemFlags2DANGLE(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext);
+angle::CallCapture CaptureTexStorageMemFlags2DMultisampleANGLE(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext);
+angle::CallCapture CaptureTexStorageMemFlags3DANGLE(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext);
+angle::CallCapture CaptureTexStorageMemFlags3DMultisampleANGLE(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext);
+
+// GL_ANGLE_memory_object_fuchsia
+angle::CallCapture CaptureImportMemoryZirconHandleANGLE(const State &glState,
+ bool isCallValid,
+ MemoryObjectID memoryPacked,
+ GLuint64 size,
+ HandleType handleTypePacked,
+ GLuint handle);
+
+// GL_ANGLE_multi_draw
+angle::CallCapture CaptureMultiDrawArraysANGLE(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ GLsizei drawcount);
+angle::CallCapture CaptureMultiDrawArraysInstancedANGLE(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount);
+angle::CallCapture CaptureMultiDrawElementsANGLE(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ GLsizei drawcount);
+angle::CallCapture CaptureMultiDrawElementsInstancedANGLE(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount);
+
+// GL_ANGLE_pack_reverse_row_order
+
+// GL_ANGLE_program_binary
+
+// GL_ANGLE_provoking_vertex
+angle::CallCapture CaptureProvokingVertexANGLE(const State &glState,
+ bool isCallValid,
+ ProvokingVertexConvention modePacked);
+
+// GL_ANGLE_request_extension
+angle::CallCapture CaptureRequestExtensionANGLE(const State &glState,
+ bool isCallValid,
+ const GLchar *name);
+angle::CallCapture CaptureDisableExtensionANGLE(const State &glState,
+ bool isCallValid,
+ const GLchar *name);
+
+// GL_ANGLE_robust_client_memory
+angle::CallCapture CaptureGetBooleanvRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *params);
+angle::CallCapture CaptureGetBufferParameterivRobustANGLE(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetFloatvRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+angle::CallCapture CaptureGetFramebufferAttachmentParameterivRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetIntegervRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *data);
+angle::CallCapture CaptureGetProgramivRobustANGLE(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetRenderbufferParameterivRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetShaderivRobustANGLE(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetTexParameterfvRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+angle::CallCapture CaptureGetTexParameterivRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetUniformfvRobustANGLE(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+angle::CallCapture CaptureGetUniformivRobustANGLE(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetVertexAttribfvRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+angle::CallCapture CaptureGetVertexAttribivRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetVertexAttribPointervRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **pointer);
+angle::CallCapture CaptureReadPixelsRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *pixels);
+angle::CallCapture CaptureTexImage2DRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+angle::CallCapture CaptureTexParameterfvRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params);
+angle::CallCapture CaptureTexParameterivRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params);
+angle::CallCapture CaptureTexSubImage2DRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+angle::CallCapture CaptureTexImage3DRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+angle::CallCapture CaptureTexSubImage3DRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+angle::CallCapture CaptureCompressedTexImage2DRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data);
+angle::CallCapture CaptureCompressedTexSubImage2DRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLsizei xoffset,
+ GLsizei yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data);
+angle::CallCapture CaptureCompressedTexImage3DRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data);
+angle::CallCapture CaptureCompressedTexSubImage3DRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data);
+angle::CallCapture CaptureGetQueryivRobustANGLE(const State &glState,
+ bool isCallValid,
+ QueryType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetQueryObjectuivRobustANGLE(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+angle::CallCapture CaptureGetBufferPointervRobustANGLE(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **params);
+angle::CallCapture CaptureGetIntegeri_vRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *data);
+angle::CallCapture CaptureGetInternalformativRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetVertexAttribIivRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetVertexAttribIuivRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+angle::CallCapture CaptureGetUniformuivRobustANGLE(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+angle::CallCapture CaptureGetActiveUniformBlockivRobustANGLE(
+ const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformBlockIndex uniformBlockIndexPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetInteger64vRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data);
+angle::CallCapture CaptureGetInteger64i_vRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data);
+angle::CallCapture CaptureGetBufferParameteri64vRobustANGLE(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params);
+angle::CallCapture CaptureSamplerParameterivRobustANGLE(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLuint pname,
+ GLsizei bufSize,
+ const GLint *param);
+angle::CallCapture CaptureSamplerParameterfvRobustANGLE(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *param);
+angle::CallCapture CaptureGetSamplerParameterivRobustANGLE(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetSamplerParameterfvRobustANGLE(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+angle::CallCapture CaptureGetFramebufferParameterivRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetProgramInterfaceivRobustANGLE(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetBooleani_vRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *data);
+angle::CallCapture CaptureGetMultisamplefvRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *val);
+angle::CallCapture CaptureGetTexLevelParameterivRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetTexLevelParameterfvRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+angle::CallCapture CaptureGetPointervRobustANGLERobustANGLE(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **params);
+angle::CallCapture CaptureReadnPixelsRobustANGLE(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *data);
+angle::CallCapture CaptureGetnUniformfvRobustANGLE(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params);
+angle::CallCapture CaptureGetnUniformivRobustANGLE(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetnUniformuivRobustANGLE(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+angle::CallCapture CaptureTexParameterIivRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params);
+angle::CallCapture CaptureTexParameterIuivRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLuint *params);
+angle::CallCapture CaptureGetTexParameterIivRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetTexParameterIuivRobustANGLE(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+angle::CallCapture CaptureSamplerParameterIivRobustANGLE(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *param);
+angle::CallCapture CaptureSamplerParameterIuivRobustANGLE(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLuint *param);
+angle::CallCapture CaptureGetSamplerParameterIivRobustANGLE(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetSamplerParameterIuivRobustANGLE(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params);
+angle::CallCapture CaptureGetQueryObjectivRobustANGLE(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+angle::CallCapture CaptureGetQueryObjecti64vRobustANGLE(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params);
+angle::CallCapture CaptureGetQueryObjectui64vRobustANGLE(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint64 *params);
+
+// GL_ANGLE_robust_resource_initialization
+
+// GL_ANGLE_semaphore_fuchsia
+angle::CallCapture CaptureImportSemaphoreZirconHandleANGLE(const State &glState,
+ bool isCallValid,
+ SemaphoreID semaphorePacked,
+ HandleType handleTypePacked,
+ GLuint handle);
+
+// GL_ANGLE_shader_pixel_local_storage
+angle::CallCapture CaptureFramebufferMemorylessPixelLocalStorageANGLE(const State &glState,
+ bool isCallValid,
+ GLint plane,
+ GLenum internalformat);
+angle::CallCapture CaptureFramebufferTexturePixelLocalStorageANGLE(const State &glState,
+ bool isCallValid,
+ GLint plane,
+ TextureID backingtexturePacked,
+ GLint level,
+ GLint layer);
+angle::CallCapture CaptureBeginPixelLocalStorageANGLE(const State &glState,
+ bool isCallValid,
+ GLsizei planes,
+ const GLenum *loadops,
+ const void *cleardata);
+angle::CallCapture CaptureEndPixelLocalStorageANGLE(const State &glState, bool isCallValid);
+angle::CallCapture CapturePixelLocalStorageBarrierANGLE(const State &glState, bool isCallValid);
+
+// GL_ANGLE_texture_compression_dxt3
+
+// GL_ANGLE_texture_compression_dxt5
+
+// GL_ANGLE_texture_external_update
+angle::CallCapture CaptureTexImage2DExternalANGLE(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type);
+angle::CallCapture CaptureInvalidateTextureANGLE(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked);
+
+// GL_ANGLE_texture_multisample
+angle::CallCapture CaptureTexStorage2DMultisampleANGLE(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations);
+angle::CallCapture CaptureGetMultisamplefvANGLE(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLuint index,
+ GLfloat *val);
+angle::CallCapture CaptureSampleMaskiANGLE(const State &glState,
+ bool isCallValid,
+ GLuint maskNumber,
+ GLbitfield mask);
+
+// GL_ANGLE_texture_usage
+
+// GL_ANGLE_translated_shader_source
+angle::CallCapture CaptureGetTranslatedShaderSourceANGLE(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *source);
+
+// GL_ANGLE_vulkan_image
+angle::CallCapture CaptureAcquireTexturesANGLE(const State &glState,
+ bool isCallValid,
+ GLuint numTextures,
+ const TextureID *texturesPacked,
+ const GLenum *layouts);
+angle::CallCapture CaptureReleaseTexturesANGLE(const State &glState,
+ bool isCallValid,
+ GLuint numTextures,
+ const TextureID *texturesPacked,
+ GLenum *layouts);
+
+// GL_APPLE_clip_distance
+
+// GL_ARB_sync
+
+// GL_CHROMIUM_bind_uniform_location
+angle::CallCapture CaptureBindUniformLocationCHROMIUM(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ const GLchar *name);
+
+// GL_CHROMIUM_copy_compressed_texture
+angle::CallCapture CaptureCompressedCopyTextureCHROMIUM(const State &glState,
+ bool isCallValid,
+ TextureID sourceIdPacked,
+ TextureID destIdPacked);
+
+// GL_CHROMIUM_copy_texture
+angle::CallCapture CaptureCopyTextureCHROMIUM(const State &glState,
+ bool isCallValid,
+ TextureID sourceIdPacked,
+ GLint sourceLevel,
+ TextureTarget destTargetPacked,
+ TextureID destIdPacked,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+angle::CallCapture CaptureCopySubTextureCHROMIUM(const State &glState,
+ bool isCallValid,
+ TextureID sourceIdPacked,
+ GLint sourceLevel,
+ TextureTarget destTargetPacked,
+ TextureID destIdPacked,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLint width,
+ GLint height,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+
+// GL_CHROMIUM_framebuffer_mixed_samples
+angle::CallCapture CaptureCoverageModulationCHROMIUM(const State &glState,
+ bool isCallValid,
+ GLenum components);
+
+// GL_CHROMIUM_lose_context
+angle::CallCapture CaptureLoseContextCHROMIUM(const State &glState,
+ bool isCallValid,
+ GraphicsResetStatus currentPacked,
+ GraphicsResetStatus otherPacked);
+
+// GL_EXT_EGL_image_array
+
+// GL_EXT_EGL_image_storage
+angle::CallCapture CaptureEGLImageTargetTexStorageEXT(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLeglImageOES image,
+ const GLint *attrib_list);
+angle::CallCapture CaptureEGLImageTargetTextureStorageEXT(const State &glState,
+ bool isCallValid,
+ GLuint texture,
+ GLeglImageOES image,
+ const GLint *attrib_list);
+
+// GL_EXT_YUV_target
+
+// GL_EXT_base_instance
+angle::CallCapture CaptureDrawArraysInstancedBaseInstanceEXT(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLint first,
+ GLsizei count,
+ GLsizei instancecount,
+ GLuint baseinstance);
+angle::CallCapture CaptureDrawElementsInstancedBaseInstanceEXT(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLuint baseinstance);
+angle::CallCapture CaptureDrawElementsInstancedBaseVertexBaseInstanceEXT(
+ const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex,
+ GLuint baseinstance);
+
+// GL_EXT_blend_func_extended
+angle::CallCapture CaptureBindFragDataLocationEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint color,
+ const GLchar *name);
+angle::CallCapture CaptureBindFragDataLocationIndexedEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint colorNumber,
+ GLuint index,
+ const GLchar *name);
+angle::CallCapture CaptureGetFragDataIndexEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ const GLchar *name,
+ GLint returnValue);
+angle::CallCapture CaptureGetProgramResourceLocationIndexEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ const GLchar *name,
+ GLint returnValue);
+
+// GL_EXT_blend_minmax
+
+// GL_EXT_buffer_storage
+angle::CallCapture CaptureBufferStorageEXT(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags);
+
+// GL_EXT_clip_control
+angle::CallCapture CaptureClipControlEXT(const State &glState,
+ bool isCallValid,
+ GLenum origin,
+ GLenum depth);
+
+// GL_EXT_clip_cull_distance
+
+// GL_EXT_color_buffer_float
+
+// GL_EXT_color_buffer_half_float
+
+// GL_EXT_copy_image
+angle::CallCapture CaptureCopyImageSubDataEXT(const State &glState,
+ bool isCallValid,
+ GLuint srcName,
+ GLenum srcTarget,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLuint dstName,
+ GLenum dstTarget,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth);
+
+// GL_EXT_debug_label
+angle::CallCapture CaptureGetObjectLabelEXT(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint object,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label);
+angle::CallCapture CaptureLabelObjectEXT(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint object,
+ GLsizei length,
+ const GLchar *label);
+
+// GL_EXT_debug_marker
+angle::CallCapture CaptureInsertEventMarkerEXT(const State &glState,
+ bool isCallValid,
+ GLsizei length,
+ const GLchar *marker);
+angle::CallCapture CapturePopGroupMarkerEXT(const State &glState, bool isCallValid);
+angle::CallCapture CapturePushGroupMarkerEXT(const State &glState,
+ bool isCallValid,
+ GLsizei length,
+ const GLchar *marker);
+
+// GL_EXT_discard_framebuffer
+angle::CallCapture CaptureDiscardFramebufferEXT(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments);
+
+// GL_EXT_disjoint_timer_query
+angle::CallCapture CaptureBeginQueryEXT(const State &glState,
+ bool isCallValid,
+ QueryType targetPacked,
+ QueryID idPacked);
+angle::CallCapture CaptureDeleteQueriesEXT(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const QueryID *idsPacked);
+angle::CallCapture CaptureEndQueryEXT(const State &glState,
+ bool isCallValid,
+ QueryType targetPacked);
+angle::CallCapture CaptureGenQueriesEXT(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ QueryID *idsPacked);
+angle::CallCapture CaptureGetInteger64vEXT(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLint64 *data);
+angle::CallCapture CaptureGetQueryObjecti64vEXT(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLint64 *params);
+angle::CallCapture CaptureGetQueryObjectivEXT(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetQueryObjectui64vEXT(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLuint64 *params);
+angle::CallCapture CaptureGetQueryObjectuivEXT(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLuint *params);
+angle::CallCapture CaptureGetQueryivEXT(const State &glState,
+ bool isCallValid,
+ QueryType targetPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureIsQueryEXT(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureQueryCounterEXT(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ QueryType targetPacked);
+
+// GL_EXT_draw_buffers
+angle::CallCapture CaptureDrawBuffersEXT(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const GLenum *bufs);
+
+// GL_EXT_draw_buffers_indexed
+angle::CallCapture CaptureBlendEquationSeparateiEXT(const State &glState,
+ bool isCallValid,
+ GLuint buf,
+ GLenum modeRGB,
+ GLenum modeAlpha);
+angle::CallCapture CaptureBlendEquationiEXT(const State &glState,
+ bool isCallValid,
+ GLuint buf,
+ GLenum mode);
+angle::CallCapture CaptureBlendFuncSeparateiEXT(const State &glState,
+ bool isCallValid,
+ GLuint buf,
+ GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha);
+angle::CallCapture CaptureBlendFunciEXT(const State &glState,
+ bool isCallValid,
+ GLuint buf,
+ GLenum src,
+ GLenum dst);
+angle::CallCapture CaptureColorMaskiEXT(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLboolean r,
+ GLboolean g,
+ GLboolean b,
+ GLboolean a);
+angle::CallCapture CaptureDisableiEXT(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index);
+angle::CallCapture CaptureEnableiEXT(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index);
+angle::CallCapture CaptureIsEnablediEXT(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLboolean returnValue);
+
+// GL_EXT_draw_elements_base_vertex
+angle::CallCapture CaptureDrawElementsBaseVertexEXT(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex);
+angle::CallCapture CaptureDrawElementsInstancedBaseVertexEXT(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex);
+angle::CallCapture CaptureDrawRangeElementsBaseVertexEXT(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex);
+angle::CallCapture CaptureMultiDrawElementsBaseVertexEXT(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *count,
+ DrawElementsType typePacked,
+ const void *const *indices,
+ GLsizei drawcount,
+ const GLint *basevertex);
+
+// GL_EXT_external_buffer
+angle::CallCapture CaptureBufferStorageExternalEXT(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLeglClientBufferEXT clientBuffer,
+ GLbitfield flags);
+angle::CallCapture CaptureNamedBufferStorageExternalEXT(const State &glState,
+ bool isCallValid,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLeglClientBufferEXT clientBuffer,
+ GLbitfield flags);
+
+// GL_EXT_float_blend
+
+// GL_EXT_geometry_shader
+angle::CallCapture CaptureFramebufferTextureEXT(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ TextureID texturePacked,
+ GLint level);
+
+// GL_EXT_gpu_shader5
+
+// GL_EXT_instanced_arrays
+angle::CallCapture CaptureDrawArraysInstancedEXT(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLint start,
+ GLsizei count,
+ GLsizei primcount);
+angle::CallCapture CaptureDrawElementsInstancedEXT(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei primcount);
+angle::CallCapture CaptureVertexAttribDivisorEXT(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLuint divisor);
+
+// GL_EXT_map_buffer_range
+angle::CallCapture CaptureFlushMappedBufferRangeEXT(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLintptr offset,
+ GLsizeiptr length);
+angle::CallCapture CaptureMapBufferRangeEXT(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access,
+ void *returnValue);
+
+// GL_EXT_memory_object
+angle::CallCapture CaptureBufferStorageMemEXT(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizeiptr size,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset);
+angle::CallCapture CaptureCreateMemoryObjectsEXT(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ MemoryObjectID *memoryObjectsPacked);
+angle::CallCapture CaptureDeleteMemoryObjectsEXT(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const MemoryObjectID *memoryObjectsPacked);
+angle::CallCapture CaptureGetMemoryObjectParameterivEXT(const State &glState,
+ bool isCallValid,
+ MemoryObjectID memoryObjectPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetUnsignedBytevEXT(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLubyte *data);
+angle::CallCapture CaptureGetUnsignedBytei_vEXT(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLubyte *data);
+angle::CallCapture CaptureIsMemoryObjectEXT(const State &glState,
+ bool isCallValid,
+ MemoryObjectID memoryObjectPacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureMemoryObjectParameterivEXT(const State &glState,
+ bool isCallValid,
+ MemoryObjectID memoryObjectPacked,
+ GLenum pname,
+ const GLint *params);
+angle::CallCapture CaptureTexStorageMem2DEXT(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset);
+angle::CallCapture CaptureTexStorageMem2DMultisampleEXT(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset);
+angle::CallCapture CaptureTexStorageMem3DEXT(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset);
+angle::CallCapture CaptureTexStorageMem3DMultisampleEXT(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset);
+
+// GL_EXT_memory_object_fd
+angle::CallCapture CaptureImportMemoryFdEXT(const State &glState,
+ bool isCallValid,
+ MemoryObjectID memoryPacked,
+ GLuint64 size,
+ HandleType handleTypePacked,
+ GLint fd);
+
+// GL_EXT_multi_draw_indirect
+angle::CallCapture CaptureMultiDrawArraysIndirectEXT(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride);
+angle::CallCapture CaptureMultiDrawElementsIndirectEXT(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ DrawElementsType typePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride);
+
+// GL_EXT_multisampled_render_to_texture
+angle::CallCapture CaptureFramebufferTexture2DMultisampleEXT(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texturePacked,
+ GLint level,
+ GLsizei samples);
+angle::CallCapture CaptureRenderbufferStorageMultisampleEXT(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+
+// GL_EXT_multisampled_render_to_texture2
+
+// GL_EXT_occlusion_query_boolean
+
+// GL_EXT_primitive_bounding_box
+angle::CallCapture CapturePrimitiveBoundingBoxEXT(const State &glState,
+ bool isCallValid,
+ GLfloat minX,
+ GLfloat minY,
+ GLfloat minZ,
+ GLfloat minW,
+ GLfloat maxX,
+ GLfloat maxY,
+ GLfloat maxZ,
+ GLfloat maxW);
+
+// GL_EXT_protected_textures
+
+// GL_EXT_pvrtc_sRGB
+
+// GL_EXT_read_format_bgra
+
+// GL_EXT_robustness
+angle::CallCapture CaptureGetGraphicsResetStatusEXT(const State &glState,
+ bool isCallValid,
+ GLenum returnValue);
+angle::CallCapture CaptureGetnUniformfvEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLfloat *params);
+angle::CallCapture CaptureGetnUniformivEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLint *params);
+angle::CallCapture CaptureReadnPixelsEXT(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *data);
+
+// GL_EXT_sRGB
+
+// GL_EXT_sRGB_write_control
+
+// GL_EXT_semaphore
+angle::CallCapture CaptureDeleteSemaphoresEXT(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const SemaphoreID *semaphoresPacked);
+angle::CallCapture CaptureGenSemaphoresEXT(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ SemaphoreID *semaphoresPacked);
+angle::CallCapture CaptureGetSemaphoreParameterui64vEXT(const State &glState,
+ bool isCallValid,
+ SemaphoreID semaphorePacked,
+ GLenum pname,
+ GLuint64 *params);
+angle::CallCapture CaptureIsSemaphoreEXT(const State &glState,
+ bool isCallValid,
+ SemaphoreID semaphorePacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureSemaphoreParameterui64vEXT(const State &glState,
+ bool isCallValid,
+ SemaphoreID semaphorePacked,
+ GLenum pname,
+ const GLuint64 *params);
+angle::CallCapture CaptureSignalSemaphoreEXT(const State &glState,
+ bool isCallValid,
+ SemaphoreID semaphorePacked,
+ GLuint numBufferBarriers,
+ const BufferID *buffersPacked,
+ GLuint numTextureBarriers,
+ const TextureID *texturesPacked,
+ const GLenum *dstLayouts);
+angle::CallCapture CaptureWaitSemaphoreEXT(const State &glState,
+ bool isCallValid,
+ SemaphoreID semaphorePacked,
+ GLuint numBufferBarriers,
+ const BufferID *buffersPacked,
+ GLuint numTextureBarriers,
+ const TextureID *texturesPacked,
+ const GLenum *srcLayouts);
+
+// GL_EXT_semaphore_fd
+angle::CallCapture CaptureImportSemaphoreFdEXT(const State &glState,
+ bool isCallValid,
+ SemaphoreID semaphorePacked,
+ HandleType handleTypePacked,
+ GLint fd);
+
+// GL_EXT_separate_shader_objects
+angle::CallCapture CaptureActiveShaderProgramEXT(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ ShaderProgramID programPacked);
+angle::CallCapture CaptureBindProgramPipelineEXT(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked);
+angle::CallCapture CaptureCreateShaderProgramvEXT(const State &glState,
+ bool isCallValid,
+ ShaderType typePacked,
+ GLsizei count,
+ const GLchar **strings,
+ GLuint returnValue);
+angle::CallCapture CaptureDeleteProgramPipelinesEXT(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const ProgramPipelineID *pipelinesPacked);
+angle::CallCapture CaptureGenProgramPipelinesEXT(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ ProgramPipelineID *pipelinesPacked);
+angle::CallCapture CaptureGetProgramPipelineInfoLogEXT(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog);
+angle::CallCapture CaptureGetProgramPipelineivEXT(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureIsProgramPipelineEXT(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureProgramParameteriEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum pname,
+ GLint value);
+angle::CallCapture CaptureProgramUniform1fEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0);
+angle::CallCapture CaptureProgramUniform1fvEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniform1iEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0);
+angle::CallCapture CaptureProgramUniform1ivEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+angle::CallCapture CaptureProgramUniform1uiEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0);
+angle::CallCapture CaptureProgramUniform1uivEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+angle::CallCapture CaptureProgramUniform2fEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1);
+angle::CallCapture CaptureProgramUniform2fvEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniform2iEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1);
+angle::CallCapture CaptureProgramUniform2ivEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+angle::CallCapture CaptureProgramUniform2uiEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1);
+angle::CallCapture CaptureProgramUniform2uivEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+angle::CallCapture CaptureProgramUniform3fEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2);
+angle::CallCapture CaptureProgramUniform3fvEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniform3iEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2);
+angle::CallCapture CaptureProgramUniform3ivEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+angle::CallCapture CaptureProgramUniform3uiEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2);
+angle::CallCapture CaptureProgramUniform3uivEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+angle::CallCapture CaptureProgramUniform4fEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2,
+ GLfloat v3);
+angle::CallCapture CaptureProgramUniform4fvEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniform4iEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2,
+ GLint v3);
+angle::CallCapture CaptureProgramUniform4ivEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+angle::CallCapture CaptureProgramUniform4uiEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3);
+angle::CallCapture CaptureProgramUniform4uivEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+angle::CallCapture CaptureProgramUniformMatrix2fvEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix2x3fvEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix2x4fvEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix3fvEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix3x2fvEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix3x4fvEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix4fvEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix4x2fvEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureProgramUniformMatrix4x3fvEXT(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+angle::CallCapture CaptureUseProgramStagesEXT(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ GLbitfield stages,
+ ShaderProgramID programPacked);
+angle::CallCapture CaptureValidateProgramPipelineEXT(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked);
+
+// GL_EXT_shader_framebuffer_fetch
+
+// GL_EXT_shader_framebuffer_fetch_non_coherent
+angle::CallCapture CaptureFramebufferFetchBarrierEXT(const State &glState, bool isCallValid);
+
+// GL_EXT_shader_io_blocks
+
+// GL_EXT_shader_non_constant_global_initializers
+
+// GL_EXT_shader_texture_lod
+
+// GL_EXT_shadow_samplers
+
+// GL_EXT_tessellation_shader
+angle::CallCapture CapturePatchParameteriEXT(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLint value);
+
+// GL_EXT_texture_border_clamp
+angle::CallCapture CaptureGetSamplerParameterIivEXT(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetSamplerParameterIuivEXT(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLuint *params);
+angle::CallCapture CaptureGetTexParameterIivEXT(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetTexParameterIuivEXT(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLuint *params);
+angle::CallCapture CaptureSamplerParameterIivEXT(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *param);
+angle::CallCapture CaptureSamplerParameterIuivEXT(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLuint *param);
+angle::CallCapture CaptureTexParameterIivEXT(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params);
+angle::CallCapture CaptureTexParameterIuivEXT(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params);
+
+// GL_EXT_texture_buffer
+angle::CallCapture CaptureTexBufferEXT(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum internalformat,
+ BufferID bufferPacked);
+angle::CallCapture CaptureTexBufferRangeEXT(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum internalformat,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size);
+
+// GL_EXT_texture_compression_bptc
+
+// GL_EXT_texture_compression_dxt1
+
+// GL_EXT_texture_compression_rgtc
+
+// GL_EXT_texture_compression_s3tc
+
+// GL_EXT_texture_compression_s3tc_srgb
+
+// GL_EXT_texture_cube_map_array
+
+// GL_EXT_texture_filter_anisotropic
+
+// GL_EXT_texture_format_BGRA8888
+
+// GL_EXT_texture_format_sRGB_override
+
+// GL_EXT_texture_norm16
+
+// GL_EXT_texture_rg
+
+// GL_EXT_texture_sRGB_R8
+
+// GL_EXT_texture_sRGB_RG8
+
+// GL_EXT_texture_sRGB_decode
+
+// GL_EXT_texture_storage
+angle::CallCapture CaptureTexStorage1DEXT(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width);
+angle::CallCapture CaptureTexStorage2DEXT(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureTexStorage3DEXT(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+
+// GL_EXT_texture_type_2_10_10_10_REV
+
+// GL_EXT_unpack_subimage
+
+// GL_IMG_texture_compression_pvrtc
+
+// GL_IMG_texture_compression_pvrtc2
+
+// GL_KHR_blend_equation_advanced
+angle::CallCapture CaptureBlendBarrierKHR(const State &glState, bool isCallValid);
+
+// GL_KHR_debug
+angle::CallCapture CaptureDebugMessageCallbackKHR(const State &glState,
+ bool isCallValid,
+ GLDEBUGPROCKHR callback,
+ const void *userParam);
+angle::CallCapture CaptureDebugMessageControlKHR(const State &glState,
+ bool isCallValid,
+ GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled);
+angle::CallCapture CaptureDebugMessageInsertKHR(const State &glState,
+ bool isCallValid,
+ GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *buf);
+angle::CallCapture CaptureGetDebugMessageLogKHR(const State &glState,
+ bool isCallValid,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog,
+ GLuint returnValue);
+angle::CallCapture CaptureGetObjectLabelKHR(const State &glState,
+ bool isCallValid,
+ GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label);
+angle::CallCapture CaptureGetObjectPtrLabelKHR(const State &glState,
+ bool isCallValid,
+ const void *ptr,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label);
+angle::CallCapture CaptureGetPointervKHR(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ void **params);
+angle::CallCapture CaptureObjectLabelKHR(const State &glState,
+ bool isCallValid,
+ GLenum identifier,
+ GLuint name,
+ GLsizei length,
+ const GLchar *label);
+angle::CallCapture CaptureObjectPtrLabelKHR(const State &glState,
+ bool isCallValid,
+ const void *ptr,
+ GLsizei length,
+ const GLchar *label);
+angle::CallCapture CapturePopDebugGroupKHR(const State &glState, bool isCallValid);
+angle::CallCapture CapturePushDebugGroupKHR(const State &glState,
+ bool isCallValid,
+ GLenum source,
+ GLuint id,
+ GLsizei length,
+ const GLchar *message);
+
+// GL_KHR_no_error
+
+// GL_KHR_parallel_shader_compile
+angle::CallCapture CaptureMaxShaderCompilerThreadsKHR(const State &glState,
+ bool isCallValid,
+ GLuint count);
+
+// GL_KHR_robust_buffer_access_behavior
+
+// GL_KHR_texture_compression_astc_hdr
+
+// GL_KHR_texture_compression_astc_ldr
+
+// GL_KHR_texture_compression_astc_sliced_3d
+
+// GL_MESA_framebuffer_flip_y
+angle::CallCapture CaptureFramebufferParameteriMESA(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLint param);
+angle::CallCapture CaptureGetFramebufferParameterivMESA(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLint *params);
+
+// GL_NV_fence
+angle::CallCapture CaptureDeleteFencesNV(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const FenceNVID *fencesPacked);
+angle::CallCapture CaptureFinishFenceNV(const State &glState,
+ bool isCallValid,
+ FenceNVID fencePacked);
+angle::CallCapture CaptureGenFencesNV(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ FenceNVID *fencesPacked);
+angle::CallCapture CaptureGetFenceivNV(const State &glState,
+ bool isCallValid,
+ FenceNVID fencePacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureIsFenceNV(const State &glState,
+ bool isCallValid,
+ FenceNVID fencePacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureSetFenceNV(const State &glState,
+ bool isCallValid,
+ FenceNVID fencePacked,
+ GLenum condition);
+angle::CallCapture CaptureTestFenceNV(const State &glState,
+ bool isCallValid,
+ FenceNVID fencePacked,
+ GLboolean returnValue);
+
+// GL_NV_framebuffer_blit
+angle::CallCapture CaptureBlitFramebufferNV(const State &glState,
+ bool isCallValid,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+
+// GL_NV_pixel_buffer_object
+
+// GL_NV_read_depth
+
+// GL_NV_read_depth_stencil
+
+// GL_NV_read_stencil
+
+// GL_NV_robustness_video_memory_purge
+
+// GL_NV_shader_noperspective_interpolation
+
+// GL_OES_EGL_image
+angle::CallCapture CaptureEGLImageTargetRenderbufferStorageOES(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLeglImageOES image);
+angle::CallCapture CaptureEGLImageTargetTexture2DOES(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLeglImageOES image);
+
+// GL_OES_EGL_image_external
+
+// GL_OES_EGL_image_external_essl3
+
+// GL_OES_compressed_ETC1_RGB8_texture
+
+// GL_OES_compressed_paletted_texture
+
+// GL_OES_copy_image
+angle::CallCapture CaptureCopyImageSubDataOES(const State &glState,
+ bool isCallValid,
+ GLuint srcName,
+ GLenum srcTarget,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLuint dstName,
+ GLenum dstTarget,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth);
+
+// GL_OES_depth24
+
+// GL_OES_depth32
+
+// GL_OES_depth_texture
+
+// GL_OES_draw_buffers_indexed
+angle::CallCapture CaptureBlendEquationSeparateiOES(const State &glState,
+ bool isCallValid,
+ GLuint buf,
+ GLenum modeRGB,
+ GLenum modeAlpha);
+angle::CallCapture CaptureBlendEquationiOES(const State &glState,
+ bool isCallValid,
+ GLuint buf,
+ GLenum mode);
+angle::CallCapture CaptureBlendFuncSeparateiOES(const State &glState,
+ bool isCallValid,
+ GLuint buf,
+ GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha);
+angle::CallCapture CaptureBlendFunciOES(const State &glState,
+ bool isCallValid,
+ GLuint buf,
+ GLenum src,
+ GLenum dst);
+angle::CallCapture CaptureColorMaskiOES(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLboolean r,
+ GLboolean g,
+ GLboolean b,
+ GLboolean a);
+angle::CallCapture CaptureDisableiOES(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index);
+angle::CallCapture CaptureEnableiOES(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index);
+angle::CallCapture CaptureIsEnablediOES(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLboolean returnValue);
+
+// GL_OES_draw_elements_base_vertex
+angle::CallCapture CaptureDrawElementsBaseVertexOES(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex);
+angle::CallCapture CaptureDrawElementsInstancedBaseVertexOES(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex);
+angle::CallCapture CaptureDrawRangeElementsBaseVertexOES(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex);
+
+// GL_OES_draw_texture
+angle::CallCapture CaptureDrawTexfOES(const State &glState,
+ bool isCallValid,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat width,
+ GLfloat height);
+angle::CallCapture CaptureDrawTexfvOES(const State &glState,
+ bool isCallValid,
+ const GLfloat *coords);
+angle::CallCapture CaptureDrawTexiOES(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint width,
+ GLint height);
+angle::CallCapture CaptureDrawTexivOES(const State &glState, bool isCallValid, const GLint *coords);
+angle::CallCapture CaptureDrawTexsOES(const State &glState,
+ bool isCallValid,
+ GLshort x,
+ GLshort y,
+ GLshort z,
+ GLshort width,
+ GLshort height);
+angle::CallCapture CaptureDrawTexsvOES(const State &glState,
+ bool isCallValid,
+ const GLshort *coords);
+angle::CallCapture CaptureDrawTexxOES(const State &glState,
+ bool isCallValid,
+ GLfixed x,
+ GLfixed y,
+ GLfixed z,
+ GLfixed width,
+ GLfixed height);
+angle::CallCapture CaptureDrawTexxvOES(const State &glState,
+ bool isCallValid,
+ const GLfixed *coords);
+
+// GL_OES_element_index_uint
+
+// GL_OES_fbo_render_mipmap
+
+// GL_OES_framebuffer_object
+angle::CallCapture CaptureBindFramebufferOES(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ FramebufferID framebufferPacked);
+angle::CallCapture CaptureBindRenderbufferOES(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ RenderbufferID renderbufferPacked);
+angle::CallCapture CaptureCheckFramebufferStatusOES(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum returnValue);
+angle::CallCapture CaptureDeleteFramebuffersOES(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const FramebufferID *framebuffersPacked);
+angle::CallCapture CaptureDeleteRenderbuffersOES(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const RenderbufferID *renderbuffersPacked);
+angle::CallCapture CaptureFramebufferRenderbufferOES(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ RenderbufferID renderbufferPacked);
+angle::CallCapture CaptureFramebufferTexture2DOES(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texturePacked,
+ GLint level);
+angle::CallCapture CaptureGenFramebuffersOES(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ FramebufferID *framebuffersPacked);
+angle::CallCapture CaptureGenRenderbuffersOES(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ RenderbufferID *renderbuffersPacked);
+angle::CallCapture CaptureGenerateMipmapOES(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked);
+angle::CallCapture CaptureGetFramebufferAttachmentParameterivOES(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetRenderbufferParameterivOES(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureIsFramebufferOES(const State &glState,
+ bool isCallValid,
+ FramebufferID framebufferPacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureIsRenderbufferOES(const State &glState,
+ bool isCallValid,
+ RenderbufferID renderbufferPacked,
+ GLboolean returnValue);
+angle::CallCapture CaptureRenderbufferStorageOES(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+
+// GL_OES_geometry_shader
+angle::CallCapture CaptureFramebufferTextureOES(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ TextureID texturePacked,
+ GLint level);
+
+// GL_OES_get_program_binary
+angle::CallCapture CaptureGetProgramBinaryOES(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary);
+angle::CallCapture CaptureProgramBinaryOES(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length);
+
+// GL_OES_mapbuffer
+angle::CallCapture CaptureGetBufferPointervOES(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ void **params);
+angle::CallCapture CaptureMapBufferOES(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum access,
+ void *returnValue);
+angle::CallCapture CaptureUnmapBufferOES(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLboolean returnValue);
+
+// GL_OES_matrix_palette
+angle::CallCapture CaptureCurrentPaletteMatrixOES(const State &glState,
+ bool isCallValid,
+ GLuint matrixpaletteindex);
+angle::CallCapture CaptureLoadPaletteFromModelViewMatrixOES(const State &glState, bool isCallValid);
+angle::CallCapture CaptureMatrixIndexPointerOES(const State &glState,
+ bool isCallValid,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer);
+angle::CallCapture CaptureWeightPointerOES(const State &glState,
+ bool isCallValid,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer);
+
+// GL_OES_packed_depth_stencil
+
+// GL_OES_point_size_array
+angle::CallCapture CapturePointSizePointerOES(const State &glState,
+ bool isCallValid,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer);
+
+// GL_OES_point_sprite
+
+// GL_OES_primitive_bounding_box
+angle::CallCapture CapturePrimitiveBoundingBoxOES(const State &glState,
+ bool isCallValid,
+ GLfloat minX,
+ GLfloat minY,
+ GLfloat minZ,
+ GLfloat minW,
+ GLfloat maxX,
+ GLfloat maxY,
+ GLfloat maxZ,
+ GLfloat maxW);
+
+// GL_OES_query_matrix
+angle::CallCapture CaptureQueryMatrixxOES(const State &glState,
+ bool isCallValid,
+ GLfixed *mantissa,
+ GLint *exponent,
+ GLbitfield returnValue);
+
+// GL_OES_rgb8_rgba8
+
+// GL_OES_sample_shading
+angle::CallCapture CaptureMinSampleShadingOES(const State &glState,
+ bool isCallValid,
+ GLfloat value);
+
+// GL_OES_sample_variables
+
+// GL_OES_shader_image_atomic
+
+// GL_OES_shader_io_blocks
+
+// GL_OES_shader_multisample_interpolation
+
+// GL_OES_standard_derivatives
+
+// GL_OES_surfaceless_context
+
+// GL_OES_texture_3D
+angle::CallCapture CaptureCompressedTexImage3DOES(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const void *data);
+angle::CallCapture CaptureCompressedTexSubImage3DOES(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+angle::CallCapture CaptureCopyTexSubImage3DOES(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+angle::CallCapture CaptureFramebufferTexture3DOES(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texturePacked,
+ GLint level,
+ GLint zoffset);
+angle::CallCapture CaptureTexImage3DOES(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+angle::CallCapture CaptureTexSubImage3DOES(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+
+// GL_OES_texture_border_clamp
+angle::CallCapture CaptureGetSamplerParameterIivOES(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetSamplerParameterIuivOES(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLuint *params);
+angle::CallCapture CaptureGetTexParameterIivOES(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetTexParameterIuivOES(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLuint *params);
+angle::CallCapture CaptureSamplerParameterIivOES(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *param);
+angle::CallCapture CaptureSamplerParameterIuivOES(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLuint *param);
+angle::CallCapture CaptureTexParameterIivOES(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params);
+angle::CallCapture CaptureTexParameterIuivOES(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params);
+
+// GL_OES_texture_buffer
+angle::CallCapture CaptureTexBufferOES(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum internalformat,
+ BufferID bufferPacked);
+angle::CallCapture CaptureTexBufferRangeOES(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum internalformat,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size);
+
+// GL_OES_texture_compression_astc
+
+// GL_OES_texture_cube_map
+angle::CallCapture CaptureGetTexGenfvOES(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLfloat *params);
+angle::CallCapture CaptureGetTexGenivOES(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLint *params);
+angle::CallCapture CaptureGetTexGenxvOES(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLfixed *params);
+angle::CallCapture CaptureTexGenfOES(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLfloat param);
+angle::CallCapture CaptureTexGenfvOES(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ const GLfloat *params);
+angle::CallCapture CaptureTexGeniOES(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLint param);
+angle::CallCapture CaptureTexGenivOES(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ const GLint *params);
+angle::CallCapture CaptureTexGenxOES(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLfixed param);
+angle::CallCapture CaptureTexGenxvOES(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ const GLfixed *params);
+
+// GL_OES_texture_cube_map_array
+
+// GL_OES_texture_float
+
+// GL_OES_texture_float_linear
+
+// GL_OES_texture_half_float
+
+// GL_OES_texture_half_float_linear
+
+// GL_OES_texture_npot
+
+// GL_OES_texture_stencil8
+
+// GL_OES_texture_storage_multisample_2d_array
+angle::CallCapture CaptureTexStorage3DMultisampleOES(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedsamplelocations);
+
+// GL_OES_vertex_array_object
+angle::CallCapture CaptureBindVertexArrayOES(const State &glState,
+ bool isCallValid,
+ VertexArrayID arrayPacked);
+angle::CallCapture CaptureDeleteVertexArraysOES(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const VertexArrayID *arraysPacked);
+angle::CallCapture CaptureGenVertexArraysOES(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ VertexArrayID *arraysPacked);
+angle::CallCapture CaptureIsVertexArrayOES(const State &glState,
+ bool isCallValid,
+ VertexArrayID arrayPacked,
+ GLboolean returnValue);
+
+// GL_OES_vertex_half_float
+
+// GL_OES_vertex_type_10_10_10_2
+
+// GL_OVR_multiview
+angle::CallCapture CaptureFramebufferTextureMultiviewOVR(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ TextureID texturePacked,
+ GLint level,
+ GLint baseViewIndex,
+ GLsizei numViews);
+
+// GL_OVR_multiview2
+
+// GL_QCOM_shading_rate
+angle::CallCapture CaptureShadingRateQCOM(const State &glState, bool isCallValid, GLenum rate);
+
+// Parameter Captures
+
+void CaptureDeletePerfMonitorsAMD_monitors(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ GLuint *monitors,
+ angle::ParamCapture *paramCapture);
+void CaptureGenPerfMonitorsAMD_monitors(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ GLuint *monitors,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPerfMonitorCounterDataAMD_data(const State &glState,
+ bool isCallValid,
+ GLuint monitor,
+ GLenum pname,
+ GLsizei dataSize,
+ GLuint *data,
+ GLint *bytesWritten,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPerfMonitorCounterDataAMD_bytesWritten(const State &glState,
+ bool isCallValid,
+ GLuint monitor,
+ GLenum pname,
+ GLsizei dataSize,
+ GLuint *data,
+ GLint *bytesWritten,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPerfMonitorCounterInfoAMD_data(const State &glState,
+ bool isCallValid,
+ GLuint group,
+ GLuint counter,
+ GLenum pname,
+ void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPerfMonitorCounterStringAMD_length(const State &glState,
+ bool isCallValid,
+ GLuint group,
+ GLuint counter,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *counterString,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPerfMonitorCounterStringAMD_counterString(const State &glState,
+ bool isCallValid,
+ GLuint group,
+ GLuint counter,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *counterString,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPerfMonitorCountersAMD_numCounters(const State &glState,
+ bool isCallValid,
+ GLuint group,
+ GLint *numCounters,
+ GLint *maxActiveCounters,
+ GLsizei counterSize,
+ GLuint *counters,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPerfMonitorCountersAMD_maxActiveCounters(const State &glState,
+ bool isCallValid,
+ GLuint group,
+ GLint *numCounters,
+ GLint *maxActiveCounters,
+ GLsizei counterSize,
+ GLuint *counters,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPerfMonitorCountersAMD_counters(const State &glState,
+ bool isCallValid,
+ GLuint group,
+ GLint *numCounters,
+ GLint *maxActiveCounters,
+ GLsizei counterSize,
+ GLuint *counters,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPerfMonitorGroupStringAMD_length(const State &glState,
+ bool isCallValid,
+ GLuint group,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *groupString,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPerfMonitorGroupStringAMD_groupString(const State &glState,
+ bool isCallValid,
+ GLuint group,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *groupString,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPerfMonitorGroupsAMD_numGroups(const State &glState,
+ bool isCallValid,
+ GLint *numGroups,
+ GLsizei groupsSize,
+ GLuint *groups,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPerfMonitorGroupsAMD_groups(const State &glState,
+ bool isCallValid,
+ GLint *numGroups,
+ GLsizei groupsSize,
+ GLuint *groups,
+ angle::ParamCapture *paramCapture);
+void CaptureSelectPerfMonitorCountersAMD_counterList(const State &glState,
+ bool isCallValid,
+ GLuint monitor,
+ GLboolean enable,
+ GLuint group,
+ GLint numCounters,
+ GLuint *counterList,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawElementsInstancedBaseVertexBaseInstanceANGLE_indices(
+ const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const GLvoid *indices,
+ GLsizei instanceCount,
+ GLint baseVertex,
+ GLuint baseInstance,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_firsts(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ const GLuint *baseInstances,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_counts(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ const GLuint *baseInstances,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_instanceCounts(
+ const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ const GLuint *baseInstances,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawArraysInstancedBaseInstanceANGLE_baseInstances(
+ const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ const GLuint *baseInstances,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_counts(
+ const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_indices(
+ const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_instanceCounts(
+ const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_baseVertices(
+ const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE_baseInstances(
+ const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexImageANGLE_pixels(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureGetCompressedTexImageANGLE_pixels(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureGetRenderbufferImageANGLE_pixels(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexLevelParameterivANGLE_params(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexLevelParameterfvANGLE_params(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawElementsInstancedANGLE_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei primcount,
+ angle::ParamCapture *paramCapture);
+void CaptureTexStorageMemFlags2DANGLE_imageCreateInfoPNext(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext,
+ angle::ParamCapture *paramCapture);
+void CaptureTexStorageMemFlags2DMultisampleANGLE_imageCreateInfoPNext(
+ const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext,
+ angle::ParamCapture *paramCapture);
+void CaptureTexStorageMemFlags3DANGLE_imageCreateInfoPNext(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext,
+ angle::ParamCapture *paramCapture);
+void CaptureTexStorageMemFlags3DMultisampleANGLE_imageCreateInfoPNext(
+ const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawArraysANGLE_firsts(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawArraysANGLE_counts(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawArraysInstancedANGLE_firsts(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawArraysInstancedANGLE_counts(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawArraysInstancedANGLE_instanceCounts(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsANGLE_counts(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsANGLE_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsInstancedANGLE_counts(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsInstancedANGLE_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsInstancedANGLE_instanceCounts(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount,
+ angle::ParamCapture *paramCapture);
+void CaptureRequestExtensionANGLE_name(const State &glState,
+ bool isCallValid,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureDisableExtensionANGLE_name(const State &glState,
+ bool isCallValid,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBooleanvRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBooleanvRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBufferParameterivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBufferParameterivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFloatvRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFloatvRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFramebufferAttachmentParameterivRobustANGLE_length(
+ const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFramebufferAttachmentParameterivRobustANGLE_params(
+ const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetIntegervRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetIntegervRobustANGLE_data(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetRenderbufferParameterivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetRenderbufferParameterivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetShaderivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetShaderivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterfvRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterfvRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUniformfvRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUniformfvRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUniformivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUniformivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribfvRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribfvRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribPointervRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **pointer,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribPointervRobustANGLE_pointer(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **pointer,
+ angle::ParamCapture *paramCapture);
+void CaptureReadPixelsRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureReadPixelsRobustANGLE_columns(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureReadPixelsRobustANGLE_rows(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureReadPixelsRobustANGLE_pixels(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureTexImage2DRobustANGLE_pixels(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureTexParameterfvRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexParameterivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexSubImage2DRobustANGLE_pixels(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureTexImage3DRobustANGLE_pixels(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureTexSubImage3DRobustANGLE_pixels(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureCompressedTexImage2DRobustANGLE_data(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data,
+ angle::ParamCapture *paramCapture);
+void CaptureCompressedTexSubImage2DRobustANGLE_data(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLsizei xoffset,
+ GLsizei yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data,
+ angle::ParamCapture *paramCapture);
+void CaptureCompressedTexImage3DRobustANGLE_data(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data,
+ angle::ParamCapture *paramCapture);
+void CaptureCompressedTexSubImage3DRobustANGLE_data(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ QueryType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ QueryType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjectuivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjectuivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBufferPointervRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBufferPointervRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetIntegeri_vRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetIntegeri_vRobustANGLE_data(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetInternalformativRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetInternalformativRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribIivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribIivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribIuivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetVertexAttribIuivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUniformuivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUniformuivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveUniformBlockivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformBlockIndex uniformBlockIndexPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetActiveUniformBlockivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformBlockIndex uniformBlockIndexPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetInteger64vRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetInteger64vRobustANGLE_data(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetInteger64i_vRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetInteger64i_vRobustANGLE_data(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBufferParameteri64vRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBufferParameteri64vRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params,
+ angle::ParamCapture *paramCapture);
+void CaptureSamplerParameterivRobustANGLE_param(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLuint pname,
+ GLsizei bufSize,
+ const GLint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureSamplerParameterfvRobustANGLE_param(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *param,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameterivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameterivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameterfvRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameterfvRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFramebufferParameterivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFramebufferParameterivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramInterfaceivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramInterfaceivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBooleani_vRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBooleani_vRobustANGLE_data(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLboolean *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetMultisamplefvRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *val,
+ angle::ParamCapture *paramCapture);
+void CaptureGetMultisamplefvRobustANGLE_val(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *val,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexLevelParameterivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexLevelParameterivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexLevelParameterfvRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexLevelParameterfvRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPointervRobustANGLERobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPointervRobustANGLERobustANGLE_params(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ void **params,
+ angle::ParamCapture *paramCapture);
+void CaptureReadnPixelsRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureReadnPixelsRobustANGLE_columns(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureReadnPixelsRobustANGLE_rows(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureReadnPixelsRobustANGLE_data(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnUniformfvRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnUniformfvRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnUniformivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnUniformivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnUniformuivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnUniformuivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexParameterIivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexParameterIuivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterIivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterIivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterIuivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterIuivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureSamplerParameterIivRobustANGLE_param(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureSamplerParameterIuivRobustANGLE_param(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLuint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameterIivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameterIivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameterIuivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameterIuivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjectivRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjectivRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjecti64vRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjecti64vRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint64 *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjectui64vRobustANGLE_length(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint64 *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjectui64vRobustANGLE_params(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLuint64 *params,
+ angle::ParamCapture *paramCapture);
+void CaptureBeginPixelLocalStorageANGLE_loadops(const State &glState,
+ bool isCallValid,
+ GLsizei planes,
+ const GLenum *loadops,
+ const void *cleardata,
+ angle::ParamCapture *paramCapture);
+void CaptureBeginPixelLocalStorageANGLE_cleardata(const State &glState,
+ bool isCallValid,
+ GLsizei planes,
+ const GLenum *loadops,
+ const void *cleardata,
+ angle::ParamCapture *paramCapture);
+void CaptureGetMultisamplefvANGLE_val(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLuint index,
+ GLfloat *val,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTranslatedShaderSourceANGLE_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *source,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTranslatedShaderSourceANGLE_source(const State &glState,
+ bool isCallValid,
+ ShaderProgramID shaderPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *source,
+ angle::ParamCapture *paramCapture);
+void CaptureAcquireTexturesANGLE_texturesPacked(const State &glState,
+ bool isCallValid,
+ GLuint numTextures,
+ const TextureID *texturesPacked,
+ const GLenum *layouts,
+ angle::ParamCapture *paramCapture);
+void CaptureAcquireTexturesANGLE_layouts(const State &glState,
+ bool isCallValid,
+ GLuint numTextures,
+ const TextureID *texturesPacked,
+ const GLenum *layouts,
+ angle::ParamCapture *paramCapture);
+void CaptureReleaseTexturesANGLE_texturesPacked(const State &glState,
+ bool isCallValid,
+ GLuint numTextures,
+ const TextureID *texturesPacked,
+ GLenum *layouts,
+ angle::ParamCapture *paramCapture);
+void CaptureReleaseTexturesANGLE_layouts(const State &glState,
+ bool isCallValid,
+ GLuint numTextures,
+ const TextureID *texturesPacked,
+ GLenum *layouts,
+ angle::ParamCapture *paramCapture);
+void CaptureBindUniformLocationCHROMIUM_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureEGLImageTargetTexStorageEXT_attrib_list(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLeglImageOES image,
+ const GLint *attrib_list,
+ angle::ParamCapture *paramCapture);
+void CaptureEGLImageTargetTextureStorageEXT_attrib_list(const State &glState,
+ bool isCallValid,
+ GLuint texture,
+ GLeglImageOES image,
+ const GLint *attrib_list,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawElementsInstancedBaseInstanceEXT_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLuint baseinstance,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawElementsInstancedBaseVertexBaseInstanceEXT_indices(
+ const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex,
+ GLuint baseinstance,
+ angle::ParamCapture *paramCapture);
+void CaptureBindFragDataLocationEXT_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint color,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureBindFragDataLocationIndexedEXT_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLuint colorNumber,
+ GLuint index,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFragDataIndexEXT_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramResourceLocationIndexEXT_name(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ const GLchar *name,
+ angle::ParamCapture *paramCapture);
+void CaptureBufferStorageEXT_data(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags,
+ angle::ParamCapture *paramCapture);
+void CaptureGetObjectLabelEXT_length(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint object,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureGetObjectLabelEXT_label(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint object,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureLabelObjectEXT_label(const State &glState,
+ bool isCallValid,
+ GLenum type,
+ GLuint object,
+ GLsizei length,
+ const GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureInsertEventMarkerEXT_marker(const State &glState,
+ bool isCallValid,
+ GLsizei length,
+ const GLchar *marker,
+ angle::ParamCapture *paramCapture);
+void CapturePushGroupMarkerEXT_marker(const State &glState,
+ bool isCallValid,
+ GLsizei length,
+ const GLchar *marker,
+ angle::ParamCapture *paramCapture);
+void CaptureDiscardFramebufferEXT_attachments(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteQueriesEXT_idsPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const QueryID *idsPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGenQueriesEXT_idsPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ QueryID *idsPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGetInteger64vEXT_data(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLint64 *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjecti64vEXT_params(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLint64 *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjectivEXT_params(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjectui64vEXT_params(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLuint64 *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryObjectuivEXT_params(const State &glState,
+ bool isCallValid,
+ QueryID idPacked,
+ GLenum pname,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetQueryivEXT_params(const State &glState,
+ bool isCallValid,
+ QueryType targetPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawBuffersEXT_bufs(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const GLenum *bufs,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawElementsBaseVertexEXT_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawElementsInstancedBaseVertexEXT_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawRangeElementsBaseVertexEXT_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsBaseVertexEXT_count(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *count,
+ DrawElementsType typePacked,
+ const void *const *indices,
+ GLsizei drawcount,
+ const GLint *basevertex,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsBaseVertexEXT_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *count,
+ DrawElementsType typePacked,
+ const void *const *indices,
+ GLsizei drawcount,
+ const GLint *basevertex,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsBaseVertexEXT_basevertex(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const GLsizei *count,
+ DrawElementsType typePacked,
+ const void *const *indices,
+ GLsizei drawcount,
+ const GLint *basevertex,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawElementsInstancedEXT_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei primcount,
+ angle::ParamCapture *paramCapture);
+void CaptureCreateMemoryObjectsEXT_memoryObjectsPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ MemoryObjectID *memoryObjectsPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteMemoryObjectsEXT_memoryObjectsPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const MemoryObjectID *memoryObjectsPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGetMemoryObjectParameterivEXT_params(const State &glState,
+ bool isCallValid,
+ MemoryObjectID memoryObjectPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUnsignedBytevEXT_data(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ GLubyte *data,
+ angle::ParamCapture *paramCapture);
+void CaptureGetUnsignedBytei_vEXT_data(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLuint index,
+ GLubyte *data,
+ angle::ParamCapture *paramCapture);
+void CaptureMemoryObjectParameterivEXT_params(const State &glState,
+ bool isCallValid,
+ MemoryObjectID memoryObjectPacked,
+ GLenum pname,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawArraysIndirectEXT_indirect(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride,
+ angle::ParamCapture *paramCapture);
+void CaptureMultiDrawElementsIndirectEXT_indirect(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ DrawElementsType typePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnUniformfvEXT_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetnUniformivEXT_params(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureReadnPixelsEXT_data(const State &glState,
+ bool isCallValid,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteSemaphoresEXT_semaphoresPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const SemaphoreID *semaphoresPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGenSemaphoresEXT_semaphoresPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ SemaphoreID *semaphoresPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSemaphoreParameterui64vEXT_params(const State &glState,
+ bool isCallValid,
+ SemaphoreID semaphorePacked,
+ GLenum pname,
+ GLuint64 *params,
+ angle::ParamCapture *paramCapture);
+void CaptureSemaphoreParameterui64vEXT_params(const State &glState,
+ bool isCallValid,
+ SemaphoreID semaphorePacked,
+ GLenum pname,
+ const GLuint64 *params,
+ angle::ParamCapture *paramCapture);
+void CaptureSignalSemaphoreEXT_buffersPacked(const State &glState,
+ bool isCallValid,
+ SemaphoreID semaphorePacked,
+ GLuint numBufferBarriers,
+ const BufferID *buffersPacked,
+ GLuint numTextureBarriers,
+ const TextureID *texturesPacked,
+ const GLenum *dstLayouts,
+ angle::ParamCapture *paramCapture);
+void CaptureSignalSemaphoreEXT_texturesPacked(const State &glState,
+ bool isCallValid,
+ SemaphoreID semaphorePacked,
+ GLuint numBufferBarriers,
+ const BufferID *buffersPacked,
+ GLuint numTextureBarriers,
+ const TextureID *texturesPacked,
+ const GLenum *dstLayouts,
+ angle::ParamCapture *paramCapture);
+void CaptureSignalSemaphoreEXT_dstLayouts(const State &glState,
+ bool isCallValid,
+ SemaphoreID semaphorePacked,
+ GLuint numBufferBarriers,
+ const BufferID *buffersPacked,
+ GLuint numTextureBarriers,
+ const TextureID *texturesPacked,
+ const GLenum *dstLayouts,
+ angle::ParamCapture *paramCapture);
+void CaptureWaitSemaphoreEXT_buffersPacked(const State &glState,
+ bool isCallValid,
+ SemaphoreID semaphorePacked,
+ GLuint numBufferBarriers,
+ const BufferID *buffersPacked,
+ GLuint numTextureBarriers,
+ const TextureID *texturesPacked,
+ const GLenum *srcLayouts,
+ angle::ParamCapture *paramCapture);
+void CaptureWaitSemaphoreEXT_texturesPacked(const State &glState,
+ bool isCallValid,
+ SemaphoreID semaphorePacked,
+ GLuint numBufferBarriers,
+ const BufferID *buffersPacked,
+ GLuint numTextureBarriers,
+ const TextureID *texturesPacked,
+ const GLenum *srcLayouts,
+ angle::ParamCapture *paramCapture);
+void CaptureWaitSemaphoreEXT_srcLayouts(const State &glState,
+ bool isCallValid,
+ SemaphoreID semaphorePacked,
+ GLuint numBufferBarriers,
+ const BufferID *buffersPacked,
+ GLuint numTextureBarriers,
+ const TextureID *texturesPacked,
+ const GLenum *srcLayouts,
+ angle::ParamCapture *paramCapture);
+void CaptureCreateShaderProgramvEXT_strings(const State &glState,
+ bool isCallValid,
+ ShaderType typePacked,
+ GLsizei count,
+ const GLchar **strings,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteProgramPipelinesEXT_pipelinesPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const ProgramPipelineID *pipelinesPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGenProgramPipelinesEXT_pipelinesPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ ProgramPipelineID *pipelinesPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramPipelineInfoLogEXT_length(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramPipelineInfoLogEXT_infoLog(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *infoLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramPipelineivEXT_params(const State &glState,
+ bool isCallValid,
+ ProgramPipelineID pipelinePacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform1fvEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform1ivEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform1uivEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform2fvEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform2ivEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform2uivEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform3fvEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform3ivEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform3uivEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform4fvEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform4ivEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniform4uivEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix2fvEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix2x3fvEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix2x4fvEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix3fvEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix3x2fvEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix3x4fvEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix4fvEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix4x2fvEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramUniformMatrix4x3fvEXT_value(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameterIivEXT_params(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameterIuivEXT_params(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterIivEXT_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterIuivEXT_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureSamplerParameterIivEXT_param(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureSamplerParameterIuivEXT_param(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLuint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureTexParameterIivEXT_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexParameterIuivEXT_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureDebugMessageCallbackKHR_userParam(const State &glState,
+ bool isCallValid,
+ GLDEBUGPROCKHR callback,
+ const void *userParam,
+ angle::ParamCapture *paramCapture);
+void CaptureDebugMessageControlKHR_ids(const State &glState,
+ bool isCallValid,
+ GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled,
+ angle::ParamCapture *paramCapture);
+void CaptureDebugMessageInsertKHR_buf(const State &glState,
+ bool isCallValid,
+ GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *buf,
+ angle::ParamCapture *paramCapture);
+void CaptureGetDebugMessageLogKHR_sources(const State &glState,
+ bool isCallValid,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetDebugMessageLogKHR_types(const State &glState,
+ bool isCallValid,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetDebugMessageLogKHR_ids(const State &glState,
+ bool isCallValid,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetDebugMessageLogKHR_severities(const State &glState,
+ bool isCallValid,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetDebugMessageLogKHR_lengths(const State &glState,
+ bool isCallValid,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetDebugMessageLogKHR_messageLog(const State &glState,
+ bool isCallValid,
+ GLuint count,
+ GLsizei bufSize,
+ GLenum *sources,
+ GLenum *types,
+ GLuint *ids,
+ GLenum *severities,
+ GLsizei *lengths,
+ GLchar *messageLog,
+ angle::ParamCapture *paramCapture);
+void CaptureGetObjectLabelKHR_length(const State &glState,
+ bool isCallValid,
+ GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureGetObjectLabelKHR_label(const State &glState,
+ bool isCallValid,
+ GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureGetObjectPtrLabelKHR_ptr(const State &glState,
+ bool isCallValid,
+ const void *ptr,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureGetObjectPtrLabelKHR_length(const State &glState,
+ bool isCallValid,
+ const void *ptr,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureGetObjectPtrLabelKHR_label(const State &glState,
+ bool isCallValid,
+ const void *ptr,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureGetPointervKHR_params(const State &glState,
+ bool isCallValid,
+ GLenum pname,
+ void **params,
+ angle::ParamCapture *paramCapture);
+void CaptureObjectLabelKHR_label(const State &glState,
+ bool isCallValid,
+ GLenum identifier,
+ GLuint name,
+ GLsizei length,
+ const GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureObjectPtrLabelKHR_ptr(const State &glState,
+ bool isCallValid,
+ const void *ptr,
+ GLsizei length,
+ const GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CaptureObjectPtrLabelKHR_label(const State &glState,
+ bool isCallValid,
+ const void *ptr,
+ GLsizei length,
+ const GLchar *label,
+ angle::ParamCapture *paramCapture);
+void CapturePushDebugGroupKHR_message(const State &glState,
+ bool isCallValid,
+ GLenum source,
+ GLuint id,
+ GLsizei length,
+ const GLchar *message,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFramebufferParameterivMESA_params(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteFencesNV_fencesPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const FenceNVID *fencesPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGenFencesNV_fencesPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ FenceNVID *fencesPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFenceivNV_params(const State &glState,
+ bool isCallValid,
+ FenceNVID fencePacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawElementsBaseVertexOES_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawElementsInstancedBaseVertexOES_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawRangeElementsBaseVertexOES_indices(const State &glState,
+ bool isCallValid,
+ PrimitiveMode modePacked,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawTexfvOES_coords(const State &glState,
+ bool isCallValid,
+ const GLfloat *coords,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawTexivOES_coords(const State &glState,
+ bool isCallValid,
+ const GLint *coords,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawTexsvOES_coords(const State &glState,
+ bool isCallValid,
+ const GLshort *coords,
+ angle::ParamCapture *paramCapture);
+void CaptureDrawTexxvOES_coords(const State &glState,
+ bool isCallValid,
+ const GLfixed *coords,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteFramebuffersOES_framebuffersPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const FramebufferID *framebuffersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteRenderbuffersOES_renderbuffersPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const RenderbufferID *renderbuffersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGenFramebuffersOES_framebuffersPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ FramebufferID *framebuffersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGenRenderbuffersOES_renderbuffersPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ RenderbufferID *renderbuffersPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGetFramebufferAttachmentParameterivOES_params(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetRenderbufferParameterivOES_params(const State &glState,
+ bool isCallValid,
+ GLenum target,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramBinaryOES_length(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramBinaryOES_binaryFormat(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary,
+ angle::ParamCapture *paramCapture);
+void CaptureGetProgramBinaryOES_binary(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLenum *binaryFormat,
+ void *binary,
+ angle::ParamCapture *paramCapture);
+void CaptureProgramBinaryOES_binary(const State &glState,
+ bool isCallValid,
+ ShaderProgramID programPacked,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length,
+ angle::ParamCapture *paramCapture);
+void CaptureGetBufferPointervOES_params(const State &glState,
+ bool isCallValid,
+ BufferBinding targetPacked,
+ GLenum pname,
+ void **params,
+ angle::ParamCapture *paramCapture);
+void CaptureMatrixIndexPointerOES_pointer(const State &glState,
+ bool isCallValid,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer,
+ angle::ParamCapture *paramCapture);
+void CaptureWeightPointerOES_pointer(const State &glState,
+ bool isCallValid,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer,
+ angle::ParamCapture *paramCapture);
+void CapturePointSizePointerOES_pointer(const State &glState,
+ bool isCallValid,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer,
+ angle::ParamCapture *paramCapture);
+void CaptureQueryMatrixxOES_mantissa(const State &glState,
+ bool isCallValid,
+ GLfixed *mantissa,
+ GLint *exponent,
+ angle::ParamCapture *paramCapture);
+void CaptureQueryMatrixxOES_exponent(const State &glState,
+ bool isCallValid,
+ GLfixed *mantissa,
+ GLint *exponent,
+ angle::ParamCapture *paramCapture);
+void CaptureCompressedTexImage3DOES_data(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureCompressedTexSubImage3DOES_data(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data,
+ angle::ParamCapture *paramCapture);
+void CaptureTexImage3DOES_pixels(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureTexSubImage3DOES_pixels(const State &glState,
+ bool isCallValid,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameterIivOES_params(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetSamplerParameterIuivOES_params(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterIivOES_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexParameterIuivOES_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureSamplerParameterIivOES_param(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureSamplerParameterIuivOES_param(const State &glState,
+ bool isCallValid,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLuint *param,
+ angle::ParamCapture *paramCapture);
+void CaptureTexParameterIivOES_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexParameterIuivOES_params(const State &glState,
+ bool isCallValid,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexGenfvOES_params(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexGenivOES_params(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureGetTexGenxvOES_params(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ GLfixed *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexGenfvOES_params(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ const GLfloat *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexGenivOES_params(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ const GLint *params,
+ angle::ParamCapture *paramCapture);
+void CaptureTexGenxvOES_params(const State &glState,
+ bool isCallValid,
+ GLenum coord,
+ GLenum pname,
+ const GLfixed *params,
+ angle::ParamCapture *paramCapture);
+void CaptureDeleteVertexArraysOES_arraysPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ const VertexArrayID *arraysPacked,
+ angle::ParamCapture *paramCapture);
+void CaptureGenVertexArraysOES_arraysPacked(const State &glState,
+ bool isCallValid,
+ GLsizei n,
+ VertexArrayID *arraysPacked,
+ angle::ParamCapture *paramCapture);
+} // namespace gl
+
+#endif // LIBANGLE_CAPTURE_GLES_EXT_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/capture/frame_capture_utils.h b/gfx/angle/checkout/src/libANGLE/capture/frame_capture_utils.h
new file mode 100644
index 0000000000..18e2fe41cc
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/frame_capture_utils.h
@@ -0,0 +1,23 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// frame_capture_utils.h:
+// ANGLE frame capture utils interface.
+//
+#ifndef FRAME_CAPTURE_UTILS_H_
+#define FRAME_CAPTURE_UTILS_H_
+
+#include "libANGLE/Error.h"
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace angle
+{
+Result SerializeContextToString(const gl::Context *context, std::string *stringOut);
+} // namespace angle
+#endif // FRAME_CAPTURE_UTILS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/capture/frame_capture_utils_autogen.h b/gfx/angle/checkout/src/libANGLE/capture/frame_capture_utils_autogen.h
new file mode 100644
index 0000000000..9c76c2fc15
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/frame_capture_utils_autogen.h
@@ -0,0 +1,3257 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// frame_capture_utils_autogen.h:
+// ANGLE Frame capture types and helper functions.
+
+#ifndef LIBANGLE_FRAME_CAPTURE_UTILS_AUTOGEN_H_
+#define LIBANGLE_FRAME_CAPTURE_UTILS_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+
+namespace angle
+{
+enum class ParamType
+{
+ TAHardwareBufferConstPointer,
+ TAlphaTestFunc,
+ TBufferBinding,
+ TBufferID,
+ TBufferIDConstPointer,
+ TBufferIDPointer,
+ TBufferUsage,
+ TClientVertexArrayType,
+ TCompositorTiming,
+ TCullFaceMode,
+ TDrawElementsType,
+ TEGLAttrib,
+ TEGLAttribKHR,
+ TEGLBoolean,
+ TEGLClientBuffer,
+ TEGLConfig,
+ TEGLContext,
+ TEGLDEBUGPROCKHR,
+ TEGLDeviceEXT,
+ TEGLDisplay,
+ TEGLFrameTokenANGLE,
+ TEGLGetBlobFuncANDROID,
+ TEGLImage,
+ TEGLLabelKHR,
+ TEGLNativeDisplayType,
+ TEGLNativePixmapType,
+ TEGLNativeWindowType,
+ TEGLObjectKHR,
+ TEGLSetBlobFuncANDROID,
+ TEGLStreamKHR,
+ TEGLSurface,
+ TEGLSync,
+ TEGLTime,
+ TEGLTimeKHR,
+ TEGLenum,
+ TEGLint,
+ TEGLnsecsANDROID,
+ TEGLuint64KHR,
+ TFenceNVID,
+ TFenceNVIDConstPointer,
+ TFenceNVIDPointer,
+ TFramebufferID,
+ TFramebufferIDConstPointer,
+ TFramebufferIDPointer,
+ TGLDEBUGPROC,
+ TGLDEBUGPROCKHR,
+ TGLbitfield,
+ TGLboolean,
+ TGLbooleanConstPointer,
+ TGLbooleanPointer,
+ TGLbyte,
+ TGLbyteConstPointer,
+ TGLcharConstPointer,
+ TGLcharConstPointerPointer,
+ TGLcharPointer,
+ TGLclampx,
+ TGLdouble,
+ TGLdoubleConstPointer,
+ TGLdoublePointer,
+ TGLeglClientBufferEXT,
+ TGLeglImageOES,
+ TGLenum,
+ TGLenumConstPointer,
+ TGLenumPointer,
+ TGLfixed,
+ TGLfixedConstPointer,
+ TGLfixedPointer,
+ TGLfloat,
+ TGLfloatConstPointer,
+ TGLfloatPointer,
+ TGLint,
+ TGLint64Pointer,
+ TGLintConstPointer,
+ TGLintPointer,
+ TGLintptr,
+ TGLintptrConstPointer,
+ TGLshort,
+ TGLshortConstPointer,
+ TGLsizei,
+ TGLsizeiConstPointer,
+ TGLsizeiPointer,
+ TGLsizeiptr,
+ TGLsizeiptrConstPointer,
+ TGLsync,
+ TGLubyte,
+ TGLubyteConstPointer,
+ TGLubytePointer,
+ TGLuint,
+ TGLuint64,
+ TGLuint64ConstPointer,
+ TGLuint64Pointer,
+ TGLuintConstPointer,
+ TGLuintPointer,
+ TGLushort,
+ TGLushortConstPointer,
+ TGLushortPointer,
+ TGLvoidConstPointer,
+ TGLvoidConstPointerPointer,
+ TGraphicsResetStatus,
+ THandleType,
+ TLightParameter,
+ TLogicalOperation,
+ TMaterialParameter,
+ TMatrixType,
+ TMemoryObjectID,
+ TMemoryObjectIDConstPointer,
+ TMemoryObjectIDPointer,
+ TObjectType,
+ TPointParameter,
+ TPrimitiveMode,
+ TProgramPipelineID,
+ TProgramPipelineIDConstPointer,
+ TProgramPipelineIDPointer,
+ TProvokingVertexConvention,
+ TQueryID,
+ TQueryIDConstPointer,
+ TQueryIDPointer,
+ TQueryType,
+ TRenderbufferID,
+ TRenderbufferIDConstPointer,
+ TRenderbufferIDPointer,
+ TSamplerID,
+ TSamplerIDConstPointer,
+ TSamplerIDPointer,
+ TSemaphoreID,
+ TSemaphoreIDConstPointer,
+ TSemaphoreIDPointer,
+ TShaderProgramID,
+ TShaderProgramIDConstPointer,
+ TShaderProgramIDPointer,
+ TShaderType,
+ TShadingModel,
+ TTextureEnvParameter,
+ TTextureEnvTarget,
+ TTextureID,
+ TTextureIDConstPointer,
+ TTextureIDPointer,
+ TTextureTarget,
+ TTextureType,
+ TTimestamp,
+ TTransformFeedbackID,
+ TTransformFeedbackIDConstPointer,
+ TTransformFeedbackIDPointer,
+ TUniformBlockIndex,
+ TUniformLocation,
+ TVertexArrayID,
+ TVertexArrayIDConstPointer,
+ TVertexArrayIDPointer,
+ TVertexAttribType,
+ TcharConstPointer,
+ TvoidConstPointer,
+ TvoidConstPointerPointer,
+ TvoidPointer,
+ TvoidPointerPointer,
+};
+
+constexpr uint32_t kParamTypeCount = 154;
+
+union ParamValue
+{
+ const AHardwareBuffer *AHardwareBufferConstPointerVal;
+ gl::AlphaTestFunc AlphaTestFuncVal;
+ gl::BufferBinding BufferBindingVal;
+ gl::BufferID BufferIDVal;
+ const gl::BufferID *BufferIDConstPointerVal;
+ gl::BufferID *BufferIDPointerVal;
+ gl::BufferUsage BufferUsageVal;
+ gl::ClientVertexArrayType ClientVertexArrayTypeVal;
+ egl::CompositorTiming CompositorTimingVal;
+ gl::CullFaceMode CullFaceModeVal;
+ gl::DrawElementsType DrawElementsTypeVal;
+ EGLAttrib EGLAttribVal;
+ EGLAttribKHR EGLAttribKHRVal;
+ EGLBoolean EGLBooleanVal;
+ EGLClientBuffer EGLClientBufferVal;
+ EGLConfig EGLConfigVal;
+ EGLContext EGLContextVal;
+ EGLDEBUGPROCKHR EGLDEBUGPROCKHRVal;
+ EGLDeviceEXT EGLDeviceEXTVal;
+ EGLDisplay EGLDisplayVal;
+ EGLFrameTokenANGLE EGLFrameTokenANGLEVal;
+ EGLGetBlobFuncANDROID EGLGetBlobFuncANDROIDVal;
+ EGLImage EGLImageVal;
+ EGLLabelKHR EGLLabelKHRVal;
+ EGLNativeDisplayType EGLNativeDisplayTypeVal;
+ EGLNativePixmapType EGLNativePixmapTypeVal;
+ EGLNativeWindowType EGLNativeWindowTypeVal;
+ EGLObjectKHR EGLObjectKHRVal;
+ EGLSetBlobFuncANDROID EGLSetBlobFuncANDROIDVal;
+ EGLStreamKHR EGLStreamKHRVal;
+ EGLSurface EGLSurfaceVal;
+ EGLSync EGLSyncVal;
+ EGLTime EGLTimeVal;
+ EGLTimeKHR EGLTimeKHRVal;
+ EGLenum EGLenumVal;
+ EGLint EGLintVal;
+ EGLnsecsANDROID EGLnsecsANDROIDVal;
+ EGLuint64KHR EGLuint64KHRVal;
+ gl::FenceNVID FenceNVIDVal;
+ const gl::FenceNVID *FenceNVIDConstPointerVal;
+ gl::FenceNVID *FenceNVIDPointerVal;
+ gl::FramebufferID FramebufferIDVal;
+ const gl::FramebufferID *FramebufferIDConstPointerVal;
+ gl::FramebufferID *FramebufferIDPointerVal;
+ GLDEBUGPROC GLDEBUGPROCVal;
+ GLDEBUGPROCKHR GLDEBUGPROCKHRVal;
+ GLbitfield GLbitfieldVal;
+ GLboolean GLbooleanVal;
+ const GLboolean *GLbooleanConstPointerVal;
+ GLboolean *GLbooleanPointerVal;
+ GLbyte GLbyteVal;
+ const GLbyte *GLbyteConstPointerVal;
+ const GLchar *GLcharConstPointerVal;
+ const GLchar *const *GLcharConstPointerPointerVal;
+ GLchar *GLcharPointerVal;
+ GLclampx GLclampxVal;
+ GLdouble GLdoubleVal;
+ const GLdouble *GLdoubleConstPointerVal;
+ GLdouble *GLdoublePointerVal;
+ GLeglClientBufferEXT GLeglClientBufferEXTVal;
+ GLeglImageOES GLeglImageOESVal;
+ GLenum GLenumVal;
+ const GLenum *GLenumConstPointerVal;
+ GLenum *GLenumPointerVal;
+ GLfixed GLfixedVal;
+ const GLfixed *GLfixedConstPointerVal;
+ GLfixed *GLfixedPointerVal;
+ GLfloat GLfloatVal;
+ const GLfloat *GLfloatConstPointerVal;
+ GLfloat *GLfloatPointerVal;
+ GLint GLintVal;
+ GLint64 *GLint64PointerVal;
+ const GLint *GLintConstPointerVal;
+ GLint *GLintPointerVal;
+ GLintptr GLintptrVal;
+ const GLintptr *GLintptrConstPointerVal;
+ GLshort GLshortVal;
+ const GLshort *GLshortConstPointerVal;
+ GLsizei GLsizeiVal;
+ const GLsizei *GLsizeiConstPointerVal;
+ GLsizei *GLsizeiPointerVal;
+ GLsizeiptr GLsizeiptrVal;
+ const GLsizeiptr *GLsizeiptrConstPointerVal;
+ GLsync GLsyncVal;
+ GLubyte GLubyteVal;
+ const GLubyte *GLubyteConstPointerVal;
+ GLubyte *GLubytePointerVal;
+ GLuint GLuintVal;
+ GLuint64 GLuint64Val;
+ const GLuint64 *GLuint64ConstPointerVal;
+ GLuint64 *GLuint64PointerVal;
+ const GLuint *GLuintConstPointerVal;
+ GLuint *GLuintPointerVal;
+ GLushort GLushortVal;
+ const GLushort *GLushortConstPointerVal;
+ GLushort *GLushortPointerVal;
+ const GLvoid *GLvoidConstPointerVal;
+ const GLvoid *const *GLvoidConstPointerPointerVal;
+ gl::GraphicsResetStatus GraphicsResetStatusVal;
+ gl::HandleType HandleTypeVal;
+ gl::LightParameter LightParameterVal;
+ gl::LogicalOperation LogicalOperationVal;
+ gl::MaterialParameter MaterialParameterVal;
+ gl::MatrixType MatrixTypeVal;
+ gl::MemoryObjectID MemoryObjectIDVal;
+ const gl::MemoryObjectID *MemoryObjectIDConstPointerVal;
+ gl::MemoryObjectID *MemoryObjectIDPointerVal;
+ egl::ObjectType ObjectTypeVal;
+ gl::PointParameter PointParameterVal;
+ gl::PrimitiveMode PrimitiveModeVal;
+ gl::ProgramPipelineID ProgramPipelineIDVal;
+ const gl::ProgramPipelineID *ProgramPipelineIDConstPointerVal;
+ gl::ProgramPipelineID *ProgramPipelineIDPointerVal;
+ gl::ProvokingVertexConvention ProvokingVertexConventionVal;
+ gl::QueryID QueryIDVal;
+ const gl::QueryID *QueryIDConstPointerVal;
+ gl::QueryID *QueryIDPointerVal;
+ gl::QueryType QueryTypeVal;
+ gl::RenderbufferID RenderbufferIDVal;
+ const gl::RenderbufferID *RenderbufferIDConstPointerVal;
+ gl::RenderbufferID *RenderbufferIDPointerVal;
+ gl::SamplerID SamplerIDVal;
+ const gl::SamplerID *SamplerIDConstPointerVal;
+ gl::SamplerID *SamplerIDPointerVal;
+ gl::SemaphoreID SemaphoreIDVal;
+ const gl::SemaphoreID *SemaphoreIDConstPointerVal;
+ gl::SemaphoreID *SemaphoreIDPointerVal;
+ gl::ShaderProgramID ShaderProgramIDVal;
+ const gl::ShaderProgramID *ShaderProgramIDConstPointerVal;
+ gl::ShaderProgramID *ShaderProgramIDPointerVal;
+ gl::ShaderType ShaderTypeVal;
+ gl::ShadingModel ShadingModelVal;
+ gl::TextureEnvParameter TextureEnvParameterVal;
+ gl::TextureEnvTarget TextureEnvTargetVal;
+ gl::TextureID TextureIDVal;
+ const gl::TextureID *TextureIDConstPointerVal;
+ gl::TextureID *TextureIDPointerVal;
+ gl::TextureTarget TextureTargetVal;
+ gl::TextureType TextureTypeVal;
+ egl::Timestamp TimestampVal;
+ gl::TransformFeedbackID TransformFeedbackIDVal;
+ const gl::TransformFeedbackID *TransformFeedbackIDConstPointerVal;
+ gl::TransformFeedbackID *TransformFeedbackIDPointerVal;
+ gl::UniformBlockIndex UniformBlockIndexVal;
+ gl::UniformLocation UniformLocationVal;
+ gl::VertexArrayID VertexArrayIDVal;
+ const gl::VertexArrayID *VertexArrayIDConstPointerVal;
+ gl::VertexArrayID *VertexArrayIDPointerVal;
+ gl::VertexAttribType VertexAttribTypeVal;
+ const char *charConstPointerVal;
+ const void *voidConstPointerVal;
+ const void *const *voidConstPointerPointerVal;
+ void *voidPointerVal;
+ void **voidPointerPointerVal;
+};
+
+template <ParamType PType, typename T>
+T GetParamVal(const ParamValue &value);
+
+template <>
+inline const AHardwareBuffer *GetParamVal<ParamType::TAHardwareBufferConstPointer,
+ const AHardwareBuffer *>(const ParamValue &value)
+{
+ return value.AHardwareBufferConstPointerVal;
+}
+
+template <>
+inline gl::AlphaTestFunc GetParamVal<ParamType::TAlphaTestFunc, gl::AlphaTestFunc>(
+ const ParamValue &value)
+{
+ return value.AlphaTestFuncVal;
+}
+
+template <>
+inline gl::BufferBinding GetParamVal<ParamType::TBufferBinding, gl::BufferBinding>(
+ const ParamValue &value)
+{
+ return value.BufferBindingVal;
+}
+
+template <>
+inline gl::BufferID GetParamVal<ParamType::TBufferID, gl::BufferID>(const ParamValue &value)
+{
+ return value.BufferIDVal;
+}
+
+template <>
+inline const gl::BufferID *GetParamVal<ParamType::TBufferIDConstPointer, const gl::BufferID *>(
+ const ParamValue &value)
+{
+ return value.BufferIDConstPointerVal;
+}
+
+template <>
+inline gl::BufferID *GetParamVal<ParamType::TBufferIDPointer, gl::BufferID *>(
+ const ParamValue &value)
+{
+ return value.BufferIDPointerVal;
+}
+
+template <>
+inline gl::BufferUsage GetParamVal<ParamType::TBufferUsage, gl::BufferUsage>(
+ const ParamValue &value)
+{
+ return value.BufferUsageVal;
+}
+
+template <>
+inline gl::ClientVertexArrayType
+GetParamVal<ParamType::TClientVertexArrayType, gl::ClientVertexArrayType>(const ParamValue &value)
+{
+ return value.ClientVertexArrayTypeVal;
+}
+
+template <>
+inline egl::CompositorTiming GetParamVal<ParamType::TCompositorTiming, egl::CompositorTiming>(
+ const ParamValue &value)
+{
+ return value.CompositorTimingVal;
+}
+
+template <>
+inline gl::CullFaceMode GetParamVal<ParamType::TCullFaceMode, gl::CullFaceMode>(
+ const ParamValue &value)
+{
+ return value.CullFaceModeVal;
+}
+
+template <>
+inline gl::DrawElementsType GetParamVal<ParamType::TDrawElementsType, gl::DrawElementsType>(
+ const ParamValue &value)
+{
+ return value.DrawElementsTypeVal;
+}
+
+template <>
+inline EGLAttrib GetParamVal<ParamType::TEGLAttrib, EGLAttrib>(const ParamValue &value)
+{
+ return value.EGLAttribVal;
+}
+
+template <>
+inline EGLAttribKHR GetParamVal<ParamType::TEGLAttribKHR, EGLAttribKHR>(const ParamValue &value)
+{
+ return value.EGLAttribKHRVal;
+}
+
+template <>
+inline EGLBoolean GetParamVal<ParamType::TEGLBoolean, EGLBoolean>(const ParamValue &value)
+{
+ return value.EGLBooleanVal;
+}
+
+template <>
+inline EGLClientBuffer GetParamVal<ParamType::TEGLClientBuffer, EGLClientBuffer>(
+ const ParamValue &value)
+{
+ return value.EGLClientBufferVal;
+}
+
+template <>
+inline EGLConfig GetParamVal<ParamType::TEGLConfig, EGLConfig>(const ParamValue &value)
+{
+ return value.EGLConfigVal;
+}
+
+template <>
+inline EGLContext GetParamVal<ParamType::TEGLContext, EGLContext>(const ParamValue &value)
+{
+ return value.EGLContextVal;
+}
+
+template <>
+inline EGLDEBUGPROCKHR GetParamVal<ParamType::TEGLDEBUGPROCKHR, EGLDEBUGPROCKHR>(
+ const ParamValue &value)
+{
+ return value.EGLDEBUGPROCKHRVal;
+}
+
+template <>
+inline EGLDeviceEXT GetParamVal<ParamType::TEGLDeviceEXT, EGLDeviceEXT>(const ParamValue &value)
+{
+ return value.EGLDeviceEXTVal;
+}
+
+template <>
+inline EGLDisplay GetParamVal<ParamType::TEGLDisplay, EGLDisplay>(const ParamValue &value)
+{
+ return value.EGLDisplayVal;
+}
+
+template <>
+inline EGLFrameTokenANGLE GetParamVal<ParamType::TEGLFrameTokenANGLE, EGLFrameTokenANGLE>(
+ const ParamValue &value)
+{
+ return value.EGLFrameTokenANGLEVal;
+}
+
+template <>
+inline EGLGetBlobFuncANDROID GetParamVal<ParamType::TEGLGetBlobFuncANDROID, EGLGetBlobFuncANDROID>(
+ const ParamValue &value)
+{
+ return value.EGLGetBlobFuncANDROIDVal;
+}
+
+template <>
+inline EGLImage GetParamVal<ParamType::TEGLImage, EGLImage>(const ParamValue &value)
+{
+ return value.EGLImageVal;
+}
+
+template <>
+inline EGLLabelKHR GetParamVal<ParamType::TEGLLabelKHR, EGLLabelKHR>(const ParamValue &value)
+{
+ return value.EGLLabelKHRVal;
+}
+
+template <>
+inline EGLNativeDisplayType GetParamVal<ParamType::TEGLNativeDisplayType, EGLNativeDisplayType>(
+ const ParamValue &value)
+{
+ return value.EGLNativeDisplayTypeVal;
+}
+
+template <>
+inline EGLNativePixmapType GetParamVal<ParamType::TEGLNativePixmapType, EGLNativePixmapType>(
+ const ParamValue &value)
+{
+ return value.EGLNativePixmapTypeVal;
+}
+
+template <>
+inline EGLNativeWindowType GetParamVal<ParamType::TEGLNativeWindowType, EGLNativeWindowType>(
+ const ParamValue &value)
+{
+ return value.EGLNativeWindowTypeVal;
+}
+
+template <>
+inline EGLObjectKHR GetParamVal<ParamType::TEGLObjectKHR, EGLObjectKHR>(const ParamValue &value)
+{
+ return value.EGLObjectKHRVal;
+}
+
+template <>
+inline EGLSetBlobFuncANDROID GetParamVal<ParamType::TEGLSetBlobFuncANDROID, EGLSetBlobFuncANDROID>(
+ const ParamValue &value)
+{
+ return value.EGLSetBlobFuncANDROIDVal;
+}
+
+template <>
+inline EGLStreamKHR GetParamVal<ParamType::TEGLStreamKHR, EGLStreamKHR>(const ParamValue &value)
+{
+ return value.EGLStreamKHRVal;
+}
+
+template <>
+inline EGLSurface GetParamVal<ParamType::TEGLSurface, EGLSurface>(const ParamValue &value)
+{
+ return value.EGLSurfaceVal;
+}
+
+template <>
+inline EGLSync GetParamVal<ParamType::TEGLSync, EGLSync>(const ParamValue &value)
+{
+ return value.EGLSyncVal;
+}
+
+template <>
+inline EGLTime GetParamVal<ParamType::TEGLTime, EGLTime>(const ParamValue &value)
+{
+ return value.EGLTimeVal;
+}
+
+template <>
+inline EGLTimeKHR GetParamVal<ParamType::TEGLTimeKHR, EGLTimeKHR>(const ParamValue &value)
+{
+ return value.EGLTimeKHRVal;
+}
+
+template <>
+inline EGLenum GetParamVal<ParamType::TEGLenum, EGLenum>(const ParamValue &value)
+{
+ return value.EGLenumVal;
+}
+
+template <>
+inline EGLint GetParamVal<ParamType::TEGLint, EGLint>(const ParamValue &value)
+{
+ return value.EGLintVal;
+}
+
+template <>
+inline EGLnsecsANDROID GetParamVal<ParamType::TEGLnsecsANDROID, EGLnsecsANDROID>(
+ const ParamValue &value)
+{
+ return value.EGLnsecsANDROIDVal;
+}
+
+template <>
+inline EGLuint64KHR GetParamVal<ParamType::TEGLuint64KHR, EGLuint64KHR>(const ParamValue &value)
+{
+ return value.EGLuint64KHRVal;
+}
+
+template <>
+inline gl::FenceNVID GetParamVal<ParamType::TFenceNVID, gl::FenceNVID>(const ParamValue &value)
+{
+ return value.FenceNVIDVal;
+}
+
+template <>
+inline const gl::FenceNVID *GetParamVal<ParamType::TFenceNVIDConstPointer, const gl::FenceNVID *>(
+ const ParamValue &value)
+{
+ return value.FenceNVIDConstPointerVal;
+}
+
+template <>
+inline gl::FenceNVID *GetParamVal<ParamType::TFenceNVIDPointer, gl::FenceNVID *>(
+ const ParamValue &value)
+{
+ return value.FenceNVIDPointerVal;
+}
+
+template <>
+inline gl::FramebufferID GetParamVal<ParamType::TFramebufferID, gl::FramebufferID>(
+ const ParamValue &value)
+{
+ return value.FramebufferIDVal;
+}
+
+template <>
+inline const gl::FramebufferID *GetParamVal<ParamType::TFramebufferIDConstPointer,
+ const gl::FramebufferID *>(const ParamValue &value)
+{
+ return value.FramebufferIDConstPointerVal;
+}
+
+template <>
+inline gl::FramebufferID *GetParamVal<ParamType::TFramebufferIDPointer, gl::FramebufferID *>(
+ const ParamValue &value)
+{
+ return value.FramebufferIDPointerVal;
+}
+
+template <>
+inline GLDEBUGPROC GetParamVal<ParamType::TGLDEBUGPROC, GLDEBUGPROC>(const ParamValue &value)
+{
+ return value.GLDEBUGPROCVal;
+}
+
+template <>
+inline GLDEBUGPROCKHR GetParamVal<ParamType::TGLDEBUGPROCKHR, GLDEBUGPROCKHR>(
+ const ParamValue &value)
+{
+ return value.GLDEBUGPROCKHRVal;
+}
+
+template <>
+inline GLbitfield GetParamVal<ParamType::TGLbitfield, GLbitfield>(const ParamValue &value)
+{
+ return value.GLbitfieldVal;
+}
+
+template <>
+inline GLboolean GetParamVal<ParamType::TGLboolean, GLboolean>(const ParamValue &value)
+{
+ return value.GLbooleanVal;
+}
+
+template <>
+inline const GLboolean *GetParamVal<ParamType::TGLbooleanConstPointer, const GLboolean *>(
+ const ParamValue &value)
+{
+ return value.GLbooleanConstPointerVal;
+}
+
+template <>
+inline GLboolean *GetParamVal<ParamType::TGLbooleanPointer, GLboolean *>(const ParamValue &value)
+{
+ return value.GLbooleanPointerVal;
+}
+
+template <>
+inline GLbyte GetParamVal<ParamType::TGLbyte, GLbyte>(const ParamValue &value)
+{
+ return value.GLbyteVal;
+}
+
+template <>
+inline const GLbyte *GetParamVal<ParamType::TGLbyteConstPointer, const GLbyte *>(
+ const ParamValue &value)
+{
+ return value.GLbyteConstPointerVal;
+}
+
+template <>
+inline const GLchar *GetParamVal<ParamType::TGLcharConstPointer, const GLchar *>(
+ const ParamValue &value)
+{
+ return value.GLcharConstPointerVal;
+}
+
+template <>
+inline const GLchar *const *
+GetParamVal<ParamType::TGLcharConstPointerPointer, const GLchar *const *>(const ParamValue &value)
+{
+ return value.GLcharConstPointerPointerVal;
+}
+
+template <>
+inline GLchar *GetParamVal<ParamType::TGLcharPointer, GLchar *>(const ParamValue &value)
+{
+ return value.GLcharPointerVal;
+}
+
+template <>
+inline GLclampx GetParamVal<ParamType::TGLclampx, GLclampx>(const ParamValue &value)
+{
+ return value.GLclampxVal;
+}
+
+template <>
+inline GLdouble GetParamVal<ParamType::TGLdouble, GLdouble>(const ParamValue &value)
+{
+ return value.GLdoubleVal;
+}
+
+template <>
+inline const GLdouble *GetParamVal<ParamType::TGLdoubleConstPointer, const GLdouble *>(
+ const ParamValue &value)
+{
+ return value.GLdoubleConstPointerVal;
+}
+
+template <>
+inline GLdouble *GetParamVal<ParamType::TGLdoublePointer, GLdouble *>(const ParamValue &value)
+{
+ return value.GLdoublePointerVal;
+}
+
+template <>
+inline GLeglClientBufferEXT GetParamVal<ParamType::TGLeglClientBufferEXT, GLeglClientBufferEXT>(
+ const ParamValue &value)
+{
+ return value.GLeglClientBufferEXTVal;
+}
+
+template <>
+inline GLeglImageOES GetParamVal<ParamType::TGLeglImageOES, GLeglImageOES>(const ParamValue &value)
+{
+ return value.GLeglImageOESVal;
+}
+
+template <>
+inline GLenum GetParamVal<ParamType::TGLenum, GLenum>(const ParamValue &value)
+{
+ return value.GLenumVal;
+}
+
+template <>
+inline const GLenum *GetParamVal<ParamType::TGLenumConstPointer, const GLenum *>(
+ const ParamValue &value)
+{
+ return value.GLenumConstPointerVal;
+}
+
+template <>
+inline GLenum *GetParamVal<ParamType::TGLenumPointer, GLenum *>(const ParamValue &value)
+{
+ return value.GLenumPointerVal;
+}
+
+template <>
+inline GLfixed GetParamVal<ParamType::TGLfixed, GLfixed>(const ParamValue &value)
+{
+ return value.GLfixedVal;
+}
+
+template <>
+inline const GLfixed *GetParamVal<ParamType::TGLfixedConstPointer, const GLfixed *>(
+ const ParamValue &value)
+{
+ return value.GLfixedConstPointerVal;
+}
+
+template <>
+inline GLfixed *GetParamVal<ParamType::TGLfixedPointer, GLfixed *>(const ParamValue &value)
+{
+ return value.GLfixedPointerVal;
+}
+
+template <>
+inline GLfloat GetParamVal<ParamType::TGLfloat, GLfloat>(const ParamValue &value)
+{
+ return value.GLfloatVal;
+}
+
+template <>
+inline const GLfloat *GetParamVal<ParamType::TGLfloatConstPointer, const GLfloat *>(
+ const ParamValue &value)
+{
+ return value.GLfloatConstPointerVal;
+}
+
+template <>
+inline GLfloat *GetParamVal<ParamType::TGLfloatPointer, GLfloat *>(const ParamValue &value)
+{
+ return value.GLfloatPointerVal;
+}
+
+template <>
+inline GLint GetParamVal<ParamType::TGLint, GLint>(const ParamValue &value)
+{
+ return value.GLintVal;
+}
+
+template <>
+inline GLint64 *GetParamVal<ParamType::TGLint64Pointer, GLint64 *>(const ParamValue &value)
+{
+ return value.GLint64PointerVal;
+}
+
+template <>
+inline const GLint *GetParamVal<ParamType::TGLintConstPointer, const GLint *>(
+ const ParamValue &value)
+{
+ return value.GLintConstPointerVal;
+}
+
+template <>
+inline GLint *GetParamVal<ParamType::TGLintPointer, GLint *>(const ParamValue &value)
+{
+ return value.GLintPointerVal;
+}
+
+template <>
+inline GLintptr GetParamVal<ParamType::TGLintptr, GLintptr>(const ParamValue &value)
+{
+ return value.GLintptrVal;
+}
+
+template <>
+inline const GLintptr *GetParamVal<ParamType::TGLintptrConstPointer, const GLintptr *>(
+ const ParamValue &value)
+{
+ return value.GLintptrConstPointerVal;
+}
+
+template <>
+inline GLshort GetParamVal<ParamType::TGLshort, GLshort>(const ParamValue &value)
+{
+ return value.GLshortVal;
+}
+
+template <>
+inline const GLshort *GetParamVal<ParamType::TGLshortConstPointer, const GLshort *>(
+ const ParamValue &value)
+{
+ return value.GLshortConstPointerVal;
+}
+
+template <>
+inline GLsizei GetParamVal<ParamType::TGLsizei, GLsizei>(const ParamValue &value)
+{
+ return value.GLsizeiVal;
+}
+
+template <>
+inline const GLsizei *GetParamVal<ParamType::TGLsizeiConstPointer, const GLsizei *>(
+ const ParamValue &value)
+{
+ return value.GLsizeiConstPointerVal;
+}
+
+template <>
+inline GLsizei *GetParamVal<ParamType::TGLsizeiPointer, GLsizei *>(const ParamValue &value)
+{
+ return value.GLsizeiPointerVal;
+}
+
+template <>
+inline GLsizeiptr GetParamVal<ParamType::TGLsizeiptr, GLsizeiptr>(const ParamValue &value)
+{
+ return value.GLsizeiptrVal;
+}
+
+template <>
+inline const GLsizeiptr *GetParamVal<ParamType::TGLsizeiptrConstPointer, const GLsizeiptr *>(
+ const ParamValue &value)
+{
+ return value.GLsizeiptrConstPointerVal;
+}
+
+template <>
+inline GLsync GetParamVal<ParamType::TGLsync, GLsync>(const ParamValue &value)
+{
+ return value.GLsyncVal;
+}
+
+template <>
+inline GLubyte GetParamVal<ParamType::TGLubyte, GLubyte>(const ParamValue &value)
+{
+ return value.GLubyteVal;
+}
+
+template <>
+inline const GLubyte *GetParamVal<ParamType::TGLubyteConstPointer, const GLubyte *>(
+ const ParamValue &value)
+{
+ return value.GLubyteConstPointerVal;
+}
+
+template <>
+inline GLubyte *GetParamVal<ParamType::TGLubytePointer, GLubyte *>(const ParamValue &value)
+{
+ return value.GLubytePointerVal;
+}
+
+template <>
+inline GLuint GetParamVal<ParamType::TGLuint, GLuint>(const ParamValue &value)
+{
+ return value.GLuintVal;
+}
+
+template <>
+inline GLuint64 GetParamVal<ParamType::TGLuint64, GLuint64>(const ParamValue &value)
+{
+ return value.GLuint64Val;
+}
+
+template <>
+inline const GLuint64 *GetParamVal<ParamType::TGLuint64ConstPointer, const GLuint64 *>(
+ const ParamValue &value)
+{
+ return value.GLuint64ConstPointerVal;
+}
+
+template <>
+inline GLuint64 *GetParamVal<ParamType::TGLuint64Pointer, GLuint64 *>(const ParamValue &value)
+{
+ return value.GLuint64PointerVal;
+}
+
+template <>
+inline const GLuint *GetParamVal<ParamType::TGLuintConstPointer, const GLuint *>(
+ const ParamValue &value)
+{
+ return value.GLuintConstPointerVal;
+}
+
+template <>
+inline GLuint *GetParamVal<ParamType::TGLuintPointer, GLuint *>(const ParamValue &value)
+{
+ return value.GLuintPointerVal;
+}
+
+template <>
+inline GLushort GetParamVal<ParamType::TGLushort, GLushort>(const ParamValue &value)
+{
+ return value.GLushortVal;
+}
+
+template <>
+inline const GLushort *GetParamVal<ParamType::TGLushortConstPointer, const GLushort *>(
+ const ParamValue &value)
+{
+ return value.GLushortConstPointerVal;
+}
+
+template <>
+inline GLushort *GetParamVal<ParamType::TGLushortPointer, GLushort *>(const ParamValue &value)
+{
+ return value.GLushortPointerVal;
+}
+
+template <>
+inline const GLvoid *GetParamVal<ParamType::TGLvoidConstPointer, const GLvoid *>(
+ const ParamValue &value)
+{
+ return value.GLvoidConstPointerVal;
+}
+
+template <>
+inline const GLvoid *const *
+GetParamVal<ParamType::TGLvoidConstPointerPointer, const GLvoid *const *>(const ParamValue &value)
+{
+ return value.GLvoidConstPointerPointerVal;
+}
+
+template <>
+inline gl::GraphicsResetStatus
+GetParamVal<ParamType::TGraphicsResetStatus, gl::GraphicsResetStatus>(const ParamValue &value)
+{
+ return value.GraphicsResetStatusVal;
+}
+
+template <>
+inline gl::HandleType GetParamVal<ParamType::THandleType, gl::HandleType>(const ParamValue &value)
+{
+ return value.HandleTypeVal;
+}
+
+template <>
+inline gl::LightParameter GetParamVal<ParamType::TLightParameter, gl::LightParameter>(
+ const ParamValue &value)
+{
+ return value.LightParameterVal;
+}
+
+template <>
+inline gl::LogicalOperation GetParamVal<ParamType::TLogicalOperation, gl::LogicalOperation>(
+ const ParamValue &value)
+{
+ return value.LogicalOperationVal;
+}
+
+template <>
+inline gl::MaterialParameter GetParamVal<ParamType::TMaterialParameter, gl::MaterialParameter>(
+ const ParamValue &value)
+{
+ return value.MaterialParameterVal;
+}
+
+template <>
+inline gl::MatrixType GetParamVal<ParamType::TMatrixType, gl::MatrixType>(const ParamValue &value)
+{
+ return value.MatrixTypeVal;
+}
+
+template <>
+inline gl::MemoryObjectID GetParamVal<ParamType::TMemoryObjectID, gl::MemoryObjectID>(
+ const ParamValue &value)
+{
+ return value.MemoryObjectIDVal;
+}
+
+template <>
+inline const gl::MemoryObjectID *GetParamVal<ParamType::TMemoryObjectIDConstPointer,
+ const gl::MemoryObjectID *>(const ParamValue &value)
+{
+ return value.MemoryObjectIDConstPointerVal;
+}
+
+template <>
+inline gl::MemoryObjectID *GetParamVal<ParamType::TMemoryObjectIDPointer, gl::MemoryObjectID *>(
+ const ParamValue &value)
+{
+ return value.MemoryObjectIDPointerVal;
+}
+
+template <>
+inline egl::ObjectType GetParamVal<ParamType::TObjectType, egl::ObjectType>(const ParamValue &value)
+{
+ return value.ObjectTypeVal;
+}
+
+template <>
+inline gl::PointParameter GetParamVal<ParamType::TPointParameter, gl::PointParameter>(
+ const ParamValue &value)
+{
+ return value.PointParameterVal;
+}
+
+template <>
+inline gl::PrimitiveMode GetParamVal<ParamType::TPrimitiveMode, gl::PrimitiveMode>(
+ const ParamValue &value)
+{
+ return value.PrimitiveModeVal;
+}
+
+template <>
+inline gl::ProgramPipelineID GetParamVal<ParamType::TProgramPipelineID, gl::ProgramPipelineID>(
+ const ParamValue &value)
+{
+ return value.ProgramPipelineIDVal;
+}
+
+template <>
+inline const gl::ProgramPipelineID *
+GetParamVal<ParamType::TProgramPipelineIDConstPointer, const gl::ProgramPipelineID *>(
+ const ParamValue &value)
+{
+ return value.ProgramPipelineIDConstPointerVal;
+}
+
+template <>
+inline gl::ProgramPipelineID *
+GetParamVal<ParamType::TProgramPipelineIDPointer, gl::ProgramPipelineID *>(const ParamValue &value)
+{
+ return value.ProgramPipelineIDPointerVal;
+}
+
+template <>
+inline gl::ProvokingVertexConvention
+GetParamVal<ParamType::TProvokingVertexConvention, gl::ProvokingVertexConvention>(
+ const ParamValue &value)
+{
+ return value.ProvokingVertexConventionVal;
+}
+
+template <>
+inline gl::QueryID GetParamVal<ParamType::TQueryID, gl::QueryID>(const ParamValue &value)
+{
+ return value.QueryIDVal;
+}
+
+template <>
+inline const gl::QueryID *GetParamVal<ParamType::TQueryIDConstPointer, const gl::QueryID *>(
+ const ParamValue &value)
+{
+ return value.QueryIDConstPointerVal;
+}
+
+template <>
+inline gl::QueryID *GetParamVal<ParamType::TQueryIDPointer, gl::QueryID *>(const ParamValue &value)
+{
+ return value.QueryIDPointerVal;
+}
+
+template <>
+inline gl::QueryType GetParamVal<ParamType::TQueryType, gl::QueryType>(const ParamValue &value)
+{
+ return value.QueryTypeVal;
+}
+
+template <>
+inline gl::RenderbufferID GetParamVal<ParamType::TRenderbufferID, gl::RenderbufferID>(
+ const ParamValue &value)
+{
+ return value.RenderbufferIDVal;
+}
+
+template <>
+inline const gl::RenderbufferID *GetParamVal<ParamType::TRenderbufferIDConstPointer,
+ const gl::RenderbufferID *>(const ParamValue &value)
+{
+ return value.RenderbufferIDConstPointerVal;
+}
+
+template <>
+inline gl::RenderbufferID *GetParamVal<ParamType::TRenderbufferIDPointer, gl::RenderbufferID *>(
+ const ParamValue &value)
+{
+ return value.RenderbufferIDPointerVal;
+}
+
+template <>
+inline gl::SamplerID GetParamVal<ParamType::TSamplerID, gl::SamplerID>(const ParamValue &value)
+{
+ return value.SamplerIDVal;
+}
+
+template <>
+inline const gl::SamplerID *GetParamVal<ParamType::TSamplerIDConstPointer, const gl::SamplerID *>(
+ const ParamValue &value)
+{
+ return value.SamplerIDConstPointerVal;
+}
+
+template <>
+inline gl::SamplerID *GetParamVal<ParamType::TSamplerIDPointer, gl::SamplerID *>(
+ const ParamValue &value)
+{
+ return value.SamplerIDPointerVal;
+}
+
+template <>
+inline gl::SemaphoreID GetParamVal<ParamType::TSemaphoreID, gl::SemaphoreID>(
+ const ParamValue &value)
+{
+ return value.SemaphoreIDVal;
+}
+
+template <>
+inline const gl::SemaphoreID *
+GetParamVal<ParamType::TSemaphoreIDConstPointer, const gl::SemaphoreID *>(const ParamValue &value)
+{
+ return value.SemaphoreIDConstPointerVal;
+}
+
+template <>
+inline gl::SemaphoreID *GetParamVal<ParamType::TSemaphoreIDPointer, gl::SemaphoreID *>(
+ const ParamValue &value)
+{
+ return value.SemaphoreIDPointerVal;
+}
+
+template <>
+inline gl::ShaderProgramID GetParamVal<ParamType::TShaderProgramID, gl::ShaderProgramID>(
+ const ParamValue &value)
+{
+ return value.ShaderProgramIDVal;
+}
+
+template <>
+inline const gl::ShaderProgramID *GetParamVal<ParamType::TShaderProgramIDConstPointer,
+ const gl::ShaderProgramID *>(const ParamValue &value)
+{
+ return value.ShaderProgramIDConstPointerVal;
+}
+
+template <>
+inline gl::ShaderProgramID *GetParamVal<ParamType::TShaderProgramIDPointer, gl::ShaderProgramID *>(
+ const ParamValue &value)
+{
+ return value.ShaderProgramIDPointerVal;
+}
+
+template <>
+inline gl::ShaderType GetParamVal<ParamType::TShaderType, gl::ShaderType>(const ParamValue &value)
+{
+ return value.ShaderTypeVal;
+}
+
+template <>
+inline gl::ShadingModel GetParamVal<ParamType::TShadingModel, gl::ShadingModel>(
+ const ParamValue &value)
+{
+ return value.ShadingModelVal;
+}
+
+template <>
+inline gl::TextureEnvParameter
+GetParamVal<ParamType::TTextureEnvParameter, gl::TextureEnvParameter>(const ParamValue &value)
+{
+ return value.TextureEnvParameterVal;
+}
+
+template <>
+inline gl::TextureEnvTarget GetParamVal<ParamType::TTextureEnvTarget, gl::TextureEnvTarget>(
+ const ParamValue &value)
+{
+ return value.TextureEnvTargetVal;
+}
+
+template <>
+inline gl::TextureID GetParamVal<ParamType::TTextureID, gl::TextureID>(const ParamValue &value)
+{
+ return value.TextureIDVal;
+}
+
+template <>
+inline const gl::TextureID *GetParamVal<ParamType::TTextureIDConstPointer, const gl::TextureID *>(
+ const ParamValue &value)
+{
+ return value.TextureIDConstPointerVal;
+}
+
+template <>
+inline gl::TextureID *GetParamVal<ParamType::TTextureIDPointer, gl::TextureID *>(
+ const ParamValue &value)
+{
+ return value.TextureIDPointerVal;
+}
+
+template <>
+inline gl::TextureTarget GetParamVal<ParamType::TTextureTarget, gl::TextureTarget>(
+ const ParamValue &value)
+{
+ return value.TextureTargetVal;
+}
+
+template <>
+inline gl::TextureType GetParamVal<ParamType::TTextureType, gl::TextureType>(
+ const ParamValue &value)
+{
+ return value.TextureTypeVal;
+}
+
+template <>
+inline egl::Timestamp GetParamVal<ParamType::TTimestamp, egl::Timestamp>(const ParamValue &value)
+{
+ return value.TimestampVal;
+}
+
+template <>
+inline gl::TransformFeedbackID
+GetParamVal<ParamType::TTransformFeedbackID, gl::TransformFeedbackID>(const ParamValue &value)
+{
+ return value.TransformFeedbackIDVal;
+}
+
+template <>
+inline const gl::TransformFeedbackID *
+GetParamVal<ParamType::TTransformFeedbackIDConstPointer, const gl::TransformFeedbackID *>(
+ const ParamValue &value)
+{
+ return value.TransformFeedbackIDConstPointerVal;
+}
+
+template <>
+inline gl::TransformFeedbackID *GetParamVal<ParamType::TTransformFeedbackIDPointer,
+ gl::TransformFeedbackID *>(const ParamValue &value)
+{
+ return value.TransformFeedbackIDPointerVal;
+}
+
+template <>
+inline gl::UniformBlockIndex GetParamVal<ParamType::TUniformBlockIndex, gl::UniformBlockIndex>(
+ const ParamValue &value)
+{
+ return value.UniformBlockIndexVal;
+}
+
+template <>
+inline gl::UniformLocation GetParamVal<ParamType::TUniformLocation, gl::UniformLocation>(
+ const ParamValue &value)
+{
+ return value.UniformLocationVal;
+}
+
+template <>
+inline gl::VertexArrayID GetParamVal<ParamType::TVertexArrayID, gl::VertexArrayID>(
+ const ParamValue &value)
+{
+ return value.VertexArrayIDVal;
+}
+
+template <>
+inline const gl::VertexArrayID *GetParamVal<ParamType::TVertexArrayIDConstPointer,
+ const gl::VertexArrayID *>(const ParamValue &value)
+{
+ return value.VertexArrayIDConstPointerVal;
+}
+
+template <>
+inline gl::VertexArrayID *GetParamVal<ParamType::TVertexArrayIDPointer, gl::VertexArrayID *>(
+ const ParamValue &value)
+{
+ return value.VertexArrayIDPointerVal;
+}
+
+template <>
+inline gl::VertexAttribType GetParamVal<ParamType::TVertexAttribType, gl::VertexAttribType>(
+ const ParamValue &value)
+{
+ return value.VertexAttribTypeVal;
+}
+
+template <>
+inline const char *GetParamVal<ParamType::TcharConstPointer, const char *>(const ParamValue &value)
+{
+ return value.charConstPointerVal;
+}
+
+template <>
+inline const void *GetParamVal<ParamType::TvoidConstPointer, const void *>(const ParamValue &value)
+{
+ return value.voidConstPointerVal;
+}
+
+template <>
+inline const void *const *GetParamVal<ParamType::TvoidConstPointerPointer, const void *const *>(
+ const ParamValue &value)
+{
+ return value.voidConstPointerPointerVal;
+}
+
+template <>
+inline void *GetParamVal<ParamType::TvoidPointer, void *>(const ParamValue &value)
+{
+ return value.voidPointerVal;
+}
+
+template <>
+inline void **GetParamVal<ParamType::TvoidPointerPointer, void **>(const ParamValue &value)
+{
+ return value.voidPointerPointerVal;
+}
+
+template <ParamType PType, typename T>
+T GetParamVal(const ParamValue &value)
+{
+ UNREACHABLE();
+ return T();
+}
+
+template <typename T>
+T AccessParamValue(ParamType paramType, const ParamValue &value)
+{
+ switch (paramType)
+ {
+ case ParamType::TAHardwareBufferConstPointer:
+ return GetParamVal<ParamType::TAHardwareBufferConstPointer, T>(value);
+ case ParamType::TAlphaTestFunc:
+ return GetParamVal<ParamType::TAlphaTestFunc, T>(value);
+ case ParamType::TBufferBinding:
+ return GetParamVal<ParamType::TBufferBinding, T>(value);
+ case ParamType::TBufferID:
+ return GetParamVal<ParamType::TBufferID, T>(value);
+ case ParamType::TBufferIDConstPointer:
+ return GetParamVal<ParamType::TBufferIDConstPointer, T>(value);
+ case ParamType::TBufferIDPointer:
+ return GetParamVal<ParamType::TBufferIDPointer, T>(value);
+ case ParamType::TBufferUsage:
+ return GetParamVal<ParamType::TBufferUsage, T>(value);
+ case ParamType::TClientVertexArrayType:
+ return GetParamVal<ParamType::TClientVertexArrayType, T>(value);
+ case ParamType::TCompositorTiming:
+ return GetParamVal<ParamType::TCompositorTiming, T>(value);
+ case ParamType::TCullFaceMode:
+ return GetParamVal<ParamType::TCullFaceMode, T>(value);
+ case ParamType::TDrawElementsType:
+ return GetParamVal<ParamType::TDrawElementsType, T>(value);
+ case ParamType::TEGLAttrib:
+ return GetParamVal<ParamType::TEGLAttrib, T>(value);
+ case ParamType::TEGLAttribKHR:
+ return GetParamVal<ParamType::TEGLAttribKHR, T>(value);
+ case ParamType::TEGLBoolean:
+ return GetParamVal<ParamType::TEGLBoolean, T>(value);
+ case ParamType::TEGLClientBuffer:
+ return GetParamVal<ParamType::TEGLClientBuffer, T>(value);
+ case ParamType::TEGLConfig:
+ return GetParamVal<ParamType::TEGLConfig, T>(value);
+ case ParamType::TEGLContext:
+ return GetParamVal<ParamType::TEGLContext, T>(value);
+ case ParamType::TEGLDEBUGPROCKHR:
+ return GetParamVal<ParamType::TEGLDEBUGPROCKHR, T>(value);
+ case ParamType::TEGLDeviceEXT:
+ return GetParamVal<ParamType::TEGLDeviceEXT, T>(value);
+ case ParamType::TEGLDisplay:
+ return GetParamVal<ParamType::TEGLDisplay, T>(value);
+ case ParamType::TEGLFrameTokenANGLE:
+ return GetParamVal<ParamType::TEGLFrameTokenANGLE, T>(value);
+ case ParamType::TEGLGetBlobFuncANDROID:
+ return GetParamVal<ParamType::TEGLGetBlobFuncANDROID, T>(value);
+ case ParamType::TEGLImage:
+ return GetParamVal<ParamType::TEGLImage, T>(value);
+ case ParamType::TEGLLabelKHR:
+ return GetParamVal<ParamType::TEGLLabelKHR, T>(value);
+ case ParamType::TEGLNativeDisplayType:
+ return GetParamVal<ParamType::TEGLNativeDisplayType, T>(value);
+ case ParamType::TEGLNativePixmapType:
+ return GetParamVal<ParamType::TEGLNativePixmapType, T>(value);
+ case ParamType::TEGLNativeWindowType:
+ return GetParamVal<ParamType::TEGLNativeWindowType, T>(value);
+ case ParamType::TEGLObjectKHR:
+ return GetParamVal<ParamType::TEGLObjectKHR, T>(value);
+ case ParamType::TEGLSetBlobFuncANDROID:
+ return GetParamVal<ParamType::TEGLSetBlobFuncANDROID, T>(value);
+ case ParamType::TEGLStreamKHR:
+ return GetParamVal<ParamType::TEGLStreamKHR, T>(value);
+ case ParamType::TEGLSurface:
+ return GetParamVal<ParamType::TEGLSurface, T>(value);
+ case ParamType::TEGLSync:
+ return GetParamVal<ParamType::TEGLSync, T>(value);
+ case ParamType::TEGLTime:
+ return GetParamVal<ParamType::TEGLTime, T>(value);
+ case ParamType::TEGLTimeKHR:
+ return GetParamVal<ParamType::TEGLTimeKHR, T>(value);
+ case ParamType::TEGLenum:
+ return GetParamVal<ParamType::TEGLenum, T>(value);
+ case ParamType::TEGLint:
+ return GetParamVal<ParamType::TEGLint, T>(value);
+ case ParamType::TEGLnsecsANDROID:
+ return GetParamVal<ParamType::TEGLnsecsANDROID, T>(value);
+ case ParamType::TEGLuint64KHR:
+ return GetParamVal<ParamType::TEGLuint64KHR, T>(value);
+ case ParamType::TFenceNVID:
+ return GetParamVal<ParamType::TFenceNVID, T>(value);
+ case ParamType::TFenceNVIDConstPointer:
+ return GetParamVal<ParamType::TFenceNVIDConstPointer, T>(value);
+ case ParamType::TFenceNVIDPointer:
+ return GetParamVal<ParamType::TFenceNVIDPointer, T>(value);
+ case ParamType::TFramebufferID:
+ return GetParamVal<ParamType::TFramebufferID, T>(value);
+ case ParamType::TFramebufferIDConstPointer:
+ return GetParamVal<ParamType::TFramebufferIDConstPointer, T>(value);
+ case ParamType::TFramebufferIDPointer:
+ return GetParamVal<ParamType::TFramebufferIDPointer, T>(value);
+ case ParamType::TGLDEBUGPROC:
+ return GetParamVal<ParamType::TGLDEBUGPROC, T>(value);
+ case ParamType::TGLDEBUGPROCKHR:
+ return GetParamVal<ParamType::TGLDEBUGPROCKHR, T>(value);
+ case ParamType::TGLbitfield:
+ return GetParamVal<ParamType::TGLbitfield, T>(value);
+ case ParamType::TGLboolean:
+ return GetParamVal<ParamType::TGLboolean, T>(value);
+ case ParamType::TGLbooleanConstPointer:
+ return GetParamVal<ParamType::TGLbooleanConstPointer, T>(value);
+ case ParamType::TGLbooleanPointer:
+ return GetParamVal<ParamType::TGLbooleanPointer, T>(value);
+ case ParamType::TGLbyte:
+ return GetParamVal<ParamType::TGLbyte, T>(value);
+ case ParamType::TGLbyteConstPointer:
+ return GetParamVal<ParamType::TGLbyteConstPointer, T>(value);
+ case ParamType::TGLcharConstPointer:
+ return GetParamVal<ParamType::TGLcharConstPointer, T>(value);
+ case ParamType::TGLcharConstPointerPointer:
+ return GetParamVal<ParamType::TGLcharConstPointerPointer, T>(value);
+ case ParamType::TGLcharPointer:
+ return GetParamVal<ParamType::TGLcharPointer, T>(value);
+ case ParamType::TGLclampx:
+ return GetParamVal<ParamType::TGLclampx, T>(value);
+ case ParamType::TGLdouble:
+ return GetParamVal<ParamType::TGLdouble, T>(value);
+ case ParamType::TGLdoubleConstPointer:
+ return GetParamVal<ParamType::TGLdoubleConstPointer, T>(value);
+ case ParamType::TGLdoublePointer:
+ return GetParamVal<ParamType::TGLdoublePointer, T>(value);
+ case ParamType::TGLeglClientBufferEXT:
+ return GetParamVal<ParamType::TGLeglClientBufferEXT, T>(value);
+ case ParamType::TGLeglImageOES:
+ return GetParamVal<ParamType::TGLeglImageOES, T>(value);
+ case ParamType::TGLenum:
+ return GetParamVal<ParamType::TGLenum, T>(value);
+ case ParamType::TGLenumConstPointer:
+ return GetParamVal<ParamType::TGLenumConstPointer, T>(value);
+ case ParamType::TGLenumPointer:
+ return GetParamVal<ParamType::TGLenumPointer, T>(value);
+ case ParamType::TGLfixed:
+ return GetParamVal<ParamType::TGLfixed, T>(value);
+ case ParamType::TGLfixedConstPointer:
+ return GetParamVal<ParamType::TGLfixedConstPointer, T>(value);
+ case ParamType::TGLfixedPointer:
+ return GetParamVal<ParamType::TGLfixedPointer, T>(value);
+ case ParamType::TGLfloat:
+ return GetParamVal<ParamType::TGLfloat, T>(value);
+ case ParamType::TGLfloatConstPointer:
+ return GetParamVal<ParamType::TGLfloatConstPointer, T>(value);
+ case ParamType::TGLfloatPointer:
+ return GetParamVal<ParamType::TGLfloatPointer, T>(value);
+ case ParamType::TGLint:
+ return GetParamVal<ParamType::TGLint, T>(value);
+ case ParamType::TGLint64Pointer:
+ return GetParamVal<ParamType::TGLint64Pointer, T>(value);
+ case ParamType::TGLintConstPointer:
+ return GetParamVal<ParamType::TGLintConstPointer, T>(value);
+ case ParamType::TGLintPointer:
+ return GetParamVal<ParamType::TGLintPointer, T>(value);
+ case ParamType::TGLintptr:
+ return GetParamVal<ParamType::TGLintptr, T>(value);
+ case ParamType::TGLintptrConstPointer:
+ return GetParamVal<ParamType::TGLintptrConstPointer, T>(value);
+ case ParamType::TGLshort:
+ return GetParamVal<ParamType::TGLshort, T>(value);
+ case ParamType::TGLshortConstPointer:
+ return GetParamVal<ParamType::TGLshortConstPointer, T>(value);
+ case ParamType::TGLsizei:
+ return GetParamVal<ParamType::TGLsizei, T>(value);
+ case ParamType::TGLsizeiConstPointer:
+ return GetParamVal<ParamType::TGLsizeiConstPointer, T>(value);
+ case ParamType::TGLsizeiPointer:
+ return GetParamVal<ParamType::TGLsizeiPointer, T>(value);
+ case ParamType::TGLsizeiptr:
+ return GetParamVal<ParamType::TGLsizeiptr, T>(value);
+ case ParamType::TGLsizeiptrConstPointer:
+ return GetParamVal<ParamType::TGLsizeiptrConstPointer, T>(value);
+ case ParamType::TGLsync:
+ return GetParamVal<ParamType::TGLsync, T>(value);
+ case ParamType::TGLubyte:
+ return GetParamVal<ParamType::TGLubyte, T>(value);
+ case ParamType::TGLubyteConstPointer:
+ return GetParamVal<ParamType::TGLubyteConstPointer, T>(value);
+ case ParamType::TGLubytePointer:
+ return GetParamVal<ParamType::TGLubytePointer, T>(value);
+ case ParamType::TGLuint:
+ return GetParamVal<ParamType::TGLuint, T>(value);
+ case ParamType::TGLuint64:
+ return GetParamVal<ParamType::TGLuint64, T>(value);
+ case ParamType::TGLuint64ConstPointer:
+ return GetParamVal<ParamType::TGLuint64ConstPointer, T>(value);
+ case ParamType::TGLuint64Pointer:
+ return GetParamVal<ParamType::TGLuint64Pointer, T>(value);
+ case ParamType::TGLuintConstPointer:
+ return GetParamVal<ParamType::TGLuintConstPointer, T>(value);
+ case ParamType::TGLuintPointer:
+ return GetParamVal<ParamType::TGLuintPointer, T>(value);
+ case ParamType::TGLushort:
+ return GetParamVal<ParamType::TGLushort, T>(value);
+ case ParamType::TGLushortConstPointer:
+ return GetParamVal<ParamType::TGLushortConstPointer, T>(value);
+ case ParamType::TGLushortPointer:
+ return GetParamVal<ParamType::TGLushortPointer, T>(value);
+ case ParamType::TGLvoidConstPointer:
+ return GetParamVal<ParamType::TGLvoidConstPointer, T>(value);
+ case ParamType::TGLvoidConstPointerPointer:
+ return GetParamVal<ParamType::TGLvoidConstPointerPointer, T>(value);
+ case ParamType::TGraphicsResetStatus:
+ return GetParamVal<ParamType::TGraphicsResetStatus, T>(value);
+ case ParamType::THandleType:
+ return GetParamVal<ParamType::THandleType, T>(value);
+ case ParamType::TLightParameter:
+ return GetParamVal<ParamType::TLightParameter, T>(value);
+ case ParamType::TLogicalOperation:
+ return GetParamVal<ParamType::TLogicalOperation, T>(value);
+ case ParamType::TMaterialParameter:
+ return GetParamVal<ParamType::TMaterialParameter, T>(value);
+ case ParamType::TMatrixType:
+ return GetParamVal<ParamType::TMatrixType, T>(value);
+ case ParamType::TMemoryObjectID:
+ return GetParamVal<ParamType::TMemoryObjectID, T>(value);
+ case ParamType::TMemoryObjectIDConstPointer:
+ return GetParamVal<ParamType::TMemoryObjectIDConstPointer, T>(value);
+ case ParamType::TMemoryObjectIDPointer:
+ return GetParamVal<ParamType::TMemoryObjectIDPointer, T>(value);
+ case ParamType::TObjectType:
+ return GetParamVal<ParamType::TObjectType, T>(value);
+ case ParamType::TPointParameter:
+ return GetParamVal<ParamType::TPointParameter, T>(value);
+ case ParamType::TPrimitiveMode:
+ return GetParamVal<ParamType::TPrimitiveMode, T>(value);
+ case ParamType::TProgramPipelineID:
+ return GetParamVal<ParamType::TProgramPipelineID, T>(value);
+ case ParamType::TProgramPipelineIDConstPointer:
+ return GetParamVal<ParamType::TProgramPipelineIDConstPointer, T>(value);
+ case ParamType::TProgramPipelineIDPointer:
+ return GetParamVal<ParamType::TProgramPipelineIDPointer, T>(value);
+ case ParamType::TProvokingVertexConvention:
+ return GetParamVal<ParamType::TProvokingVertexConvention, T>(value);
+ case ParamType::TQueryID:
+ return GetParamVal<ParamType::TQueryID, T>(value);
+ case ParamType::TQueryIDConstPointer:
+ return GetParamVal<ParamType::TQueryIDConstPointer, T>(value);
+ case ParamType::TQueryIDPointer:
+ return GetParamVal<ParamType::TQueryIDPointer, T>(value);
+ case ParamType::TQueryType:
+ return GetParamVal<ParamType::TQueryType, T>(value);
+ case ParamType::TRenderbufferID:
+ return GetParamVal<ParamType::TRenderbufferID, T>(value);
+ case ParamType::TRenderbufferIDConstPointer:
+ return GetParamVal<ParamType::TRenderbufferIDConstPointer, T>(value);
+ case ParamType::TRenderbufferIDPointer:
+ return GetParamVal<ParamType::TRenderbufferIDPointer, T>(value);
+ case ParamType::TSamplerID:
+ return GetParamVal<ParamType::TSamplerID, T>(value);
+ case ParamType::TSamplerIDConstPointer:
+ return GetParamVal<ParamType::TSamplerIDConstPointer, T>(value);
+ case ParamType::TSamplerIDPointer:
+ return GetParamVal<ParamType::TSamplerIDPointer, T>(value);
+ case ParamType::TSemaphoreID:
+ return GetParamVal<ParamType::TSemaphoreID, T>(value);
+ case ParamType::TSemaphoreIDConstPointer:
+ return GetParamVal<ParamType::TSemaphoreIDConstPointer, T>(value);
+ case ParamType::TSemaphoreIDPointer:
+ return GetParamVal<ParamType::TSemaphoreIDPointer, T>(value);
+ case ParamType::TShaderProgramID:
+ return GetParamVal<ParamType::TShaderProgramID, T>(value);
+ case ParamType::TShaderProgramIDConstPointer:
+ return GetParamVal<ParamType::TShaderProgramIDConstPointer, T>(value);
+ case ParamType::TShaderProgramIDPointer:
+ return GetParamVal<ParamType::TShaderProgramIDPointer, T>(value);
+ case ParamType::TShaderType:
+ return GetParamVal<ParamType::TShaderType, T>(value);
+ case ParamType::TShadingModel:
+ return GetParamVal<ParamType::TShadingModel, T>(value);
+ case ParamType::TTextureEnvParameter:
+ return GetParamVal<ParamType::TTextureEnvParameter, T>(value);
+ case ParamType::TTextureEnvTarget:
+ return GetParamVal<ParamType::TTextureEnvTarget, T>(value);
+ case ParamType::TTextureID:
+ return GetParamVal<ParamType::TTextureID, T>(value);
+ case ParamType::TTextureIDConstPointer:
+ return GetParamVal<ParamType::TTextureIDConstPointer, T>(value);
+ case ParamType::TTextureIDPointer:
+ return GetParamVal<ParamType::TTextureIDPointer, T>(value);
+ case ParamType::TTextureTarget:
+ return GetParamVal<ParamType::TTextureTarget, T>(value);
+ case ParamType::TTextureType:
+ return GetParamVal<ParamType::TTextureType, T>(value);
+ case ParamType::TTimestamp:
+ return GetParamVal<ParamType::TTimestamp, T>(value);
+ case ParamType::TTransformFeedbackID:
+ return GetParamVal<ParamType::TTransformFeedbackID, T>(value);
+ case ParamType::TTransformFeedbackIDConstPointer:
+ return GetParamVal<ParamType::TTransformFeedbackIDConstPointer, T>(value);
+ case ParamType::TTransformFeedbackIDPointer:
+ return GetParamVal<ParamType::TTransformFeedbackIDPointer, T>(value);
+ case ParamType::TUniformBlockIndex:
+ return GetParamVal<ParamType::TUniformBlockIndex, T>(value);
+ case ParamType::TUniformLocation:
+ return GetParamVal<ParamType::TUniformLocation, T>(value);
+ case ParamType::TVertexArrayID:
+ return GetParamVal<ParamType::TVertexArrayID, T>(value);
+ case ParamType::TVertexArrayIDConstPointer:
+ return GetParamVal<ParamType::TVertexArrayIDConstPointer, T>(value);
+ case ParamType::TVertexArrayIDPointer:
+ return GetParamVal<ParamType::TVertexArrayIDPointer, T>(value);
+ case ParamType::TVertexAttribType:
+ return GetParamVal<ParamType::TVertexAttribType, T>(value);
+ case ParamType::TcharConstPointer:
+ return GetParamVal<ParamType::TcharConstPointer, T>(value);
+ case ParamType::TvoidConstPointer:
+ return GetParamVal<ParamType::TvoidConstPointer, T>(value);
+ case ParamType::TvoidConstPointerPointer:
+ return GetParamVal<ParamType::TvoidConstPointerPointer, T>(value);
+ case ParamType::TvoidPointer:
+ return GetParamVal<ParamType::TvoidPointer, T>(value);
+ case ParamType::TvoidPointerPointer:
+ return GetParamVal<ParamType::TvoidPointerPointer, T>(value);
+ }
+ UNREACHABLE();
+ return T();
+}
+
+template <ParamType PType, typename T>
+void SetParamVal(T valueIn, ParamValue *valueOut);
+
+template <>
+inline void SetParamVal<ParamType::TAHardwareBufferConstPointer>(const AHardwareBuffer *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->AHardwareBufferConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TAlphaTestFunc>(gl::AlphaTestFunc valueIn, ParamValue *valueOut)
+{
+ valueOut->AlphaTestFuncVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TBufferBinding>(gl::BufferBinding valueIn, ParamValue *valueOut)
+{
+ valueOut->BufferBindingVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TBufferID>(gl::BufferID valueIn, ParamValue *valueOut)
+{
+ valueOut->BufferIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TBufferIDConstPointer>(const gl::BufferID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->BufferIDConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TBufferIDPointer>(gl::BufferID *valueIn, ParamValue *valueOut)
+{
+ valueOut->BufferIDPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TBufferUsage>(gl::BufferUsage valueIn, ParamValue *valueOut)
+{
+ valueOut->BufferUsageVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TClientVertexArrayType>(gl::ClientVertexArrayType valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->ClientVertexArrayTypeVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TCompositorTiming>(egl::CompositorTiming valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->CompositorTimingVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TCullFaceMode>(gl::CullFaceMode valueIn, ParamValue *valueOut)
+{
+ valueOut->CullFaceModeVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TDrawElementsType>(gl::DrawElementsType valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->DrawElementsTypeVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLAttrib>(EGLAttrib valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLAttribVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLAttribKHR>(EGLAttribKHR valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLAttribKHRVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLBoolean>(EGLBoolean valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLBooleanVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLClientBuffer>(EGLClientBuffer valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLClientBufferVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLConfig>(EGLConfig valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLConfigVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLContext>(EGLContext valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLContextVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLDEBUGPROCKHR>(EGLDEBUGPROCKHR valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLDEBUGPROCKHRVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLDeviceEXT>(EGLDeviceEXT valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLDeviceEXTVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLDisplay>(EGLDisplay valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLDisplayVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLFrameTokenANGLE>(EGLFrameTokenANGLE valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->EGLFrameTokenANGLEVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLGetBlobFuncANDROID>(EGLGetBlobFuncANDROID valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->EGLGetBlobFuncANDROIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLImage>(EGLImage valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLImageVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLLabelKHR>(EGLLabelKHR valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLLabelKHRVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLNativeDisplayType>(EGLNativeDisplayType valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->EGLNativeDisplayTypeVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLNativePixmapType>(EGLNativePixmapType valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->EGLNativePixmapTypeVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLNativeWindowType>(EGLNativeWindowType valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->EGLNativeWindowTypeVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLObjectKHR>(EGLObjectKHR valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLObjectKHRVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLSetBlobFuncANDROID>(EGLSetBlobFuncANDROID valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->EGLSetBlobFuncANDROIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLStreamKHR>(EGLStreamKHR valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLStreamKHRVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLSurface>(EGLSurface valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLSurfaceVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLSync>(EGLSync valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLSyncVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLTime>(EGLTime valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLTimeVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLTimeKHR>(EGLTimeKHR valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLTimeKHRVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLenum>(EGLenum valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLenumVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLint>(EGLint valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLintVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLnsecsANDROID>(EGLnsecsANDROID valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLnsecsANDROIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TEGLuint64KHR>(EGLuint64KHR valueIn, ParamValue *valueOut)
+{
+ valueOut->EGLuint64KHRVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TFenceNVID>(gl::FenceNVID valueIn, ParamValue *valueOut)
+{
+ valueOut->FenceNVIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TFenceNVIDConstPointer>(const gl::FenceNVID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->FenceNVIDConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TFenceNVIDPointer>(gl::FenceNVID *valueIn, ParamValue *valueOut)
+{
+ valueOut->FenceNVIDPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TFramebufferID>(gl::FramebufferID valueIn, ParamValue *valueOut)
+{
+ valueOut->FramebufferIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TFramebufferIDConstPointer>(const gl::FramebufferID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->FramebufferIDConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TFramebufferIDPointer>(gl::FramebufferID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->FramebufferIDPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLDEBUGPROC>(GLDEBUGPROC valueIn, ParamValue *valueOut)
+{
+ valueOut->GLDEBUGPROCVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLDEBUGPROCKHR>(GLDEBUGPROCKHR valueIn, ParamValue *valueOut)
+{
+ valueOut->GLDEBUGPROCKHRVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLbitfield>(GLbitfield valueIn, ParamValue *valueOut)
+{
+ valueOut->GLbitfieldVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLboolean>(GLboolean valueIn, ParamValue *valueOut)
+{
+ valueOut->GLbooleanVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLbooleanConstPointer>(const GLboolean *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->GLbooleanConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLbooleanPointer>(GLboolean *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLbooleanPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLbyte>(GLbyte valueIn, ParamValue *valueOut)
+{
+ valueOut->GLbyteVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLbyteConstPointer>(const GLbyte *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLbyteConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLcharConstPointer>(const GLchar *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLcharConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLcharConstPointerPointer>(const GLchar *const *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->GLcharConstPointerPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLcharPointer>(GLchar *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLcharPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLclampx>(GLclampx valueIn, ParamValue *valueOut)
+{
+ valueOut->GLclampxVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLdouble>(GLdouble valueIn, ParamValue *valueOut)
+{
+ valueOut->GLdoubleVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLdoubleConstPointer>(const GLdouble *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->GLdoubleConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLdoublePointer>(GLdouble *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLdoublePointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLeglClientBufferEXT>(GLeglClientBufferEXT valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->GLeglClientBufferEXTVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLeglImageOES>(GLeglImageOES valueIn, ParamValue *valueOut)
+{
+ valueOut->GLeglImageOESVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLenum>(GLenum valueIn, ParamValue *valueOut)
+{
+ valueOut->GLenumVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLenumConstPointer>(const GLenum *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLenumConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLenumPointer>(GLenum *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLenumPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLfixed>(GLfixed valueIn, ParamValue *valueOut)
+{
+ valueOut->GLfixedVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLfixedConstPointer>(const GLfixed *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->GLfixedConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLfixedPointer>(GLfixed *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLfixedPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLfloat>(GLfloat valueIn, ParamValue *valueOut)
+{
+ valueOut->GLfloatVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLfloatConstPointer>(const GLfloat *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->GLfloatConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLfloatPointer>(GLfloat *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLfloatPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLint>(GLint valueIn, ParamValue *valueOut)
+{
+ valueOut->GLintVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLint64Pointer>(GLint64 *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLint64PointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLintConstPointer>(const GLint *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLintConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLintPointer>(GLint *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLintPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLintptr>(GLintptr valueIn, ParamValue *valueOut)
+{
+ valueOut->GLintptrVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLintptrConstPointer>(const GLintptr *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->GLintptrConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLshort>(GLshort valueIn, ParamValue *valueOut)
+{
+ valueOut->GLshortVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLshortConstPointer>(const GLshort *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->GLshortConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLsizei>(GLsizei valueIn, ParamValue *valueOut)
+{
+ valueOut->GLsizeiVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLsizeiConstPointer>(const GLsizei *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->GLsizeiConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLsizeiPointer>(GLsizei *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLsizeiPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLsizeiptr>(GLsizeiptr valueIn, ParamValue *valueOut)
+{
+ valueOut->GLsizeiptrVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLsizeiptrConstPointer>(const GLsizeiptr *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->GLsizeiptrConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLsync>(GLsync valueIn, ParamValue *valueOut)
+{
+ valueOut->GLsyncVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLubyte>(GLubyte valueIn, ParamValue *valueOut)
+{
+ valueOut->GLubyteVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLubyteConstPointer>(const GLubyte *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->GLubyteConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLubytePointer>(GLubyte *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLubytePointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLuint>(GLuint valueIn, ParamValue *valueOut)
+{
+ valueOut->GLuintVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLuint64>(GLuint64 valueIn, ParamValue *valueOut)
+{
+ valueOut->GLuint64Val = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLuint64ConstPointer>(const GLuint64 *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->GLuint64ConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLuint64Pointer>(GLuint64 *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLuint64PointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLuintConstPointer>(const GLuint *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLuintConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLuintPointer>(GLuint *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLuintPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLushort>(GLushort valueIn, ParamValue *valueOut)
+{
+ valueOut->GLushortVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLushortConstPointer>(const GLushort *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->GLushortConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLushortPointer>(GLushort *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLushortPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLvoidConstPointer>(const GLvoid *valueIn, ParamValue *valueOut)
+{
+ valueOut->GLvoidConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGLvoidConstPointerPointer>(const GLvoid *const *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->GLvoidConstPointerPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TGraphicsResetStatus>(gl::GraphicsResetStatus valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->GraphicsResetStatusVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::THandleType>(gl::HandleType valueIn, ParamValue *valueOut)
+{
+ valueOut->HandleTypeVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TLightParameter>(gl::LightParameter valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->LightParameterVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TLogicalOperation>(gl::LogicalOperation valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->LogicalOperationVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TMaterialParameter>(gl::MaterialParameter valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->MaterialParameterVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TMatrixType>(gl::MatrixType valueIn, ParamValue *valueOut)
+{
+ valueOut->MatrixTypeVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TMemoryObjectID>(gl::MemoryObjectID valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->MemoryObjectIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TMemoryObjectIDConstPointer>(const gl::MemoryObjectID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->MemoryObjectIDConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TMemoryObjectIDPointer>(gl::MemoryObjectID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->MemoryObjectIDPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TObjectType>(egl::ObjectType valueIn, ParamValue *valueOut)
+{
+ valueOut->ObjectTypeVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TPointParameter>(gl::PointParameter valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->PointParameterVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TPrimitiveMode>(gl::PrimitiveMode valueIn, ParamValue *valueOut)
+{
+ valueOut->PrimitiveModeVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TProgramPipelineID>(gl::ProgramPipelineID valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->ProgramPipelineIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TProgramPipelineIDConstPointer>(
+ const gl::ProgramPipelineID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->ProgramPipelineIDConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TProgramPipelineIDPointer>(gl::ProgramPipelineID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->ProgramPipelineIDPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TProvokingVertexConvention>(
+ gl::ProvokingVertexConvention valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->ProvokingVertexConventionVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TQueryID>(gl::QueryID valueIn, ParamValue *valueOut)
+{
+ valueOut->QueryIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TQueryIDConstPointer>(const gl::QueryID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->QueryIDConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TQueryIDPointer>(gl::QueryID *valueIn, ParamValue *valueOut)
+{
+ valueOut->QueryIDPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TQueryType>(gl::QueryType valueIn, ParamValue *valueOut)
+{
+ valueOut->QueryTypeVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TRenderbufferID>(gl::RenderbufferID valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->RenderbufferIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TRenderbufferIDConstPointer>(const gl::RenderbufferID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->RenderbufferIDConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TRenderbufferIDPointer>(gl::RenderbufferID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->RenderbufferIDPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TSamplerID>(gl::SamplerID valueIn, ParamValue *valueOut)
+{
+ valueOut->SamplerIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TSamplerIDConstPointer>(const gl::SamplerID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->SamplerIDConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TSamplerIDPointer>(gl::SamplerID *valueIn, ParamValue *valueOut)
+{
+ valueOut->SamplerIDPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TSemaphoreID>(gl::SemaphoreID valueIn, ParamValue *valueOut)
+{
+ valueOut->SemaphoreIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TSemaphoreIDConstPointer>(const gl::SemaphoreID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->SemaphoreIDConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TSemaphoreIDPointer>(gl::SemaphoreID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->SemaphoreIDPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TShaderProgramID>(gl::ShaderProgramID valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->ShaderProgramIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TShaderProgramIDConstPointer>(const gl::ShaderProgramID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->ShaderProgramIDConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TShaderProgramIDPointer>(gl::ShaderProgramID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->ShaderProgramIDPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TShaderType>(gl::ShaderType valueIn, ParamValue *valueOut)
+{
+ valueOut->ShaderTypeVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TShadingModel>(gl::ShadingModel valueIn, ParamValue *valueOut)
+{
+ valueOut->ShadingModelVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TTextureEnvParameter>(gl::TextureEnvParameter valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->TextureEnvParameterVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TTextureEnvTarget>(gl::TextureEnvTarget valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->TextureEnvTargetVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TTextureID>(gl::TextureID valueIn, ParamValue *valueOut)
+{
+ valueOut->TextureIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TTextureIDConstPointer>(const gl::TextureID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->TextureIDConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TTextureIDPointer>(gl::TextureID *valueIn, ParamValue *valueOut)
+{
+ valueOut->TextureIDPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TTextureTarget>(gl::TextureTarget valueIn, ParamValue *valueOut)
+{
+ valueOut->TextureTargetVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TTextureType>(gl::TextureType valueIn, ParamValue *valueOut)
+{
+ valueOut->TextureTypeVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TTimestamp>(egl::Timestamp valueIn, ParamValue *valueOut)
+{
+ valueOut->TimestampVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TTransformFeedbackID>(gl::TransformFeedbackID valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->TransformFeedbackIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TTransformFeedbackIDConstPointer>(
+ const gl::TransformFeedbackID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->TransformFeedbackIDConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TTransformFeedbackIDPointer>(gl::TransformFeedbackID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->TransformFeedbackIDPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TUniformBlockIndex>(gl::UniformBlockIndex valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->UniformBlockIndexVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TUniformLocation>(gl::UniformLocation valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->UniformLocationVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TVertexArrayID>(gl::VertexArrayID valueIn, ParamValue *valueOut)
+{
+ valueOut->VertexArrayIDVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TVertexArrayIDConstPointer>(const gl::VertexArrayID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->VertexArrayIDConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TVertexArrayIDPointer>(gl::VertexArrayID *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->VertexArrayIDPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TVertexAttribType>(gl::VertexAttribType valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->VertexAttribTypeVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TcharConstPointer>(const char *valueIn, ParamValue *valueOut)
+{
+ valueOut->charConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TvoidConstPointer>(const void *valueIn, ParamValue *valueOut)
+{
+ valueOut->voidConstPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TvoidConstPointerPointer>(const void *const *valueIn,
+ ParamValue *valueOut)
+{
+ valueOut->voidConstPointerPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TvoidPointer>(void *valueIn, ParamValue *valueOut)
+{
+ valueOut->voidPointerVal = valueIn;
+}
+
+template <>
+inline void SetParamVal<ParamType::TvoidPointerPointer>(void **valueIn, ParamValue *valueOut)
+{
+ valueOut->voidPointerPointerVal = valueIn;
+}
+
+template <ParamType PType, typename T>
+void SetParamVal(T valueIn, ParamValue *valueOut)
+{
+ UNREACHABLE();
+}
+
+template <typename T>
+void InitParamValue(ParamType paramType, T valueIn, ParamValue *valueOut)
+{
+ switch (paramType)
+ {
+ case ParamType::TAHardwareBufferConstPointer:
+ SetParamVal<ParamType::TAHardwareBufferConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TAlphaTestFunc:
+ SetParamVal<ParamType::TAlphaTestFunc>(valueIn, valueOut);
+ break;
+ case ParamType::TBufferBinding:
+ SetParamVal<ParamType::TBufferBinding>(valueIn, valueOut);
+ break;
+ case ParamType::TBufferID:
+ SetParamVal<ParamType::TBufferID>(valueIn, valueOut);
+ break;
+ case ParamType::TBufferIDConstPointer:
+ SetParamVal<ParamType::TBufferIDConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TBufferIDPointer:
+ SetParamVal<ParamType::TBufferIDPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TBufferUsage:
+ SetParamVal<ParamType::TBufferUsage>(valueIn, valueOut);
+ break;
+ case ParamType::TClientVertexArrayType:
+ SetParamVal<ParamType::TClientVertexArrayType>(valueIn, valueOut);
+ break;
+ case ParamType::TCompositorTiming:
+ SetParamVal<ParamType::TCompositorTiming>(valueIn, valueOut);
+ break;
+ case ParamType::TCullFaceMode:
+ SetParamVal<ParamType::TCullFaceMode>(valueIn, valueOut);
+ break;
+ case ParamType::TDrawElementsType:
+ SetParamVal<ParamType::TDrawElementsType>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLAttrib:
+ SetParamVal<ParamType::TEGLAttrib>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLAttribKHR:
+ SetParamVal<ParamType::TEGLAttribKHR>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLBoolean:
+ SetParamVal<ParamType::TEGLBoolean>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLClientBuffer:
+ SetParamVal<ParamType::TEGLClientBuffer>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLConfig:
+ SetParamVal<ParamType::TEGLConfig>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLContext:
+ SetParamVal<ParamType::TEGLContext>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLDEBUGPROCKHR:
+ SetParamVal<ParamType::TEGLDEBUGPROCKHR>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLDeviceEXT:
+ SetParamVal<ParamType::TEGLDeviceEXT>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLDisplay:
+ SetParamVal<ParamType::TEGLDisplay>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLFrameTokenANGLE:
+ SetParamVal<ParamType::TEGLFrameTokenANGLE>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLGetBlobFuncANDROID:
+ SetParamVal<ParamType::TEGLGetBlobFuncANDROID>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLImage:
+ SetParamVal<ParamType::TEGLImage>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLLabelKHR:
+ SetParamVal<ParamType::TEGLLabelKHR>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLNativeDisplayType:
+ SetParamVal<ParamType::TEGLNativeDisplayType>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLNativePixmapType:
+ SetParamVal<ParamType::TEGLNativePixmapType>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLNativeWindowType:
+ SetParamVal<ParamType::TEGLNativeWindowType>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLObjectKHR:
+ SetParamVal<ParamType::TEGLObjectKHR>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLSetBlobFuncANDROID:
+ SetParamVal<ParamType::TEGLSetBlobFuncANDROID>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLStreamKHR:
+ SetParamVal<ParamType::TEGLStreamKHR>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLSurface:
+ SetParamVal<ParamType::TEGLSurface>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLSync:
+ SetParamVal<ParamType::TEGLSync>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLTime:
+ SetParamVal<ParamType::TEGLTime>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLTimeKHR:
+ SetParamVal<ParamType::TEGLTimeKHR>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLenum:
+ SetParamVal<ParamType::TEGLenum>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLint:
+ SetParamVal<ParamType::TEGLint>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLnsecsANDROID:
+ SetParamVal<ParamType::TEGLnsecsANDROID>(valueIn, valueOut);
+ break;
+ case ParamType::TEGLuint64KHR:
+ SetParamVal<ParamType::TEGLuint64KHR>(valueIn, valueOut);
+ break;
+ case ParamType::TFenceNVID:
+ SetParamVal<ParamType::TFenceNVID>(valueIn, valueOut);
+ break;
+ case ParamType::TFenceNVIDConstPointer:
+ SetParamVal<ParamType::TFenceNVIDConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TFenceNVIDPointer:
+ SetParamVal<ParamType::TFenceNVIDPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TFramebufferID:
+ SetParamVal<ParamType::TFramebufferID>(valueIn, valueOut);
+ break;
+ case ParamType::TFramebufferIDConstPointer:
+ SetParamVal<ParamType::TFramebufferIDConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TFramebufferIDPointer:
+ SetParamVal<ParamType::TFramebufferIDPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLDEBUGPROC:
+ SetParamVal<ParamType::TGLDEBUGPROC>(valueIn, valueOut);
+ break;
+ case ParamType::TGLDEBUGPROCKHR:
+ SetParamVal<ParamType::TGLDEBUGPROCKHR>(valueIn, valueOut);
+ break;
+ case ParamType::TGLbitfield:
+ SetParamVal<ParamType::TGLbitfield>(valueIn, valueOut);
+ break;
+ case ParamType::TGLboolean:
+ SetParamVal<ParamType::TGLboolean>(valueIn, valueOut);
+ break;
+ case ParamType::TGLbooleanConstPointer:
+ SetParamVal<ParamType::TGLbooleanConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLbooleanPointer:
+ SetParamVal<ParamType::TGLbooleanPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLbyte:
+ SetParamVal<ParamType::TGLbyte>(valueIn, valueOut);
+ break;
+ case ParamType::TGLbyteConstPointer:
+ SetParamVal<ParamType::TGLbyteConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLcharConstPointer:
+ SetParamVal<ParamType::TGLcharConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLcharConstPointerPointer:
+ SetParamVal<ParamType::TGLcharConstPointerPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLcharPointer:
+ SetParamVal<ParamType::TGLcharPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLclampx:
+ SetParamVal<ParamType::TGLclampx>(valueIn, valueOut);
+ break;
+ case ParamType::TGLdouble:
+ SetParamVal<ParamType::TGLdouble>(valueIn, valueOut);
+ break;
+ case ParamType::TGLdoubleConstPointer:
+ SetParamVal<ParamType::TGLdoubleConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLdoublePointer:
+ SetParamVal<ParamType::TGLdoublePointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLeglClientBufferEXT:
+ SetParamVal<ParamType::TGLeglClientBufferEXT>(valueIn, valueOut);
+ break;
+ case ParamType::TGLeglImageOES:
+ SetParamVal<ParamType::TGLeglImageOES>(valueIn, valueOut);
+ break;
+ case ParamType::TGLenum:
+ SetParamVal<ParamType::TGLenum>(valueIn, valueOut);
+ break;
+ case ParamType::TGLenumConstPointer:
+ SetParamVal<ParamType::TGLenumConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLenumPointer:
+ SetParamVal<ParamType::TGLenumPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLfixed:
+ SetParamVal<ParamType::TGLfixed>(valueIn, valueOut);
+ break;
+ case ParamType::TGLfixedConstPointer:
+ SetParamVal<ParamType::TGLfixedConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLfixedPointer:
+ SetParamVal<ParamType::TGLfixedPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLfloat:
+ SetParamVal<ParamType::TGLfloat>(valueIn, valueOut);
+ break;
+ case ParamType::TGLfloatConstPointer:
+ SetParamVal<ParamType::TGLfloatConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLfloatPointer:
+ SetParamVal<ParamType::TGLfloatPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLint:
+ SetParamVal<ParamType::TGLint>(valueIn, valueOut);
+ break;
+ case ParamType::TGLint64Pointer:
+ SetParamVal<ParamType::TGLint64Pointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLintConstPointer:
+ SetParamVal<ParamType::TGLintConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLintPointer:
+ SetParamVal<ParamType::TGLintPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLintptr:
+ SetParamVal<ParamType::TGLintptr>(valueIn, valueOut);
+ break;
+ case ParamType::TGLintptrConstPointer:
+ SetParamVal<ParamType::TGLintptrConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLshort:
+ SetParamVal<ParamType::TGLshort>(valueIn, valueOut);
+ break;
+ case ParamType::TGLshortConstPointer:
+ SetParamVal<ParamType::TGLshortConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLsizei:
+ SetParamVal<ParamType::TGLsizei>(valueIn, valueOut);
+ break;
+ case ParamType::TGLsizeiConstPointer:
+ SetParamVal<ParamType::TGLsizeiConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLsizeiPointer:
+ SetParamVal<ParamType::TGLsizeiPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLsizeiptr:
+ SetParamVal<ParamType::TGLsizeiptr>(valueIn, valueOut);
+ break;
+ case ParamType::TGLsizeiptrConstPointer:
+ SetParamVal<ParamType::TGLsizeiptrConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLsync:
+ SetParamVal<ParamType::TGLsync>(valueIn, valueOut);
+ break;
+ case ParamType::TGLubyte:
+ SetParamVal<ParamType::TGLubyte>(valueIn, valueOut);
+ break;
+ case ParamType::TGLubyteConstPointer:
+ SetParamVal<ParamType::TGLubyteConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLubytePointer:
+ SetParamVal<ParamType::TGLubytePointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLuint:
+ SetParamVal<ParamType::TGLuint>(valueIn, valueOut);
+ break;
+ case ParamType::TGLuint64:
+ SetParamVal<ParamType::TGLuint64>(valueIn, valueOut);
+ break;
+ case ParamType::TGLuint64ConstPointer:
+ SetParamVal<ParamType::TGLuint64ConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLuint64Pointer:
+ SetParamVal<ParamType::TGLuint64Pointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLuintConstPointer:
+ SetParamVal<ParamType::TGLuintConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLuintPointer:
+ SetParamVal<ParamType::TGLuintPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLushort:
+ SetParamVal<ParamType::TGLushort>(valueIn, valueOut);
+ break;
+ case ParamType::TGLushortConstPointer:
+ SetParamVal<ParamType::TGLushortConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLushortPointer:
+ SetParamVal<ParamType::TGLushortPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLvoidConstPointer:
+ SetParamVal<ParamType::TGLvoidConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGLvoidConstPointerPointer:
+ SetParamVal<ParamType::TGLvoidConstPointerPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TGraphicsResetStatus:
+ SetParamVal<ParamType::TGraphicsResetStatus>(valueIn, valueOut);
+ break;
+ case ParamType::THandleType:
+ SetParamVal<ParamType::THandleType>(valueIn, valueOut);
+ break;
+ case ParamType::TLightParameter:
+ SetParamVal<ParamType::TLightParameter>(valueIn, valueOut);
+ break;
+ case ParamType::TLogicalOperation:
+ SetParamVal<ParamType::TLogicalOperation>(valueIn, valueOut);
+ break;
+ case ParamType::TMaterialParameter:
+ SetParamVal<ParamType::TMaterialParameter>(valueIn, valueOut);
+ break;
+ case ParamType::TMatrixType:
+ SetParamVal<ParamType::TMatrixType>(valueIn, valueOut);
+ break;
+ case ParamType::TMemoryObjectID:
+ SetParamVal<ParamType::TMemoryObjectID>(valueIn, valueOut);
+ break;
+ case ParamType::TMemoryObjectIDConstPointer:
+ SetParamVal<ParamType::TMemoryObjectIDConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TMemoryObjectIDPointer:
+ SetParamVal<ParamType::TMemoryObjectIDPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TObjectType:
+ SetParamVal<ParamType::TObjectType>(valueIn, valueOut);
+ break;
+ case ParamType::TPointParameter:
+ SetParamVal<ParamType::TPointParameter>(valueIn, valueOut);
+ break;
+ case ParamType::TPrimitiveMode:
+ SetParamVal<ParamType::TPrimitiveMode>(valueIn, valueOut);
+ break;
+ case ParamType::TProgramPipelineID:
+ SetParamVal<ParamType::TProgramPipelineID>(valueIn, valueOut);
+ break;
+ case ParamType::TProgramPipelineIDConstPointer:
+ SetParamVal<ParamType::TProgramPipelineIDConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TProgramPipelineIDPointer:
+ SetParamVal<ParamType::TProgramPipelineIDPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TProvokingVertexConvention:
+ SetParamVal<ParamType::TProvokingVertexConvention>(valueIn, valueOut);
+ break;
+ case ParamType::TQueryID:
+ SetParamVal<ParamType::TQueryID>(valueIn, valueOut);
+ break;
+ case ParamType::TQueryIDConstPointer:
+ SetParamVal<ParamType::TQueryIDConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TQueryIDPointer:
+ SetParamVal<ParamType::TQueryIDPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TQueryType:
+ SetParamVal<ParamType::TQueryType>(valueIn, valueOut);
+ break;
+ case ParamType::TRenderbufferID:
+ SetParamVal<ParamType::TRenderbufferID>(valueIn, valueOut);
+ break;
+ case ParamType::TRenderbufferIDConstPointer:
+ SetParamVal<ParamType::TRenderbufferIDConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TRenderbufferIDPointer:
+ SetParamVal<ParamType::TRenderbufferIDPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TSamplerID:
+ SetParamVal<ParamType::TSamplerID>(valueIn, valueOut);
+ break;
+ case ParamType::TSamplerIDConstPointer:
+ SetParamVal<ParamType::TSamplerIDConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TSamplerIDPointer:
+ SetParamVal<ParamType::TSamplerIDPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TSemaphoreID:
+ SetParamVal<ParamType::TSemaphoreID>(valueIn, valueOut);
+ break;
+ case ParamType::TSemaphoreIDConstPointer:
+ SetParamVal<ParamType::TSemaphoreIDConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TSemaphoreIDPointer:
+ SetParamVal<ParamType::TSemaphoreIDPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TShaderProgramID:
+ SetParamVal<ParamType::TShaderProgramID>(valueIn, valueOut);
+ break;
+ case ParamType::TShaderProgramIDConstPointer:
+ SetParamVal<ParamType::TShaderProgramIDConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TShaderProgramIDPointer:
+ SetParamVal<ParamType::TShaderProgramIDPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TShaderType:
+ SetParamVal<ParamType::TShaderType>(valueIn, valueOut);
+ break;
+ case ParamType::TShadingModel:
+ SetParamVal<ParamType::TShadingModel>(valueIn, valueOut);
+ break;
+ case ParamType::TTextureEnvParameter:
+ SetParamVal<ParamType::TTextureEnvParameter>(valueIn, valueOut);
+ break;
+ case ParamType::TTextureEnvTarget:
+ SetParamVal<ParamType::TTextureEnvTarget>(valueIn, valueOut);
+ break;
+ case ParamType::TTextureID:
+ SetParamVal<ParamType::TTextureID>(valueIn, valueOut);
+ break;
+ case ParamType::TTextureIDConstPointer:
+ SetParamVal<ParamType::TTextureIDConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TTextureIDPointer:
+ SetParamVal<ParamType::TTextureIDPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TTextureTarget:
+ SetParamVal<ParamType::TTextureTarget>(valueIn, valueOut);
+ break;
+ case ParamType::TTextureType:
+ SetParamVal<ParamType::TTextureType>(valueIn, valueOut);
+ break;
+ case ParamType::TTimestamp:
+ SetParamVal<ParamType::TTimestamp>(valueIn, valueOut);
+ break;
+ case ParamType::TTransformFeedbackID:
+ SetParamVal<ParamType::TTransformFeedbackID>(valueIn, valueOut);
+ break;
+ case ParamType::TTransformFeedbackIDConstPointer:
+ SetParamVal<ParamType::TTransformFeedbackIDConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TTransformFeedbackIDPointer:
+ SetParamVal<ParamType::TTransformFeedbackIDPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TUniformBlockIndex:
+ SetParamVal<ParamType::TUniformBlockIndex>(valueIn, valueOut);
+ break;
+ case ParamType::TUniformLocation:
+ SetParamVal<ParamType::TUniformLocation>(valueIn, valueOut);
+ break;
+ case ParamType::TVertexArrayID:
+ SetParamVal<ParamType::TVertexArrayID>(valueIn, valueOut);
+ break;
+ case ParamType::TVertexArrayIDConstPointer:
+ SetParamVal<ParamType::TVertexArrayIDConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TVertexArrayIDPointer:
+ SetParamVal<ParamType::TVertexArrayIDPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TVertexAttribType:
+ SetParamVal<ParamType::TVertexAttribType>(valueIn, valueOut);
+ break;
+ case ParamType::TcharConstPointer:
+ SetParamVal<ParamType::TcharConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TvoidConstPointer:
+ SetParamVal<ParamType::TvoidConstPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TvoidConstPointerPointer:
+ SetParamVal<ParamType::TvoidConstPointerPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TvoidPointer:
+ SetParamVal<ParamType::TvoidPointer>(valueIn, valueOut);
+ break;
+ case ParamType::TvoidPointerPointer:
+ SetParamVal<ParamType::TvoidPointerPointer>(valueIn, valueOut);
+ break;
+ }
+}
+
+struct CallCapture;
+struct ParamCapture;
+
+void WriteParamCaptureReplay(std::ostream &os, const CallCapture &call, const ParamCapture &param);
+const char *ParamTypeToString(ParamType paramType);
+
+enum class ResourceIDType
+{
+ Buffer,
+ FenceNV,
+ Framebuffer,
+ MemoryObject,
+ ProgramPipeline,
+ Query,
+ Renderbuffer,
+ Sampler,
+ Semaphore,
+ ShaderProgram,
+ Texture,
+ TransformFeedback,
+ VertexArray,
+ EnumCount,
+ InvalidEnum = EnumCount
+};
+
+ResourceIDType GetResourceIDTypeFromParamType(ParamType paramType);
+const char *GetResourceIDTypeName(ResourceIDType resourceIDType);
+
+template <typename ResourceType>
+struct GetResourceIDTypeFromType;
+
+template <>
+struct GetResourceIDTypeFromType<gl::BufferID>
+{
+ static constexpr ResourceIDType IDType = ResourceIDType::Buffer;
+};
+
+template <>
+struct GetResourceIDTypeFromType<gl::FenceNVID>
+{
+ static constexpr ResourceIDType IDType = ResourceIDType::FenceNV;
+};
+
+template <>
+struct GetResourceIDTypeFromType<gl::FramebufferID>
+{
+ static constexpr ResourceIDType IDType = ResourceIDType::Framebuffer;
+};
+
+template <>
+struct GetResourceIDTypeFromType<gl::MemoryObjectID>
+{
+ static constexpr ResourceIDType IDType = ResourceIDType::MemoryObject;
+};
+
+template <>
+struct GetResourceIDTypeFromType<gl::ProgramPipelineID>
+{
+ static constexpr ResourceIDType IDType = ResourceIDType::ProgramPipeline;
+};
+
+template <>
+struct GetResourceIDTypeFromType<gl::QueryID>
+{
+ static constexpr ResourceIDType IDType = ResourceIDType::Query;
+};
+
+template <>
+struct GetResourceIDTypeFromType<gl::RenderbufferID>
+{
+ static constexpr ResourceIDType IDType = ResourceIDType::Renderbuffer;
+};
+
+template <>
+struct GetResourceIDTypeFromType<gl::SamplerID>
+{
+ static constexpr ResourceIDType IDType = ResourceIDType::Sampler;
+};
+
+template <>
+struct GetResourceIDTypeFromType<gl::SemaphoreID>
+{
+ static constexpr ResourceIDType IDType = ResourceIDType::Semaphore;
+};
+
+template <>
+struct GetResourceIDTypeFromType<gl::ShaderProgramID>
+{
+ static constexpr ResourceIDType IDType = ResourceIDType::ShaderProgram;
+};
+
+template <>
+struct GetResourceIDTypeFromType<gl::TextureID>
+{
+ static constexpr ResourceIDType IDType = ResourceIDType::Texture;
+};
+
+template <>
+struct GetResourceIDTypeFromType<gl::TransformFeedbackID>
+{
+ static constexpr ResourceIDType IDType = ResourceIDType::TransformFeedback;
+};
+
+template <>
+struct GetResourceIDTypeFromType<gl::VertexArrayID>
+{
+ static constexpr ResourceIDType IDType = ResourceIDType::VertexArray;
+};
+
+} // namespace angle
+
+#endif // LIBANGLE_FRAME_CAPTURE_UTILS_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/capture/frame_capture_utils_mock.cpp b/gfx/angle/checkout/src/libANGLE/capture/frame_capture_utils_mock.cpp
new file mode 100644
index 0000000000..f136a3c17d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/frame_capture_utils_mock.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright 2021 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// frame_capture_utils_mock.cpp:
+// ANGLE frame capture util stub implementation.
+//
+
+#include "libANGLE/capture/frame_capture_utils.h"
+
+namespace angle
+{
+Result SerializeContextToString(const gl::Context *context, std::string *stringOut)
+{
+ *stringOut = "SerializationNotAvailable";
+ return angle::Result::Continue;
+}
+} // namespace angle
diff --git a/gfx/angle/checkout/src/libANGLE/capture/gl_enum_utils.h b/gfx/angle/checkout/src/libANGLE/capture/gl_enum_utils.h
new file mode 100644
index 0000000000..1fac416138
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/gl_enum_utils.h
@@ -0,0 +1,32 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// gl_enum_utils.h:
+// Utility functions for converting GLenums to string.
+
+#ifndef LIBANGLE_GL_ENUM_UTILS_H_
+#define LIBANGLE_GL_ENUM_UTILS_H_
+
+#include <ostream>
+#include <string>
+
+#include "libANGLE/capture/gl_enum_utils_autogen.h"
+
+namespace gl
+{
+const char *GLbooleanToString(unsigned int value);
+const char *GLenumToString(GLESEnum enumGroup, unsigned int value);
+const char *GLenumToString(BigGLEnum enumGroup, unsigned int value);
+std::string GLbitfieldToString(GLESEnum enumGroup, unsigned int value);
+std::string GLbitfieldToString(BigGLEnum enumGroup, unsigned int value);
+void OutputGLenumString(std::ostream &out, GLESEnum enumGroup, unsigned int value);
+void OutputGLenumString(std::ostream &out, BigGLEnum enumGroup, unsigned int value);
+void OutputGLbitfieldString(std::ostream &out, GLESEnum enumGroup, unsigned int value);
+const char *GLinternalFormatToString(unsigned int format);
+
+extern const char kUnknownGLenumString[];
+} // namespace gl
+
+#endif // LIBANGLE_GL_ENUM_UTILS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/capture/gl_enum_utils_autogen.h b/gfx/angle/checkout/src/libANGLE/capture/gl_enum_utils_autogen.h
new file mode 100644
index 0000000000..6d0fe3da3e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/capture/gl_enum_utils_autogen.h
@@ -0,0 +1,419 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_gl_enum_utils.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// gl_enum_utils_autogen.h:
+// mapping of GLenum value to string.
+
+#ifndef LIBANGLE_GL_ENUM_UTILS_AUTOGEN_H_
+#define LIBANGLE_GL_ENUM_UTILS_AUTOGEN_H_
+
+namespace gl
+{
+enum class GLESEnum
+{
+ AccumOp,
+ AllEnums,
+ AlphaFunction,
+ AtomicCounterBufferPName,
+ AttribMask,
+ AttributeType,
+ BindTransformFeedbackTarget,
+ BinormalPointerTypeEXT,
+ BlendEquationModeEXT,
+ BlendingFactor,
+ BlitFramebufferFilter,
+ Boolean,
+ Buffer,
+ BufferAccessARB,
+ BufferPNameARB,
+ BufferPointerNameARB,
+ BufferStorageMask,
+ BufferStorageTarget,
+ BufferTargetARB,
+ BufferUsageARB,
+ ClampColorModeARB,
+ ClearBufferMask,
+ ClipPlaneName,
+ ColorBuffer,
+ ColorMaterialParameter,
+ ColorPointerType,
+ CombinerBiasNV,
+ CombinerComponentUsageNV,
+ CombinerPortionNV,
+ CombinerScaleNV,
+ ContainerType,
+ ContextFlagMask,
+ CopyBufferSubDataTarget,
+ CopyImageSubDataTarget,
+ DebugSeverity,
+ DebugSource,
+ DebugType,
+ DepthFunction,
+ DepthStencilTextureMode,
+ DrawBufferMode,
+ DrawElementsType,
+ ElementPointerTypeATI,
+ EnableCap,
+ ErrorCode,
+ ExternalHandleType,
+ FenceConditionNV,
+ FenceParameterNameNV,
+ FogCoordinatePointerType,
+ FogMode,
+ FogPName,
+ FogParameter,
+ FogPointerTypeEXT,
+ FogPointerTypeIBM,
+ FragmentLightParameterSGIX,
+ FragmentShaderDestMaskATI,
+ FragmentShaderDestModMaskATI,
+ FragmentShaderGenericSourceATI,
+ FragmentShaderTextureSourceATI,
+ FragmentShaderValueRepATI,
+ FramebufferAttachment,
+ FramebufferAttachmentParameterName,
+ FramebufferParameterName,
+ FramebufferStatus,
+ FramebufferTarget,
+ FrontFaceDirection,
+ GetFramebufferParameter,
+ GetMultisamplePNameNV,
+ GetPName,
+ GetPointervPName,
+ GetTextureParameter,
+ GraphicsResetStatus,
+ HintMode,
+ HintTarget,
+ IndexFunctionEXT,
+ IndexPointerType,
+ InternalFormat,
+ InternalFormatPName,
+ InvalidateFramebufferAttachment,
+ LightEnvModeSGIX,
+ LightModelParameter,
+ LightName,
+ LightParameter,
+ ListNameType,
+ LogicOp,
+ MapBufferAccessMask,
+ MapTypeNV,
+ MaterialParameter,
+ MatrixIndexPointerTypeARB,
+ MatrixMode,
+ MemoryBarrierMask,
+ MemoryObjectParameterName,
+ NormalPointerType,
+ ObjectIdentifier,
+ PatchParameterName,
+ PathColor,
+ PathColorFormat,
+ PathFillMode,
+ PathFontStyle,
+ PathGenMode,
+ PathTransformType,
+ PipelineParameterName,
+ PixelCopyType,
+ PixelFormat,
+ PixelStoreParameter,
+ PixelTexGenModeSGIX,
+ PixelTransferParameter,
+ PixelType,
+ PointParameterNameARB,
+ PrecisionType,
+ PrimitiveType,
+ ProgramInterface,
+ ProgramInterfacePName,
+ ProgramParameterPName,
+ ProgramPropertyARB,
+ ProgramResourceProperty,
+ QueryCounterTarget,
+ QueryObjectParameterName,
+ QueryParameterName,
+ QueryTarget,
+ ReadBufferMode,
+ RenderbufferParameterName,
+ RenderbufferTarget,
+ ReplacementCodeTypeSUN,
+ SamplerParameterF,
+ SamplerParameterI,
+ ScalarType,
+ SecondaryColorPointerTypeIBM,
+ SemaphoreParameterName,
+ ShaderBinaryFormat,
+ ShaderParameterName,
+ ShaderType,
+ ShadingModel,
+ ShadingRateQCOM,
+ SizedInternalFormat,
+ StencilFunction,
+ StencilOp,
+ StringName,
+ SubroutineParameterName,
+ SyncBehaviorFlags,
+ SyncCondition,
+ SyncObjectMask,
+ SyncParameterName,
+ SyncStatus,
+ TangentPointerTypeEXT,
+ TexCoordPointerType,
+ TextureCompareMode,
+ TextureCoordName,
+ TextureEnvMode,
+ TextureEnvParameter,
+ TextureEnvTarget,
+ TextureGenParameter,
+ TextureLayout,
+ TextureMagFilter,
+ TextureMinFilter,
+ TextureParameterName,
+ TextureSwizzle,
+ TextureTarget,
+ TextureUnit,
+ TextureWrapMode,
+ TransformFeedbackBufferMode,
+ TransformFeedbackPName,
+ TriangleFace,
+ UniformBlockPName,
+ UniformPName,
+ UniformType,
+ UseProgramStageMask,
+ VertexArrayPName,
+ VertexAttribEnum,
+ VertexAttribIType,
+ VertexAttribPointerPropertyARB,
+ VertexAttribPointerType,
+ VertexAttribPropertyARB,
+ VertexAttribType,
+ VertexBufferObjectUsage,
+ VertexPointerType,
+ VertexProvokingMode,
+ VertexShaderTextureUnitParameter,
+ VertexShaderWriteMaskEXT,
+ VertexWeightPointerTypeEXT,
+ WeightPointerTypeARB
+};
+
+enum class BigGLEnum
+{
+ AccumOp,
+ AllEnums,
+ AlphaFunction,
+ AtomicCounterBufferPName,
+ AttribMask,
+ AttributeType,
+ BindTransformFeedbackTarget,
+ BinormalPointerTypeEXT,
+ BlendEquationModeEXT,
+ BlendingFactor,
+ BlitFramebufferFilter,
+ Boolean,
+ Buffer,
+ BufferAccessARB,
+ BufferPNameARB,
+ BufferPointerNameARB,
+ BufferStorageMask,
+ BufferStorageTarget,
+ BufferTargetARB,
+ BufferUsageARB,
+ ClampColorModeARB,
+ ClampColorTargetARB,
+ ClearBufferMask,
+ ClientAttribMask,
+ ClipControlDepth,
+ ClipControlOrigin,
+ ClipPlaneName,
+ ColorBuffer,
+ ColorMaterialParameter,
+ ColorPointerType,
+ ColorTableTarget,
+ ColorTableTargetSGI,
+ CombinerBiasNV,
+ CombinerComponentUsageNV,
+ CombinerPortionNV,
+ CombinerScaleNV,
+ ConditionalRenderMode,
+ ContainerType,
+ ContextFlagMask,
+ ContextProfileMask,
+ ConvolutionTarget,
+ ConvolutionTargetEXT,
+ CopyBufferSubDataTarget,
+ CopyImageSubDataTarget,
+ DebugSeverity,
+ DebugSource,
+ DebugType,
+ DepthFunction,
+ DepthStencilTextureMode,
+ DrawBufferMode,
+ DrawElementsType,
+ ElementPointerTypeATI,
+ EnableCap,
+ ErrorCode,
+ ExternalHandleType,
+ FeedBackToken,
+ FeedbackType,
+ FenceConditionNV,
+ FenceParameterNameNV,
+ FogCoordSrc,
+ FogCoordinatePointerType,
+ FogMode,
+ FogPName,
+ FogParameter,
+ FogPointerTypeEXT,
+ FogPointerTypeIBM,
+ FragmentLightParameterSGIX,
+ FragmentShaderDestMaskATI,
+ FragmentShaderDestModMaskATI,
+ FragmentShaderGenericSourceATI,
+ FragmentShaderTextureSourceATI,
+ FragmentShaderValueRepATI,
+ FramebufferAttachment,
+ FramebufferAttachmentParameterName,
+ FramebufferParameterName,
+ FramebufferStatus,
+ FramebufferTarget,
+ FrontFaceDirection,
+ GetFramebufferParameter,
+ GetMapQuery,
+ GetMultisamplePNameNV,
+ GetPName,
+ GetPointervPName,
+ GetTextureParameter,
+ GraphicsResetStatus,
+ HintMode,
+ HintTarget,
+ HistogramTarget,
+ HistogramTargetEXT,
+ IndexFunctionEXT,
+ IndexMaterialParameterEXT,
+ IndexPointerType,
+ InterleavedArrayFormat,
+ InternalFormat,
+ InternalFormatPName,
+ InvalidateFramebufferAttachment,
+ LightEnvModeSGIX,
+ LightModelColorControl,
+ LightModelParameter,
+ LightName,
+ LightParameter,
+ LightTextureModeEXT,
+ ListMode,
+ ListNameType,
+ LogicOp,
+ MapBufferAccessMask,
+ MapQuery,
+ MapTarget,
+ MapTypeNV,
+ MaterialParameter,
+ MatrixIndexPointerTypeARB,
+ MatrixMode,
+ MemoryBarrierMask,
+ MemoryObjectParameterName,
+ MeshMode1,
+ MeshMode2,
+ MinmaxTarget,
+ MinmaxTargetEXT,
+ NormalPointerType,
+ ObjectIdentifier,
+ PatchParameterName,
+ PathColor,
+ PathColorFormat,
+ PathFillMode,
+ PathFontStyle,
+ PathGenMode,
+ PathTransformType,
+ PipelineParameterName,
+ PixelCopyType,
+ PixelFormat,
+ PixelMap,
+ PixelStoreParameter,
+ PixelTexGenModeSGIX,
+ PixelTransferParameter,
+ PixelType,
+ PointParameterNameARB,
+ PolygonMode,
+ PrecisionType,
+ PrimitiveType,
+ ProgramInterface,
+ ProgramInterfacePName,
+ ProgramParameterPName,
+ ProgramPropertyARB,
+ ProgramResourceProperty,
+ ProgramStagePName,
+ QueryCounterTarget,
+ QueryObjectParameterName,
+ QueryParameterName,
+ QueryTarget,
+ ReadBufferMode,
+ RenderbufferParameterName,
+ RenderbufferTarget,
+ RenderingMode,
+ ReplacementCodeTypeSUN,
+ SamplerParameterF,
+ SamplerParameterI,
+ ScalarType,
+ SecondaryColorPointerTypeIBM,
+ SemaphoreParameterName,
+ SeparableTarget,
+ SeparableTargetEXT,
+ ShaderBinaryFormat,
+ ShaderParameterName,
+ ShaderType,
+ ShadingModel,
+ SizedInternalFormat,
+ StencilFunction,
+ StencilOp,
+ StringName,
+ SubroutineParameterName,
+ SyncBehaviorFlags,
+ SyncCondition,
+ SyncObjectMask,
+ SyncParameterName,
+ SyncStatus,
+ TangentPointerTypeEXT,
+ TexCoordPointerType,
+ TextureCompareMode,
+ TextureCoordName,
+ TextureEnvMode,
+ TextureEnvParameter,
+ TextureEnvTarget,
+ TextureGenMode,
+ TextureGenParameter,
+ TextureLayout,
+ TextureMagFilter,
+ TextureMinFilter,
+ TextureParameterName,
+ TextureSwizzle,
+ TextureTarget,
+ TextureUnit,
+ TextureWrapMode,
+ TransformFeedbackBufferMode,
+ TransformFeedbackPName,
+ TriangleFace,
+ UniformBlockPName,
+ UniformPName,
+ UniformType,
+ UseProgramStageMask,
+ VertexArrayPName,
+ VertexAttribEnum,
+ VertexAttribIType,
+ VertexAttribLType,
+ VertexAttribPointerPropertyARB,
+ VertexAttribPointerType,
+ VertexAttribPropertyARB,
+ VertexAttribType,
+ VertexBufferObjectUsage,
+ VertexPointerType,
+ VertexProvokingMode,
+ VertexShaderTextureUnitParameter,
+ VertexShaderWriteMaskEXT,
+ VertexWeightPointerTypeEXT,
+ WeightPointerTypeARB
+};
+} // namespace gl
+
+#endif // LIBANGLE_GL_ENUM_UTILS_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/entry_points_utils.h b/gfx/angle/checkout/src/libANGLE/entry_points_utils.h
new file mode 100644
index 0000000000..c5a3178308
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/entry_points_utils.h
@@ -0,0 +1,127 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// entry_point_utils:
+// These helpers are used in GL/GLES entry point routines.
+
+#ifndef LIBANGLE_ENTRY_POINT_UTILS_H_
+#define LIBANGLE_ENTRY_POINT_UTILS_H_
+
+#include "angle_gl.h"
+#include "common/Optional.h"
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "common/entry_points_enum_autogen.h"
+#include "common/mathutil.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+
+namespace gl
+{
+// A template struct for determining the default value to return for each entry point.
+template <angle::EntryPoint EP, typename ReturnType>
+struct DefaultReturnValue;
+
+// Default return values for each basic return type.
+template <angle::EntryPoint EP>
+struct DefaultReturnValue<EP, GLint>
+{
+ static constexpr GLint kValue = -1;
+};
+
+// This doubles as the GLenum return value.
+template <angle::EntryPoint EP>
+struct DefaultReturnValue<EP, GLuint>
+{
+ static constexpr GLuint kValue = 0;
+};
+
+template <angle::EntryPoint EP>
+struct DefaultReturnValue<EP, GLboolean>
+{
+ static constexpr GLboolean kValue = GL_FALSE;
+};
+
+template <angle::EntryPoint EP>
+struct DefaultReturnValue<EP, ShaderProgramID>
+{
+ static constexpr ShaderProgramID kValue = {0};
+};
+
+// Catch-all rules for pointer types.
+template <angle::EntryPoint EP, typename PointerType>
+struct DefaultReturnValue<EP, const PointerType *>
+{
+ static constexpr const PointerType *kValue = nullptr;
+};
+
+template <angle::EntryPoint EP, typename PointerType>
+struct DefaultReturnValue<EP, PointerType *>
+{
+ static constexpr PointerType *kValue = nullptr;
+};
+
+// Overloaded to return invalid index
+template <>
+struct DefaultReturnValue<angle::EntryPoint::GLGetUniformBlockIndex, GLuint>
+{
+ static constexpr GLuint kValue = GL_INVALID_INDEX;
+};
+
+// Specialized enum error value.
+template <>
+struct DefaultReturnValue<angle::EntryPoint::GLClientWaitSync, GLenum>
+{
+ static constexpr GLenum kValue = GL_WAIT_FAILED;
+};
+
+// glTestFenceNV should still return TRUE for an invalid fence.
+template <>
+struct DefaultReturnValue<angle::EntryPoint::GLTestFenceNV, GLboolean>
+{
+ static constexpr GLboolean kValue = GL_TRUE;
+};
+
+template <angle::EntryPoint EP, typename ReturnType>
+constexpr ANGLE_INLINE ReturnType GetDefaultReturnValue()
+{
+ return DefaultReturnValue<EP, ReturnType>::kValue;
+}
+
+#if ANGLE_CAPTURE_ENABLED
+# define ANGLE_CAPTURE_GL(Func, ...) CaptureCallToFrameCapture(Capture##Func, __VA_ARGS__)
+# define ANGLE_CAPTURE_EGL(Func, ...) CaptureCallToCaptureEGL(Capture##Func, __VA_ARGS__)
+#else
+# define ANGLE_CAPTURE_GL(...)
+# define ANGLE_CAPTURE_EGL(...)
+#endif // ANGLE_CAPTURE_ENABLED
+
+#define EGL_EVENT(EP, FMT, ...) EVENT(nullptr, EGL##EP, FMT, ##__VA_ARGS__)
+
+inline int CID(const Context *context)
+{
+ return context == nullptr ? 0 : static_cast<int>(context->id().value);
+}
+} // namespace gl
+
+namespace egl
+{
+inline int CID(EGLDisplay display, EGLContext context)
+{
+ auto *displayPtr = reinterpret_cast<const egl::Display *>(display);
+ if (!Display::isValidDisplay(displayPtr))
+ {
+ return -1;
+ }
+ auto *contextPtr = reinterpret_cast<const gl::Context *>(context);
+ if (!displayPtr->isValidContext(contextPtr))
+ {
+ return -1;
+ }
+ return gl::CID(contextPtr);
+}
+} // namespace egl
+
+#endif // LIBANGLE_ENTRY_POINT_UTILS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/es3_copy_conversion_table_autogen.cpp b/gfx/angle/checkout/src/libANGLE/es3_copy_conversion_table_autogen.cpp
new file mode 100644
index 0000000000..3647445c50
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/es3_copy_conversion_table_autogen.cpp
@@ -0,0 +1,171 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_copy_conversion_table.py using data from es3_copy_conversion_formats.json.
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// format_map:
+// Determining the sized internal format from a (format,type) pair.
+// Also check es3 format combinations for validity.
+
+#include "angle_gl.h"
+#include "common/debug.h"
+
+namespace gl
+{
+
+bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat)
+{
+ switch (textureFormat)
+ {
+ case GL_ALPHA:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_BGRA_EXT:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_LUMINANCE:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ case GL_RED:
+ case GL_RG:
+ case GL_RGB:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RED:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ case GL_RED:
+ case GL_RG:
+ case GL_RGB:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RED_INTEGER:
+ switch (framebufferFormat)
+ {
+ case GL_RED_INTEGER:
+ case GL_RGBA_INTEGER:
+ case GL_RGB_INTEGER:
+ case GL_RG_INTEGER:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RG:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ case GL_RG:
+ case GL_RGB:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGB:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ case GL_RGB:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGBA:
+ switch (framebufferFormat)
+ {
+ case GL_BGRA_EXT:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGBA_INTEGER:
+ switch (framebufferFormat)
+ {
+ case GL_RGBA_INTEGER:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGB_INTEGER:
+ switch (framebufferFormat)
+ {
+ case GL_RGBA_INTEGER:
+ case GL_RGB_INTEGER:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RG_INTEGER:
+ switch (framebufferFormat)
+ {
+ case GL_RGBA_INTEGER:
+ case GL_RGB_INTEGER:
+ case GL_RG_INTEGER:
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/features.h b/gfx/angle/checkout/src/libANGLE/features.h
new file mode 100644
index 0000000000..0a8891e822
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/features.h
@@ -0,0 +1,56 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef LIBANGLE_FEATURES_H_
+#define LIBANGLE_FEATURES_H_
+
+#include "common/platform.h"
+
+#define ANGLE_DISABLED 0
+#define ANGLE_ENABLED 1
+
+// Feature defaults
+
+// Direct3D9EX
+// The "Debug This Pixel..." feature in PIX often fails when using the
+// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7
+// machine, define "ANGLE_D3D9EX=0" in your project file.
+#if !defined(ANGLE_D3D9EX)
+# define ANGLE_D3D9EX ANGLE_ENABLED
+#endif
+
+// Vsync
+// ENABLED allows Vsync to be configured at runtime
+// DISABLED disallows Vsync
+#if !defined(ANGLE_VSYNC)
+# define ANGLE_VSYNC ANGLE_ENABLED
+#endif
+
+// Append HLSL assembly to shader debug info. Defaults to enabled in Debug and off in Release.
+#if !defined(ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO)
+# if !defined(NDEBUG)
+# define ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO ANGLE_ENABLED
+# else
+# define ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO ANGLE_DISABLED
+# endif // !defined(NDEBUG)
+#endif // !defined(ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO)
+
+// Program link validation of precisions for uniforms. This feature was
+// requested by developers to allow non-conformant shaders to be used which
+// contain mismatched precisions.
+// ENABLED validate that precision for uniforms match between vertex and fragment shaders
+// DISABLED allow precision for uniforms to differ between vertex and fragment shaders
+#if !defined(ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION)
+# define ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION ANGLE_ENABLED
+#endif
+
+// Controls if our threading code uses std::async or falls back to single-threaded operations.
+// Note that we can't easily use std::async in UWPs due to UWP threading restrictions.
+#if !defined(ANGLE_STD_ASYNC_WORKERS) && !defined(ANGLE_ENABLE_WINDOWS_UWP)
+# define ANGLE_STD_ASYNC_WORKERS ANGLE_ENABLED
+#endif // !defined(ANGLE_STD_ASYNC_WORKERS) && & !defined(ANGLE_ENABLE_WINDOWS_UWP)
+
+#endif // LIBANGLE_FEATURES_H_
diff --git a/gfx/angle/checkout/src/libANGLE/format_map_autogen.cpp b/gfx/angle/checkout/src/libANGLE/format_map_autogen.cpp
new file mode 100644
index 0000000000..4685bb8931
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/format_map_autogen.cpp
@@ -0,0 +1,1781 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_format_map.py using data from format_map_data.json.
+// ES3 format info from es3_format_type_combinations.json.
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// format_map:
+// Determining the sized internal format from a (format,type) pair.
+// Also check es3 format combinations for validity.
+
+#include "angle_gl.h"
+#include "common/debug.h"
+
+namespace gl
+{
+
+GLenum GetSizedFormatInternal(GLenum format, GLenum type)
+{
+ switch (format)
+ {
+ case GL_ALPHA:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return GL_ALPHA32F_EXT;
+ case GL_HALF_FLOAT:
+ return GL_ALPHA16F_EXT;
+ case GL_HALF_FLOAT_OES:
+ return GL_ALPHA16F_EXT;
+ case GL_UNSIGNED_BYTE:
+ return GL_ALPHA8_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_BGRA8_EXT;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return GL_BGR10_A2_ANGLEX;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ return GL_BGR5_A1_ANGLEX;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ return GL_BGRA4_ANGLEX;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return GL_BGR565_ANGLEX;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RED_GREEN_RGTC2_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RED_RGTC1_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RED_RGTC1_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGBA_BPTC_UNORM_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_SIGNED_RED_RGTC1_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_DEPTH_COMPONENT:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return GL_DEPTH_COMPONENT32F;
+ case GL_UNSIGNED_INT:
+ return GL_DEPTH_COMPONENT32_OES;
+ case GL_UNSIGNED_INT_24_8:
+ return GL_DEPTH24_STENCIL8;
+ case GL_UNSIGNED_SHORT:
+ return GL_DEPTH_COMPONENT16;
+ default:
+ break;
+ }
+ break;
+
+ case GL_DEPTH_STENCIL:
+ switch (type)
+ {
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ return GL_DEPTH32F_STENCIL8;
+ case GL_UNSIGNED_INT_24_8:
+ return GL_DEPTH24_STENCIL8;
+ default:
+ break;
+ }
+ break;
+
+ case GL_LUMINANCE:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return GL_LUMINANCE32F_EXT;
+ case GL_HALF_FLOAT:
+ return GL_LUMINANCE16F_EXT;
+ case GL_HALF_FLOAT_OES:
+ return GL_LUMINANCE16F_EXT;
+ case GL_UNSIGNED_BYTE:
+ return GL_LUMINANCE8_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return GL_LUMINANCE_ALPHA32F_EXT;
+ case GL_HALF_FLOAT:
+ return GL_LUMINANCE_ALPHA16F_EXT;
+ case GL_HALF_FLOAT_OES:
+ return GL_LUMINANCE_ALPHA16F_EXT;
+ case GL_UNSIGNED_BYTE:
+ return GL_LUMINANCE8_ALPHA8_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RED:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_R8_SNORM;
+ case GL_FLOAT:
+ return GL_R32F;
+ case GL_HALF_FLOAT:
+ return GL_R16F;
+ case GL_HALF_FLOAT_OES:
+ return GL_R16F;
+ case GL_SHORT:
+ return GL_R16_SNORM_EXT;
+ case GL_UNSIGNED_BYTE:
+ return GL_R8;
+ case GL_UNSIGNED_SHORT:
+ return GL_R16_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RED_INTEGER:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_R8I;
+ case GL_INT:
+ return GL_R32I;
+ case GL_SHORT:
+ return GL_R16I;
+ case GL_UNSIGNED_BYTE:
+ return GL_R8UI;
+ case GL_UNSIGNED_INT:
+ return GL_R32UI;
+ case GL_UNSIGNED_SHORT:
+ return GL_R16UI;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RG:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_RG8_SNORM;
+ case GL_FLOAT:
+ return GL_RG32F;
+ case GL_HALF_FLOAT:
+ return GL_RG16F;
+ case GL_HALF_FLOAT_OES:
+ return GL_RG16F;
+ case GL_SHORT:
+ return GL_RG16_SNORM_EXT;
+ case GL_UNSIGNED_BYTE:
+ return GL_RG8;
+ case GL_UNSIGNED_SHORT:
+ return GL_RG16_EXT;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGB:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_RGB8_SNORM;
+ case GL_FLOAT:
+ return GL_RGB32F;
+ case GL_HALF_FLOAT:
+ return GL_RGB16F;
+ case GL_HALF_FLOAT_OES:
+ return GL_RGB16F;
+ case GL_SHORT:
+ return GL_RGB16_SNORM_EXT;
+ case GL_UNSIGNED_BYTE:
+ return GL_RGB8;
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ return GL_R11F_G11F_B10F;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return GL_RGB10_UNORM_ANGLEX;
+ case GL_UNSIGNED_INT_5_9_9_9_REV:
+ return GL_RGB9_E5;
+ case GL_UNSIGNED_SHORT:
+ return GL_RGB16_EXT;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return GL_RGB565;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_RGBA8_SNORM;
+ case GL_FLOAT:
+ return GL_RGBA32F;
+ case GL_HALF_FLOAT:
+ return GL_RGBA16F;
+ case GL_HALF_FLOAT_OES:
+ return GL_RGBA16F;
+ case GL_SHORT:
+ return GL_RGBA16_SNORM_EXT;
+ case GL_UNSIGNED_BYTE:
+ return GL_RGBA8;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return GL_RGB10_A2;
+ case GL_UNSIGNED_SHORT:
+ return GL_RGBA16_EXT;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ return GL_RGBA4;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ return GL_RGB5_A1;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGBA_INTEGER:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_RGBA8I;
+ case GL_INT:
+ return GL_RGBA32I;
+ case GL_SHORT:
+ return GL_RGBA16I;
+ case GL_UNSIGNED_BYTE:
+ return GL_RGBA8UI;
+ case GL_UNSIGNED_INT:
+ return GL_RGBA32UI;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return GL_RGB10_A2UI;
+ case GL_UNSIGNED_SHORT:
+ return GL_RGBA16UI;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGB_INTEGER:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_RGB8I;
+ case GL_INT:
+ return GL_RGB32I;
+ case GL_SHORT:
+ return GL_RGB16I;
+ case GL_UNSIGNED_BYTE:
+ return GL_RGB8UI;
+ case GL_UNSIGNED_INT:
+ return GL_RGB32UI;
+ case GL_UNSIGNED_SHORT:
+ return GL_RGB16UI;
+ default:
+ break;
+ }
+ break;
+
+ case GL_RG_INTEGER:
+ switch (type)
+ {
+ case GL_BYTE:
+ return GL_RG8I;
+ case GL_INT:
+ return GL_RG32I;
+ case GL_SHORT:
+ return GL_RG16I;
+ case GL_UNSIGNED_BYTE:
+ return GL_RG8UI;
+ case GL_UNSIGNED_INT:
+ return GL_RG32UI;
+ case GL_UNSIGNED_SHORT:
+ return GL_RG16UI;
+ default:
+ break;
+ }
+ break;
+
+ case GL_SRGB_ALPHA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_SRGB8_ALPHA8;
+ default:
+ break;
+ }
+ break;
+
+ case GL_SRGB_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_SRGB8;
+ default:
+ break;
+ }
+ break;
+
+ case GL_STENCIL:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_STENCIL_INDEX8;
+ default:
+ break;
+ }
+ break;
+
+ case GL_STENCIL_INDEX_OES:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return GL_STENCIL_INDEX8;
+ default:
+ break;
+ }
+ break;
+
+ case GL_NONE:
+ return GL_NONE;
+
+ default:
+ break;
+ }
+
+ return GL_NONE;
+}
+
+bool ValidES3Format(GLenum format)
+{
+ switch (format)
+ {
+ case GL_ALPHA:
+ case GL_BGRA_EXT:
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RED:
+ case GL_RED_INTEGER:
+ case GL_RG:
+ case GL_RGB:
+ case GL_RGBA:
+ case GL_RGBA_INTEGER:
+ case GL_RGB_INTEGER:
+ case GL_RG_INTEGER:
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB_EXT:
+ case GL_STENCIL_INDEX:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidES3Type(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ case GL_FLOAT:
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ case GL_HALF_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ case GL_INT:
+ case GL_SHORT:
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_INT:
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL_UNSIGNED_INT_24_8:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_5_9_9_9_REV:
+ case GL_UNSIGNED_SHORT:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat)
+{
+ ASSERT(ValidES3Format(format) && ValidES3Type(type));
+
+ switch (format)
+ {
+ case GL_ALPHA:
+ switch (type)
+ {
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ case GL_ALPHA32F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ case GL_ALPHA16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ case GL_ALPHA16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ case GL_ALPHA8_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_BGRA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_BGRA_EXT:
+ case GL_BGRA8_EXT:
+ case GL_BGRA4_ANGLEX:
+ case GL_BGR5_A1_ANGLEX:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ {
+ switch (internalFormat)
+ {
+ case GL_BGR5_A1_ANGLEX:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ {
+ switch (internalFormat)
+ {
+ case GL_BGRA4_ANGLEX:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_DEPTH_COMPONENT:
+ switch (type)
+ {
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT32F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT_24_8:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT32_OES:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_DEPTH_STENCIL:
+ switch (type)
+ {
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH32F_STENCIL8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT_24_8:
+ {
+ switch (internalFormat)
+ {
+ case GL_DEPTH_STENCIL:
+ case GL_DEPTH24_STENCIL8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_LUMINANCE:
+ switch (type)
+ {
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE:
+ case GL_LUMINANCE32F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE:
+ case GL_LUMINANCE16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE:
+ case GL_LUMINANCE16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE:
+ case GL_LUMINANCE8_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ switch (type)
+ {
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE8_ALPHA8_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RED:
+ switch (type)
+ {
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_R8_SNORM:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R32F:
+ case GL_R16F:
+ case GL_RED:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R16F:
+ case GL_RED:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_R16F:
+ case GL_RED:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R16_SNORM_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_R8:
+ case GL_RED:
+ case GL_SR8_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R16_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RED_INTEGER:
+ switch (type)
+ {
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_R8I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R32I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R16I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_R8UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R32UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_R16UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RG:
+ switch (type)
+ {
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG8_SNORM:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG32F:
+ case GL_RG16F:
+ case GL_RG:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG16F:
+ case GL_RG:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG16F:
+ case GL_RG:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG16_SNORM_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG8:
+ case GL_RG:
+ case GL_SRG8_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG16_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGB:
+ switch (type)
+ {
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB8_SNORM:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB32F:
+ case GL_RGB16F:
+ case GL_R11F_G11F_B10F:
+ case GL_RGB9_E5:
+ case GL_RGB:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB16F:
+ case GL_R11F_G11F_B10F:
+ case GL_RGB9_E5:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB16F:
+ case GL_R11F_G11F_B10F:
+ case GL_RGB9_E5:
+ case GL_RGB:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB16_SNORM_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB8:
+ case GL_RGB565:
+ case GL_SRGB8:
+ case GL_RGB:
+ case GL_RGBX8_ANGLE:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ {
+ switch (internalFormat)
+ {
+ case GL_R11F_G11F_B10F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT_5_9_9_9_REV:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB9_E5:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB16_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT_5_6_5:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB565:
+ case GL_RGB:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA8_SNORM:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA32F:
+ case GL_RGBA16F:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA16F:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_HALF_FLOAT_OES:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA16F:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA16_SNORM_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA8:
+ case GL_RGB5_A1:
+ case GL_RGBA4:
+ case GL_SRGB8_ALPHA8:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB10_A2:
+ case GL_RGB5_A1:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA16_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA4:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB5_A1:
+ case GL_RGBA:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGBA_INTEGER:
+ switch (type)
+ {
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA8I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA32I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA16I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA8UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA32UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB10_A2UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGBA16UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RGB_INTEGER:
+ switch (type)
+ {
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB8I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB32I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB16I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB8UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB32UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RGB16UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_RG_INTEGER:
+ switch (type)
+ {
+ case GL_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG8I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG32I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG16I:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG8UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG32UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ switch (internalFormat)
+ {
+ case GL_RG16UI:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_SRGB_ALPHA_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB8_ALPHA8_EXT:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_SRGB_EXT:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_SRGB_EXT:
+ case GL_SRGB8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ case GL_STENCIL_INDEX:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ {
+ switch (internalFormat)
+ {
+ case GL_STENCIL_INDEX8:
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return false;
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/format_map_desktop.cpp b/gfx/angle/checkout/src/libANGLE/format_map_desktop.cpp
new file mode 100644
index 0000000000..17122af6a7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/format_map_desktop.cpp
@@ -0,0 +1,128 @@
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// format_map_desktop:
+// Determining the sized internal format from a (format,type) pair.
+// Also check DesktopGL format combinations for validity.
+
+#include "angle_gl.h"
+#include "common/debug.h"
+#include "formatutils.h"
+#include "renderer/gl/functionsgl_enums.h"
+
+// TODO(http://anglebug.com/3730): switch ANGLE to generate its own GL enum types from gl.xml
+
+namespace gl
+{
+
+bool ValidDesktopFormat(GLenum format)
+{
+ switch (format)
+ {
+ case GL_STENCIL_INDEX:
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL:
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_RG:
+ case GL_RGB:
+ case GL_RGBA:
+ case GL_BGR:
+ case GL_BGRA:
+ case GL_RED_INTEGER:
+ case GL_GREEN_INTEGER:
+ case GL_BLUE_INTEGER:
+ case GL_RG_INTEGER:
+ case GL_RGB_INTEGER:
+ case GL_RGBA_INTEGER:
+ case GL_BGR_INTEGER:
+ case GL_BGRA_INTEGER:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidDesktopType(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_BYTE:
+ case GL_UNSIGNED_SHORT:
+ case GL_SHORT:
+ case GL_UNSIGNED_INT:
+ case GL_INT:
+ case GL_HALF_FLOAT:
+ case GL_FLOAT:
+ case GL_UNSIGNED_BYTE_3_3_2:
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ case GL_UNSIGNED_INT_10_10_10_2:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_24_8:
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL_UNSIGNED_INT_5_9_9_9_REV:
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+// From OpenGL 4.6 spec section 8.4
+bool ValidDesktopFormatCombination(GLenum format, GLenum type, GLenum internalFormat)
+{
+ ASSERT(ValidDesktopFormat(format) && ValidDesktopType(type));
+ const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
+ const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
+
+ switch (format)
+ {
+ case GL_RED_INTEGER:
+ case GL_GREEN_INTEGER:
+ case GL_BLUE_INTEGER:
+ case GL_RG_INTEGER:
+ case GL_RGB_INTEGER:
+ case GL_RGBA_INTEGER:
+ case GL_BGR_INTEGER:
+ case GL_BGRA_INTEGER:
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ case GL_FLOAT:
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL_UNSIGNED_INT_5_9_9_9_REV:
+ return false;
+ default:
+ break;
+ }
+ if (!internalFormatInfo.isInt())
+ return false;
+ break;
+ default:
+ // format is not an integer
+ if (internalFormatInfo.isInt())
+ return false;
+
+ if (formatInfo.isDepthOrStencil() != internalFormatInfo.isDepthOrStencil())
+ return false;
+
+ if (format == GL_STENCIL_INDEX && internalFormat != GL_STENCIL_INDEX)
+ return false;
+ break;
+ }
+
+ return true;
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/formatutils.cpp b/gfx/angle/checkout/src/libANGLE/formatutils.cpp
new file mode 100644
index 0000000000..76273f3be3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/formatutils.cpp
@@ -0,0 +1,3220 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// formatutils.cpp: Queries for GL image formats.
+
+#include "libANGLE/formatutils.h"
+
+#include "anglebase/no_destructor.h"
+#include "common/mathutil.h"
+#include "gpu_info_util/SystemInfo.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+
+using namespace angle;
+
+namespace gl
+{
+
+// ES2 requires that format is equal to internal format at all glTex*Image2D entry points and the
+// implementation can decide the true, sized, internal format. The ES2FormatMap determines the
+// internal format for all valid format and type combinations.
+GLenum GetSizedFormatInternal(GLenum format, GLenum type);
+
+namespace
+{
+bool CheckedMathResult(const CheckedNumeric<GLuint> &value, GLuint *resultOut)
+{
+ if (!value.IsValid())
+ {
+ return false;
+ }
+ else
+ {
+ *resultOut = value.ValueOrDie();
+ return true;
+ }
+}
+
+constexpr uint32_t PackTypeInfo(GLuint bytes, bool specialized)
+{
+ // static_assert within constexpr requires c++17
+ // static_assert(isPow2(bytes));
+ return bytes | (rx::Log2(bytes) << 8) | (specialized << 16);
+}
+
+} // anonymous namespace
+
+FormatType::FormatType() : format(GL_NONE), type(GL_NONE) {}
+
+FormatType::FormatType(GLenum format_, GLenum type_) : format(format_), type(type_) {}
+
+bool FormatType::operator<(const FormatType &other) const
+{
+ if (format != other.format)
+ return format < other.format;
+ return type < other.type;
+}
+
+bool operator<(const Type &a, const Type &b)
+{
+ return memcmp(&a, &b, sizeof(Type)) < 0;
+}
+
+// Information about internal formats
+static bool AlwaysSupported(const Version &, const Extensions &)
+{
+ return true;
+}
+
+static bool NeverSupported(const Version &, const Extensions &)
+{
+ return false;
+}
+
+static bool RequireES1(const Version &clientVersion, const Extensions &extensions)
+{
+ return clientVersion.major == 1;
+}
+
+template <GLuint minCoreGLMajorVersion, GLuint minCoreGLMinorVersion>
+static bool RequireES(const Version &clientVersion, const Extensions &)
+{
+ return clientVersion >= Version(minCoreGLMajorVersion, minCoreGLMinorVersion);
+}
+
+// Check support for a single extension
+template <ExtensionBool bool1>
+static bool RequireExt(const Version &, const Extensions &extensions)
+{
+ return extensions.*bool1;
+}
+
+// Check for a minimum client version or a single extension
+template <GLuint minCoreGLMajorVersion, GLuint minCoreGLMinorVersion, ExtensionBool bool1>
+static bool RequireESOrExt(const Version &clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= Version(minCoreGLMajorVersion, minCoreGLMinorVersion) ||
+ extensions.*bool1;
+}
+
+// Check for a minimum client version or two extensions
+template <GLuint minCoreGLMajorVersion,
+ GLuint minCoreGLMinorVersion,
+ ExtensionBool bool1,
+ ExtensionBool bool2>
+static bool RequireESOrExtAndExt(const Version &clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= Version(minCoreGLMajorVersion, minCoreGLMinorVersion) ||
+ (extensions.*bool1 && extensions.*bool2);
+}
+
+// Check for a minimum client version or at least one of two extensions
+template <GLuint minCoreGLMajorVersion,
+ GLuint minCoreGLMinorVersion,
+ ExtensionBool bool1,
+ ExtensionBool bool2>
+static bool RequireESOrExtOrExt(const Version &clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= Version(minCoreGLMajorVersion, minCoreGLMinorVersion) ||
+ extensions.*bool1 || extensions.*bool2;
+}
+
+// Check support for two extensions
+template <ExtensionBool bool1, ExtensionBool bool2>
+static bool RequireExtAndExt(const Version &, const Extensions &extensions)
+{
+ return extensions.*bool1 && extensions.*bool2;
+}
+
+// Check support for either of two extensions
+template <ExtensionBool bool1, ExtensionBool bool2>
+static bool RequireExtOrExt(const Version &, const Extensions &extensions)
+{
+ return extensions.*bool1 || extensions.*bool2;
+}
+
+// Check support for any of three extensions
+template <ExtensionBool bool1, ExtensionBool bool2, ExtensionBool bool3>
+static bool RequireExtOrExtOrExt(const Version &, const Extensions &extensions)
+{
+ return extensions.*bool1 || extensions.*bool2 || extensions.*bool3;
+}
+
+// R8, RG8
+static bool SizedRGSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= Version(3, 0) ||
+ (extensions.textureStorageEXT && extensions.textureRgEXT);
+}
+
+// R16F, RG16F with HALF_FLOAT_OES type
+static bool SizedHalfFloatOESRGSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ return extensions.textureStorageEXT && extensions.textureHalfFloatOES &&
+ extensions.textureRgEXT;
+}
+
+static bool SizedHalfFloatOESRGTextureAttachmentSupport(const Version &clientVersion,
+ const Extensions &extensions)
+{
+ return SizedHalfFloatOESRGSupport(clientVersion, extensions) &&
+ extensions.colorBufferHalfFloatEXT;
+}
+
+// R16F, RG16F with either HALF_FLOAT_OES or HALF_FLOAT types
+static bool SizedHalfFloatRGSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ // HALF_FLOAT
+ if (clientVersion >= Version(3, 0))
+ {
+ return true;
+ }
+ // HALF_FLOAT_OES
+ else
+ {
+ return SizedHalfFloatOESRGSupport(clientVersion, extensions);
+ }
+}
+
+static bool SizedHalfFloatRGTextureAttachmentSupport(const Version &clientVersion,
+ const Extensions &extensions)
+{
+ // HALF_FLOAT
+ if (clientVersion >= Version(3, 0))
+ {
+ // WebGL 2 supports EXT_color_buffer_half_float.
+ return extensions.colorBufferFloatEXT ||
+ (extensions.webglCompatibilityANGLE && extensions.colorBufferHalfFloatEXT);
+ }
+ // HALF_FLOAT_OES
+ else
+ {
+ return SizedHalfFloatOESRGTextureAttachmentSupport(clientVersion, extensions);
+ }
+}
+
+static bool SizedHalfFloatRGRenderbufferSupport(const Version &clientVersion,
+ const Extensions &extensions)
+{
+ return (clientVersion >= Version(3, 0) ||
+ (extensions.textureHalfFloatOES && extensions.textureRgEXT)) &&
+ (extensions.colorBufferFloatEXT || extensions.colorBufferHalfFloatEXT);
+}
+
+// RGB16F, RGBA16F with HALF_FLOAT_OES type
+static bool SizedHalfFloatOESSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ return extensions.textureStorageEXT && extensions.textureHalfFloatOES;
+}
+
+static bool SizedHalfFloatOESTextureAttachmentSupport(const Version &clientVersion,
+ const Extensions &extensions)
+{
+ return SizedHalfFloatOESSupport(clientVersion, extensions) &&
+ extensions.colorBufferHalfFloatEXT;
+}
+
+// RGB16F, RGBA16F with either HALF_FLOAT_OES or HALF_FLOAT types
+static bool SizedHalfFloatSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ // HALF_FLOAT
+ if (clientVersion >= Version(3, 0))
+ {
+ return true;
+ }
+ // HALF_FLOAT_OES
+ else
+ {
+ return SizedHalfFloatOESSupport(clientVersion, extensions);
+ }
+}
+
+static bool SizedHalfFloatFilterSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ // HALF_FLOAT
+ if (clientVersion >= Version(3, 0))
+ {
+ return true;
+ }
+ // HALF_FLOAT_OES
+ else
+ {
+ return extensions.textureHalfFloatLinearOES;
+ }
+}
+
+static bool SizedHalfFloatRGBTextureAttachmentSupport(const Version &clientVersion,
+ const Extensions &extensions)
+{
+ // HALF_FLOAT
+ if (clientVersion >= Version(3, 0))
+ {
+ // It is unclear how EXT_color_buffer_half_float applies to ES3.0 and above, however,
+ // dEQP GLES3 es3fFboColorbufferTests.cpp verifies that texture attachment of GL_RGB16F
+ // is possible, so assume that all GLES implementations support it.
+ // The WebGL version of the extension explicitly forbids RGB formats.
+ return extensions.colorBufferHalfFloatEXT && !extensions.webglCompatibilityANGLE;
+ }
+ // HALF_FLOAT_OES
+ else
+ {
+ return SizedHalfFloatOESTextureAttachmentSupport(clientVersion, extensions);
+ }
+}
+
+static bool SizedHalfFloatRGBRenderbufferSupport(const Version &clientVersion,
+ const Extensions &extensions)
+{
+ return !extensions.webglCompatibilityANGLE &&
+ ((clientVersion >= Version(3, 0) || extensions.textureHalfFloatOES) &&
+ extensions.colorBufferHalfFloatEXT);
+}
+
+static bool SizedHalfFloatRGBATextureAttachmentSupport(const Version &clientVersion,
+ const Extensions &extensions)
+{
+ // HALF_FLOAT
+ if (clientVersion >= Version(3, 0))
+ {
+ // WebGL 2 supports EXT_color_buffer_half_float.
+ return extensions.colorBufferFloatEXT ||
+ (extensions.webglCompatibilityANGLE && extensions.colorBufferHalfFloatEXT);
+ }
+ // HALF_FLOAT_OES
+ else
+ {
+ return SizedHalfFloatOESTextureAttachmentSupport(clientVersion, extensions);
+ }
+}
+
+static bool SizedHalfFloatRGBARenderbufferSupport(const Version &clientVersion,
+ const Extensions &extensions)
+{
+ return (clientVersion >= Version(3, 0) || extensions.textureHalfFloatOES) &&
+ (extensions.colorBufferFloatEXT || extensions.colorBufferHalfFloatEXT);
+}
+
+// R32F, RG32F
+static bool SizedFloatRGSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= Version(3, 0) ||
+ (extensions.textureStorageEXT && extensions.textureFloatOES && extensions.textureRgEXT);
+}
+
+// RGB32F
+static bool SizedFloatRGBSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= Version(3, 0) ||
+ (extensions.textureStorageEXT && extensions.textureFloatOES) ||
+ extensions.colorBufferFloatRgbCHROMIUM;
+}
+
+// RGBA32F
+static bool SizedFloatRGBASupport(const Version &clientVersion, const Extensions &extensions)
+{
+ return clientVersion >= Version(3, 0) ||
+ (extensions.textureStorageEXT && extensions.textureFloatOES) ||
+ extensions.colorBufferFloatRgbaCHROMIUM;
+}
+
+static bool SizedFloatRGBARenderableSupport(const Version &clientVersion,
+ const Extensions &extensions)
+{
+ // This logic is the same for both Renderbuffers and TextureAttachment.
+ return extensions.colorBufferFloatRgbaCHROMIUM || // ES2
+ extensions.colorBufferFloatEXT; // ES3
+}
+
+static bool Float32BlendableSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ // EXT_float_blend may be exposed on ES2 client contexts. Ensure that RGBA32F is renderable.
+ return (extensions.colorBufferFloatRgbaCHROMIUM || extensions.colorBufferFloatEXT) &&
+ extensions.floatBlendEXT;
+}
+
+template <ExtensionBool bool1>
+static bool ETC2EACSupport(const Version &clientVersion, const Extensions &extensions)
+{
+ if (extensions.compressedTextureEtcANGLE)
+ {
+ return true;
+ }
+
+ // ETC2/EAC formats are always available in ES 3.0+ but require an extension (checked above)
+ // in WebGL. If that extension is not available, hide these formats from WebGL contexts.
+ return !extensions.webglCompatibilityANGLE &&
+ (clientVersion >= Version(3, 0) || extensions.*bool1);
+}
+
+InternalFormat::InternalFormat()
+ : internalFormat(GL_NONE),
+ sized(false),
+ sizedInternalFormat(GL_NONE),
+ redBits(0),
+ greenBits(0),
+ blueBits(0),
+ luminanceBits(0),
+ alphaBits(0),
+ sharedBits(0),
+ depthBits(0),
+ stencilBits(0),
+ pixelBytes(0),
+ componentCount(0),
+ compressed(false),
+ compressedBlockWidth(0),
+ compressedBlockHeight(0),
+ compressedBlockDepth(0),
+ paletted(false),
+ paletteBits(0),
+ format(GL_NONE),
+ type(GL_NONE),
+ componentType(GL_NONE),
+ colorEncoding(GL_NONE),
+ textureSupport(NeverSupported),
+ filterSupport(NeverSupported),
+ textureAttachmentSupport(NeverSupported),
+ renderbufferSupport(NeverSupported),
+ blendSupport(NeverSupported)
+{}
+
+InternalFormat::InternalFormat(const InternalFormat &other) = default;
+
+InternalFormat &InternalFormat::operator=(const InternalFormat &other) = default;
+
+bool InternalFormat::isLUMA() const
+{
+ return ((redBits + greenBits + blueBits + depthBits + stencilBits) == 0 &&
+ (luminanceBits + alphaBits) > 0);
+}
+
+GLenum InternalFormat::getReadPixelsFormat(const Extensions &extensions) const
+{
+ switch (format)
+ {
+ case GL_BGRA_EXT:
+ // BGRA textures may be enabled but calling glReadPixels with BGRA is disallowed without
+ // GL_EXT_texture_format_BGRA8888. Read as RGBA instead.
+ if (!extensions.readFormatBgraEXT)
+ {
+ return GL_RGBA;
+ }
+ return GL_BGRA_EXT;
+
+ default:
+ return format;
+ }
+}
+
+GLenum InternalFormat::getReadPixelsType(const Version &version) const
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ if (version < Version(3, 0))
+ {
+ // The internal format may have a type of GL_HALF_FLOAT but when exposing this type
+ // as the IMPLEMENTATION_READ_TYPE, only HALF_FLOAT_OES is allowed by
+ // OES_texture_half_float. HALF_FLOAT becomes core in ES3 and is acceptable to use
+ // as an IMPLEMENTATION_READ_TYPE.
+ return GL_HALF_FLOAT_OES;
+ }
+ return GL_HALF_FLOAT;
+
+ default:
+ return type;
+ }
+}
+
+bool InternalFormat::supportSubImage() const
+{
+ return !CompressedFormatRequiresWholeImage(internalFormat);
+}
+
+bool InternalFormat::isRequiredRenderbufferFormat(const Version &version) const
+{
+ // GLES 3.0.5 section 4.4.2.2:
+ // "Implementations are required to support the same internal formats for renderbuffers as the
+ // required formats for textures enumerated in section 3.8.3.1, with the exception of the color
+ // formats labelled "texture-only"."
+ if (!sized || compressed)
+ {
+ return false;
+ }
+
+ // Luma formats.
+ if (isLUMA())
+ {
+ return false;
+ }
+
+ // Depth/stencil formats.
+ if (depthBits > 0 || stencilBits > 0)
+ {
+ // GLES 2.0.25 table 4.5.
+ // GLES 3.0.5 section 3.8.3.1.
+ // GLES 3.1 table 8.14.
+
+ // Required formats in all versions.
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT16:
+ case GL_STENCIL_INDEX8:
+ // Note that STENCIL_INDEX8 is not mentioned in GLES 3.0.5 section 3.8.3.1, but it
+ // is in section 4.4.2.2.
+ return true;
+ default:
+ break;
+ }
+ if (version.major < 3)
+ {
+ return false;
+ }
+ // Required formats in GLES 3.0 and up.
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT32F:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH32F_STENCIL8:
+ case GL_DEPTH24_STENCIL8:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ // RGBA formats.
+ // GLES 2.0.25 table 4.5.
+ // GLES 3.0.5 section 3.8.3.1.
+ // GLES 3.1 table 8.13.
+
+ // Required formats in all versions.
+ switch (internalFormat)
+ {
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGB565:
+ return true;
+ default:
+ break;
+ }
+ if (version.major < 3)
+ {
+ return false;
+ }
+
+ if (format == GL_BGRA_EXT)
+ {
+ return false;
+ }
+
+ switch (componentType)
+ {
+ case GL_SIGNED_NORMALIZED:
+ case GL_FLOAT:
+ return false;
+ case GL_UNSIGNED_INT:
+ case GL_INT:
+ // Integer RGB formats are not required renderbuffer formats.
+ if (alphaBits == 0 && blueBits != 0)
+ {
+ return false;
+ }
+ // All integer R and RG formats are required.
+ // Integer RGBA formats including RGB10_A2_UI are required.
+ return true;
+ case GL_UNSIGNED_NORMALIZED:
+ if (internalFormat == GL_SRGB8)
+ {
+ return false;
+ }
+ return true;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool InternalFormat::isInt() const
+{
+ return componentType == GL_INT || componentType == GL_UNSIGNED_INT;
+}
+
+bool InternalFormat::isDepthOrStencil() const
+{
+ return depthBits != 0 || stencilBits != 0;
+}
+
+Format::Format(GLenum internalFormat) : Format(GetSizedInternalFormatInfo(internalFormat)) {}
+
+Format::Format(const InternalFormat &internalFormat) : info(&internalFormat) {}
+
+Format::Format(GLenum internalFormat, GLenum type)
+ : info(&GetInternalFormatInfo(internalFormat, type))
+{}
+
+Format::Format(const Format &other) = default;
+Format &Format::operator=(const Format &other) = default;
+
+bool Format::valid() const
+{
+ return info->internalFormat != GL_NONE;
+}
+
+// static
+bool Format::SameSized(const Format &a, const Format &b)
+{
+ return a.info->sizedInternalFormat == b.info->sizedInternalFormat;
+}
+
+static GLenum EquivalentBlitInternalFormat(GLenum internalformat)
+{
+ // BlitFramebuffer works if the color channels are identically
+ // sized, even if there is a swizzle (for example, blitting from a
+ // multisampled RGBA8 renderbuffer to a BGRA8 texture). This could
+ // be expanded and/or autogenerated if that is found necessary.
+ if (internalformat == GL_BGRA8_EXT)
+ {
+ return GL_RGBA8;
+ }
+
+ // GL_ANGLE_rgbx_internal_format: Treat RGBX8 as RGB8, since the X channel is ignored.
+ if (internalformat == GL_RGBX8_ANGLE)
+ {
+ return GL_RGB8;
+ }
+
+ // Treat ANGLE's BGRX8 as RGB8 since it's swizzled and the X channel is ignored.
+ if (internalformat == GL_BGRX8_ANGLEX)
+ {
+ return GL_RGB8;
+ }
+
+ return internalformat;
+}
+
+// static
+bool Format::EquivalentForBlit(const Format &a, const Format &b)
+{
+ return (EquivalentBlitInternalFormat(a.info->sizedInternalFormat) ==
+ EquivalentBlitInternalFormat(b.info->sizedInternalFormat));
+}
+
+// static
+Format Format::Invalid()
+{
+ static Format invalid(GL_NONE, GL_NONE);
+ return invalid;
+}
+
+std::ostream &operator<<(std::ostream &os, const Format &fmt)
+{
+ // TODO(ynovikov): return string representation when available
+ return FmtHex(os, fmt.info->sizedInternalFormat);
+}
+
+bool InternalFormat::operator==(const InternalFormat &other) const
+{
+ // We assume all internal formats are unique if they have the same internal format and type
+ return internalFormat == other.internalFormat && type == other.type;
+}
+
+bool InternalFormat::operator!=(const InternalFormat &other) const
+{
+ return !(*this == other);
+}
+
+void InsertFormatInfo(InternalFormatInfoMap *map, const InternalFormat &formatInfo)
+{
+ ASSERT(!formatInfo.sized || (*map).count(formatInfo.internalFormat) == 0);
+ ASSERT((*map)[formatInfo.internalFormat].count(formatInfo.type) == 0);
+ (*map)[formatInfo.internalFormat][formatInfo.type] = formatInfo;
+}
+
+// YuvFormatInfo implementation
+YuvFormatInfo::YuvFormatInfo(GLenum internalFormat, const Extents &yPlaneExtent)
+{
+ ASSERT(gl::IsYuvFormat(internalFormat));
+ ASSERT((gl::GetPlaneCount(internalFormat) > 0) && (gl::GetPlaneCount(internalFormat) <= 3));
+
+ glInternalFormat = internalFormat;
+ planeCount = gl::GetPlaneCount(internalFormat);
+
+ // Chroma planes of a YUV format can be subsampled
+ int horizontalSubsampleFactor = 0;
+ int verticalSubsampleFactor = 0;
+ gl::GetSubSampleFactor(internalFormat, &horizontalSubsampleFactor, &verticalSubsampleFactor);
+
+ // Compute plane Bpp
+ planeBpp[0] = gl::GetYPlaneBpp(internalFormat);
+ planeBpp[1] = gl::GetChromaPlaneBpp(internalFormat);
+ planeBpp[2] = (planeCount > 2) ? planeBpp[1] : 0;
+
+ // Compute plane extent
+ planeExtent[0] = yPlaneExtent;
+ planeExtent[1] = {(yPlaneExtent.width / horizontalSubsampleFactor),
+ (yPlaneExtent.height / verticalSubsampleFactor), yPlaneExtent.depth};
+ planeExtent[2] = (planeCount > 2) ? planeExtent[1] : Extents();
+
+ // Compute plane pitch
+ planePitch[0] = planeExtent[0].width * planeBpp[0];
+ planePitch[1] = planeExtent[1].width * planeBpp[1];
+ planePitch[2] = planeExtent[2].width * planeBpp[2];
+
+ // Compute plane size
+ planeSize[0] = planePitch[0] * planeExtent[0].height;
+ planeSize[1] = planePitch[1] * planeExtent[1].height;
+ planeSize[2] = planePitch[2] * planeExtent[2].height;
+
+ // Compute plane offset
+ planeOffset[0] = 0;
+ planeOffset[1] = planeSize[0];
+ planeOffset[2] = planeSize[0] + planeSize[1];
+}
+
+// YUV format related helpers
+bool IsYuvFormat(GLenum format)
+{
+ switch (format)
+ {
+ case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE:
+ case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE:
+ case GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G16_B16R16_2PLANE_420_UNORM_ANGLE:
+ case GL_G16_B16_R16_3PLANE_420_UNORM_ANGLE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+uint32_t GetPlaneCount(GLenum format)
+{
+ switch (format)
+ {
+ case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE:
+ case GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G16_B16R16_2PLANE_420_UNORM_ANGLE:
+ return 2;
+ case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE:
+ case GL_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G16_B16_R16_3PLANE_420_UNORM_ANGLE:
+ return 3;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+uint32_t GetYPlaneBpp(GLenum format)
+{
+ switch (format)
+ {
+ case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE:
+ case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE:
+ return 1;
+ case GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G16_B16R16_2PLANE_420_UNORM_ANGLE:
+ case GL_G16_B16_R16_3PLANE_420_UNORM_ANGLE:
+ return 2;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+uint32_t GetChromaPlaneBpp(GLenum format)
+{
+ // 2 plane 420 YUV formats have CbCr channels interleaved.
+ // 3 plane 420 YUV formats have separate Cb and Cr planes.
+ switch (format)
+ {
+ case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE:
+ return 1;
+ case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE:
+ case GL_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G16_B16_R16_3PLANE_420_UNORM_ANGLE:
+ return 2;
+ case GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G16_B16R16_2PLANE_420_UNORM_ANGLE:
+ return 4;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+void GetSubSampleFactor(GLenum format, int *horizontalSubsampleFactor, int *verticalSubsampleFactor)
+{
+ ASSERT(horizontalSubsampleFactor && verticalSubsampleFactor);
+
+ switch (format)
+ {
+ case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE:
+ case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE:
+ case GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_ANGLE:
+ case GL_G16_B16R16_2PLANE_420_UNORM_ANGLE:
+ case GL_G16_B16_R16_3PLANE_420_UNORM_ANGLE:
+ *horizontalSubsampleFactor = 2;
+ *verticalSubsampleFactor = 2;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+struct FormatBits
+{
+ constexpr GLuint pixelBytes() const
+ {
+ return (red + green + blue + alpha + shared + unused) / 8;
+ }
+ constexpr GLuint componentCount() const
+ {
+ return ((red > 0) ? 1 : 0) + ((green > 0) ? 1 : 0) + ((blue > 0) ? 1 : 0) +
+ ((alpha > 0) ? 1 : 0);
+ }
+ constexpr bool valid() const
+ {
+ return ((red + green + blue + alpha + shared + unused) % 8) == 0;
+ }
+
+ GLuint red;
+ GLuint green;
+ GLuint blue;
+ GLuint alpha;
+ GLuint unused;
+ GLuint shared;
+};
+
+template <GLuint red, GLuint green, GLuint blue, GLuint alpha, GLuint unused, GLuint shared>
+constexpr FormatBits FB()
+{
+ constexpr FormatBits formatBits = {red, green, blue, alpha, unused, shared};
+ static_assert(formatBits.valid(), "Invalid FormatBits");
+ return formatBits;
+}
+
+void AddRGBAXFormat(InternalFormatInfoMap *map,
+ GLenum internalFormat,
+ bool sized,
+ const FormatBits &formatBits,
+ GLenum format,
+ GLenum type,
+ GLenum componentType,
+ bool srgb,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction filterSupport,
+ InternalFormat::SupportCheckFunction textureAttachmentSupport,
+ InternalFormat::SupportCheckFunction renderbufferSupport,
+ InternalFormat::SupportCheckFunction blendSupport)
+{
+ ASSERT(formatBits.valid());
+
+ InternalFormat formatInfo;
+ formatInfo.internalFormat = internalFormat;
+ formatInfo.sized = sized;
+ formatInfo.sizedInternalFormat =
+ sized ? internalFormat : GetSizedFormatInternal(internalFormat, type);
+ formatInfo.redBits = formatBits.red;
+ formatInfo.greenBits = formatBits.green;
+ formatInfo.blueBits = formatBits.blue;
+ formatInfo.alphaBits = formatBits.alpha;
+ formatInfo.sharedBits = formatBits.shared;
+ formatInfo.pixelBytes = formatBits.pixelBytes();
+ formatInfo.componentCount = formatBits.componentCount();
+ formatInfo.format = format;
+ formatInfo.type = type;
+ formatInfo.componentType = componentType;
+ formatInfo.colorEncoding = (srgb ? GL_SRGB : GL_LINEAR);
+ formatInfo.textureSupport = textureSupport;
+ formatInfo.filterSupport = filterSupport;
+ formatInfo.textureAttachmentSupport = textureAttachmentSupport;
+ formatInfo.renderbufferSupport = renderbufferSupport;
+ formatInfo.blendSupport = blendSupport;
+
+ InsertFormatInfo(map, formatInfo);
+}
+
+void AddRGBAFormat(InternalFormatInfoMap *map,
+ GLenum internalFormat,
+ bool sized,
+ GLuint red,
+ GLuint green,
+ GLuint blue,
+ GLuint alpha,
+ GLuint shared,
+ GLenum format,
+ GLenum type,
+ GLenum componentType,
+ bool srgb,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction filterSupport,
+ InternalFormat::SupportCheckFunction textureAttachmentSupport,
+ InternalFormat::SupportCheckFunction renderbufferSupport,
+ InternalFormat::SupportCheckFunction blendSupport)
+{
+ return AddRGBAXFormat(map, internalFormat, sized, {red, green, blue, alpha, 0, shared}, format,
+ type, componentType, srgb, textureSupport, filterSupport,
+ textureAttachmentSupport, renderbufferSupport, blendSupport);
+}
+
+static void AddLUMAFormat(InternalFormatInfoMap *map,
+ GLenum internalFormat,
+ bool sized,
+ GLuint luminance,
+ GLuint alpha,
+ GLenum format,
+ GLenum type,
+ GLenum componentType,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction filterSupport,
+ InternalFormat::SupportCheckFunction textureAttachmentSupport,
+ InternalFormat::SupportCheckFunction renderbufferSupport,
+ InternalFormat::SupportCheckFunction blendSupport)
+{
+ InternalFormat formatInfo;
+ formatInfo.internalFormat = internalFormat;
+ formatInfo.sized = sized;
+ formatInfo.sizedInternalFormat =
+ sized ? internalFormat : GetSizedFormatInternal(internalFormat, type);
+ formatInfo.luminanceBits = luminance;
+ formatInfo.alphaBits = alpha;
+ formatInfo.pixelBytes = (luminance + alpha) / 8;
+ formatInfo.componentCount = ((luminance > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0);
+ formatInfo.format = format;
+ formatInfo.type = type;
+ formatInfo.componentType = componentType;
+ formatInfo.colorEncoding = GL_LINEAR;
+ formatInfo.textureSupport = textureSupport;
+ formatInfo.filterSupport = filterSupport;
+ formatInfo.textureAttachmentSupport = textureAttachmentSupport;
+ formatInfo.renderbufferSupport = renderbufferSupport;
+ formatInfo.blendSupport = blendSupport;
+
+ InsertFormatInfo(map, formatInfo);
+}
+
+void AddDepthStencilFormat(InternalFormatInfoMap *map,
+ GLenum internalFormat,
+ bool sized,
+ GLuint depthBits,
+ GLuint stencilBits,
+ GLuint unusedBits,
+ GLenum format,
+ GLenum type,
+ GLenum componentType,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction filterSupport,
+ InternalFormat::SupportCheckFunction textureAttachmentSupport,
+ InternalFormat::SupportCheckFunction renderbufferSupport,
+ InternalFormat::SupportCheckFunction blendSupport)
+{
+ InternalFormat formatInfo;
+ formatInfo.internalFormat = internalFormat;
+ formatInfo.sized = sized;
+ formatInfo.sizedInternalFormat =
+ sized ? internalFormat : GetSizedFormatInternal(internalFormat, type);
+ formatInfo.depthBits = depthBits;
+ formatInfo.stencilBits = stencilBits;
+ formatInfo.pixelBytes = (depthBits + stencilBits + unusedBits) / 8;
+ formatInfo.componentCount = ((depthBits > 0) ? 1 : 0) + ((stencilBits > 0) ? 1 : 0);
+ formatInfo.format = format;
+ formatInfo.type = type;
+ formatInfo.componentType = componentType;
+ formatInfo.colorEncoding = GL_LINEAR;
+ formatInfo.textureSupport = textureSupport;
+ formatInfo.filterSupport = filterSupport;
+ formatInfo.textureAttachmentSupport = textureAttachmentSupport;
+ formatInfo.renderbufferSupport = renderbufferSupport;
+ formatInfo.blendSupport = blendSupport;
+
+ InsertFormatInfo(map, formatInfo);
+}
+
+void AddCompressedFormat(InternalFormatInfoMap *map,
+ GLenum internalFormat,
+ GLuint compressedBlockWidth,
+ GLuint compressedBlockHeight,
+ GLuint compressedBlockDepth,
+ GLuint compressedBlockSize,
+ GLuint componentCount,
+ bool srgb,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction filterSupport,
+ InternalFormat::SupportCheckFunction textureAttachmentSupport,
+ InternalFormat::SupportCheckFunction renderbufferSupport,
+ InternalFormat::SupportCheckFunction blendSupport)
+{
+ InternalFormat formatInfo;
+ formatInfo.internalFormat = internalFormat;
+ formatInfo.sized = true;
+ formatInfo.sizedInternalFormat = internalFormat;
+ formatInfo.compressedBlockWidth = compressedBlockWidth;
+ formatInfo.compressedBlockHeight = compressedBlockHeight;
+ formatInfo.compressedBlockDepth = compressedBlockDepth;
+ formatInfo.pixelBytes = compressedBlockSize / 8;
+ formatInfo.componentCount = componentCount;
+ formatInfo.format = internalFormat;
+ formatInfo.type = GL_UNSIGNED_BYTE;
+ formatInfo.componentType = GL_UNSIGNED_NORMALIZED;
+ formatInfo.colorEncoding = (srgb ? GL_SRGB : GL_LINEAR);
+ formatInfo.compressed = true;
+ formatInfo.textureSupport = textureSupport;
+ formatInfo.filterSupport = filterSupport;
+ formatInfo.textureAttachmentSupport = textureAttachmentSupport;
+ formatInfo.renderbufferSupport = renderbufferSupport;
+ formatInfo.blendSupport = blendSupport;
+
+ InsertFormatInfo(map, formatInfo);
+}
+
+void AddPalettedFormat(InternalFormatInfoMap *map,
+ GLenum internalFormat,
+ GLuint paletteBits,
+ GLuint pixelBytes,
+ GLenum format,
+ GLuint componentCount,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction filterSupport,
+ InternalFormat::SupportCheckFunction textureAttachmentSupport,
+ InternalFormat::SupportCheckFunction renderbufferSupport,
+ InternalFormat::SupportCheckFunction blendSupport)
+{
+ InternalFormat formatInfo;
+ formatInfo.internalFormat = internalFormat;
+ formatInfo.sized = true;
+ formatInfo.sizedInternalFormat = internalFormat;
+ formatInfo.paletteBits = paletteBits;
+ formatInfo.pixelBytes = pixelBytes;
+ formatInfo.componentCount = componentCount;
+ formatInfo.format = format;
+ formatInfo.type = GL_UNSIGNED_BYTE;
+ formatInfo.componentType = GL_UNSIGNED_NORMALIZED;
+ formatInfo.colorEncoding = GL_LINEAR;
+ formatInfo.paletted = true;
+ formatInfo.textureSupport = textureSupport;
+ formatInfo.filterSupport = filterSupport;
+ formatInfo.textureAttachmentSupport = textureAttachmentSupport;
+ formatInfo.renderbufferSupport = renderbufferSupport;
+ formatInfo.blendSupport = blendSupport;
+
+ InsertFormatInfo(map, formatInfo);
+}
+
+void AddYUVFormat(InternalFormatInfoMap *map,
+ GLenum internalFormat,
+ bool sized,
+ GLuint cr,
+ GLuint y,
+ GLuint cb,
+ GLuint alpha,
+ GLuint shared,
+ GLenum format,
+ GLenum type,
+ GLenum componentType,
+ bool srgb,
+ InternalFormat::SupportCheckFunction textureSupport,
+ InternalFormat::SupportCheckFunction filterSupport,
+ InternalFormat::SupportCheckFunction textureAttachmentSupport,
+ InternalFormat::SupportCheckFunction renderbufferSupport,
+ InternalFormat::SupportCheckFunction blendSupport)
+{
+ ASSERT(sized);
+
+ InternalFormat formatInfo;
+ formatInfo.internalFormat = internalFormat;
+ formatInfo.sized = sized;
+ formatInfo.sizedInternalFormat = internalFormat;
+ formatInfo.redBits = cr;
+ formatInfo.greenBits = y;
+ formatInfo.blueBits = cb;
+ formatInfo.alphaBits = alpha;
+ formatInfo.sharedBits = shared;
+ formatInfo.pixelBytes = (cr + y + cb + alpha + shared) / 8;
+ formatInfo.componentCount =
+ ((cr > 0) ? 1 : 0) + ((y > 0) ? 1 : 0) + ((cb > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0);
+ formatInfo.format = format;
+ formatInfo.type = type;
+ formatInfo.componentType = componentType;
+ formatInfo.colorEncoding = (srgb ? GL_SRGB : GL_LINEAR);
+ formatInfo.textureSupport = textureSupport;
+ formatInfo.filterSupport = filterSupport;
+ formatInfo.textureAttachmentSupport = textureAttachmentSupport;
+ formatInfo.renderbufferSupport = renderbufferSupport;
+ formatInfo.blendSupport = blendSupport;
+
+ InsertFormatInfo(map, formatInfo);
+}
+
+// Notes:
+// 1. "Texture supported" includes all the means by which texture can be created, however,
+// GL_EXT_texture_storage in ES2 is a special case, when only glTexStorage* is allowed.
+// The assumption is that ES2 validation will not check textureSupport for sized formats.
+//
+// 2. Sized half float types are a combination of GL_HALF_FLOAT and GL_HALF_FLOAT_OES support,
+// due to a limitation that only one type for sized formats is allowed.
+//
+// TODO(ynovikov): http://anglebug.com/2846 Verify support fields of BGRA, depth, stencil
+// and compressed formats. Perform texturable check as part of filterable and attachment checks.
+static InternalFormatInfoMap BuildInternalFormatInfoMap()
+{
+ InternalFormatInfoMap map;
+
+ // From ES 3.0.1 spec, table 3.12
+ map[GL_NONE][GL_NONE] = InternalFormat();
+
+ // clang-format off
+
+ // | Internal format |sized| R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddRGBAFormat(&map, GL_R8, true, 8, 0, 0, 0, 0, GL_RED, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, SizedRGSupport, AlwaysSupported, SizedRGSupport, RequireESOrExt<3, 0, &Extensions::textureRgEXT>, RequireESOrExt<3, 0, &Extensions::textureRgEXT>);
+ AddRGBAFormat(&map, GL_R8_SNORM, true, 8, 0, 0, 0, 0, GL_RED, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3, 0>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG8, true, 8, 8, 0, 0, 0, GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, SizedRGSupport, AlwaysSupported, SizedRGSupport, RequireESOrExt<3, 0, &Extensions::textureRgEXT>, RequireESOrExt<3, 0, &Extensions::textureRgEXT>);
+ AddRGBAFormat(&map, GL_RG8_SNORM, true, 8, 8, 0, 0, 0, GL_RG, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3, 0>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB8, true, 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::textureStorageEXT>, AlwaysSupported, RequireESOrExt<3, 0, &Extensions::textureStorageEXT>, RequireESOrExt<3, 0, &Extensions::rgb8Rgba8OES>, RequireESOrExt<3, 0, &Extensions::rgb8Rgba8OES>);
+ AddRGBAFormat(&map, GL_RGB8_SNORM, true, 8, 8, 8, 0, 0, GL_RGB, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3, 0>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB565, true, 5, 6, 5, 0, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::textureStorageEXT>, AlwaysSupported, RequireESOrExt<3, 0, &Extensions::textureStorageEXT>, RequireES<2, 0>, RequireES<2, 0>);
+ AddRGBAFormat(&map, GL_RGBA4, true, 4, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::textureStorageEXT>, AlwaysSupported, RequireESOrExt<3, 0, &Extensions::textureStorageEXT>, RequireES<2, 0>, RequireES<2, 0>);
+ AddRGBAFormat(&map, GL_RGB5_A1, true, 5, 5, 5, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::textureStorageEXT>, AlwaysSupported, RequireESOrExt<3, 0, &Extensions::textureStorageEXT>, RequireES<2, 0>, RequireES<2, 0>);
+ AddRGBAFormat(&map, GL_RGBA8, true, 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, 0, &Extensions::textureStorageEXT>, AlwaysSupported, RequireESOrExt<3, 0, &Extensions::textureStorageEXT>, RequireESOrExt<3, 0, &Extensions::rgb8Rgba8OES>, RequireESOrExt<3, 0, &Extensions::rgb8Rgba8OES>);
+ AddRGBAFormat(&map, GL_RGBA8_SNORM, true, 8, 8, 8, 8, 0, GL_RGBA, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3, 0>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB10_A2UI, true, 10, 10, 10, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_SRGB8, true, 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireES<3, 0>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_SRGB8_ALPHA8, true, 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESOrExt<3, 0, &Extensions::sRGBEXT>, AlwaysSupported, RequireES<3, 0>, RequireESOrExt<3, 0, &Extensions::sRGBEXT>, RequireESOrExt<3, 0, &Extensions::sRGBEXT>);
+ AddRGBAFormat(&map, GL_R11F_G11F_B10F, true, 11, 11, 10, 0, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT, false, RequireES<3, 0>, AlwaysSupported, RequireExt<&Extensions::colorBufferFloatEXT>, RequireExt<&Extensions::colorBufferFloatEXT>, RequireExt<&Extensions::colorBufferFloatEXT>);
+ AddRGBAFormat(&map, GL_RGB9_E5, true, 9, 9, 9, 0, 5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT, false, RequireES<3, 0>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_R8I, true, 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R8UI, true, 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R16I, true, 16, 0, 0, 0, 0, GL_RED_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R16UI, true, 16, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R32I, true, 32, 0, 0, 0, 0, GL_RED_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_R32UI, true, 32, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG8I, true, 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG8UI, true, 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG16I, true, 16, 16, 0, 0, 0, GL_RG_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG16UI, true, 16, 16, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG32I, true, 32, 32, 0, 0, 0, GL_RG_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RG32UI, true, 32, 32, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB8I, true, 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB8UI, true, 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB16I, true, 16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB16UI, true, 16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB32I, true, 32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB32UI, true, 32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA8I, true, 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA8UI, true, 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA16I, true, 16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA16UI, true, 16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA32I, true, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA32UI, true, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, RequireES<3, 0>, RequireES<3, 0>, NeverSupported);
+
+ AddRGBAFormat(&map, GL_BGRA8_EXT, true, 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888EXT>, AlwaysSupported, RequireExt<&Extensions::textureFormatBGRA8888EXT>, RequireExt<&Extensions::textureFormatBGRA8888EXT>, RequireExt<&Extensions::textureFormatBGRA8888EXT>);
+ AddRGBAFormat(&map, GL_BGRA4_ANGLEX, true, 4, 4, 4, 4, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888EXT>, AlwaysSupported, RequireExt<&Extensions::textureFormatBGRA8888EXT>, RequireExt<&Extensions::textureFormatBGRA8888EXT>, RequireExt<&Extensions::textureFormatBGRA8888EXT>);
+ AddRGBAFormat(&map, GL_BGR5_A1_ANGLEX, true, 5, 5, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888EXT>, AlwaysSupported, RequireExt<&Extensions::textureFormatBGRA8888EXT>, RequireExt<&Extensions::textureFormatBGRA8888EXT>, RequireExt<&Extensions::textureFormatBGRA8888EXT>);
+
+ // Special format that is used for D3D textures that are used within ANGLE via the
+ // EGL_ANGLE_d3d_texture_client_buffer extension. We don't allow uploading texture images with
+ // this format, but textures in this format can be created from D3D textures, and filtering them
+ // and rendering to them is allowed.
+ AddRGBAFormat(&map, GL_BGRA8_SRGB_ANGLEX, true, 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, NeverSupported, AlwaysSupported, AlwaysSupported, AlwaysSupported, AlwaysSupported);
+
+ // Special format which is not really supported, so always false for all supports.
+ AddRGBAFormat(&map, GL_BGR565_ANGLEX, true, 5, 6, 5, 0, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_BGR10_A2_ANGLEX, true, 10, 10, 10, 2, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // Special format to emulate RGB8 with RGBA8 within ANGLE.
+ AddRGBAFormat(&map, GL_RGBX8_ANGLE, true, 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported, AlwaysSupported, NeverSupported);
+
+ // Special format to emulate BGR8 with BGRA8 within ANGLE.
+ AddRGBAFormat(&map, GL_BGRX8_ANGLEX, true, 8, 8, 8, 0, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, NeverSupported, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // This format is supported on ES 2.0 with two extensions, so keep it out-of-line to not widen the table above even more.
+ // | Internal format |sized| R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddRGBAFormat(&map, GL_RGB10_A2, true, 10, 10, 10, 2, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, RequireESOrExtAndExt<3, 0, &Extensions::textureStorageEXT, &Extensions::textureType2101010REVEXT>, AlwaysSupported, RequireES<3, 0>, RequireES<3, 0>, RequireES<3, 0>);
+
+ // Floating point formats
+ // | Internal format |sized| R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ // It's not possible to have two entries per sized format.
+ // E.g. for GL_RG16F, one with GL_HALF_FLOAT type and the other with GL_HALF_FLOAT_OES type.
+ // So, GL_HALF_FLOAT type formats conditions are merged with GL_HALF_FLOAT_OES type conditions.
+ AddRGBAFormat(&map, GL_R16F, true, 16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT, GL_FLOAT, false, SizedHalfFloatRGSupport, SizedHalfFloatFilterSupport, SizedHalfFloatRGTextureAttachmentSupport, SizedHalfFloatRGRenderbufferSupport, SizedHalfFloatRGRenderbufferSupport);
+ AddRGBAFormat(&map, GL_RG16F, true, 16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT, GL_FLOAT, false, SizedHalfFloatRGSupport, SizedHalfFloatFilterSupport, SizedHalfFloatRGTextureAttachmentSupport, SizedHalfFloatRGRenderbufferSupport, SizedHalfFloatRGRenderbufferSupport);
+ AddRGBAFormat(&map, GL_RGB16F, true, 16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT, GL_FLOAT, false, SizedHalfFloatSupport, SizedHalfFloatFilterSupport, SizedHalfFloatRGBTextureAttachmentSupport, SizedHalfFloatRGBRenderbufferSupport, SizedHalfFloatRGBRenderbufferSupport);
+ AddRGBAFormat(&map, GL_RGBA16F, true, 16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT, false, SizedHalfFloatSupport, SizedHalfFloatFilterSupport, SizedHalfFloatRGBATextureAttachmentSupport, SizedHalfFloatRGBARenderbufferSupport, SizedHalfFloatRGBARenderbufferSupport);
+ AddRGBAFormat(&map, GL_R32F, true, 32, 0, 0, 0, 0, GL_RED, GL_FLOAT, GL_FLOAT, false, SizedFloatRGSupport, RequireExt<&Extensions::textureFloatLinearOES>, RequireExt<&Extensions::colorBufferFloatEXT>, RequireExt<&Extensions::colorBufferFloatEXT>, Float32BlendableSupport);
+ AddRGBAFormat(&map, GL_RG32F, true, 32, 32, 0, 0, 0, GL_RG, GL_FLOAT, GL_FLOAT, false, SizedFloatRGSupport, RequireExt<&Extensions::textureFloatLinearOES>, RequireExt<&Extensions::colorBufferFloatEXT>, RequireExt<&Extensions::colorBufferFloatEXT>, Float32BlendableSupport);
+ AddRGBAFormat(&map, GL_RGB32F, true, 32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, SizedFloatRGBSupport, RequireExt<&Extensions::textureFloatLinearOES>, RequireExt<&Extensions::colorBufferFloatRgbCHROMIUM>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA32F, true, 32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, SizedFloatRGBASupport, RequireExt<&Extensions::textureFloatLinearOES>, SizedFloatRGBARenderableSupport, SizedFloatRGBARenderableSupport, Float32BlendableSupport);
+
+ // ANGLE Depth stencil formats
+ // | Internal format |sized| D |S | X | Format | Type | Component type | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT16, true, 16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, RequireESOrExtOrExt<3, 0, &Extensions::depthTextureANGLE, &Extensions::depthTextureOES>, RequireESOrExtOrExt<3, 0, &Extensions::depthTextureANGLE, &Extensions::depthTextureOES>, RequireES<1, 0>, RequireES<1, 0>, RequireES<1, 0>);
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT24, true, 24, 0, 8, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireES<3, 0>, RequireESOrExt<3, 0, &Extensions::depthTextureANGLE>, RequireES<3, 0>, RequireESOrExt<3, 0, &Extensions::depth24OES>, RequireESOrExt<3, 0, &Extensions::depth24OES>);
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT32F, true, 32, 0, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT, RequireES<3, 0>, RequireESOrExt<3, 0, &Extensions::depthTextureANGLE>, RequireES<3, 0>, RequireES<3, 0>, RequireES<3, 0>);
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT32_OES, true, 32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>, AlwaysSupported, RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>, RequireExtOrExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES, &Extensions::depth32OES>, RequireExtOrExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES, &Extensions::depth32OES>);
+ AddDepthStencilFormat(&map, GL_DEPTH24_STENCIL8, true, 24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESOrExtOrExt<3, 0, &Extensions::depthTextureANGLE, &Extensions::packedDepthStencilOES>, AlwaysSupported, RequireESOrExtOrExt<3, 0, &Extensions::depthTextureANGLE, &Extensions::packedDepthStencilOES>, RequireESOrExtOrExt<3, 0, &Extensions::depthTextureANGLE, &Extensions::packedDepthStencilOES>, RequireESOrExtOrExt<3, 0, &Extensions::depthTextureANGLE, &Extensions::packedDepthStencilOES>);
+ AddDepthStencilFormat(&map, GL_DEPTH32F_STENCIL8, true, 32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireESOrExt<3, 0, &Extensions::depthBufferFloat2NV>, AlwaysSupported, RequireESOrExt<3, 0, &Extensions::depthBufferFloat2NV>, RequireESOrExt<3, 0, &Extensions::depthBufferFloat2NV>, RequireESOrExt<3, 0, &Extensions::depthBufferFloat2NV>);
+ // STENCIL_INDEX8 is special-cased, see around the bottom of the list.
+
+ // Luminance alpha formats
+ // | Internal format |sized| L | A | Format | Type | Component type | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddLUMAFormat(&map, GL_ALPHA8_EXT, true, 0, 8, GL_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorageEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_LUMINANCE8_EXT, true, 8, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorageEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_LUMINANCE8_ALPHA8_EXT, true, 8, 8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::textureStorageEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_ALPHA16F_EXT, true, 0, 16, GL_ALPHA, GL_HALF_FLOAT_OES, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorageEXT, &Extensions::textureHalfFloatOES>, RequireExt<&Extensions::textureHalfFloatLinearOES>, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_LUMINANCE16F_EXT, true, 16, 0, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorageEXT, &Extensions::textureHalfFloatOES>, RequireExt<&Extensions::textureHalfFloatLinearOES>, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_LUMINANCE_ALPHA16F_EXT, true, 16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorageEXT, &Extensions::textureHalfFloatOES>, RequireExt<&Extensions::textureHalfFloatLinearOES>, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_ALPHA32F_EXT, true, 0, 32, GL_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorageEXT, &Extensions::textureFloatOES>, RequireExt<&Extensions::textureFloatLinearOES>, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_LUMINANCE32F_EXT, true, 32, 0, GL_LUMINANCE, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorageEXT, &Extensions::textureFloatOES>, RequireExt<&Extensions::textureFloatLinearOES>, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_LUMINANCE_ALPHA32F_EXT, true, 32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtAndExt<&Extensions::textureStorageEXT, &Extensions::textureFloatOES>, RequireExt<&Extensions::textureFloatLinearOES>, NeverSupported, NeverSupported, NeverSupported);
+
+ // Compressed formats, From ES 3.0.1 spec, table 3.16
+ // | Internal format |W |H |D | BS |CC| SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddCompressedFormat(&map, GL_COMPRESSED_R11_EAC, 4, 4, 1, 64, 1, false, ETC2EACSupport<&Extensions::compressedEACR11UnsignedTextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SIGNED_R11_EAC, 4, 4, 1, 64, 1, false, ETC2EACSupport<&Extensions::compressedEACR11SignedTextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RG11_EAC, 4, 4, 1, 128, 2, false, ETC2EACSupport<&Extensions::compressedEACRG11UnsignedTextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SIGNED_RG11_EAC, 4, 4, 1, 128, 2, false, ETC2EACSupport<&Extensions::compressedEACRG11SignedTextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGB8_ETC2, 4, 4, 1, 64, 3, false, ETC2EACSupport<&Extensions::compressedETC2RGB8TextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ETC2, 4, 4, 1, 64, 3, true, ETC2EACSupport<&Extensions::compressedETC2SRGB8TextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 1, 64, 4, false, ETC2EACSupport<&Extensions::compressedETC2PunchthroughARGBA8TextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 4, 4, 1, 64, 4, true, ETC2EACSupport<&Extensions::compressedETC2PunchthroughASRGB8AlphaTextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, 4, 4, 1, 128, 4, false, ETC2EACSupport<&Extensions::compressedETC2RGBA8TextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, 4, 4, 1, 128, 4, true, ETC2EACSupport<&Extensions::compressedETC2SRGB8Alpha8TextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // From GL_EXT_texture_compression_dxt1
+ // | Internal format |W |H |D | BS |CC| SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddCompressedFormat(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 1, 64, 3, false, RequireExt<&Extensions::textureCompressionDxt1EXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 1, 64, 4, false, RequireExt<&Extensions::textureCompressionDxt1EXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // From GL_ANGLE_texture_compression_dxt3
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, 4, 4, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionDxt3ANGLE>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // From GL_ANGLE_texture_compression_dxt5
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, 4, 4, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionDxt5ANGLE>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // From GL_OES_compressed_ETC1_RGB8_texture
+ AddCompressedFormat(&map, GL_ETC1_RGB8_OES, 4, 4, 1, 64, 3, false, RequireExt<&Extensions::compressedETC1RGB8TextureOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // From GL_EXT_texture_compression_s3tc_srgb
+ // | Internal format |W |H |D | BS |CC|SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 4, 4, 1, 64, 3, true, RequireExt<&Extensions::textureCompressionS3tcSrgbEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 4, 4, 1, 64, 4, true, RequireExt<&Extensions::textureCompressionS3tcSrgbEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 4, 4, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionS3tcSrgbEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 4, 4, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionS3tcSrgbEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // From GL_KHR_texture_compression_astc_ldr and KHR_texture_compression_astc_hdr and GL_OES_texture_compression_astc
+ // | Internal format | W | H |D | BS |CC| SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, 4, 4, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, 5, 4, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, 5, 5, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, 6, 5, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, 6, 6, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, 8, 5, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, 8, 6, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, 8, 8, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, 10, 5, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, 10, 6, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, 10, 8, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, 10, 10, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, 12, 10, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, 12, 12, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, 4, 4, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, 5, 4, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, 5, 5, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, 6, 5, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, 6, 6, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, 8, 5, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, 8, 6, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, 8, 8, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, 10, 5, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, 10, 6, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, 10, 8, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, 10, 10, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, 12, 10, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, 12, 12, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcLdrKHR>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_3x3x3_OES, 3, 3, 3, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_4x3x3_OES, 4, 3, 3, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_4x4x3_OES, 4, 4, 3, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_4x4x4_OES, 4, 4, 4, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_5x4x4_OES, 5, 4, 4, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_5x5x4_OES, 5, 5, 4, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_5x5x5_OES, 5, 5, 5, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_6x5x5_OES, 6, 5, 5, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_6x6x5_OES, 6, 6, 5, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_ASTC_6x6x6_OES, 6, 6, 6, 128, 4, false, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES, 3, 3, 3, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES, 4, 3, 3, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES, 4, 4, 3, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES, 4, 4, 4, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES, 5, 4, 4, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES, 5, 5, 4, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES, 5, 5, 5, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES, 6, 5, 5, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES, 6, 6, 5, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES, 6, 6, 6, 128, 4, true, RequireExt<&Extensions::textureCompressionAstcOES>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // From EXT_texture_compression_rgtc
+ // | Internal format | W | H |D | BS |CC| SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddCompressedFormat(&map, GL_COMPRESSED_RED_RGTC1_EXT, 4, 4, 1, 64, 1, false, RequireExt<&Extensions::textureCompressionRgtcEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SIGNED_RED_RGTC1_EXT, 4, 4, 1, 64, 1, false, RequireExt<&Extensions::textureCompressionRgtcEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RED_GREEN_RGTC2_EXT, 4, 4, 1, 128, 2, false, RequireExt<&Extensions::textureCompressionRgtcEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, 4, 4, 1, 128, 2, false, RequireExt<&Extensions::textureCompressionRgtcEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // From EXT_texture_compression_bptc
+ // | Internal format | W | H |D | BS |CC| SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 4, 4, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionBptcEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, 4, 4, 1, 128, 4, true, RequireExt<&Extensions::textureCompressionBptcEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, 4, 4, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionBptcEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, 4, 4, 1, 128, 4, false, RequireExt<&Extensions::textureCompressionBptcEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // Paletted formats
+ // | Internal format | | PS | Format | CC | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddPalettedFormat(&map, GL_PALETTE4_RGB8_OES, 4, 3, GL_RGB, 3, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddPalettedFormat(&map, GL_PALETTE4_RGBA8_OES, 4, 4, GL_RGBA, 4, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddPalettedFormat(&map, GL_PALETTE4_R5_G6_B5_OES, 4, 2, GL_RGB, 3, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddPalettedFormat(&map, GL_PALETTE4_RGBA4_OES, 4, 2, GL_RGBA, 4, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddPalettedFormat(&map, GL_PALETTE4_RGB5_A1_OES, 4, 2, GL_RGBA, 4, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddPalettedFormat(&map, GL_PALETTE8_RGB8_OES, 8, 3, GL_RGB, 3, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddPalettedFormat(&map, GL_PALETTE8_RGBA8_OES, 8, 4, GL_RGBA, 4, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddPalettedFormat(&map, GL_PALETTE8_R5_G6_B5_OES, 8, 2, GL_RGB, 3, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddPalettedFormat(&map, GL_PALETTE8_RGBA4_OES, 8, 2, GL_RGBA, 4, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddPalettedFormat(&map, GL_PALETTE8_RGB5_A1_OES, 8, 2, GL_RGBA, 4, RequireES1, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // From GL_IMG_texture_compression_pvrtc
+ // | Internal format | W | H | D | BS |CC| SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddCompressedFormat(&map, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 4, 4, 1, 64, 3, false, RequireExt<&Extensions::textureCompressionPvrtcIMG>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, 8, 4, 1, 64, 3, false, RequireExt<&Extensions::textureCompressionPvrtcIMG>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, 4, 4, 1, 64, 4, false, RequireExt<&Extensions::textureCompressionPvrtcIMG>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, 8, 4, 1, 64, 4, false, RequireExt<&Extensions::textureCompressionPvrtcIMG>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // From GL_EXT_pvrtc_sRGB
+ // | Internal format | W | H | D | BS |CC| SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT, 8, 4, 1, 64, 3, true, RequireExtAndExt<&Extensions::textureCompressionPvrtcIMG, &Extensions::pvrtcSRGBEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT, 4, 4, 1, 64, 3, true, RequireExtAndExt<&Extensions::textureCompressionPvrtcIMG, &Extensions::pvrtcSRGBEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT, 8, 4, 1, 64, 4, true, RequireExtAndExt<&Extensions::textureCompressionPvrtcIMG, &Extensions::pvrtcSRGBEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT, 4, 4, 1, 64, 4, true, RequireExtAndExt<&Extensions::textureCompressionPvrtcIMG, &Extensions::pvrtcSRGBEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // For STENCIL_INDEX8 we chose a normalized component type for the following reasons:
+ // - Multisampled buffer are disallowed for non-normalized integer component types and we want to support it for STENCIL_INDEX8
+ // - All other stencil formats (all depth-stencil) are either float or normalized
+ // - It affects only validation of internalformat in RenderbufferStorageMultisample.
+ // | Internal format |sized|D |S |X | Format | Type | Component type | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddDepthStencilFormat(&map, GL_STENCIL_INDEX8, true, 0, 8, 0, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireESOrExt<1, 0, &Extensions::textureStencil8OES>, NeverSupported, RequireESOrExt<1, 0, &Extensions::textureStencil8OES>, RequireES<1, 0>, RequireES<1, 0>);
+
+ // From GL_ANGLE_lossy_etc_decode
+ // | Internal format |W |H |D |BS |CC| SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddCompressedFormat(&map, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, 4, 4, 1, 64, 3, false, RequireExt<&Extensions::lossyEtcDecodeANGLE>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, 4, 4, 1, 64, 3, false, RequireExt<&Extensions::lossyEtcDecodeANGLE>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, 4, 4, 1, 64, 3, true, RequireExt<&Extensions::lossyEtcDecodeANGLE>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 4, 4, 1, 64, 3, false, RequireExt<&Extensions::lossyEtcDecodeANGLE>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddCompressedFormat(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, 4, 4, 1, 64, 3, true, RequireExt<&Extensions::lossyEtcDecodeANGLE>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // From GL_EXT_texture_norm16
+ // | Internal format |sized| R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddRGBAFormat(&map, GL_R16_EXT, true, 16, 0, 0, 0, 0, GL_RED, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16EXT>, AlwaysSupported, RequireExt<&Extensions::textureNorm16EXT>, RequireExt<&Extensions::textureNorm16EXT>, RequireExt<&Extensions::textureNorm16EXT>);
+ AddRGBAFormat(&map, GL_R16_SNORM_EXT, true, 16, 0, 0, 0, 0, GL_RED, GL_SHORT, GL_SIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16EXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG16_EXT, true, 16, 16, 0, 0, 0, GL_RG, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16EXT>, AlwaysSupported, RequireExt<&Extensions::textureNorm16EXT>, RequireExt<&Extensions::textureNorm16EXT>, RequireExt<&Extensions::textureNorm16EXT>);
+ AddRGBAFormat(&map, GL_RG16_SNORM_EXT, true, 16, 16, 0, 0, 0, GL_RG, GL_SHORT, GL_SIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16EXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB16_EXT, true, 16, 16, 16, 0, 0, GL_RGB, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16EXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB16_SNORM_EXT, true, 16, 16, 16, 0, 0, GL_RGB, GL_SHORT, GL_SIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16EXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA16_EXT, true, 16, 16, 16, 16, 0, GL_RGBA, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16EXT>, AlwaysSupported, RequireExt<&Extensions::textureNorm16EXT>, RequireExt<&Extensions::textureNorm16EXT>, RequireExt<&Extensions::textureNorm16EXT>);
+ AddRGBAFormat(&map, GL_RGBA16_SNORM_EXT, true, 16, 16, 16, 16, 0, GL_RGBA, GL_SHORT, GL_SIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16EXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // From EXT_texture_sRGB_R8
+ // | Internal format |sized| R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddRGBAFormat(&map, GL_SR8_EXT, true, 8, 0, 0, 0, 0, GL_RED, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireExt<&Extensions::textureSRGBR8EXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // From EXT_texture_sRGB_RG8
+ // | Internal format |sized| R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddRGBAFormat(&map, GL_SRG8_EXT, true, 8, 8, 0, 0, 0, GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireExt<&Extensions::textureSRGBRG8EXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // From GL_EXT_texture_type_2_10_10_10_REV
+ // GL_RGB10_UNORM_ANGLEX is never used directly but needs to be in the list of all sized internal formats so that the backends can determine support.
+ // | Internal format |sized| R | G | B | A |S |X | Format | Type | Component type | SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddRGBAXFormat(&map, GL_RGB10_UNORM_ANGLEX, true, FB<10, 10, 10, 0, 0, 2>(), GL_RGB, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // Unsized formats
+ // | Internal format |sized | R | G | B | A |S |X | Format | Type | Component type | SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddRGBAXFormat(&map, GL_RED, false, FB< 8, 0, 0, 0, 0, 0>(), GL_RED, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureRgEXT>, AlwaysSupported, RequireExt<&Extensions::textureRgEXT>, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_RED, false, FB< 8, 0, 0, 0, 0, 0>(), GL_RED, GL_BYTE, GL_SIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_RED, false, FB<16, 0, 0, 0, 0, 0>(), GL_RED, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16EXT>, AlwaysSupported, RequireExt<&Extensions::textureNorm16EXT>, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_RG, false, FB< 8, 8, 0, 0, 0, 0>(), GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureRgEXT>, AlwaysSupported, RequireExt<&Extensions::textureRgEXT>, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_RG, false, FB< 8, 8, 0, 0, 0, 0>(), GL_RG, GL_BYTE, GL_SIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_RG, false, FB<16, 16, 0, 0, 0, 0>(), GL_RG, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16EXT>, AlwaysSupported, RequireExt<&Extensions::textureNorm16EXT>, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_RGB, false, FB< 8, 8, 8, 0, 0, 0>(), GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, RequireESOrExt<2, 0, &Extensions::framebufferObjectOES>, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_RGB, false, FB< 5, 6, 5, 0, 0, 0>(), GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, RequireESOrExt<2, 0, &Extensions::framebufferObjectOES>, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_RGB, false, FB< 8, 8, 8, 0, 0, 0>(), GL_RGB, GL_BYTE, GL_SIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_RGB, false, FB<10, 10, 10, 0, 0, 2>(), GL_RGB, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureType2101010REVEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_RGBA, false, FB< 4, 4, 4, 4, 0, 0>(), GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, RequireESOrExt<2, 0, &Extensions::framebufferObjectOES>, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_RGBA, false, FB< 5, 5, 5, 1, 0, 0>(), GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, RequireESOrExt<2, 0, &Extensions::framebufferObjectOES>, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_RGBA, false, FB< 8, 8, 8, 8, 0, 0>(), GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, RequireESOrExt<2, 0, &Extensions::framebufferObjectOES>, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_RGBA, false, FB<16, 16, 16, 16, 0, 0>(), GL_RGBA, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureNorm16EXT>, AlwaysSupported, RequireExt<&Extensions::textureNorm16EXT>, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_RGBA, false, FB<10, 10, 10, 2, 0, 0>(), GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureType2101010REVEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_RGBA, false, FB< 8, 8, 8, 8, 0, 0>(), GL_RGBA, GL_BYTE, GL_SIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_SRGB, false, FB< 8, 8, 8, 0, 0, 0>(), GL_SRGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireExt<&Extensions::sRGBEXT>, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAXFormat(&map, GL_SRGB_ALPHA_EXT, false, FB< 8, 8, 8, 8, 0, 0>(), GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireExt<&Extensions::sRGBEXT>, AlwaysSupported, RequireExt<&Extensions::sRGBEXT>, NeverSupported, NeverSupported);
+#if (defined(ANGLE_PLATFORM_IOS) && !defined(ANGLE_PLATFORM_MACCATALYST)) || (defined(ANGLE_PLATFORM_MACCATALYST) && defined(ANGLE_CPU_ARM64))
+ angle::SystemInfo info;
+ if (angle::GetSystemInfo(&info))
+ {
+ if (info.needsEAGLOnMac)
+ {
+ // Using OpenGLES.framework.
+ AddRGBAFormat(&map, GL_BGRA_EXT, false, 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireES<2, 0>, AlwaysSupported, RequireES<2, 0>, NeverSupported, NeverSupported);
+ }
+ else
+ {
+ // Using OpenGL.framework.
+ AddRGBAFormat(&map, GL_BGRA_EXT, false, 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888EXT>, AlwaysSupported, RequireExt<&Extensions::textureFormatBGRA8888EXT>, NeverSupported, NeverSupported);
+ }
+ }
+#else
+ AddRGBAFormat(&map, GL_BGRA_EXT, false, 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888EXT>, AlwaysSupported, RequireExt<&Extensions::textureFormatBGRA8888EXT>, NeverSupported, NeverSupported);
+#endif
+
+ // Unsized integer formats
+ // |Internal format |sized | R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddRGBAFormat(&map, GL_RED_INTEGER, false, 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RED_INTEGER, false, 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RED_INTEGER, false, 16, 0, 0, 0, 0, GL_RED_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RED_INTEGER, false, 16, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RED_INTEGER, false, 32, 0, 0, 0, 0, GL_RED_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RED_INTEGER, false, 32, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG_INTEGER, false, 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG_INTEGER, false, 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG_INTEGER, false, 16, 16, 0, 0, 0, GL_RG_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG_INTEGER, false, 16, 16, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG_INTEGER, false, 32, 32, 0, 0, 0, GL_RG_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG_INTEGER, false, 32, 32, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB_INTEGER, false, 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB_INTEGER, false, 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB_INTEGER, false, 16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB_INTEGER, false, 16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB_INTEGER, false, 32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB_INTEGER, false, 32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_BYTE, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT, GL_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA_INTEGER, false, 10, 10, 10, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT, false, RequireES<3, 0>, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+
+ // Unsized floating point formats
+ // |Internal format |sized | R | G | B | A |S | Format | Type | Comp | SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddRGBAFormat(&map, GL_RED, false, 16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT, GL_FLOAT, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG, false, 16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT, GL_FLOAT, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB, false, 16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT, GL_FLOAT, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA, false, 16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RED, false, 16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT_OES, GL_FLOAT, false, RequireExtAndExt<&Extensions::textureHalfFloatOES, &Extensions::textureRgEXT>, RequireExt<&Extensions::textureHalfFloatLinearOES>, AlwaysSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG, false, 16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT_OES, GL_FLOAT, false, RequireExtAndExt<&Extensions::textureHalfFloatOES, &Extensions::textureRgEXT>, RequireExt<&Extensions::textureHalfFloatLinearOES>, AlwaysSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB, false, 16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT_OES, GL_FLOAT, false, RequireExt<&Extensions::textureHalfFloatOES>, RequireExt<&Extensions::textureHalfFloatLinearOES>, RequireExt<&Extensions::colorBufferHalfFloatEXT>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA, false, 16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT_OES, GL_FLOAT, false, RequireExt<&Extensions::textureHalfFloatOES>, RequireExt<&Extensions::textureHalfFloatLinearOES>, RequireExt<&Extensions::colorBufferHalfFloatEXT>, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RED, false, 32, 0, 0, 0, 0, GL_RED, GL_FLOAT, GL_FLOAT, false, RequireExtAndExt<&Extensions::textureFloatOES, &Extensions::textureRgEXT>, RequireExt<&Extensions::textureFloatLinearOES>, AlwaysSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RG, false, 32, 32, 0, 0, 0, GL_RG, GL_FLOAT, GL_FLOAT, false, RequireExtAndExt<&Extensions::textureFloatOES, &Extensions::textureRgEXT>, RequireExt<&Extensions::textureFloatLinearOES>, AlwaysSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB, false, 32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, RequireExt<&Extensions::textureFloatOES>, RequireExt<&Extensions::textureFloatLinearOES>, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB, false, 9, 9, 9, 0, 5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGB, false, 11, 11, 10, 0, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddRGBAFormat(&map, GL_RGBA, false, 32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, RequireExt<&Extensions::textureFloatOES>, RequireExt<&Extensions::textureFloatLinearOES>, NeverSupported, NeverSupported, NeverSupported);
+
+ // Unsized luminance alpha formats
+ // | Internal format |sized | L | A | Format | Type | Component type | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddLUMAFormat(&map, GL_ALPHA, false, 0, 8, GL_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, AlwaysSupported, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_LUMINANCE, false, 8, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, AlwaysSupported, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_LUMINANCE_ALPHA, false, 8, 8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, AlwaysSupported, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_ALPHA, false, 0, 16, GL_ALPHA, GL_HALF_FLOAT_OES, GL_FLOAT, RequireExt<&Extensions::textureHalfFloatOES>, RequireExt<&Extensions::textureHalfFloatLinearOES>, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_LUMINANCE, false, 16, 0, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_FLOAT, RequireExt<&Extensions::textureHalfFloatOES>, RequireExt<&Extensions::textureHalfFloatLinearOES>, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_LUMINANCE_ALPHA, false, 16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_FLOAT, RequireExt<&Extensions::textureHalfFloatOES>, RequireExt<&Extensions::textureHalfFloatLinearOES>, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_ALPHA, false, 0, 32, GL_ALPHA, GL_FLOAT, GL_FLOAT, RequireExt<&Extensions::textureFloatOES>, RequireExt<&Extensions::textureFloatLinearOES>, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_LUMINANCE, false, 32, 0, GL_LUMINANCE, GL_FLOAT, GL_FLOAT, RequireExt<&Extensions::textureFloatOES>, RequireExt<&Extensions::textureFloatLinearOES>, NeverSupported, NeverSupported, NeverSupported);
+ AddLUMAFormat(&map, GL_LUMINANCE_ALPHA, false, 32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_FLOAT, RequireExt<&Extensions::textureFloatOES>, RequireExt<&Extensions::textureFloatLinearOES>, NeverSupported, NeverSupported, NeverSupported);
+
+ // Unsized depth stencil formats
+ // | Internal format |sized | D |S | X | Format | Type | Component type | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT, false, 16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, RequireES<1, 0>, AlwaysSupported, RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>, RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>, RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>);
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT, false, 24, 0, 8, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireES<1, 0>, AlwaysSupported, RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>, RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>, RequireExtOrExt<&Extensions::depthTextureANGLE, &Extensions::depthTextureOES>);
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT, false, 32, 0, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT, RequireES<1, 0>, AlwaysSupported, RequireES<1, 0>, RequireES<1, 0>, RequireES<1, 0>);
+ AddDepthStencilFormat(&map, GL_DEPTH_COMPONENT, false, 24, 8, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, 0, &Extensions::packedDepthStencilOES>, AlwaysSupported, RequireExtAndExt<&Extensions::packedDepthStencilOES, &Extensions::depthTextureANGLE>, RequireExtAndExt<&Extensions::packedDepthStencilOES, &Extensions::depthTextureANGLE>, RequireExtAndExt<&Extensions::packedDepthStencilOES, &Extensions::depthTextureANGLE>);
+ AddDepthStencilFormat(&map, GL_DEPTH_STENCIL, false, 24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, 0, &Extensions::packedDepthStencilOES>, AlwaysSupported, RequireExtAndExt<&Extensions::packedDepthStencilOES, &Extensions::depthTextureANGLE>, RequireExtAndExt<&Extensions::packedDepthStencilOES, &Extensions::depthTextureANGLE>, RequireExtAndExt<&Extensions::packedDepthStencilOES, &Extensions::depthTextureANGLE>);
+ AddDepthStencilFormat(&map, GL_DEPTH_STENCIL, false, 32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireESOrExt<3, 0, &Extensions::packedDepthStencilOES>, AlwaysSupported, RequireExt<&Extensions::packedDepthStencilOES>, RequireExt<&Extensions::packedDepthStencilOES>, RequireExt<&Extensions::packedDepthStencilOES>);
+ AddDepthStencilFormat(&map, GL_STENCIL, false, 0, 8, 0, GL_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireES<1, 0>, NeverSupported , RequireES<1, 0>, RequireES<1, 0>, RequireES<1, 0>);
+ AddDepthStencilFormat(&map, GL_STENCIL_INDEX, false, 0, 8, 0, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireES<3, 1>, NeverSupported , RequireES<3, 1>, RequireES<3, 1>, RequireES<3, 1>);
+
+ // Non-standard YUV formats
+ // | Internal format | sized | Cr | Y | Cb | A | S | Format | Type | Comp | SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
+ AddYUVFormat(&map, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, true, 8, 8, 8, 0, 0, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::yuvInternalFormatANGLE>, RequireExt<&Extensions::yuvInternalFormatANGLE>, RequireExt<&Extensions::yuvInternalFormatANGLE>, NeverSupported, NeverSupported);
+ AddYUVFormat(&map, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, true, 8, 8, 8, 0, 0, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::yuvInternalFormatANGLE>, RequireExt<&Extensions::yuvInternalFormatANGLE>, RequireExt<&Extensions::yuvInternalFormatANGLE>, NeverSupported, NeverSupported);
+
+#if defined(ANGLE_PLATFORM_LINUX)
+ // From GL_OES_required_internalformat
+ // The |shared| bit shouldn't be 2. But given this hits assertion when bits
+ // are checked, it's fine to have this bit set as 2 as a workaround.
+ AddRGBAFormat(&map, GL_RGB10_EXT, true, 10, 10, 10, 0, 2, GL_RGB, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, RequireES<1, 0>, NeverSupported, RequireES<1, 0>, RequireES<1, 0>, NeverSupported);
+#endif
+ // clang-format on
+
+ return map;
+}
+
+const InternalFormatInfoMap &GetInternalFormatMap()
+{
+ static const angle::base::NoDestructor<InternalFormatInfoMap> formatMap(
+ BuildInternalFormatInfoMap());
+ return *formatMap;
+}
+
+int GetAndroidHardwareBufferFormatFromChannelSizes(const egl::AttributeMap &attribMap)
+{
+ // Retrieve channel size from attribute map. The default value should be 0, per spec.
+ GLuint redSize = static_cast<GLuint>(attribMap.getAsInt(EGL_RED_SIZE, 0));
+ GLuint greenSize = static_cast<GLuint>(attribMap.getAsInt(EGL_GREEN_SIZE, 0));
+ GLuint blueSize = static_cast<GLuint>(attribMap.getAsInt(EGL_BLUE_SIZE, 0));
+ GLuint alphaSize = static_cast<GLuint>(attribMap.getAsInt(EGL_ALPHA_SIZE, 0));
+
+ GLenum glInternalFormat = 0;
+ for (GLenum sizedInternalFormat : angle::android::kSupportedSizedInternalFormats)
+ {
+ const gl::InternalFormat &internalFormat = GetSizedInternalFormatInfo(sizedInternalFormat);
+ ASSERT(internalFormat.internalFormat != GL_NONE && internalFormat.sized);
+
+ if (internalFormat.isChannelSizeCompatible(redSize, greenSize, blueSize, alphaSize))
+ {
+ glInternalFormat = sizedInternalFormat;
+ break;
+ }
+ }
+
+ return (glInternalFormat != 0)
+ ? angle::android::GLInternalFormatToNativePixelFormat(glInternalFormat)
+ : 0;
+}
+
+GLenum GetConfigColorBufferFormat(const egl::Config *config)
+{
+ GLenum componentType = GL_NONE;
+ switch (config->colorComponentType)
+ {
+ case EGL_COLOR_COMPONENT_TYPE_FIXED_EXT:
+ componentType = GL_UNSIGNED_NORMALIZED;
+ break;
+ case EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT:
+ componentType = GL_FLOAT;
+ break;
+ default:
+ UNREACHABLE();
+ return GL_NONE;
+ }
+
+ GLenum colorEncoding = GL_LINEAR;
+
+ for (GLenum sizedInternalFormat : GetAllSizedInternalFormats())
+ {
+ const gl::InternalFormat &internalFormat = GetSizedInternalFormatInfo(sizedInternalFormat);
+
+ if (internalFormat.componentType == componentType &&
+ internalFormat.colorEncoding == colorEncoding &&
+ internalFormat.isChannelSizeCompatible(config->redSize, config->greenSize,
+ config->blueSize, config->alphaSize))
+ {
+ return sizedInternalFormat;
+ }
+ }
+
+ // Only expect to get here if there is no color bits in the config
+ ASSERT(config->redSize == 0 && config->greenSize == 0 && config->blueSize == 0 &&
+ config->alphaSize == 0);
+ return GL_NONE;
+}
+
+GLenum GetConfigDepthStencilBufferFormat(const egl::Config *config)
+{
+ GLenum componentType = GL_UNSIGNED_NORMALIZED;
+
+ for (GLenum sizedInternalFormat : GetAllSizedInternalFormats())
+ {
+ const gl::InternalFormat &internalFormat = GetSizedInternalFormatInfo(sizedInternalFormat);
+
+ if (internalFormat.componentType == componentType &&
+ static_cast<EGLint>(internalFormat.depthBits) == config->depthSize &&
+ static_cast<EGLint>(internalFormat.stencilBits) == config->stencilSize)
+ {
+ return sizedInternalFormat;
+ }
+ }
+
+ // Only expect to get here if there is no depth or stencil bits in the config
+ ASSERT(config->depthSize == 0 && config->stencilSize == 0);
+ return GL_NONE;
+}
+
+static FormatSet BuildAllSizedInternalFormatSet()
+{
+ FormatSet result;
+
+ for (const auto &internalFormat : GetInternalFormatMap())
+ {
+ for (const auto &type : internalFormat.second)
+ {
+ if (type.second.sized)
+ {
+ // TODO(jmadill): Fix this hack.
+ if (internalFormat.first == GL_BGR565_ANGLEX)
+ continue;
+
+ result.insert(internalFormat.first);
+ }
+ }
+ }
+
+ return result;
+}
+
+uint32_t GetPackedTypeInfo(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_BYTE:
+ {
+ static constexpr uint32_t kPacked = PackTypeInfo(1, false);
+ return kPacked;
+ }
+ case GL_UNSIGNED_SHORT:
+ case GL_SHORT:
+ case GL_HALF_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ {
+ static constexpr uint32_t kPacked = PackTypeInfo(2, false);
+ return kPacked;
+ }
+ case GL_UNSIGNED_INT:
+ case GL_INT:
+ case GL_FLOAT:
+ {
+ static constexpr uint32_t kPacked = PackTypeInfo(4, false);
+ return kPacked;
+ }
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ {
+ static constexpr uint32_t kPacked = PackTypeInfo(2, true);
+ return kPacked;
+ }
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_24_8:
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL_UNSIGNED_INT_5_9_9_9_REV:
+ {
+ ASSERT(GL_UNSIGNED_INT_24_8_OES == GL_UNSIGNED_INT_24_8);
+ static constexpr uint32_t kPacked = PackTypeInfo(4, true);
+ return kPacked;
+ }
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ {
+ static constexpr uint32_t kPacked = PackTypeInfo(8, true);
+ return kPacked;
+ }
+ default:
+ {
+ return 0;
+ }
+ }
+}
+
+const InternalFormat &GetSizedInternalFormatInfo(GLenum internalFormat)
+{
+ static const InternalFormat defaultInternalFormat;
+ const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
+ auto iter = formatMap.find(internalFormat);
+
+ // Sized internal formats only have one type per entry
+ if (iter == formatMap.end() || iter->second.size() != 1)
+ {
+ return defaultInternalFormat;
+ }
+
+ const InternalFormat &internalFormatInfo = iter->second.begin()->second;
+ if (!internalFormatInfo.sized)
+ {
+ return defaultInternalFormat;
+ }
+
+ return internalFormatInfo;
+}
+
+const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, GLenum type)
+{
+ static const InternalFormat defaultInternalFormat;
+ const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
+
+ auto internalFormatIter = formatMap.find(internalFormat);
+ if (internalFormatIter == formatMap.end())
+ {
+ return defaultInternalFormat;
+ }
+
+ // If the internal format is sized, simply return it without the type check.
+ if (internalFormatIter->second.size() == 1 && internalFormatIter->second.begin()->second.sized)
+ {
+ return internalFormatIter->second.begin()->second;
+ }
+
+ auto typeIter = internalFormatIter->second.find(type);
+ if (typeIter == internalFormatIter->second.end())
+ {
+ return defaultInternalFormat;
+ }
+
+ return typeIter->second;
+}
+
+GLuint InternalFormat::computePixelBytes(GLenum formatType) const
+{
+ const auto &typeInfo = GetTypeInfo(formatType);
+ GLuint components = typeInfo.specialInterpretation ? 1u : componentCount;
+ return components * typeInfo.bytes;
+}
+
+bool InternalFormat::computeBufferRowLength(uint32_t width, uint32_t *resultOut) const
+{
+ CheckedNumeric<GLuint> checkedWidth(width);
+
+ if (compressed)
+ {
+ angle::CheckedNumeric<uint32_t> checkedRowLength =
+ rx::CheckedRoundUp<uint32_t>(width, compressedBlockWidth);
+
+ return CheckedMathResult(checkedRowLength, resultOut);
+ }
+
+ return CheckedMathResult(checkedWidth, resultOut);
+}
+
+bool InternalFormat::computeBufferImageHeight(uint32_t height, uint32_t *resultOut) const
+{
+ CheckedNumeric<GLuint> checkedHeight(height);
+
+ if (compressed)
+ {
+ angle::CheckedNumeric<uint32_t> checkedImageHeight =
+ rx::CheckedRoundUp<uint32_t>(height, compressedBlockHeight);
+
+ return CheckedMathResult(checkedImageHeight, resultOut);
+ }
+
+ return CheckedMathResult(checkedHeight, resultOut);
+}
+
+bool InternalFormat::computePalettedImageRowPitch(GLsizei width, GLuint *resultOut) const
+{
+ ASSERT(paletted);
+ switch (paletteBits)
+ {
+ case 4:
+ *resultOut = (width + 1) / 2;
+ return true;
+ case 8:
+ *resultOut = width;
+ return true;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool InternalFormat::computeRowPitch(GLenum formatType,
+ GLsizei width,
+ GLint alignment,
+ GLint rowLength,
+ GLuint *resultOut) const
+{
+ if (paletted)
+ {
+ return computePalettedImageRowPitch(width, resultOut);
+ }
+
+ // Compressed images do not use pack/unpack parameters (rowLength).
+ if (compressed)
+ {
+ return computeCompressedImageSize(Extents(width, 1, 1), resultOut);
+ }
+
+ CheckedNumeric<GLuint> checkedWidth(rowLength > 0 ? rowLength : width);
+ CheckedNumeric<GLuint> checkedRowBytes = checkedWidth * computePixelBytes(formatType);
+
+ ASSERT(alignment > 0 && isPow2(alignment));
+ CheckedNumeric<GLuint> checkedAlignment(alignment);
+ auto aligned = rx::roundUp(checkedRowBytes, checkedAlignment);
+ return CheckedMathResult(aligned, resultOut);
+}
+
+bool InternalFormat::computeDepthPitch(GLsizei height,
+ GLint imageHeight,
+ GLuint rowPitch,
+ GLuint *resultOut) const
+{
+ // Compressed images do not use pack/unpack parameters (imageHeight).
+ CheckedNumeric<GLuint> pixelsHeight(!compressed && (imageHeight > 0)
+ ? static_cast<GLuint>(imageHeight)
+ : static_cast<GLuint>(height));
+
+ CheckedNumeric<GLuint> rowCount;
+ if (compressed)
+ {
+ CheckedNumeric<GLuint> checkedBlockHeight(compressedBlockHeight);
+ rowCount = (pixelsHeight + checkedBlockHeight - 1u) / checkedBlockHeight;
+ }
+ else
+ {
+ rowCount = pixelsHeight;
+ }
+
+ CheckedNumeric<GLuint> checkedRowPitch(rowPitch);
+
+ return CheckedMathResult(checkedRowPitch * rowCount, resultOut);
+}
+
+bool InternalFormat::computeDepthPitch(GLenum formatType,
+ GLsizei width,
+ GLsizei height,
+ GLint alignment,
+ GLint rowLength,
+ GLint imageHeight,
+ GLuint *resultOut) const
+{
+ GLuint rowPitch = 0;
+ if (!computeRowPitch(formatType, width, alignment, rowLength, &rowPitch))
+ {
+ return false;
+ }
+ return computeDepthPitch(height, imageHeight, rowPitch, resultOut);
+}
+
+bool InternalFormat::computeCompressedImageSize(const Extents &size, GLuint *resultOut) const
+{
+ CheckedNumeric<GLuint> checkedWidth(size.width);
+ CheckedNumeric<GLuint> checkedHeight(size.height);
+ CheckedNumeric<GLuint> checkedDepth(size.depth);
+
+ if (paletted)
+ {
+ ASSERT(!compressed);
+
+ GLuint paletteSize = 1 << paletteBits;
+ GLuint paletteBytes = paletteSize * pixelBytes;
+
+ GLuint rowPitch;
+ if (!computePalettedImageRowPitch(size.width, &rowPitch))
+ {
+ return false;
+ }
+
+ if (size.depth != 1)
+ {
+ return false;
+ }
+
+ CheckedNumeric<GLuint> checkedPaletteBytes(paletteBytes);
+ CheckedNumeric<GLuint> checkedRowPitch(rowPitch);
+
+ return CheckedMathResult(checkedPaletteBytes + checkedRowPitch * checkedHeight, resultOut);
+ }
+
+ CheckedNumeric<GLuint> checkedBlockWidth(compressedBlockWidth);
+ CheckedNumeric<GLuint> checkedBlockHeight(compressedBlockHeight);
+ GLuint minBlockWidth, minBlockHeight;
+ std::tie(minBlockWidth, minBlockHeight) = getCompressedImageMinBlocks();
+
+ ASSERT(compressed);
+ auto numBlocksWide = (checkedWidth + checkedBlockWidth - 1u) / checkedBlockWidth;
+ auto numBlocksHigh = (checkedHeight + checkedBlockHeight - 1u) / checkedBlockHeight;
+ if (numBlocksWide.IsValid() && numBlocksWide.ValueOrDie() < minBlockWidth)
+ numBlocksWide = minBlockWidth;
+ if (numBlocksHigh.IsValid() && numBlocksHigh.ValueOrDie() < minBlockHeight)
+ numBlocksHigh = minBlockHeight;
+ auto bytes = numBlocksWide * numBlocksHigh * pixelBytes * checkedDepth;
+ return CheckedMathResult(bytes, resultOut);
+}
+
+std::pair<GLuint, GLuint> InternalFormat::getCompressedImageMinBlocks() const
+{
+ GLuint minBlockWidth = 0;
+ GLuint minBlockHeight = 0;
+
+ // Per the specification, a PVRTC block needs information from the 3 nearest blocks.
+ // GL_IMG_texture_compression_pvrtc specifies the minimum size requirement in pixels, but
+ // ANGLE's texture tables are written in terms of blocks. The 4BPP formats use 4x4 blocks, and
+ // the 2BPP formats, 8x4 blocks. Therefore, both kinds of formats require a minimum of 2x2
+ // blocks.
+ switch (internalFormat)
+ {
+ case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
+ case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
+ case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
+ case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
+ case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
+ case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
+ minBlockWidth = 2;
+ minBlockHeight = 2;
+ break;
+
+ default:
+ break;
+ }
+
+ return std::make_pair(minBlockWidth, minBlockHeight);
+}
+
+bool InternalFormat::computeSkipBytes(GLenum formatType,
+ GLuint rowPitch,
+ GLuint depthPitch,
+ const PixelStoreStateBase &state,
+ bool is3D,
+ GLuint *resultOut) const
+{
+ CheckedNumeric<GLuint> checkedRowPitch(rowPitch);
+ CheckedNumeric<GLuint> checkedDepthPitch(depthPitch);
+ CheckedNumeric<GLuint> checkedSkipImages(static_cast<GLuint>(state.skipImages));
+ CheckedNumeric<GLuint> checkedSkipRows(static_cast<GLuint>(state.skipRows));
+ CheckedNumeric<GLuint> checkedSkipPixels(static_cast<GLuint>(state.skipPixels));
+ CheckedNumeric<GLuint> checkedPixelBytes(computePixelBytes(formatType));
+ auto checkedSkipImagesBytes = checkedSkipImages * checkedDepthPitch;
+ if (!is3D)
+ {
+ checkedSkipImagesBytes = 0;
+ }
+ auto skipBytes = checkedSkipImagesBytes + checkedSkipRows * checkedRowPitch +
+ checkedSkipPixels * checkedPixelBytes;
+ return CheckedMathResult(skipBytes, resultOut);
+}
+
+bool InternalFormat::computePackUnpackEndByte(GLenum formatType,
+ const Extents &size,
+ const PixelStoreStateBase &state,
+ bool is3D,
+ GLuint *resultOut) const
+{
+ GLuint rowPitch = 0;
+ if (!computeRowPitch(formatType, size.width, state.alignment, state.rowLength, &rowPitch))
+ {
+ return false;
+ }
+
+ GLuint depthPitch = 0;
+ if (is3D && !computeDepthPitch(size.height, state.imageHeight, rowPitch, &depthPitch))
+ {
+ return false;
+ }
+
+ CheckedNumeric<GLuint> checkedCopyBytes(0);
+ if (compressed)
+ {
+ GLuint copyBytes = 0;
+ if (!computeCompressedImageSize(size, &copyBytes))
+ {
+ return false;
+ }
+ checkedCopyBytes = copyBytes;
+ }
+ else if (size.height != 0 && (!is3D || size.depth != 0))
+ {
+ CheckedNumeric<GLuint> bytes = computePixelBytes(formatType);
+ checkedCopyBytes += size.width * bytes;
+
+ CheckedNumeric<GLuint> heightMinusOne = size.height - 1;
+ checkedCopyBytes += heightMinusOne * rowPitch;
+
+ if (is3D)
+ {
+ CheckedNumeric<GLuint> depthMinusOne = size.depth - 1;
+ checkedCopyBytes += depthMinusOne * depthPitch;
+ }
+ }
+
+ GLuint skipBytes = 0;
+ if (!computeSkipBytes(formatType, rowPitch, depthPitch, state, is3D, &skipBytes))
+ {
+ return false;
+ }
+
+ CheckedNumeric<GLuint> endByte = checkedCopyBytes + CheckedNumeric<GLuint>(skipBytes);
+
+ return CheckedMathResult(endByte, resultOut);
+}
+
+GLenum GetUnsizedFormat(GLenum internalFormat)
+{
+ auto sizedFormatInfo = GetSizedInternalFormatInfo(internalFormat);
+ if (sizedFormatInfo.internalFormat != GL_NONE)
+ {
+ return sizedFormatInfo.format;
+ }
+
+ return internalFormat;
+}
+
+bool CompressedFormatRequiresWholeImage(GLenum internalFormat)
+{
+ // List of compressed texture format that require that the sub-image size is equal to texture's
+ // respective mip level's size
+ return IsPVRTC1Format(internalFormat);
+}
+
+void MaybeOverrideLuminance(GLenum &format, GLenum &type, GLenum actualFormat, GLenum actualType)
+{
+ gl::InternalFormat internalFormat = gl::GetInternalFormatInfo(format, type);
+ if (internalFormat.isLUMA())
+ {
+ // Ensure the format and type are compatible
+ ASSERT(internalFormat.pixelBytes ==
+ gl::GetInternalFormatInfo(actualFormat, actualType).pixelBytes);
+
+ // For Luminance formats, override with the internal format. Since this is not
+ // renderable, our pixel pack routines don't handle it correctly.
+ format = actualFormat;
+ type = actualType;
+ }
+}
+
+const FormatSet &GetAllSizedInternalFormats()
+{
+ static angle::base::NoDestructor<FormatSet> formatSet(BuildAllSizedInternalFormatSet());
+ return *formatSet;
+}
+
+AttributeType GetAttributeType(GLenum enumValue)
+{
+ switch (enumValue)
+ {
+ case GL_FLOAT:
+ return ATTRIBUTE_FLOAT;
+ case GL_FLOAT_VEC2:
+ return ATTRIBUTE_VEC2;
+ case GL_FLOAT_VEC3:
+ return ATTRIBUTE_VEC3;
+ case GL_FLOAT_VEC4:
+ return ATTRIBUTE_VEC4;
+ case GL_INT:
+ return ATTRIBUTE_INT;
+ case GL_INT_VEC2:
+ return ATTRIBUTE_IVEC2;
+ case GL_INT_VEC3:
+ return ATTRIBUTE_IVEC3;
+ case GL_INT_VEC4:
+ return ATTRIBUTE_IVEC4;
+ case GL_UNSIGNED_INT:
+ return ATTRIBUTE_UINT;
+ case GL_UNSIGNED_INT_VEC2:
+ return ATTRIBUTE_UVEC2;
+ case GL_UNSIGNED_INT_VEC3:
+ return ATTRIBUTE_UVEC3;
+ case GL_UNSIGNED_INT_VEC4:
+ return ATTRIBUTE_UVEC4;
+ case GL_FLOAT_MAT2:
+ return ATTRIBUTE_MAT2;
+ case GL_FLOAT_MAT3:
+ return ATTRIBUTE_MAT3;
+ case GL_FLOAT_MAT4:
+ return ATTRIBUTE_MAT4;
+ case GL_FLOAT_MAT2x3:
+ return ATTRIBUTE_MAT2x3;
+ case GL_FLOAT_MAT2x4:
+ return ATTRIBUTE_MAT2x4;
+ case GL_FLOAT_MAT3x2:
+ return ATTRIBUTE_MAT3x2;
+ case GL_FLOAT_MAT3x4:
+ return ATTRIBUTE_MAT3x4;
+ case GL_FLOAT_MAT4x2:
+ return ATTRIBUTE_MAT4x2;
+ case GL_FLOAT_MAT4x3:
+ return ATTRIBUTE_MAT4x3;
+ default:
+ UNREACHABLE();
+ return ATTRIBUTE_FLOAT;
+ }
+}
+
+angle::FormatID GetVertexFormatID(VertexAttribType type,
+ GLboolean normalized,
+ GLuint components,
+ bool pureInteger)
+{
+ switch (type)
+ {
+ case VertexAttribType::Byte:
+ switch (components)
+ {
+ case 1:
+ if (pureInteger)
+ return angle::FormatID::R8_SINT;
+ if (normalized)
+ return angle::FormatID::R8_SNORM;
+ return angle::FormatID::R8_SSCALED;
+ case 2:
+ if (pureInteger)
+ return angle::FormatID::R8G8_SINT;
+ if (normalized)
+ return angle::FormatID::R8G8_SNORM;
+ return angle::FormatID::R8G8_SSCALED;
+ case 3:
+ if (pureInteger)
+ return angle::FormatID::R8G8B8_SINT;
+ if (normalized)
+ return angle::FormatID::R8G8B8_SNORM;
+ return angle::FormatID::R8G8B8_SSCALED;
+ case 4:
+ if (pureInteger)
+ return angle::FormatID::R8G8B8A8_SINT;
+ if (normalized)
+ return angle::FormatID::R8G8B8A8_SNORM;
+ return angle::FormatID::R8G8B8A8_SSCALED;
+ default:
+ UNREACHABLE();
+ return angle::FormatID::NONE;
+ }
+ case VertexAttribType::UnsignedByte:
+ switch (components)
+ {
+ case 1:
+ if (pureInteger)
+ return angle::FormatID::R8_UINT;
+ if (normalized)
+ return angle::FormatID::R8_UNORM;
+ return angle::FormatID::R8_USCALED;
+ case 2:
+ if (pureInteger)
+ return angle::FormatID::R8G8_UINT;
+ if (normalized)
+ return angle::FormatID::R8G8_UNORM;
+ return angle::FormatID::R8G8_USCALED;
+ case 3:
+ if (pureInteger)
+ return angle::FormatID::R8G8B8_UINT;
+ if (normalized)
+ return angle::FormatID::R8G8B8_UNORM;
+ return angle::FormatID::R8G8B8_USCALED;
+ case 4:
+ if (pureInteger)
+ return angle::FormatID::R8G8B8A8_UINT;
+ if (normalized)
+ return angle::FormatID::R8G8B8A8_UNORM;
+ return angle::FormatID::R8G8B8A8_USCALED;
+ default:
+ UNREACHABLE();
+ return angle::FormatID::NONE;
+ }
+ case VertexAttribType::Short:
+ switch (components)
+ {
+ case 1:
+ if (pureInteger)
+ return angle::FormatID::R16_SINT;
+ if (normalized)
+ return angle::FormatID::R16_SNORM;
+ return angle::FormatID::R16_SSCALED;
+ case 2:
+ if (pureInteger)
+ return angle::FormatID::R16G16_SINT;
+ if (normalized)
+ return angle::FormatID::R16G16_SNORM;
+ return angle::FormatID::R16G16_SSCALED;
+ case 3:
+ if (pureInteger)
+ return angle::FormatID::R16G16B16_SINT;
+ if (normalized)
+ return angle::FormatID::R16G16B16_SNORM;
+ return angle::FormatID::R16G16B16_SSCALED;
+ case 4:
+ if (pureInteger)
+ return angle::FormatID::R16G16B16A16_SINT;
+ if (normalized)
+ return angle::FormatID::R16G16B16A16_SNORM;
+ return angle::FormatID::R16G16B16A16_SSCALED;
+ default:
+ UNREACHABLE();
+ return angle::FormatID::NONE;
+ }
+ case VertexAttribType::UnsignedShort:
+ switch (components)
+ {
+ case 1:
+ if (pureInteger)
+ return angle::FormatID::R16_UINT;
+ if (normalized)
+ return angle::FormatID::R16_UNORM;
+ return angle::FormatID::R16_USCALED;
+ case 2:
+ if (pureInteger)
+ return angle::FormatID::R16G16_UINT;
+ if (normalized)
+ return angle::FormatID::R16G16_UNORM;
+ return angle::FormatID::R16G16_USCALED;
+ case 3:
+ if (pureInteger)
+ return angle::FormatID::R16G16B16_UINT;
+ if (normalized)
+ return angle::FormatID::R16G16B16_UNORM;
+ return angle::FormatID::R16G16B16_USCALED;
+ case 4:
+ if (pureInteger)
+ return angle::FormatID::R16G16B16A16_UINT;
+ if (normalized)
+ return angle::FormatID::R16G16B16A16_UNORM;
+ return angle::FormatID::R16G16B16A16_USCALED;
+ default:
+ UNREACHABLE();
+ return angle::FormatID::NONE;
+ }
+ case VertexAttribType::Int:
+ switch (components)
+ {
+ case 1:
+ if (pureInteger)
+ return angle::FormatID::R32_SINT;
+ if (normalized)
+ return angle::FormatID::R32_SNORM;
+ return angle::FormatID::R32_SSCALED;
+ case 2:
+ if (pureInteger)
+ return angle::FormatID::R32G32_SINT;
+ if (normalized)
+ return angle::FormatID::R32G32_SNORM;
+ return angle::FormatID::R32G32_SSCALED;
+ case 3:
+ if (pureInteger)
+ return angle::FormatID::R32G32B32_SINT;
+ if (normalized)
+ return angle::FormatID::R32G32B32_SNORM;
+ return angle::FormatID::R32G32B32_SSCALED;
+ case 4:
+ if (pureInteger)
+ return angle::FormatID::R32G32B32A32_SINT;
+ if (normalized)
+ return angle::FormatID::R32G32B32A32_SNORM;
+ return angle::FormatID::R32G32B32A32_SSCALED;
+ default:
+ UNREACHABLE();
+ return angle::FormatID::NONE;
+ }
+ case VertexAttribType::UnsignedInt:
+ switch (components)
+ {
+ case 1:
+ if (pureInteger)
+ return angle::FormatID::R32_UINT;
+ if (normalized)
+ return angle::FormatID::R32_UNORM;
+ return angle::FormatID::R32_USCALED;
+ case 2:
+ if (pureInteger)
+ return angle::FormatID::R32G32_UINT;
+ if (normalized)
+ return angle::FormatID::R32G32_UNORM;
+ return angle::FormatID::R32G32_USCALED;
+ case 3:
+ if (pureInteger)
+ return angle::FormatID::R32G32B32_UINT;
+ if (normalized)
+ return angle::FormatID::R32G32B32_UNORM;
+ return angle::FormatID::R32G32B32_USCALED;
+ case 4:
+ if (pureInteger)
+ return angle::FormatID::R32G32B32A32_UINT;
+ if (normalized)
+ return angle::FormatID::R32G32B32A32_UNORM;
+ return angle::FormatID::R32G32B32A32_USCALED;
+ default:
+ UNREACHABLE();
+ return angle::FormatID::NONE;
+ }
+ case VertexAttribType::Float:
+ switch (components)
+ {
+ case 1:
+ return angle::FormatID::R32_FLOAT;
+ case 2:
+ return angle::FormatID::R32G32_FLOAT;
+ case 3:
+ return angle::FormatID::R32G32B32_FLOAT;
+ case 4:
+ return angle::FormatID::R32G32B32A32_FLOAT;
+ default:
+ UNREACHABLE();
+ return angle::FormatID::NONE;
+ }
+ case VertexAttribType::HalfFloat:
+ case VertexAttribType::HalfFloatOES:
+ switch (components)
+ {
+ case 1:
+ return angle::FormatID::R16_FLOAT;
+ case 2:
+ return angle::FormatID::R16G16_FLOAT;
+ case 3:
+ return angle::FormatID::R16G16B16_FLOAT;
+ case 4:
+ return angle::FormatID::R16G16B16A16_FLOAT;
+ default:
+ UNREACHABLE();
+ return angle::FormatID::NONE;
+ }
+ case VertexAttribType::Fixed:
+ switch (components)
+ {
+ case 1:
+ return angle::FormatID::R32_FIXED;
+ case 2:
+ return angle::FormatID::R32G32_FIXED;
+ case 3:
+ return angle::FormatID::R32G32B32_FIXED;
+ case 4:
+ return angle::FormatID::R32G32B32A32_FIXED;
+ default:
+ UNREACHABLE();
+ return angle::FormatID::NONE;
+ }
+ case VertexAttribType::Int2101010:
+ if (pureInteger)
+ return angle::FormatID::R10G10B10A2_SINT;
+ if (normalized)
+ return angle::FormatID::R10G10B10A2_SNORM;
+ return angle::FormatID::R10G10B10A2_SSCALED;
+ case VertexAttribType::UnsignedInt2101010:
+ if (pureInteger)
+ return angle::FormatID::R10G10B10A2_UINT;
+ if (normalized)
+ return angle::FormatID::R10G10B10A2_UNORM;
+ return angle::FormatID::R10G10B10A2_USCALED;
+ case VertexAttribType::Int1010102:
+ switch (components)
+ {
+ case 3:
+ if (pureInteger)
+ return angle::FormatID::X2R10G10B10_SINT_VERTEX;
+ if (normalized)
+ return angle::FormatID::X2R10G10B10_SNORM_VERTEX;
+ return angle::FormatID::X2R10G10B10_SSCALED_VERTEX;
+ case 4:
+ if (pureInteger)
+ return angle::FormatID::A2R10G10B10_SINT_VERTEX;
+ if (normalized)
+ return angle::FormatID::A2R10G10B10_SNORM_VERTEX;
+ return angle::FormatID::A2R10G10B10_SSCALED_VERTEX;
+ default:
+ UNREACHABLE();
+ return angle::FormatID::NONE;
+ }
+ case VertexAttribType::UnsignedInt1010102:
+ switch (components)
+ {
+ case 3:
+ if (pureInteger)
+ return angle::FormatID::X2R10G10B10_UINT_VERTEX;
+ if (normalized)
+ return angle::FormatID::X2R10G10B10_UNORM_VERTEX;
+ return angle::FormatID::X2R10G10B10_USCALED_VERTEX;
+
+ case 4:
+ if (pureInteger)
+ return angle::FormatID::A2R10G10B10_UINT_VERTEX;
+ if (normalized)
+ return angle::FormatID::A2R10G10B10_UNORM_VERTEX;
+ return angle::FormatID::A2R10G10B10_USCALED_VERTEX;
+ default:
+ UNREACHABLE();
+ return angle::FormatID::NONE;
+ }
+ default:
+ UNREACHABLE();
+ return angle::FormatID::NONE;
+ }
+}
+
+angle::FormatID GetVertexFormatID(const VertexAttribute &attrib, VertexAttribType currentValueType)
+{
+ if (!attrib.enabled)
+ {
+ return GetCurrentValueFormatID(currentValueType);
+ }
+ return attrib.format->id;
+}
+
+angle::FormatID GetCurrentValueFormatID(VertexAttribType currentValueType)
+{
+ switch (currentValueType)
+ {
+ case VertexAttribType::Float:
+ return angle::FormatID::R32G32B32A32_FLOAT;
+ case VertexAttribType::Int:
+ return angle::FormatID::R32G32B32A32_SINT;
+ case VertexAttribType::UnsignedInt:
+ return angle::FormatID::R32G32B32A32_UINT;
+ default:
+ UNREACHABLE();
+ return angle::FormatID::NONE;
+ }
+}
+
+const VertexFormat &GetVertexFormatFromID(angle::FormatID vertexFormatID)
+{
+ switch (vertexFormatID)
+ {
+ case angle::FormatID::R8_SSCALED:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 1, false);
+ return format;
+ }
+ case angle::FormatID::R8_SNORM:
+ {
+ static const VertexFormat format(GL_BYTE, GL_TRUE, 1, false);
+ return format;
+ }
+ case angle::FormatID::R8G8_SSCALED:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 2, false);
+ return format;
+ }
+ case angle::FormatID::R8G8_SNORM:
+ {
+ static const VertexFormat format(GL_BYTE, GL_TRUE, 2, false);
+ return format;
+ }
+ case angle::FormatID::R8G8B8_SSCALED:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 3, false);
+ return format;
+ }
+ case angle::FormatID::R8G8B8_SNORM:
+ {
+ static const VertexFormat format(GL_BYTE, GL_TRUE, 3, false);
+ return format;
+ }
+ case angle::FormatID::R8G8B8A8_SSCALED:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R8G8B8A8_SNORM:
+ {
+ static const VertexFormat format(GL_BYTE, GL_TRUE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R8_USCALED:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 1, false);
+ return format;
+ }
+ case angle::FormatID::R8_UNORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 1, false);
+ return format;
+ }
+ case angle::FormatID::R8G8_USCALED:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 2, false);
+ return format;
+ }
+ case angle::FormatID::R8G8_UNORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 2, false);
+ return format;
+ }
+ case angle::FormatID::R8G8B8_USCALED:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 3, false);
+ return format;
+ }
+ case angle::FormatID::R8G8B8_UNORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 3, false);
+ return format;
+ }
+ case angle::FormatID::R8G8B8A8_USCALED:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R8G8B8A8_UNORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R16_SSCALED:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 1, false);
+ return format;
+ }
+ case angle::FormatID::R16_SNORM:
+ {
+ static const VertexFormat format(GL_SHORT, GL_TRUE, 1, false);
+ return format;
+ }
+ case angle::FormatID::R16G16_SSCALED:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 2, false);
+ return format;
+ }
+ case angle::FormatID::R16G16_SNORM:
+ {
+ static const VertexFormat format(GL_SHORT, GL_TRUE, 2, false);
+ return format;
+ }
+ case angle::FormatID::R16G16B16_SSCALED:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 3, false);
+ return format;
+ }
+ case angle::FormatID::R16G16B16_SNORM:
+ {
+ static const VertexFormat format(GL_SHORT, GL_TRUE, 3, false);
+ return format;
+ }
+ case angle::FormatID::R16G16B16A16_SSCALED:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R16G16B16A16_SNORM:
+ {
+ static const VertexFormat format(GL_SHORT, GL_TRUE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R16_USCALED:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 1, false);
+ return format;
+ }
+ case angle::FormatID::R16_UNORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 1, false);
+ return format;
+ }
+ case angle::FormatID::R16G16_USCALED:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 2, false);
+ return format;
+ }
+ case angle::FormatID::R16G16_UNORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 2, false);
+ return format;
+ }
+ case angle::FormatID::R16G16B16_USCALED:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 3, false);
+ return format;
+ }
+ case angle::FormatID::R16G16B16_UNORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 3, false);
+ return format;
+ }
+ case angle::FormatID::R16G16B16A16_USCALED:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R16G16B16A16_UNORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R32_SSCALED:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 1, false);
+ return format;
+ }
+ case angle::FormatID::R32_SNORM:
+ {
+ static const VertexFormat format(GL_INT, GL_TRUE, 1, false);
+ return format;
+ }
+ case angle::FormatID::R32G32_SSCALED:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 2, false);
+ return format;
+ }
+ case angle::FormatID::R32G32_SNORM:
+ {
+ static const VertexFormat format(GL_INT, GL_TRUE, 2, false);
+ return format;
+ }
+ case angle::FormatID::R32G32B32_SSCALED:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 3, false);
+ return format;
+ }
+ case angle::FormatID::R32G32B32_SNORM:
+ {
+ static const VertexFormat format(GL_INT, GL_TRUE, 3, false);
+ return format;
+ }
+ case angle::FormatID::R32G32B32A32_SSCALED:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R32G32B32A32_SNORM:
+ {
+ static const VertexFormat format(GL_INT, GL_TRUE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R32_USCALED:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 1, false);
+ return format;
+ }
+ case angle::FormatID::R32_UNORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 1, false);
+ return format;
+ }
+ case angle::FormatID::R32G32_USCALED:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 2, false);
+ return format;
+ }
+ case angle::FormatID::R32G32_UNORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 2, false);
+ return format;
+ }
+ case angle::FormatID::R32G32B32_USCALED:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 3, false);
+ return format;
+ }
+ case angle::FormatID::R32G32B32_UNORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 3, false);
+ return format;
+ }
+ case angle::FormatID::R32G32B32A32_USCALED:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R32G32B32A32_UNORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R8_SINT:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 1, true);
+ return format;
+ }
+ case angle::FormatID::R8G8_SINT:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 2, true);
+ return format;
+ }
+ case angle::FormatID::R8G8B8_SINT:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 3, true);
+ return format;
+ }
+ case angle::FormatID::R8G8B8A8_SINT:
+ {
+ static const VertexFormat format(GL_BYTE, GL_FALSE, 4, true);
+ return format;
+ }
+ case angle::FormatID::R8_UINT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 1, true);
+ return format;
+ }
+ case angle::FormatID::R8G8_UINT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 2, true);
+ return format;
+ }
+ case angle::FormatID::R8G8B8_UINT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 3, true);
+ return format;
+ }
+ case angle::FormatID::R8G8B8A8_UINT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 4, true);
+ return format;
+ }
+ case angle::FormatID::R16_SINT:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 1, true);
+ return format;
+ }
+ case angle::FormatID::R16G16_SINT:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 2, true);
+ return format;
+ }
+ case angle::FormatID::R16G16B16_SINT:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 3, true);
+ return format;
+ }
+ case angle::FormatID::R16G16B16A16_SINT:
+ {
+ static const VertexFormat format(GL_SHORT, GL_FALSE, 4, true);
+ return format;
+ }
+ case angle::FormatID::R16_UINT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 1, true);
+ return format;
+ }
+ case angle::FormatID::R16G16_UINT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 2, true);
+ return format;
+ }
+ case angle::FormatID::R16G16B16_UINT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 3, true);
+ return format;
+ }
+ case angle::FormatID::R16G16B16A16_UINT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 4, true);
+ return format;
+ }
+ case angle::FormatID::R32_SINT:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 1, true);
+ return format;
+ }
+ case angle::FormatID::R32G32_SINT:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 2, true);
+ return format;
+ }
+ case angle::FormatID::R32G32B32_SINT:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 3, true);
+ return format;
+ }
+ case angle::FormatID::R32G32B32A32_SINT:
+ {
+ static const VertexFormat format(GL_INT, GL_FALSE, 4, true);
+ return format;
+ }
+ case angle::FormatID::R32_UINT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 1, true);
+ return format;
+ }
+ case angle::FormatID::R32G32_UINT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 2, true);
+ return format;
+ }
+ case angle::FormatID::R32G32B32_UINT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 3, true);
+ return format;
+ }
+ case angle::FormatID::R32G32B32A32_UINT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 4, true);
+ return format;
+ }
+ case angle::FormatID::R32_FIXED:
+ {
+ static const VertexFormat format(GL_FIXED, GL_FALSE, 1, false);
+ return format;
+ }
+ case angle::FormatID::R32G32_FIXED:
+ {
+ static const VertexFormat format(GL_FIXED, GL_FALSE, 2, false);
+ return format;
+ }
+ case angle::FormatID::R32G32B32_FIXED:
+ {
+ static const VertexFormat format(GL_FIXED, GL_FALSE, 3, false);
+ return format;
+ }
+ case angle::FormatID::R32G32B32A32_FIXED:
+ {
+ static const VertexFormat format(GL_FIXED, GL_FALSE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R16_FLOAT:
+ {
+ static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 1, false);
+ return format;
+ }
+ case angle::FormatID::R16G16_FLOAT:
+ {
+ static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 2, false);
+ return format;
+ }
+ case angle::FormatID::R16G16B16_FLOAT:
+ {
+ static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 3, false);
+ return format;
+ }
+ case angle::FormatID::R16G16B16A16_FLOAT:
+ {
+ static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R32_FLOAT:
+ {
+ static const VertexFormat format(GL_FLOAT, GL_FALSE, 1, false);
+ return format;
+ }
+ case angle::FormatID::R32G32_FLOAT:
+ {
+ static const VertexFormat format(GL_FLOAT, GL_FALSE, 2, false);
+ return format;
+ }
+ case angle::FormatID::R32G32B32_FLOAT:
+ {
+ static const VertexFormat format(GL_FLOAT, GL_FALSE, 3, false);
+ return format;
+ }
+ case angle::FormatID::R32G32B32A32_FLOAT:
+ {
+ static const VertexFormat format(GL_FLOAT, GL_FALSE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R10G10B10A2_SSCALED:
+ {
+ static const VertexFormat format(GL_INT_2_10_10_10_REV, GL_FALSE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R10G10B10A2_USCALED:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R10G10B10A2_SNORM:
+ {
+ static const VertexFormat format(GL_INT_2_10_10_10_REV, GL_TRUE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R10G10B10A2_UNORM:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, false);
+ return format;
+ }
+ case angle::FormatID::R10G10B10A2_SINT:
+ {
+ static const VertexFormat format(GL_INT_2_10_10_10_REV, GL_FALSE, 4, true);
+ return format;
+ }
+ case angle::FormatID::R10G10B10A2_UINT:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, true);
+ return format;
+ }
+ case angle::FormatID::A2R10G10B10_SSCALED_VERTEX:
+ {
+ static const VertexFormat format(GL_INT_10_10_10_2_OES, GL_FALSE, 4, false);
+ return format;
+ }
+ case angle::FormatID::A2R10G10B10_USCALED_VERTEX:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT_10_10_10_2_OES, GL_FALSE, 4, false);
+ return format;
+ }
+ case angle::FormatID::A2R10G10B10_SNORM_VERTEX:
+ {
+ static const VertexFormat format(GL_INT_10_10_10_2_OES, GL_TRUE, 4, false);
+ return format;
+ }
+ case angle::FormatID::A2R10G10B10_UNORM_VERTEX:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT_10_10_10_2_OES, GL_TRUE, 4, false);
+ return format;
+ }
+ case angle::FormatID::A2R10G10B10_SINT_VERTEX:
+ {
+ static const VertexFormat format(GL_INT_10_10_10_2_OES, GL_FALSE, 4, true);
+ return format;
+ }
+ case angle::FormatID::A2R10G10B10_UINT_VERTEX:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT_10_10_10_2_OES, GL_FALSE, 4, true);
+ return format;
+ }
+ case angle::FormatID::X2R10G10B10_SSCALED_VERTEX:
+ {
+ static const VertexFormat format(GL_INT_10_10_10_2_OES, GL_FALSE, 4, false);
+ return format;
+ }
+ case angle::FormatID::X2R10G10B10_USCALED_VERTEX:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT_10_10_10_2_OES, GL_FALSE, 4, false);
+ return format;
+ }
+ case angle::FormatID::X2R10G10B10_SNORM_VERTEX:
+ {
+ static const VertexFormat format(GL_INT_10_10_10_2_OES, GL_TRUE, 4, false);
+ return format;
+ }
+ case angle::FormatID::X2R10G10B10_UNORM_VERTEX:
+ {
+ static const VertexFormat format(GL_UNSIGNED_INT_10_10_10_2_OES, GL_TRUE, 4, false);
+ return format;
+ }
+ case angle::FormatID::X2R10G10B10_SINT_VERTEX:
+ {
+ static const VertexFormat format(GL_INT_10_10_10_2_OES, GL_FALSE, 4, true);
+ return format;
+ }
+ default:
+ {
+ static const VertexFormat format(GL_NONE, GL_FALSE, 0, false);
+ return format;
+ }
+ }
+}
+
+size_t GetVertexFormatSize(angle::FormatID vertexFormatID)
+{
+ switch (vertexFormatID)
+ {
+ case angle::FormatID::R8_SSCALED:
+ case angle::FormatID::R8_SNORM:
+ case angle::FormatID::R8_USCALED:
+ case angle::FormatID::R8_UNORM:
+ case angle::FormatID::R8_SINT:
+ case angle::FormatID::R8_UINT:
+ return 1;
+
+ case angle::FormatID::R8G8_SSCALED:
+ case angle::FormatID::R8G8_SNORM:
+ case angle::FormatID::R8G8_USCALED:
+ case angle::FormatID::R8G8_UNORM:
+ case angle::FormatID::R8G8_SINT:
+ case angle::FormatID::R8G8_UINT:
+ case angle::FormatID::R16_SSCALED:
+ case angle::FormatID::R16_SNORM:
+ case angle::FormatID::R16_USCALED:
+ case angle::FormatID::R16_UNORM:
+ case angle::FormatID::R16_SINT:
+ case angle::FormatID::R16_UINT:
+ case angle::FormatID::R16_FLOAT:
+ return 2;
+
+ case angle::FormatID::R8G8B8_SSCALED:
+ case angle::FormatID::R8G8B8_SNORM:
+ case angle::FormatID::R8G8B8_USCALED:
+ case angle::FormatID::R8G8B8_UNORM:
+ case angle::FormatID::R8G8B8_SINT:
+ case angle::FormatID::R8G8B8_UINT:
+ return 3;
+
+ case angle::FormatID::R8G8B8A8_SSCALED:
+ case angle::FormatID::R8G8B8A8_SNORM:
+ case angle::FormatID::R8G8B8A8_USCALED:
+ case angle::FormatID::R8G8B8A8_UNORM:
+ case angle::FormatID::R8G8B8A8_SINT:
+ case angle::FormatID::R8G8B8A8_UINT:
+ case angle::FormatID::R16G16_SSCALED:
+ case angle::FormatID::R16G16_SNORM:
+ case angle::FormatID::R16G16_USCALED:
+ case angle::FormatID::R16G16_UNORM:
+ case angle::FormatID::R16G16_SINT:
+ case angle::FormatID::R16G16_UINT:
+ case angle::FormatID::R32_SSCALED:
+ case angle::FormatID::R32_SNORM:
+ case angle::FormatID::R32_USCALED:
+ case angle::FormatID::R32_UNORM:
+ case angle::FormatID::R32_SINT:
+ case angle::FormatID::R32_UINT:
+ case angle::FormatID::R16G16_FLOAT:
+ case angle::FormatID::R32_FIXED:
+ case angle::FormatID::R32_FLOAT:
+ case angle::FormatID::R10G10B10A2_SSCALED:
+ case angle::FormatID::R10G10B10A2_USCALED:
+ case angle::FormatID::R10G10B10A2_SNORM:
+ case angle::FormatID::R10G10B10A2_UNORM:
+ case angle::FormatID::R10G10B10A2_SINT:
+ case angle::FormatID::R10G10B10A2_UINT:
+ case angle::FormatID::A2R10G10B10_SSCALED_VERTEX:
+ case angle::FormatID::A2R10G10B10_USCALED_VERTEX:
+ case angle::FormatID::A2R10G10B10_SINT_VERTEX:
+ case angle::FormatID::A2R10G10B10_UINT_VERTEX:
+ case angle::FormatID::A2R10G10B10_SNORM_VERTEX:
+ case angle::FormatID::A2R10G10B10_UNORM_VERTEX:
+ case angle::FormatID::X2R10G10B10_SSCALED_VERTEX:
+ case angle::FormatID::X2R10G10B10_USCALED_VERTEX:
+ case angle::FormatID::X2R10G10B10_SINT_VERTEX:
+ case angle::FormatID::X2R10G10B10_UINT_VERTEX:
+ case angle::FormatID::X2R10G10B10_SNORM_VERTEX:
+ case angle::FormatID::X2R10G10B10_UNORM_VERTEX:
+ return 4;
+
+ case angle::FormatID::R16G16B16_SSCALED:
+ case angle::FormatID::R16G16B16_SNORM:
+ case angle::FormatID::R16G16B16_USCALED:
+ case angle::FormatID::R16G16B16_UNORM:
+ case angle::FormatID::R16G16B16_SINT:
+ case angle::FormatID::R16G16B16_UINT:
+ case angle::FormatID::R16G16B16_FLOAT:
+ return 6;
+
+ case angle::FormatID::R16G16B16A16_SSCALED:
+ case angle::FormatID::R16G16B16A16_SNORM:
+ case angle::FormatID::R16G16B16A16_USCALED:
+ case angle::FormatID::R16G16B16A16_UNORM:
+ case angle::FormatID::R16G16B16A16_SINT:
+ case angle::FormatID::R16G16B16A16_UINT:
+ case angle::FormatID::R32G32_SSCALED:
+ case angle::FormatID::R32G32_SNORM:
+ case angle::FormatID::R32G32_USCALED:
+ case angle::FormatID::R32G32_UNORM:
+ case angle::FormatID::R32G32_SINT:
+ case angle::FormatID::R32G32_UINT:
+ case angle::FormatID::R16G16B16A16_FLOAT:
+ case angle::FormatID::R32G32_FIXED:
+ case angle::FormatID::R32G32_FLOAT:
+ return 8;
+
+ case angle::FormatID::R32G32B32_SSCALED:
+ case angle::FormatID::R32G32B32_SNORM:
+ case angle::FormatID::R32G32B32_USCALED:
+ case angle::FormatID::R32G32B32_UNORM:
+ case angle::FormatID::R32G32B32_SINT:
+ case angle::FormatID::R32G32B32_UINT:
+ case angle::FormatID::R32G32B32_FIXED:
+ case angle::FormatID::R32G32B32_FLOAT:
+ return 12;
+
+ case angle::FormatID::R32G32B32A32_SSCALED:
+ case angle::FormatID::R32G32B32A32_SNORM:
+ case angle::FormatID::R32G32B32A32_USCALED:
+ case angle::FormatID::R32G32B32A32_UNORM:
+ case angle::FormatID::R32G32B32A32_SINT:
+ case angle::FormatID::R32G32B32A32_UINT:
+ case angle::FormatID::R32G32B32A32_FIXED:
+ case angle::FormatID::R32G32B32A32_FLOAT:
+ return 16;
+
+ case angle::FormatID::NONE:
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+angle::FormatID ConvertFormatSignedness(const angle::Format &format)
+{
+ switch (format.id)
+ {
+ // 1 byte signed to unsigned
+ case angle::FormatID::R8_SINT:
+ return angle::FormatID::R8_UINT;
+ case angle::FormatID::R8_SNORM:
+ return angle::FormatID::R8_UNORM;
+ case angle::FormatID::R8_SSCALED:
+ return angle::FormatID::R8_USCALED;
+ case angle::FormatID::R8G8_SINT:
+ return angle::FormatID::R8G8_UINT;
+ case angle::FormatID::R8G8_SNORM:
+ return angle::FormatID::R8G8_UNORM;
+ case angle::FormatID::R8G8_SSCALED:
+ return angle::FormatID::R8G8_USCALED;
+ case angle::FormatID::R8G8B8_SINT:
+ return angle::FormatID::R8G8B8_UINT;
+ case angle::FormatID::R8G8B8_SNORM:
+ return angle::FormatID::R8G8B8_UNORM;
+ case angle::FormatID::R8G8B8_SSCALED:
+ return angle::FormatID::R8G8B8_USCALED;
+ case angle::FormatID::R8G8B8A8_SINT:
+ return angle::FormatID::R8G8B8A8_UINT;
+ case angle::FormatID::R8G8B8A8_SNORM:
+ return angle::FormatID::R8G8B8A8_UNORM;
+ case angle::FormatID::R8G8B8A8_SSCALED:
+ return angle::FormatID::R8G8B8A8_USCALED;
+ // 1 byte unsigned to signed
+ case angle::FormatID::R8_UINT:
+ return angle::FormatID::R8_SINT;
+ case angle::FormatID::R8_UNORM:
+ return angle::FormatID::R8_SNORM;
+ case angle::FormatID::R8_USCALED:
+ return angle::FormatID::R8_SSCALED;
+ case angle::FormatID::R8G8_UINT:
+ return angle::FormatID::R8G8_SINT;
+ case angle::FormatID::R8G8_UNORM:
+ return angle::FormatID::R8G8_SNORM;
+ case angle::FormatID::R8G8_USCALED:
+ return angle::FormatID::R8G8_SSCALED;
+ case angle::FormatID::R8G8B8_UINT:
+ return angle::FormatID::R8G8B8_SINT;
+ case angle::FormatID::R8G8B8_UNORM:
+ return angle::FormatID::R8G8B8_SNORM;
+ case angle::FormatID::R8G8B8_USCALED:
+ return angle::FormatID::R8G8B8_SSCALED;
+ case angle::FormatID::R8G8B8A8_UINT:
+ return angle::FormatID::R8G8B8A8_SINT;
+ case angle::FormatID::R8G8B8A8_UNORM:
+ return angle::FormatID::R8G8B8A8_SNORM;
+ case angle::FormatID::R8G8B8A8_USCALED:
+ return angle::FormatID::R8G8B8A8_SSCALED;
+ // 2 byte signed to unsigned
+ case angle::FormatID::R16_SINT:
+ return angle::FormatID::R16_UINT;
+ case angle::FormatID::R16_SNORM:
+ return angle::FormatID::R16_UNORM;
+ case angle::FormatID::R16_SSCALED:
+ return angle::FormatID::R16_USCALED;
+ case angle::FormatID::R16G16_SINT:
+ return angle::FormatID::R16G16_UINT;
+ case angle::FormatID::R16G16_SNORM:
+ return angle::FormatID::R16G16_UNORM;
+ case angle::FormatID::R16G16_SSCALED:
+ return angle::FormatID::R16G16_USCALED;
+ case angle::FormatID::R16G16B16_SINT:
+ return angle::FormatID::R16G16B16_UINT;
+ case angle::FormatID::R16G16B16_SNORM:
+ return angle::FormatID::R16G16B16_UNORM;
+ case angle::FormatID::R16G16B16_SSCALED:
+ return angle::FormatID::R16G16B16_USCALED;
+ case angle::FormatID::R16G16B16A16_SINT:
+ return angle::FormatID::R16G16B16A16_UINT;
+ case angle::FormatID::R16G16B16A16_SNORM:
+ return angle::FormatID::R16G16B16A16_UNORM;
+ case angle::FormatID::R16G16B16A16_SSCALED:
+ return angle::FormatID::R16G16B16A16_USCALED;
+ // 2 byte unsigned to signed
+ case angle::FormatID::R16_UINT:
+ return angle::FormatID::R16_SINT;
+ case angle::FormatID::R16_UNORM:
+ return angle::FormatID::R16_SNORM;
+ case angle::FormatID::R16_USCALED:
+ return angle::FormatID::R16_SSCALED;
+ case angle::FormatID::R16G16_UINT:
+ return angle::FormatID::R16G16_SINT;
+ case angle::FormatID::R16G16_UNORM:
+ return angle::FormatID::R16G16_SNORM;
+ case angle::FormatID::R16G16_USCALED:
+ return angle::FormatID::R16G16_SSCALED;
+ case angle::FormatID::R16G16B16_UINT:
+ return angle::FormatID::R16G16B16_SINT;
+ case angle::FormatID::R16G16B16_UNORM:
+ return angle::FormatID::R16G16B16_SNORM;
+ case angle::FormatID::R16G16B16_USCALED:
+ return angle::FormatID::R16G16B16_SSCALED;
+ case angle::FormatID::R16G16B16A16_UINT:
+ return angle::FormatID::R16G16B16A16_SINT;
+ case angle::FormatID::R16G16B16A16_UNORM:
+ return angle::FormatID::R16G16B16A16_SNORM;
+ case angle::FormatID::R16G16B16A16_USCALED:
+ return angle::FormatID::R16G16B16A16_SSCALED;
+ // 4 byte signed to unsigned
+ case angle::FormatID::R32_SINT:
+ return angle::FormatID::R32_UINT;
+ case angle::FormatID::R32_SNORM:
+ return angle::FormatID::R32_UNORM;
+ case angle::FormatID::R32_SSCALED:
+ return angle::FormatID::R32_USCALED;
+ case angle::FormatID::R32G32_SINT:
+ return angle::FormatID::R32G32_UINT;
+ case angle::FormatID::R32G32_SNORM:
+ return angle::FormatID::R32G32_UNORM;
+ case angle::FormatID::R32G32_SSCALED:
+ return angle::FormatID::R32G32_USCALED;
+ case angle::FormatID::R32G32B32_SINT:
+ return angle::FormatID::R32G32B32_UINT;
+ case angle::FormatID::R32G32B32_SNORM:
+ return angle::FormatID::R32G32B32_UNORM;
+ case angle::FormatID::R32G32B32_SSCALED:
+ return angle::FormatID::R32G32B32_USCALED;
+ case angle::FormatID::R32G32B32A32_SINT:
+ return angle::FormatID::R32G32B32A32_UINT;
+ case angle::FormatID::R32G32B32A32_SNORM:
+ return angle::FormatID::R32G32B32A32_UNORM;
+ case angle::FormatID::R32G32B32A32_SSCALED:
+ return angle::FormatID::R32G32B32A32_USCALED;
+ // 4 byte unsigned to signed
+ case angle::FormatID::R32_UINT:
+ return angle::FormatID::R32_SINT;
+ case angle::FormatID::R32_UNORM:
+ return angle::FormatID::R32_SNORM;
+ case angle::FormatID::R32_USCALED:
+ return angle::FormatID::R32_SSCALED;
+ case angle::FormatID::R32G32_UINT:
+ return angle::FormatID::R32G32_SINT;
+ case angle::FormatID::R32G32_UNORM:
+ return angle::FormatID::R32G32_SNORM;
+ case angle::FormatID::R32G32_USCALED:
+ return angle::FormatID::R32G32_SSCALED;
+ case angle::FormatID::R32G32B32_UINT:
+ return angle::FormatID::R32G32B32_SINT;
+ case angle::FormatID::R32G32B32_UNORM:
+ return angle::FormatID::R32G32B32_SNORM;
+ case angle::FormatID::R32G32B32_USCALED:
+ return angle::FormatID::R32G32B32_SSCALED;
+ case angle::FormatID::R32G32B32A32_UINT:
+ return angle::FormatID::R32G32B32A32_SINT;
+ case angle::FormatID::R32G32B32A32_UNORM:
+ return angle::FormatID::R32G32B32A32_SNORM;
+ case angle::FormatID::R32G32B32A32_USCALED:
+ return angle::FormatID::R32G32B32A32_SSCALED;
+ // 1010102 signed to unsigned
+ case angle::FormatID::R10G10B10A2_SINT:
+ return angle::FormatID::R10G10B10A2_UINT;
+ case angle::FormatID::R10G10B10A2_SSCALED:
+ return angle::FormatID::R10G10B10A2_USCALED;
+ case angle::FormatID::R10G10B10A2_SNORM:
+ return angle::FormatID::R10G10B10A2_UNORM;
+ // 1010102 unsigned to signed
+ case angle::FormatID::R10G10B10A2_UINT:
+ return angle::FormatID::R10G10B10A2_SINT;
+ case angle::FormatID::R10G10B10A2_USCALED:
+ return angle::FormatID::R10G10B10A2_SSCALED;
+ case angle::FormatID::R10G10B10A2_UNORM:
+ return angle::FormatID::R10G10B10A2_SNORM;
+ default:
+ UNREACHABLE();
+ return angle::FormatID::NONE;
+ }
+}
+
+bool ValidES3InternalFormat(GLenum internalFormat)
+{
+ const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
+ return internalFormat != GL_NONE && formatMap.find(internalFormat) != formatMap.end();
+}
+
+VertexFormat::VertexFormat(GLenum typeIn,
+ GLboolean normalizedIn,
+ GLuint componentsIn,
+ bool pureIntegerIn)
+ : type(typeIn), normalized(normalizedIn), components(componentsIn), pureInteger(pureIntegerIn)
+{
+ // float -> !normalized
+ ASSERT(!(type == GL_FLOAT || type == GL_HALF_FLOAT || type == GL_FIXED) ||
+ normalized == GL_FALSE);
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/formatutils.h b/gfx/angle/checkout/src/libANGLE/formatutils.h
new file mode 100644
index 0000000000..64cc42ec1f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/formatutils.h
@@ -0,0 +1,577 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// formatutils.h: Queries for GL image formats.
+
+#ifndef LIBANGLE_FORMATUTILS_H_
+#define LIBANGLE_FORMATUTILS_H_
+
+#include <stdint.h>
+#include <cstddef>
+#include <ostream>
+
+#include "angle_gl.h"
+#include "common/android_util.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+struct VertexAttribute;
+
+struct FormatType final
+{
+ FormatType();
+ FormatType(GLenum format_, GLenum type_);
+ FormatType(const FormatType &other) = default;
+ FormatType &operator=(const FormatType &other) = default;
+
+ bool operator<(const FormatType &other) const;
+
+ GLenum format;
+ GLenum type;
+};
+
+struct Type
+{
+ Type() : bytes(0), bytesShift(0), specialInterpretation(0) {}
+
+ explicit Type(uint32_t packedTypeInfo)
+ : bytes(packedTypeInfo & 0xff),
+ bytesShift((packedTypeInfo >> 8) & 0xff),
+ specialInterpretation((packedTypeInfo >> 16) & 1)
+ {}
+
+ GLuint bytes;
+ GLuint bytesShift; // Bit shift by this value to effectively divide/multiply by "bytes" in a
+ // more optimal way
+ bool specialInterpretation;
+};
+
+uint32_t GetPackedTypeInfo(GLenum type);
+
+ANGLE_INLINE GLenum GetNonLinearFormat(const GLenum format)
+{
+ switch (format)
+ {
+ case GL_BGRA8_EXT:
+ return GL_BGRA8_SRGB_ANGLEX;
+ case GL_RGBA8:
+ return GL_SRGB8_ALPHA8;
+ case GL_RGB8:
+ case GL_BGRX8_ANGLEX:
+ case GL_RGBX8_ANGLE:
+ return GL_SRGB8;
+ case GL_RGBA16F:
+ return GL_RGBA16F;
+ default:
+ return GL_NONE;
+ }
+}
+
+ANGLE_INLINE bool ColorspaceFormatOverride(const EGLenum colorspace, GLenum *rendertargetformat)
+{
+ // Override the rendertargetformat based on colorpsace
+ switch (colorspace)
+ {
+ case EGL_GL_COLORSPACE_LINEAR: // linear colorspace no translation needed
+ case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT: // linear colorspace no translation needed
+ case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT: // linear colorspace no translation needed
+ case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT: // App, not the HW, will specify the
+ // transfer function
+ case EGL_GL_COLORSPACE_SCRGB_EXT: // App, not the HW, will specify the transfer function
+ // No translation
+ return true;
+ case EGL_GL_COLORSPACE_SRGB_KHR:
+ case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
+ {
+ GLenum nonLinearFormat = GetNonLinearFormat(*rendertargetformat);
+ if (nonLinearFormat != GL_NONE)
+ {
+ *rendertargetformat = nonLinearFormat;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ break;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+ANGLE_INLINE const Type GetTypeInfo(GLenum type)
+{
+ return Type(GetPackedTypeInfo(type));
+}
+
+// This helpers use tricks based on the assumption that the type has certain values.
+static_assert(static_cast<GLuint>(DrawElementsType::UnsignedByte) == 0, "Please update this code.");
+static_assert(static_cast<GLuint>(DrawElementsType::UnsignedShort) == 1,
+ "Please update this code.");
+static_assert(static_cast<GLuint>(DrawElementsType::UnsignedInt) == 2, "Please update this code.");
+ANGLE_INLINE GLuint GetDrawElementsTypeSize(DrawElementsType type)
+{
+ return (1 << static_cast<GLuint>(type));
+}
+
+ANGLE_INLINE GLuint GetDrawElementsTypeShift(DrawElementsType type)
+{
+ return static_cast<GLuint>(type);
+}
+
+// Information about an OpenGL internal format. Can be keyed on the internalFormat and type
+// members.
+struct InternalFormat
+{
+ InternalFormat();
+ InternalFormat(const InternalFormat &other);
+ InternalFormat &operator=(const InternalFormat &other);
+
+ GLuint computePixelBytes(GLenum formatType) const;
+
+ [[nodiscard]] bool computeBufferRowLength(uint32_t width, uint32_t *resultOut) const;
+ [[nodiscard]] bool computeBufferImageHeight(uint32_t height, uint32_t *resultOut) const;
+
+ [[nodiscard]] bool computeRowPitch(GLenum formatType,
+ GLsizei width,
+ GLint alignment,
+ GLint rowLength,
+ GLuint *resultOut) const;
+ [[nodiscard]] bool computeDepthPitch(GLsizei height,
+ GLint imageHeight,
+ GLuint rowPitch,
+ GLuint *resultOut) const;
+ [[nodiscard]] bool computeDepthPitch(GLenum formatType,
+ GLsizei width,
+ GLsizei height,
+ GLint alignment,
+ GLint rowLength,
+ GLint imageHeight,
+ GLuint *resultOut) const;
+
+ [[nodiscard]] bool computePalettedImageRowPitch(GLsizei width, GLuint *resultOut) const;
+
+ [[nodiscard]] bool computeCompressedImageSize(const Extents &size, GLuint *resultOut) const;
+
+ [[nodiscard]] std::pair<GLuint, GLuint> getCompressedImageMinBlocks() const;
+
+ [[nodiscard]] bool computeSkipBytes(GLenum formatType,
+ GLuint rowPitch,
+ GLuint depthPitch,
+ const PixelStoreStateBase &state,
+ bool is3D,
+ GLuint *resultOut) const;
+
+ [[nodiscard]] bool computePackUnpackEndByte(GLenum formatType,
+ const Extents &size,
+ const PixelStoreStateBase &state,
+ bool is3D,
+ GLuint *resultOut) const;
+
+ bool isLUMA() const;
+ GLenum getReadPixelsFormat(const Extensions &extensions) const;
+ GLenum getReadPixelsType(const Version &version) const;
+
+ // Support upload a portion of image?
+ bool supportSubImage() const;
+
+ ANGLE_INLINE bool isChannelSizeCompatible(GLuint redSize,
+ GLuint greenSize,
+ GLuint blueSize,
+ GLuint alphaSize) const
+ {
+ // We only check for equality in all channel sizes
+ return ((redSize == redBits) && (greenSize == greenBits) && (blueSize == blueBits) &&
+ (alphaSize == alphaBits));
+ }
+
+ // Return true if the format is a required renderbuffer format in the given version of the core
+ // spec. Note that it isn't always clear whether all the rules that apply to core required
+ // renderbuffer formats also apply to additional formats added by extensions. Because of this
+ // extension formats are conservatively not included.
+ bool isRequiredRenderbufferFormat(const Version &version) const;
+
+ bool isInt() const;
+ bool isDepthOrStencil() const;
+
+ bool operator==(const InternalFormat &other) const;
+ bool operator!=(const InternalFormat &other) const;
+
+ GLenum internalFormat;
+
+ bool sized;
+ GLenum sizedInternalFormat;
+
+ GLuint redBits;
+ GLuint greenBits;
+ GLuint blueBits;
+
+ GLuint luminanceBits;
+
+ GLuint alphaBits;
+ GLuint sharedBits;
+
+ GLuint depthBits;
+ GLuint stencilBits;
+
+ GLuint pixelBytes;
+
+ GLuint componentCount;
+
+ bool compressed;
+ GLuint compressedBlockWidth;
+ GLuint compressedBlockHeight;
+ GLuint compressedBlockDepth;
+
+ bool paletted;
+ GLuint paletteBits;
+
+ GLenum format;
+ GLenum type;
+
+ GLenum componentType;
+ GLenum colorEncoding;
+
+ typedef bool (*SupportCheckFunction)(const Version &, const Extensions &);
+ SupportCheckFunction textureSupport;
+ SupportCheckFunction filterSupport;
+ SupportCheckFunction textureAttachmentSupport; // glFramebufferTexture2D
+ SupportCheckFunction renderbufferSupport; // glFramebufferRenderbuffer
+ SupportCheckFunction blendSupport;
+};
+
+// A "Format" wraps an InternalFormat struct, querying it from either a sized internal format or
+// unsized internal format and type.
+// TODO(geofflang): Remove this, it doesn't add any more information than the InternalFormat object.
+struct Format
+{
+ // Sized types only.
+ explicit Format(GLenum internalFormat);
+
+ // Sized or unsized types.
+ explicit Format(const InternalFormat &internalFormat);
+ Format(GLenum internalFormat, GLenum type);
+
+ Format(const Format &other);
+ Format &operator=(const Format &other);
+
+ bool valid() const;
+
+ static Format Invalid();
+ static bool SameSized(const Format &a, const Format &b);
+ static bool EquivalentForBlit(const Format &a, const Format &b);
+
+ friend std::ostream &operator<<(std::ostream &os, const Format &fmt);
+
+ // This is the sized info.
+ const InternalFormat *info;
+};
+
+const InternalFormat &GetSizedInternalFormatInfo(GLenum internalFormat);
+const InternalFormat &GetInternalFormatInfo(GLenum internalFormat, GLenum type);
+
+// Strip sizing information from an internal format. Doesn't necessarily validate that the internal
+// format is valid.
+GLenum GetUnsizedFormat(GLenum internalFormat);
+
+// Return whether the compressed format requires whole image/mip level to be uploaded to texture.
+bool CompressedFormatRequiresWholeImage(GLenum internalFormat);
+
+// In support of GetImage, check for LUMA formats and override with real format
+void MaybeOverrideLuminance(GLenum &format, GLenum &type, GLenum actualFormat, GLenum actualType);
+
+typedef std::set<GLenum> FormatSet;
+const FormatSet &GetAllSizedInternalFormats();
+
+typedef angle::HashMap<GLenum, angle::HashMap<GLenum, InternalFormat>> InternalFormatInfoMap;
+const InternalFormatInfoMap &GetInternalFormatMap();
+
+int GetAndroidHardwareBufferFormatFromChannelSizes(const egl::AttributeMap &attribMap);
+
+GLenum GetConfigColorBufferFormat(const egl::Config *config);
+GLenum GetConfigDepthStencilBufferFormat(const egl::Config *config);
+
+ANGLE_INLINE int GetNativeVisualID(const InternalFormat &internalFormat)
+{
+ int nativeVisualId = 0;
+#if defined(ANGLE_PLATFORM_ANDROID)
+ nativeVisualId =
+ angle::android::GLInternalFormatToNativePixelFormat(internalFormat.internalFormat);
+#endif
+#if defined(ANGLE_PLATFORM_LINUX) && defined(ANGLE_USES_GBM)
+ nativeVisualId = angle::GLInternalFormatToGbmFourCCFormat(internalFormat.internalFormat);
+#endif
+
+ return nativeVisualId;
+}
+
+// From the ESSL 3.00.4 spec:
+// Vertex shader inputs can only be float, floating-point vectors, matrices, signed and unsigned
+// integers and integer vectors. Vertex shader inputs cannot be arrays or structures.
+
+enum AttributeType
+{
+ ATTRIBUTE_FLOAT,
+ ATTRIBUTE_VEC2,
+ ATTRIBUTE_VEC3,
+ ATTRIBUTE_VEC4,
+ ATTRIBUTE_INT,
+ ATTRIBUTE_IVEC2,
+ ATTRIBUTE_IVEC3,
+ ATTRIBUTE_IVEC4,
+ ATTRIBUTE_UINT,
+ ATTRIBUTE_UVEC2,
+ ATTRIBUTE_UVEC3,
+ ATTRIBUTE_UVEC4,
+ ATTRIBUTE_MAT2,
+ ATTRIBUTE_MAT3,
+ ATTRIBUTE_MAT4,
+ ATTRIBUTE_MAT2x3,
+ ATTRIBUTE_MAT2x4,
+ ATTRIBUTE_MAT3x2,
+ ATTRIBUTE_MAT3x4,
+ ATTRIBUTE_MAT4x2,
+ ATTRIBUTE_MAT4x3,
+};
+
+AttributeType GetAttributeType(GLenum enumValue);
+
+typedef std::vector<angle::FormatID> InputLayout;
+
+struct VertexFormat : private angle::NonCopyable
+{
+ VertexFormat(GLenum typeIn, GLboolean normalizedIn, GLuint componentsIn, bool pureIntegerIn);
+
+ GLenum type;
+ GLboolean normalized;
+ GLuint components;
+ bool pureInteger;
+};
+
+angle::FormatID GetVertexFormatID(VertexAttribType type,
+ GLboolean normalized,
+ GLuint components,
+ bool pureInteger);
+
+angle::FormatID GetVertexFormatID(const VertexAttribute &attrib, VertexAttribType currentValueType);
+angle::FormatID GetCurrentValueFormatID(VertexAttribType currentValueType);
+const VertexFormat &GetVertexFormatFromID(angle::FormatID vertexFormatID);
+size_t GetVertexFormatSize(angle::FormatID vertexFormatID);
+angle::FormatID ConvertFormatSignedness(const angle::Format &format);
+
+ANGLE_INLINE bool IsS3TCFormat(const GLenum format)
+{
+ switch (format)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+ANGLE_INLINE bool IsRGTCFormat(const GLenum format)
+{
+ switch (format)
+ {
+ case GL_COMPRESSED_RED_RGTC1_EXT:
+ case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
+ case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
+ case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+ANGLE_INLINE bool IsBPTCFormat(const GLenum format)
+{
+ switch (format)
+ {
+ case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+ANGLE_INLINE bool IsASTC2DFormat(const GLenum format)
+{
+ if ((format >= GL_COMPRESSED_RGBA_ASTC_4x4_KHR &&
+ format <= GL_COMPRESSED_RGBA_ASTC_12x12_KHR) ||
+ (format >= GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR &&
+ format <= GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR))
+ {
+ return true;
+ }
+ return false;
+}
+
+ANGLE_INLINE bool IsETC1Format(const GLenum format)
+{
+ switch (format)
+ {
+ case GL_ETC1_RGB8_OES:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+ANGLE_INLINE bool IsETC2EACFormat(const GLenum format)
+{
+ // ES 3.1, Table 8.19
+ switch (format)
+ {
+ case GL_COMPRESSED_R11_EAC:
+ case GL_COMPRESSED_SIGNED_R11_EAC:
+ case GL_COMPRESSED_RG11_EAC:
+ case GL_COMPRESSED_SIGNED_RG11_EAC:
+ case GL_COMPRESSED_RGB8_ETC2:
+ case GL_COMPRESSED_SRGB8_ETC2:
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ case GL_COMPRESSED_RGBA8_ETC2_EAC:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+ANGLE_INLINE bool IsPVRTC1Format(const GLenum format)
+{
+ switch (format)
+ {
+ case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
+ case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
+ case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
+ case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
+ case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
+ case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+ANGLE_INLINE bool IsBGRAFormat(const GLenum internalFormat)
+{
+ switch (internalFormat)
+ {
+ case GL_BGRA8_EXT:
+ case GL_BGRA4_ANGLEX:
+ case GL_BGR5_A1_ANGLEX:
+ case GL_BGRA8_SRGB_ANGLEX:
+ case GL_BGRX8_ANGLEX:
+ case GL_RGBX8_ANGLE:
+ case GL_BGR565_ANGLEX:
+ case GL_BGR10_A2_ANGLEX:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+// Check if an internal format is ever valid in ES3. Makes no checks about support for a specific
+// context.
+bool ValidES3InternalFormat(GLenum internalFormat);
+
+// Implemented in format_map_autogen.cpp
+bool ValidES3Format(GLenum format);
+bool ValidES3Type(GLenum type);
+bool ValidES3FormatCombination(GLenum format, GLenum type, GLenum internalFormat);
+
+// Implemented in format_map_desktop.cpp
+bool ValidDesktopFormat(GLenum format);
+bool ValidDesktopType(GLenum type);
+bool ValidDesktopFormatCombination(GLenum format, GLenum type, GLenum internalFormat);
+
+// Implemented in es3_copy_conversion_table_autogen.cpp
+bool ValidES3CopyConversion(GLenum textureFormat, GLenum framebufferFormat);
+
+ANGLE_INLINE ComponentType GetVertexAttributeComponentType(bool pureInteger, VertexAttribType type)
+{
+ if (pureInteger)
+ {
+ switch (type)
+ {
+ case VertexAttribType::Byte:
+ case VertexAttribType::Short:
+ case VertexAttribType::Int:
+ return ComponentType::Int;
+
+ case VertexAttribType::UnsignedByte:
+ case VertexAttribType::UnsignedShort:
+ case VertexAttribType::UnsignedInt:
+ return ComponentType::UnsignedInt;
+
+ default:
+ UNREACHABLE();
+ return ComponentType::NoType;
+ }
+ }
+ else
+ {
+ return ComponentType::Float;
+ }
+}
+
+constexpr std::size_t kMaxYuvPlaneCount = 3;
+template <typename T>
+using YuvPlaneArray = std::array<T, kMaxYuvPlaneCount>;
+
+struct YuvFormatInfo
+{
+ // Sized types only.
+ YuvFormatInfo(GLenum internalFormat, const Extents &yPlaneExtent);
+
+ GLenum glInternalFormat;
+ uint32_t planeCount;
+ YuvPlaneArray<uint32_t> planeBpp;
+ YuvPlaneArray<Extents> planeExtent;
+ YuvPlaneArray<uint32_t> planePitch;
+ YuvPlaneArray<uint32_t> planeSize;
+ YuvPlaneArray<uint32_t> planeOffset;
+};
+
+bool IsYuvFormat(GLenum format);
+uint32_t GetPlaneCount(GLenum format);
+uint32_t GetYPlaneBpp(GLenum format);
+uint32_t GetChromaPlaneBpp(GLenum format);
+void GetSubSampleFactor(GLenum format,
+ int *horizontalSubsampleFactor,
+ int *verticalSubsampleFactor);
+} // namespace gl
+
+#endif // LIBANGLE_FORMATUTILS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/gles_extensions_autogen.cpp b/gfx/angle/checkout/src/libANGLE/gles_extensions_autogen.cpp
new file mode 100644
index 0000000000..0caab7e0d9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/gles_extensions_autogen.cpp
@@ -0,0 +1,278 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_extensions.py using data from registry_xml.py and gl.xml
+//
+// Copyright 2021 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// gles_extensions_autogen.h: GLES extension strings information.
+
+#include "anglebase/no_destructor.h"
+#include "libANGLE/Caps.h"
+
+namespace gl
+{
+const ExtensionInfoMap &GetExtensionInfoMap()
+{
+ auto buildExtensionInfoMap = []() {
+ auto enableableExtension = [](ExtensionBool member) {
+ ExtensionInfo info;
+ info.Requestable = true;
+ info.ExtensionsMember = member;
+ return info;
+ };
+
+ auto enableableDisablableExtension = [&](ExtensionBool member) {
+ ExtensionInfo info = enableableExtension(member);
+ info.Disablable = true;
+ return info;
+ };
+
+ auto esOnlyExtension = [](ExtensionBool member) {
+ ExtensionInfo info;
+ info.ExtensionsMember = member;
+ return info;
+ };
+
+ // clang-format off
+ ExtensionInfoMap map;
+
+ // GLES 2.0 extension strings
+ // --------------------------
+ map["GL_EXT_base_instance"] = enableableExtension(&Extensions::baseInstanceEXT);
+ map["GL_KHR_blend_equation_advanced"] = esOnlyExtension(&Extensions::blendEquationAdvancedKHR);
+ map["GL_EXT_blend_func_extended"] = enableableExtension(&Extensions::blendFuncExtendedEXT);
+ map["GL_EXT_blend_minmax"] = enableableExtension(&Extensions::blendMinmaxEXT);
+ map["GL_EXT_buffer_storage"] = enableableExtension(&Extensions::bufferStorageEXT);
+ map["GL_EXT_clip_control"] = enableableExtension(&Extensions::clipControlEXT);
+ map["GL_EXT_clip_cull_distance"] = enableableExtension(&Extensions::clipCullDistanceEXT);
+ map["GL_APPLE_clip_distance"] = enableableExtension(&Extensions::clipDistanceAPPLE);
+ map["GL_EXT_color_buffer_float"] = enableableExtension(&Extensions::colorBufferFloatEXT);
+ map["GL_EXT_color_buffer_half_float"] = enableableExtension(&Extensions::colorBufferHalfFloatEXT);
+ map["GL_OES_compressed_EAC_R11_signed_texture"] = enableableExtension(&Extensions::compressedEACR11SignedTextureOES);
+ map["GL_OES_compressed_EAC_R11_unsigned_texture"] = enableableExtension(&Extensions::compressedEACR11UnsignedTextureOES);
+ map["GL_OES_compressed_EAC_RG11_signed_texture"] = enableableExtension(&Extensions::compressedEACRG11SignedTextureOES);
+ map["GL_OES_compressed_EAC_RG11_unsigned_texture"] = enableableExtension(&Extensions::compressedEACRG11UnsignedTextureOES);
+ map["GL_EXT_compressed_ETC1_RGB8_sub_texture"] = enableableExtension(&Extensions::compressedETC1RGB8SubTextureEXT);
+ map["GL_OES_compressed_ETC1_RGB8_texture"] = enableableExtension(&Extensions::compressedETC1RGB8TextureOES);
+ map["GL_OES_compressed_ETC2_punchthroughA_RGBA8_texture"] = enableableExtension(&Extensions::compressedETC2PunchthroughARGBA8TextureOES);
+ map["GL_OES_compressed_ETC2_punchthroughA_sRGB8_alpha_texture"] = enableableExtension(&Extensions::compressedETC2PunchthroughASRGB8AlphaTextureOES);
+ map["GL_OES_compressed_ETC2_RGB8_texture"] = enableableExtension(&Extensions::compressedETC2RGB8TextureOES);
+ map["GL_OES_compressed_ETC2_RGBA8_texture"] = enableableExtension(&Extensions::compressedETC2RGBA8TextureOES);
+ map["GL_OES_compressed_ETC2_sRGB8_alpha8_texture"] = enableableExtension(&Extensions::compressedETC2SRGB8Alpha8TextureOES);
+ map["GL_OES_compressed_ETC2_sRGB8_texture"] = enableableExtension(&Extensions::compressedETC2SRGB8TextureOES);
+ map["GL_OES_compressed_paletted_texture"] = enableableExtension(&Extensions::compressedPalettedTextureOES);
+ map["GL_EXT_copy_image"] = enableableExtension(&Extensions::copyImageEXT);
+ map["GL_OES_copy_image"] = enableableExtension(&Extensions::copyImageOES);
+ map["GL_KHR_debug"] = esOnlyExtension(&Extensions::debugKHR);
+ map["GL_EXT_debug_label"] = esOnlyExtension(&Extensions::debugLabelEXT);
+ map["GL_EXT_debug_marker"] = esOnlyExtension(&Extensions::debugMarkerEXT);
+ map["GL_OES_depth24"] = esOnlyExtension(&Extensions::depth24OES);
+ map["GL_OES_depth32"] = esOnlyExtension(&Extensions::depth32OES);
+ map["GL_NV_depth_buffer_float2"] = enableableExtension(&Extensions::depthBufferFloat2NV);
+ map["GL_ANGLE_depth_texture"] = esOnlyExtension(&Extensions::depthTextureANGLE);
+ map["GL_OES_depth_texture"] = esOnlyExtension(&Extensions::depthTextureOES);
+ map["GL_OES_depth_texture_cube_map"] = enableableExtension(&Extensions::depthTextureCubeMapOES);
+ map["GL_EXT_discard_framebuffer"] = esOnlyExtension(&Extensions::discardFramebufferEXT);
+ map["GL_EXT_disjoint_timer_query"] = enableableExtension(&Extensions::disjointTimerQueryEXT);
+ map["GL_EXT_draw_buffers"] = enableableExtension(&Extensions::drawBuffersEXT);
+ map["GL_EXT_draw_buffers_indexed"] = enableableExtension(&Extensions::drawBuffersIndexedEXT);
+ map["GL_OES_draw_buffers_indexed"] = enableableExtension(&Extensions::drawBuffersIndexedOES);
+ map["GL_EXT_draw_elements_base_vertex"] = enableableExtension(&Extensions::drawElementsBaseVertexEXT);
+ map["GL_OES_draw_elements_base_vertex"] = enableableExtension(&Extensions::drawElementsBaseVertexOES);
+ map["GL_OES_EGL_image"] = enableableExtension(&Extensions::EGLImageOES);
+ map["GL_EXT_EGL_image_array"] = enableableExtension(&Extensions::EGLImageArrayEXT);
+ map["GL_OES_EGL_image_external"] = enableableExtension(&Extensions::EGLImageExternalOES);
+ map["GL_OES_EGL_image_external_essl3"] = enableableExtension(&Extensions::EGLImageExternalEssl3OES);
+ map["GL_EXT_EGL_image_external_wrap_modes"] = enableableExtension(&Extensions::EGLImageExternalWrapModesEXT);
+ map["GL_EXT_EGL_image_storage"] = enableableExtension(&Extensions::EGLImageStorageEXT);
+ map["GL_NV_EGL_stream_consumer_external"] = enableableExtension(&Extensions::EGLStreamConsumerExternalNV);
+ map["GL_OES_EGL_sync"] = esOnlyExtension(&Extensions::EGLSyncOES);
+ map["GL_OES_element_index_uint"] = enableableExtension(&Extensions::elementIndexUintOES);
+ map["GL_ANDROID_extension_pack_es31a"] = esOnlyExtension(&Extensions::extensionPackEs31aANDROID);
+ map["GL_EXT_external_buffer"] = enableableExtension(&Extensions::externalBufferEXT);
+ map["GL_OES_fbo_render_mipmap"] = enableableExtension(&Extensions::fboRenderMipmapOES);
+ map["GL_NV_fence"] = esOnlyExtension(&Extensions::fenceNV);
+ map["GL_EXT_float_blend"] = enableableExtension(&Extensions::floatBlendEXT);
+ map["GL_EXT_frag_depth"] = enableableExtension(&Extensions::fragDepthEXT);
+ map["GL_ANGLE_framebuffer_blit"] = enableableExtension(&Extensions::framebufferBlitANGLE);
+ map["GL_NV_framebuffer_blit"] = enableableExtension(&Extensions::framebufferBlitNV);
+ map["GL_MESA_framebuffer_flip_y"] = enableableExtension(&Extensions::framebufferFlipYMESA);
+ map["GL_EXT_geometry_shader"] = enableableExtension(&Extensions::geometryShaderEXT);
+ map["GL_OES_geometry_shader"] = enableableExtension(&Extensions::geometryShaderOES);
+ map["GL_OES_get_program_binary"] = enableableExtension(&Extensions::getProgramBinaryOES);
+ map["GL_EXT_gpu_shader5"] = enableableExtension(&Extensions::gpuShader5EXT);
+ map["GL_ANGLE_instanced_arrays"] = enableableExtension(&Extensions::instancedArraysANGLE);
+ map["GL_EXT_instanced_arrays"] = enableableExtension(&Extensions::instancedArraysEXT);
+ map["GL_OES_mapbuffer"] = enableableExtension(&Extensions::mapbufferOES);
+ map["GL_EXT_map_buffer_range"] = enableableExtension(&Extensions::mapBufferRangeEXT);
+ map["GL_EXT_memory_object"] = enableableExtension(&Extensions::memoryObjectEXT);
+ map["GL_EXT_memory_object_fd"] = enableableExtension(&Extensions::memoryObjectFdEXT);
+ map["GL_EXT_multi_draw_indirect"] = enableableExtension(&Extensions::multiDrawIndirectEXT);
+ map["GL_EXT_multisample_compatibility"] = esOnlyExtension(&Extensions::multisampleCompatibilityEXT);
+ map["GL_EXT_multisampled_render_to_texture"] = enableableExtension(&Extensions::multisampledRenderToTextureEXT);
+ map["GL_EXT_multisampled_render_to_texture2"] = enableableExtension(&Extensions::multisampledRenderToTexture2EXT);
+ map["GL_OVR_multiview"] = enableableExtension(&Extensions::multiviewOVR);
+ map["GL_OVR_multiview2"] = enableableExtension(&Extensions::multiview2OVR);
+ map["GL_KHR_no_error"] = esOnlyExtension(&Extensions::noErrorKHR);
+ map["GL_EXT_occlusion_query_boolean"] = enableableExtension(&Extensions::occlusionQueryBooleanEXT);
+ map["GL_OES_packed_depth_stencil"] = esOnlyExtension(&Extensions::packedDepthStencilOES);
+ map["GL_ANGLE_pack_reverse_row_order"] = enableableExtension(&Extensions::packReverseRowOrderANGLE);
+ map["GL_NV_pack_subimage"] = enableableExtension(&Extensions::packSubimageNV);
+ map["GL_KHR_parallel_shader_compile"] = enableableExtension(&Extensions::parallelShaderCompileKHR);
+ map["GL_AMD_performance_monitor"] = esOnlyExtension(&Extensions::performanceMonitorAMD);
+ map["GL_NV_pixel_buffer_object"] = enableableExtension(&Extensions::pixelBufferObjectNV);
+ map["GL_EXT_primitive_bounding_box"] = esOnlyExtension(&Extensions::primitiveBoundingBoxEXT);
+ map["GL_OES_primitive_bounding_box"] = esOnlyExtension(&Extensions::primitiveBoundingBoxOES);
+ map["GL_EXT_protected_textures"] = enableableExtension(&Extensions::protectedTexturesEXT);
+ map["GL_EXT_pvrtc_sRGB"] = enableableExtension(&Extensions::pvrtcSRGBEXT);
+ map["GL_NV_read_depth"] = enableableExtension(&Extensions::readDepthNV);
+ map["GL_NV_read_depth_stencil"] = enableableExtension(&Extensions::readDepthStencilNV);
+ map["GL_EXT_read_format_bgra"] = enableableExtension(&Extensions::readFormatBgraEXT);
+ map["GL_NV_read_stencil"] = enableableExtension(&Extensions::readStencilNV);
+ map["GL_OES_rgb8_rgba8"] = enableableExtension(&Extensions::rgb8Rgba8OES);
+ map["GL_KHR_robust_buffer_access_behavior"] = esOnlyExtension(&Extensions::robustBufferAccessBehaviorKHR);
+ map["GL_EXT_robustness"] = esOnlyExtension(&Extensions::robustnessEXT);
+ map["GL_NV_robustness_video_memory_purge"] = esOnlyExtension(&Extensions::robustnessVideoMemoryPurgeNV);
+ map["GL_OES_sample_shading"] = enableableExtension(&Extensions::sampleShadingOES);
+ map["GL_OES_sample_variables"] = enableableExtension(&Extensions::sampleVariablesOES);
+ map["GL_EXT_semaphore"] = enableableExtension(&Extensions::semaphoreEXT);
+ map["GL_EXT_semaphore_fd"] = enableableExtension(&Extensions::semaphoreFdEXT);
+ map["GL_EXT_separate_shader_objects"] = enableableExtension(&Extensions::separateShaderObjectsEXT);
+ map["GL_EXT_shader_framebuffer_fetch"] = enableableExtension(&Extensions::shaderFramebufferFetchEXT);
+ map["GL_EXT_shader_framebuffer_fetch_non_coherent"] = enableableExtension(&Extensions::shaderFramebufferFetchNonCoherentEXT);
+ map["GL_OES_shader_image_atomic"] = enableableExtension(&Extensions::shaderImageAtomicOES);
+ map["GL_EXT_shader_io_blocks"] = enableableExtension(&Extensions::shaderIoBlocksEXT);
+ map["GL_OES_shader_io_blocks"] = enableableExtension(&Extensions::shaderIoBlocksOES);
+ map["GL_OES_shader_multisample_interpolation"] = enableableExtension(&Extensions::shaderMultisampleInterpolationOES);
+ map["GL_EXT_shader_non_constant_global_initializers"] = enableableExtension(&Extensions::shaderNonConstantGlobalInitializersEXT);
+ map["GL_NV_shader_noperspective_interpolation"] = enableableExtension(&Extensions::shaderNoperspectiveInterpolationNV);
+ map["GL_EXT_shader_texture_lod"] = enableableExtension(&Extensions::shaderTextureLodEXT);
+ map["GL_QCOM_shading_rate"] = enableableExtension(&Extensions::shadingRateQCOM);
+ map["GL_EXT_shadow_samplers"] = enableableExtension(&Extensions::shadowSamplersEXT);
+ map["GL_EXT_sRGB"] = enableableExtension(&Extensions::sRGBEXT);
+ map["GL_EXT_sRGB_write_control"] = esOnlyExtension(&Extensions::sRGBWriteControlEXT);
+ map["GL_OES_standard_derivatives"] = enableableExtension(&Extensions::standardDerivativesOES);
+ map["GL_OES_surfaceless_context"] = esOnlyExtension(&Extensions::surfacelessContextOES);
+ map["GL_ARB_sync"] = enableableExtension(&Extensions::syncARB);
+ map["GL_EXT_tessellation_shader"] = enableableExtension(&Extensions::tessellationShaderEXT);
+ map["GL_OES_texture_3D"] = enableableExtension(&Extensions::texture3DOES);
+ map["GL_EXT_texture_border_clamp"] = enableableExtension(&Extensions::textureBorderClampEXT);
+ map["GL_OES_texture_border_clamp"] = enableableExtension(&Extensions::textureBorderClampOES);
+ map["GL_EXT_texture_buffer"] = enableableExtension(&Extensions::textureBufferEXT);
+ map["GL_OES_texture_buffer"] = enableableExtension(&Extensions::textureBufferOES);
+ map["GL_OES_texture_compression_astc"] = enableableExtension(&Extensions::textureCompressionAstcOES);
+ map["GL_KHR_texture_compression_astc_hdr"] = enableableExtension(&Extensions::textureCompressionAstcHdrKHR);
+ map["GL_KHR_texture_compression_astc_ldr"] = enableableExtension(&Extensions::textureCompressionAstcLdrKHR);
+ map["GL_KHR_texture_compression_astc_sliced_3d"] = enableableExtension(&Extensions::textureCompressionAstcSliced3dKHR);
+ map["GL_EXT_texture_compression_bptc"] = enableableExtension(&Extensions::textureCompressionBptcEXT);
+ map["GL_EXT_texture_compression_dxt1"] = enableableExtension(&Extensions::textureCompressionDxt1EXT);
+ map["GL_IMG_texture_compression_pvrtc"] = enableableExtension(&Extensions::textureCompressionPvrtcIMG);
+ map["GL_IMG_texture_compression_pvrtc2"] = enableableExtension(&Extensions::textureCompressionPvrtc2IMG);
+ map["GL_EXT_texture_compression_rgtc"] = enableableExtension(&Extensions::textureCompressionRgtcEXT);
+ map["GL_EXT_texture_compression_s3tc"] = enableableExtension(&Extensions::textureCompressionS3tcEXT);
+ map["GL_EXT_texture_compression_s3tc_srgb"] = enableableExtension(&Extensions::textureCompressionS3tcSrgbEXT);
+ map["GL_EXT_texture_cube_map_array"] = enableableExtension(&Extensions::textureCubeMapArrayEXT);
+ map["GL_OES_texture_cube_map_array"] = enableableExtension(&Extensions::textureCubeMapArrayOES);
+ map["GL_EXT_texture_filter_anisotropic"] = enableableExtension(&Extensions::textureFilterAnisotropicEXT);
+ map["GL_OES_texture_float"] = enableableExtension(&Extensions::textureFloatOES);
+ map["GL_OES_texture_float_linear"] = enableableExtension(&Extensions::textureFloatLinearOES);
+ map["GL_EXT_texture_format_BGRA8888"] = enableableExtension(&Extensions::textureFormatBGRA8888EXT);
+ map["GL_EXT_texture_format_sRGB_override"] = esOnlyExtension(&Extensions::textureFormatSRGBOverrideEXT);
+ map["GL_OES_texture_half_float"] = enableableExtension(&Extensions::textureHalfFloatOES);
+ map["GL_OES_texture_half_float_linear"] = enableableExtension(&Extensions::textureHalfFloatLinearOES);
+ map["GL_EXT_texture_norm16"] = enableableExtension(&Extensions::textureNorm16EXT);
+ map["GL_OES_texture_npot"] = enableableExtension(&Extensions::textureNpotOES);
+ map["GL_EXT_texture_rg"] = enableableExtension(&Extensions::textureRgEXT);
+ map["GL_EXT_texture_sRGB_decode"] = esOnlyExtension(&Extensions::textureSRGBDecodeEXT);
+ map["GL_EXT_texture_sRGB_R8"] = enableableExtension(&Extensions::textureSRGBR8EXT);
+ map["GL_EXT_texture_sRGB_RG8"] = enableableExtension(&Extensions::textureSRGBRG8EXT);
+ map["GL_OES_texture_stencil8"] = enableableExtension(&Extensions::textureStencil8OES);
+ map["GL_EXT_texture_storage"] = enableableExtension(&Extensions::textureStorageEXT);
+ map["GL_OES_texture_storage_multisample_2d_array"] = enableableExtension(&Extensions::textureStorageMultisample2dArrayOES);
+ map["GL_EXT_texture_type_2_10_10_10_REV"] = enableableExtension(&Extensions::textureType2101010REVEXT);
+ map["GL_ANGLE_texture_usage"] = enableableExtension(&Extensions::textureUsageANGLE);
+ map["GL_ANGLE_translated_shader_source"] = esOnlyExtension(&Extensions::translatedShaderSourceANGLE);
+ map["GL_EXT_unpack_subimage"] = enableableExtension(&Extensions::unpackSubimageEXT);
+ map["GL_OES_vertex_array_object"] = enableableExtension(&Extensions::vertexArrayObjectOES);
+ map["GL_OES_vertex_half_float"] = enableableExtension(&Extensions::vertexHalfFloatOES);
+ map["GL_OES_vertex_type_10_10_10_2"] = enableableExtension(&Extensions::vertexType1010102OES);
+ map["GL_WEBGL_video_texture"] = enableableExtension(&Extensions::videoTextureWEBGL);
+ map["GL_EXT_YUV_target"] = enableableExtension(&Extensions::YUVTargetEXT);
+
+ // ANGLE unofficial extension strings
+ // ----------------------------------
+ map["GL_ANGLE_base_vertex_base_instance"] = enableableExtension(&Extensions::baseVertexBaseInstanceANGLE);
+ map["GL_ANGLE_base_vertex_base_instance_shader_builtin"] = enableableExtension(&Extensions::baseVertexBaseInstanceShaderBuiltinANGLE);
+ map["GL_CHROMIUM_bind_generates_resource"] = esOnlyExtension(&Extensions::bindGeneratesResourceCHROMIUM);
+ map["GL_CHROMIUM_bind_uniform_location"] = esOnlyExtension(&Extensions::bindUniformLocationCHROMIUM);
+ map["GL_ANGLE_client_arrays"] = esOnlyExtension(&Extensions::clientArraysANGLE);
+ map["GL_CHROMIUM_color_buffer_float_rgb"] = enableableExtension(&Extensions::colorBufferFloatRgbCHROMIUM);
+ map["GL_CHROMIUM_color_buffer_float_rgba"] = enableableExtension(&Extensions::colorBufferFloatRgbaCHROMIUM);
+ map["GL_ANGLE_compressed_texture_etc"] = enableableExtension(&Extensions::compressedTextureEtcANGLE);
+ map["GL_CHROMIUM_copy_compressed_texture"] = esOnlyExtension(&Extensions::copyCompressedTextureCHROMIUM);
+ map["GL_CHROMIUM_copy_texture"] = esOnlyExtension(&Extensions::copyTextureCHROMIUM);
+ map["GL_ANGLE_copy_texture_3d"] = enableableExtension(&Extensions::copyTexture3dANGLE);
+ map["GL_CHROMIUM_framebuffer_mixed_samples"] = esOnlyExtension(&Extensions::framebufferMixedSamplesCHROMIUM);
+ map["GL_ANGLE_framebuffer_multisample"] = enableableExtension(&Extensions::framebufferMultisampleANGLE);
+ map["GL_ANGLE_get_image"] = enableableExtension(&Extensions::getImageANGLE);
+ map["GL_ANGLE_get_serialized_context_string"] = esOnlyExtension(&Extensions::getSerializedContextStringANGLE);
+ map["GL_ANGLE_get_tex_level_parameter"] = enableableExtension(&Extensions::getTexLevelParameterANGLE);
+ map["GL_ANGLE_logic_op"] = enableableExtension(&Extensions::logicOpANGLE);
+ map["GL_CHROMIUM_lose_context"] = enableableExtension(&Extensions::loseContextCHROMIUM);
+ map["GL_ANGLE_lossy_etc_decode"] = enableableExtension(&Extensions::lossyEtcDecodeANGLE);
+ map["GL_ANGLE_memory_object_flags"] = enableableExtension(&Extensions::memoryObjectFlagsANGLE);
+ map["GL_ANGLE_memory_object_fuchsia"] = enableableExtension(&Extensions::memoryObjectFuchsiaANGLE);
+ map["GL_ANGLE_memory_size"] = enableableExtension(&Extensions::memorySizeANGLE);
+ map["GL_ANGLE_multi_draw"] = enableableExtension(&Extensions::multiDrawANGLE);
+ map["GL_ANGLE_multiview_multisample"] = enableableExtension(&Extensions::multiviewMultisampleANGLE);
+ map["GL_ANGLE_program_binary"] = esOnlyExtension(&Extensions::programBinaryANGLE);
+ map["GL_ANGLE_program_cache_control"] = esOnlyExtension(&Extensions::programCacheControlANGLE);
+ map["GL_ANGLE_provoking_vertex"] = enableableExtension(&Extensions::provokingVertexANGLE);
+ map["GL_ANGLE_read_only_depth_stencil_feedback_loops"] = enableableExtension(&Extensions::readOnlyDepthStencilFeedbackLoopsANGLE);
+ map["GL_ANGLE_relaxed_vertex_attribute_type"] = esOnlyExtension(&Extensions::relaxedVertexAttributeTypeANGLE);
+ map["GL_ANGLE_request_extension"] = esOnlyExtension(&Extensions::requestExtensionANGLE);
+ map["GL_ANGLE_rgbx_internal_format"] = esOnlyExtension(&Extensions::rgbxInternalFormatANGLE);
+ map["GL_ANGLE_robust_client_memory"] = esOnlyExtension(&Extensions::robustClientMemoryANGLE);
+ map["GL_ANGLE_robust_fragment_shader_output"] = enableableExtension(&Extensions::robustFragmentShaderOutputANGLE);
+ map["GL_ANGLE_robust_resource_initialization"] = esOnlyExtension(&Extensions::robustResourceInitializationANGLE);
+ map["GL_ANGLE_semaphore_fuchsia"] = enableableExtension(&Extensions::semaphoreFuchsiaANGLE);
+ map["GL_ANGLE_shader_pixel_local_storage"] = esOnlyExtension(&Extensions::shaderPixelLocalStorageANGLE);
+ map["GL_ANGLE_shader_pixel_local_storage_coherent"] = esOnlyExtension(&Extensions::shaderPixelLocalStorageCoherentANGLE);
+ map["GL_CHROMIUM_sync_query"] = enableableExtension(&Extensions::syncQueryCHROMIUM);
+ map["GL_ANGLE_texture_compression_dxt3"] = enableableExtension(&Extensions::textureCompressionDxt3ANGLE);
+ map["GL_ANGLE_texture_compression_dxt5"] = enableableExtension(&Extensions::textureCompressionDxt5ANGLE);
+ map["GL_ANGLE_texture_external_update"] = enableableExtension(&Extensions::textureExternalUpdateANGLE);
+ map["GL_CHROMIUM_texture_filtering_hint"] = enableableExtension(&Extensions::textureFilteringHintCHROMIUM);
+ map["GL_ANGLE_texture_multisample"] = enableableExtension(&Extensions::textureMultisampleANGLE);
+ map["GL_ANGLE_texture_rectangle"] = enableableDisablableExtension(&Extensions::textureRectangleANGLE);
+ map["GL_ANGLE_vulkan_image"] = enableableExtension(&Extensions::vulkanImageANGLE);
+ map["GL_ANGLE_webgl_compatibility"] = esOnlyExtension(&Extensions::webglCompatibilityANGLE);
+ map["GL_ANGLE_yuv_internal_format"] = enableableExtension(&Extensions::yuvInternalFormatANGLE);
+
+ // GLES 1.0 and 1.1 extension strings
+ // ----------------------------------
+ map["GL_OES_draw_texture"] = enableableExtension(&Extensions::drawTextureOES);
+ map["GL_OES_framebuffer_object"] = enableableExtension(&Extensions::framebufferObjectOES);
+ map["GL_OES_matrix_palette"] = enableableExtension(&Extensions::matrixPaletteOES);
+ map["GL_OES_point_size_array"] = enableableExtension(&Extensions::pointSizeArrayOES);
+ map["GL_OES_point_sprite"] = enableableExtension(&Extensions::pointSpriteOES);
+ map["GL_OES_query_matrix"] = enableableExtension(&Extensions::queryMatrixOES);
+ map["GL_OES_texture_cube_map"] = enableableExtension(&Extensions::textureCubeMapOES);
+ // clang-format on
+
+#if defined(ANGLE_ENABLE_ASSERTS)
+ // Verify all extension strings start with GL_
+ for (const auto &extension : map)
+ {
+ ASSERT(extension.first.rfind("GL_", 0) == 0);
+ }
+#endif
+
+ return map;
+ };
+
+ static const angle::base::NoDestructor<ExtensionInfoMap> extensionInfo(buildExtensionInfoMap());
+ return *extensionInfo;
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/gles_extensions_autogen.h b/gfx/angle/checkout/src/libANGLE/gles_extensions_autogen.h
new file mode 100644
index 0000000000..00994189a3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/gles_extensions_autogen.h
@@ -0,0 +1,727 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_extensions.py using data from registry_xml.py and gl.xml
+//
+// Copyright 2021 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// gles_extensions_autogen.h: GLES extension information.
+
+#ifndef LIBANGLE_GLES_EXTENSIONS_AUTOGEN_H_
+#define LIBANGLE_GLES_EXTENSIONS_AUTOGEN_H_
+
+namespace gl
+{
+class TextureCapsMap;
+
+struct Extensions
+{
+ Extensions();
+ Extensions(const Extensions &other);
+
+ Extensions &operator=(const Extensions &other);
+
+ // Generate a vector of supported extension strings
+ std::vector<std::string> getStrings() const;
+
+ // Set all texture related extension support based on the supported textures.
+ // Determines support for:
+ // GL_OES_packed_depth_stencil
+ // GL_OES_rgb8_rgba8
+ // GL_EXT_texture_format_BGRA8888
+ // GL_EXT_color_buffer_half_float,
+ // GL_OES_texture_half_float, GL_OES_texture_half_float_linear
+ // GL_OES_texture_float, GL_OES_texture_float_linear
+ // GL_EXT_texture_rg
+ // GL_EXT_texture_type_2_10_10_10_REV
+ // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3,
+ // GL_ANGLE_texture_compression_dxt5
+ // GL_KHR_texture_compression_astc_ldr, GL_OES_texture_compression_astc.
+ // NOTE: GL_KHR_texture_compression_astc_hdr must be enabled separately. Support for the
+ // HDR profile cannot be determined from the format enums alone.
+ // GL_OES_compressed_ETC1_RGB8_texture
+ // GL_EXT_sRGB
+ // GL_ANGLE_depth_texture, GL_OES_depth32
+ // GL_EXT_color_buffer_float
+ // GL_EXT_texture_norm16
+ // GL_EXT_texture_compression_bptc
+ // GL_EXT_texture_compression_rgtc
+ void setTextureExtensionSupport(const TextureCapsMap &textureCaps);
+
+ // Helper functions
+ bool copyImageAny() const { return (copyImageEXT || copyImageOES); }
+ bool depthTextureAny() const { return (depthTextureANGLE || depthTextureOES); }
+ bool drawBuffersIndexedAny() const { return (drawBuffersIndexedEXT || drawBuffersIndexedOES); }
+ bool drawElementsBaseVertexAny() const
+ {
+ return (drawElementsBaseVertexEXT || drawElementsBaseVertexOES);
+ }
+ bool framebufferBlitAny() const { return (framebufferBlitANGLE || framebufferBlitNV); }
+ bool geometryShaderAny() const { return (geometryShaderEXT || geometryShaderOES); }
+ bool instancedArraysAny() const { return (instancedArraysANGLE || instancedArraysEXT); }
+ bool primitiveBoundingBoxAny() const
+ {
+ return (primitiveBoundingBoxEXT || primitiveBoundingBoxOES);
+ }
+ bool shaderIoBlocksAny() const { return (shaderIoBlocksEXT || shaderIoBlocksOES); }
+ bool textureBorderClampAny() const { return (textureBorderClampEXT || textureBorderClampOES); }
+ bool textureBufferAny() const { return (textureBufferEXT || textureBufferOES); }
+ bool textureCubeMapArrayAny() const
+ {
+ return (textureCubeMapArrayEXT || textureCubeMapArrayOES);
+ }
+
+ // GLES 2.0+ extensions
+ // --------------------
+
+ // GL_EXT_base_instance
+ bool baseInstanceEXT = false;
+
+ // GL_KHR_blend_equation_advanced
+ bool blendEquationAdvancedKHR = false;
+
+ // GL_EXT_blend_func_extended
+ bool blendFuncExtendedEXT = false;
+
+ // GL_EXT_blend_minmax
+ bool blendMinmaxEXT = false;
+
+ // GL_EXT_buffer_storage
+ bool bufferStorageEXT = false;
+
+ // GL_EXT_clip_control
+ bool clipControlEXT = false;
+
+ // GL_EXT_clip_cull_distance
+ bool clipCullDistanceEXT = false;
+
+ // GL_APPLE_clip_distance
+ bool clipDistanceAPPLE = false;
+
+ // GL_EXT_color_buffer_float
+ bool colorBufferFloatEXT = false;
+
+ // GL_EXT_color_buffer_half_float
+ bool colorBufferHalfFloatEXT = false;
+
+ // GL_OES_compressed_EAC_R11_signed_texture
+ bool compressedEACR11SignedTextureOES = false;
+
+ // GL_OES_compressed_EAC_R11_unsigned_texture
+ bool compressedEACR11UnsignedTextureOES = false;
+
+ // GL_OES_compressed_EAC_RG11_signed_texture
+ bool compressedEACRG11SignedTextureOES = false;
+
+ // GL_OES_compressed_EAC_RG11_unsigned_texture
+ bool compressedEACRG11UnsignedTextureOES = false;
+
+ // GL_EXT_compressed_ETC1_RGB8_sub_texture
+ bool compressedETC1RGB8SubTextureEXT = false;
+
+ // GL_OES_compressed_ETC1_RGB8_texture
+ bool compressedETC1RGB8TextureOES = false;
+
+ // GL_OES_compressed_ETC2_punchthroughA_RGBA8_texture
+ bool compressedETC2PunchthroughARGBA8TextureOES = false;
+
+ // GL_OES_compressed_ETC2_punchthroughA_sRGB8_alpha_texture
+ bool compressedETC2PunchthroughASRGB8AlphaTextureOES = false;
+
+ // GL_OES_compressed_ETC2_RGB8_texture
+ bool compressedETC2RGB8TextureOES = false;
+
+ // GL_OES_compressed_ETC2_RGBA8_texture
+ bool compressedETC2RGBA8TextureOES = false;
+
+ // GL_OES_compressed_ETC2_sRGB8_alpha8_texture
+ bool compressedETC2SRGB8Alpha8TextureOES = false;
+
+ // GL_OES_compressed_ETC2_sRGB8_texture
+ bool compressedETC2SRGB8TextureOES = false;
+
+ // GL_OES_compressed_paletted_texture
+ bool compressedPalettedTextureOES = false;
+
+ // GL_EXT_copy_image
+ bool copyImageEXT = false;
+
+ // GL_OES_copy_image
+ bool copyImageOES = false;
+
+ // GL_KHR_debug
+ bool debugKHR = false;
+
+ // GL_EXT_debug_label
+ bool debugLabelEXT = false;
+
+ // GL_EXT_debug_marker
+ bool debugMarkerEXT = false;
+
+ // GL_OES_depth24
+ bool depth24OES = false;
+
+ // GL_OES_depth32
+ bool depth32OES = false;
+
+ // GL_NV_depth_buffer_float2
+ bool depthBufferFloat2NV = false;
+
+ // GL_ANGLE_depth_texture
+ bool depthTextureANGLE = false;
+
+ // GL_OES_depth_texture
+ bool depthTextureOES = false;
+
+ // GL_OES_depth_texture_cube_map
+ bool depthTextureCubeMapOES = false;
+
+ // GL_EXT_discard_framebuffer
+ bool discardFramebufferEXT = false;
+
+ // GL_EXT_disjoint_timer_query
+ bool disjointTimerQueryEXT = false;
+
+ // GL_EXT_draw_buffers
+ bool drawBuffersEXT = false;
+
+ // GL_EXT_draw_buffers_indexed
+ bool drawBuffersIndexedEXT = false;
+
+ // GL_OES_draw_buffers_indexed
+ bool drawBuffersIndexedOES = false;
+
+ // GL_EXT_draw_elements_base_vertex
+ bool drawElementsBaseVertexEXT = false;
+
+ // GL_OES_draw_elements_base_vertex
+ bool drawElementsBaseVertexOES = false;
+
+ // GL_OES_EGL_image
+ bool EGLImageOES = false;
+
+ // GL_EXT_EGL_image_array
+ bool EGLImageArrayEXT = false;
+
+ // GL_OES_EGL_image_external
+ bool EGLImageExternalOES = false;
+
+ // GL_OES_EGL_image_external_essl3
+ bool EGLImageExternalEssl3OES = false;
+
+ // GL_EXT_EGL_image_external_wrap_modes
+ bool EGLImageExternalWrapModesEXT = false;
+
+ // GL_EXT_EGL_image_storage
+ bool EGLImageStorageEXT = false;
+
+ // GL_NV_EGL_stream_consumer_external
+ bool EGLStreamConsumerExternalNV = false;
+
+ // GL_OES_EGL_sync
+ bool EGLSyncOES = false;
+
+ // GL_OES_element_index_uint
+ bool elementIndexUintOES = false;
+
+ // GL_ANDROID_extension_pack_es31a
+ bool extensionPackEs31aANDROID = false;
+
+ // GL_EXT_external_buffer
+ bool externalBufferEXT = false;
+
+ // GL_OES_fbo_render_mipmap
+ bool fboRenderMipmapOES = false;
+
+ // GL_NV_fence
+ bool fenceNV = false;
+
+ // GL_EXT_float_blend
+ bool floatBlendEXT = false;
+
+ // GL_EXT_frag_depth
+ bool fragDepthEXT = false;
+
+ // GL_ANGLE_framebuffer_blit
+ bool framebufferBlitANGLE = false;
+
+ // GL_NV_framebuffer_blit
+ bool framebufferBlitNV = false;
+
+ // GL_MESA_framebuffer_flip_y
+ bool framebufferFlipYMESA = false;
+
+ // GL_EXT_geometry_shader
+ bool geometryShaderEXT = false;
+
+ // GL_OES_geometry_shader
+ bool geometryShaderOES = false;
+
+ // GL_OES_get_program_binary
+ bool getProgramBinaryOES = false;
+
+ // GL_EXT_gpu_shader5
+ bool gpuShader5EXT = false;
+
+ // GL_ANGLE_instanced_arrays
+ bool instancedArraysANGLE = false;
+
+ // GL_EXT_instanced_arrays
+ bool instancedArraysEXT = false;
+
+ // GL_OES_mapbuffer
+ bool mapbufferOES = false;
+
+ // GL_EXT_map_buffer_range
+ bool mapBufferRangeEXT = false;
+
+ // GL_EXT_memory_object
+ bool memoryObjectEXT = false;
+
+ // GL_EXT_memory_object_fd
+ bool memoryObjectFdEXT = false;
+
+ // GL_EXT_multi_draw_indirect
+ bool multiDrawIndirectEXT = false;
+
+ // GL_EXT_multisample_compatibility
+ bool multisampleCompatibilityEXT = false;
+
+ // GL_EXT_multisampled_render_to_texture
+ bool multisampledRenderToTextureEXT = false;
+
+ // GL_EXT_multisampled_render_to_texture2
+ bool multisampledRenderToTexture2EXT = false;
+
+ // GL_OVR_multiview
+ bool multiviewOVR = false;
+
+ // GL_OVR_multiview2
+ bool multiview2OVR = false;
+
+ // GL_KHR_no_error
+ bool noErrorKHR = false;
+
+ // GL_EXT_occlusion_query_boolean
+ bool occlusionQueryBooleanEXT = false;
+
+ // GL_OES_packed_depth_stencil
+ bool packedDepthStencilOES = false;
+
+ // GL_ANGLE_pack_reverse_row_order
+ bool packReverseRowOrderANGLE = false;
+
+ // GL_NV_pack_subimage
+ bool packSubimageNV = false;
+
+ // GL_KHR_parallel_shader_compile
+ bool parallelShaderCompileKHR = false;
+
+ // GL_AMD_performance_monitor
+ bool performanceMonitorAMD = false;
+
+ // GL_NV_pixel_buffer_object
+ bool pixelBufferObjectNV = false;
+
+ // GL_EXT_primitive_bounding_box
+ bool primitiveBoundingBoxEXT = false;
+
+ // GL_OES_primitive_bounding_box
+ bool primitiveBoundingBoxOES = false;
+
+ // GL_EXT_protected_textures
+ bool protectedTexturesEXT = false;
+
+ // GL_EXT_pvrtc_sRGB
+ bool pvrtcSRGBEXT = false;
+
+ // GL_NV_read_depth
+ bool readDepthNV = false;
+
+ // GL_NV_read_depth_stencil
+ bool readDepthStencilNV = false;
+
+ // GL_EXT_read_format_bgra
+ bool readFormatBgraEXT = false;
+
+ // GL_NV_read_stencil
+ bool readStencilNV = false;
+
+ // GL_OES_rgb8_rgba8
+ bool rgb8Rgba8OES = false;
+
+ // GL_KHR_robust_buffer_access_behavior
+ bool robustBufferAccessBehaviorKHR = false;
+
+ // GL_EXT_robustness
+ bool robustnessEXT = false;
+
+ // GL_NV_robustness_video_memory_purge
+ bool robustnessVideoMemoryPurgeNV = false;
+
+ // GL_OES_sample_shading
+ bool sampleShadingOES = false;
+
+ // GL_OES_sample_variables
+ bool sampleVariablesOES = false;
+
+ // GL_EXT_semaphore
+ bool semaphoreEXT = false;
+
+ // GL_EXT_semaphore_fd
+ bool semaphoreFdEXT = false;
+
+ // GL_EXT_separate_shader_objects
+ bool separateShaderObjectsEXT = false;
+
+ // GL_EXT_shader_framebuffer_fetch
+ bool shaderFramebufferFetchEXT = false;
+
+ // GL_EXT_shader_framebuffer_fetch_non_coherent
+ bool shaderFramebufferFetchNonCoherentEXT = false;
+
+ // GL_OES_shader_image_atomic
+ bool shaderImageAtomicOES = false;
+
+ // GL_EXT_shader_io_blocks
+ bool shaderIoBlocksEXT = false;
+
+ // GL_OES_shader_io_blocks
+ bool shaderIoBlocksOES = false;
+
+ // GL_OES_shader_multisample_interpolation
+ bool shaderMultisampleInterpolationOES = false;
+
+ // GL_EXT_shader_non_constant_global_initializers
+ bool shaderNonConstantGlobalInitializersEXT = false;
+
+ // GL_NV_shader_noperspective_interpolation
+ bool shaderNoperspectiveInterpolationNV = false;
+
+ // GL_EXT_shader_texture_lod
+ bool shaderTextureLodEXT = false;
+
+ // GL_QCOM_shading_rate
+ bool shadingRateQCOM = false;
+
+ // GL_EXT_shadow_samplers
+ bool shadowSamplersEXT = false;
+
+ // GL_EXT_sRGB
+ bool sRGBEXT = false;
+
+ // GL_EXT_sRGB_write_control
+ bool sRGBWriteControlEXT = false;
+
+ // GL_OES_standard_derivatives
+ bool standardDerivativesOES = false;
+
+ // GL_OES_surfaceless_context
+ bool surfacelessContextOES = false;
+
+ // GL_ARB_sync
+ bool syncARB = false;
+
+ // GL_EXT_tessellation_shader
+ bool tessellationShaderEXT = false;
+
+ // GL_OES_texture_3D
+ bool texture3DOES = false;
+
+ // GL_EXT_texture_border_clamp
+ bool textureBorderClampEXT = false;
+
+ // GL_OES_texture_border_clamp
+ bool textureBorderClampOES = false;
+
+ // GL_EXT_texture_buffer
+ bool textureBufferEXT = false;
+
+ // GL_OES_texture_buffer
+ bool textureBufferOES = false;
+
+ // GL_OES_texture_compression_astc
+ bool textureCompressionAstcOES = false;
+
+ // GL_KHR_texture_compression_astc_hdr
+ bool textureCompressionAstcHdrKHR = false;
+
+ // GL_KHR_texture_compression_astc_ldr
+ bool textureCompressionAstcLdrKHR = false;
+
+ // GL_KHR_texture_compression_astc_sliced_3d
+ bool textureCompressionAstcSliced3dKHR = false;
+
+ // GL_EXT_texture_compression_bptc
+ bool textureCompressionBptcEXT = false;
+
+ // GL_EXT_texture_compression_dxt1
+ bool textureCompressionDxt1EXT = false;
+
+ // GL_IMG_texture_compression_pvrtc
+ bool textureCompressionPvrtcIMG = false;
+
+ // GL_IMG_texture_compression_pvrtc2
+ bool textureCompressionPvrtc2IMG = false;
+
+ // GL_EXT_texture_compression_rgtc
+ bool textureCompressionRgtcEXT = false;
+
+ // GL_EXT_texture_compression_s3tc
+ bool textureCompressionS3tcEXT = false;
+
+ // GL_EXT_texture_compression_s3tc_srgb
+ bool textureCompressionS3tcSrgbEXT = false;
+
+ // GL_EXT_texture_cube_map_array
+ bool textureCubeMapArrayEXT = false;
+
+ // GL_OES_texture_cube_map_array
+ bool textureCubeMapArrayOES = false;
+
+ // GL_EXT_texture_filter_anisotropic
+ bool textureFilterAnisotropicEXT = false;
+
+ // GL_OES_texture_float
+ bool textureFloatOES = false;
+
+ // GL_OES_texture_float_linear
+ bool textureFloatLinearOES = false;
+
+ // GL_EXT_texture_format_BGRA8888
+ bool textureFormatBGRA8888EXT = false;
+
+ // GL_EXT_texture_format_sRGB_override
+ bool textureFormatSRGBOverrideEXT = false;
+
+ // GL_OES_texture_half_float
+ bool textureHalfFloatOES = false;
+
+ // GL_OES_texture_half_float_linear
+ bool textureHalfFloatLinearOES = false;
+
+ // GL_EXT_texture_norm16
+ bool textureNorm16EXT = false;
+
+ // GL_OES_texture_npot
+ bool textureNpotOES = false;
+
+ // GL_EXT_texture_rg
+ bool textureRgEXT = false;
+
+ // GL_EXT_texture_sRGB_decode
+ bool textureSRGBDecodeEXT = false;
+
+ // GL_EXT_texture_sRGB_R8
+ bool textureSRGBR8EXT = false;
+
+ // GL_EXT_texture_sRGB_RG8
+ bool textureSRGBRG8EXT = false;
+
+ // GL_OES_texture_stencil8
+ bool textureStencil8OES = false;
+
+ // GL_EXT_texture_storage
+ bool textureStorageEXT = false;
+
+ // GL_OES_texture_storage_multisample_2d_array
+ bool textureStorageMultisample2dArrayOES = false;
+
+ // GL_EXT_texture_type_2_10_10_10_REV
+ bool textureType2101010REVEXT = false;
+
+ // GL_ANGLE_texture_usage
+ bool textureUsageANGLE = false;
+
+ // GL_ANGLE_translated_shader_source
+ bool translatedShaderSourceANGLE = false;
+
+ // GL_EXT_unpack_subimage
+ bool unpackSubimageEXT = false;
+
+ // GL_OES_vertex_array_object
+ bool vertexArrayObjectOES = false;
+
+ // GL_OES_vertex_half_float
+ bool vertexHalfFloatOES = false;
+
+ // GL_OES_vertex_type_10_10_10_2
+ bool vertexType1010102OES = false;
+
+ // GL_WEBGL_video_texture
+ bool videoTextureWEBGL = false;
+
+ // GL_EXT_YUV_target
+ bool YUVTargetEXT = false;
+
+ // ANGLE unofficial extensions
+ // ---------------------------
+
+ // GL_ANGLE_base_vertex_base_instance
+ bool baseVertexBaseInstanceANGLE = false;
+
+ // GL_ANGLE_base_vertex_base_instance_shader_builtin
+ bool baseVertexBaseInstanceShaderBuiltinANGLE = false;
+
+ // GL_CHROMIUM_bind_generates_resource
+ bool bindGeneratesResourceCHROMIUM = false;
+
+ // GL_CHROMIUM_bind_uniform_location
+ bool bindUniformLocationCHROMIUM = false;
+
+ // GL_ANGLE_client_arrays
+ bool clientArraysANGLE = false;
+
+ // GL_CHROMIUM_color_buffer_float_rgb
+ bool colorBufferFloatRgbCHROMIUM = false;
+
+ // GL_CHROMIUM_color_buffer_float_rgba
+ bool colorBufferFloatRgbaCHROMIUM = false;
+
+ // GL_ANGLE_compressed_texture_etc
+ bool compressedTextureEtcANGLE = false;
+
+ // GL_CHROMIUM_copy_compressed_texture
+ bool copyCompressedTextureCHROMIUM = false;
+
+ // GL_CHROMIUM_copy_texture
+ bool copyTextureCHROMIUM = false;
+
+ // GL_ANGLE_copy_texture_3d
+ bool copyTexture3dANGLE = false;
+
+ // GL_CHROMIUM_framebuffer_mixed_samples
+ bool framebufferMixedSamplesCHROMIUM = false;
+
+ // GL_ANGLE_framebuffer_multisample
+ bool framebufferMultisampleANGLE = false;
+
+ // GL_ANGLE_get_image
+ bool getImageANGLE = false;
+
+ // GL_ANGLE_get_serialized_context_string
+ bool getSerializedContextStringANGLE = false;
+
+ // GL_ANGLE_get_tex_level_parameter
+ bool getTexLevelParameterANGLE = false;
+
+ // GL_ANGLE_logic_op
+ bool logicOpANGLE = false;
+
+ // GL_CHROMIUM_lose_context
+ bool loseContextCHROMIUM = false;
+
+ // GL_ANGLE_lossy_etc_decode
+ bool lossyEtcDecodeANGLE = false;
+
+ // GL_ANGLE_memory_object_flags
+ bool memoryObjectFlagsANGLE = false;
+
+ // GL_ANGLE_memory_object_fuchsia
+ bool memoryObjectFuchsiaANGLE = false;
+
+ // GL_ANGLE_memory_size
+ bool memorySizeANGLE = false;
+
+ // GL_ANGLE_multi_draw
+ bool multiDrawANGLE = false;
+
+ // GL_ANGLE_multiview_multisample
+ bool multiviewMultisampleANGLE = false;
+
+ // GL_ANGLE_program_binary
+ bool programBinaryANGLE = false;
+
+ // GL_ANGLE_program_cache_control
+ bool programCacheControlANGLE = false;
+
+ // GL_ANGLE_provoking_vertex
+ bool provokingVertexANGLE = false;
+
+ // GL_ANGLE_read_only_depth_stencil_feedback_loops
+ bool readOnlyDepthStencilFeedbackLoopsANGLE = false;
+
+ // GL_ANGLE_relaxed_vertex_attribute_type
+ bool relaxedVertexAttributeTypeANGLE = false;
+
+ // GL_ANGLE_request_extension
+ bool requestExtensionANGLE = false;
+
+ // GL_ANGLE_rgbx_internal_format
+ bool rgbxInternalFormatANGLE = false;
+
+ // GL_ANGLE_robust_client_memory
+ bool robustClientMemoryANGLE = false;
+
+ // GL_ANGLE_robust_fragment_shader_output
+ bool robustFragmentShaderOutputANGLE = false;
+
+ // GL_ANGLE_robust_resource_initialization
+ bool robustResourceInitializationANGLE = false;
+
+ // GL_ANGLE_semaphore_fuchsia
+ bool semaphoreFuchsiaANGLE = false;
+
+ // GL_ANGLE_shader_pixel_local_storage
+ bool shaderPixelLocalStorageANGLE = false;
+
+ // GL_ANGLE_shader_pixel_local_storage_coherent
+ bool shaderPixelLocalStorageCoherentANGLE = false;
+
+ // GL_CHROMIUM_sync_query
+ bool syncQueryCHROMIUM = false;
+
+ // GL_ANGLE_texture_compression_dxt3
+ bool textureCompressionDxt3ANGLE = false;
+
+ // GL_ANGLE_texture_compression_dxt5
+ bool textureCompressionDxt5ANGLE = false;
+
+ // GL_ANGLE_texture_external_update
+ bool textureExternalUpdateANGLE = false;
+
+ // GL_CHROMIUM_texture_filtering_hint
+ bool textureFilteringHintCHROMIUM = false;
+
+ // GL_ANGLE_texture_multisample
+ bool textureMultisampleANGLE = false;
+
+ // GL_ANGLE_texture_rectangle
+ bool textureRectangleANGLE = false;
+
+ // GL_ANGLE_vulkan_image
+ bool vulkanImageANGLE = false;
+
+ // GL_ANGLE_webgl_compatibility
+ bool webglCompatibilityANGLE = false;
+
+ // GL_ANGLE_yuv_internal_format
+ bool yuvInternalFormatANGLE = false;
+
+ // GLES 1.0 and 1.1 extensions
+ // ---------------------------
+
+ // GL_OES_draw_texture
+ bool drawTextureOES = false;
+
+ // GL_OES_framebuffer_object
+ bool framebufferObjectOES = false;
+
+ // GL_OES_matrix_palette
+ bool matrixPaletteOES = false;
+
+ // GL_OES_point_size_array
+ bool pointSizeArrayOES = false;
+
+ // GL_OES_point_sprite
+ bool pointSpriteOES = false;
+
+ // GL_OES_query_matrix
+ bool queryMatrixOES = false;
+
+ // GL_OES_texture_cube_map
+ bool textureCubeMapOES = false;
+};
+} // namespace gl
+
+#endif // LIBANGLE_GLES_EXTENSIONS_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/histogram_macros.h b/gfx/angle/checkout/src/libANGLE/histogram_macros.h
new file mode 100644
index 0000000000..cf27a895a1
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/histogram_macros.h
@@ -0,0 +1,110 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// histogram_macros.h:
+// Helpers for making histograms, to keep consistency with Chromium's
+// histogram_macros.h.
+
+#ifndef LIBANGLE_HISTOGRAM_MACROS_H_
+#define LIBANGLE_HISTOGRAM_MACROS_H_
+
+#include <platform/PlatformMethods.h>
+
+#define ANGLE_HISTOGRAM_TIMES(name, sample) ANGLE_HISTOGRAM_CUSTOM_TIMES(name, sample, 1, 10000, 50)
+
+#define ANGLE_HISTOGRAM_MEDIUM_TIMES(name, sample) \
+ ANGLE_HISTOGRAM_CUSTOM_TIMES(name, sample, 10, 180000, 50)
+
+// Use this macro when times can routinely be much longer than 10 seconds.
+#define ANGLE_HISTOGRAM_LONG_TIMES(name, sample) \
+ ANGLE_HISTOGRAM_CUSTOM_TIMES(name, sample, 1, 3600000, 50)
+
+// Use this macro when times can routinely be much longer than 10 seconds and
+// you want 100 buckets.
+#define ANGLE_HISTOGRAM_LONG_TIMES_100(name, sample) \
+ ANGLE_HISTOGRAM_CUSTOM_TIMES(name, sample, 1, 3600000, 100)
+
+// For folks that need real specific times, use this to select a precise range
+// of times you want plotted, and the number of buckets you want used.
+#define ANGLE_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \
+ ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count)
+
+#define ANGLE_HISTOGRAM_COUNTS(name, sample) \
+ ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 1000000, 50)
+
+#define ANGLE_HISTOGRAM_COUNTS_100(name, sample) \
+ ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 100, 50)
+
+#define ANGLE_HISTOGRAM_COUNTS_10000(name, sample) \
+ ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 10000, 50)
+
+#define ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \
+ ANGLEPlatformCurrent()->histogramCustomCounts(ANGLEPlatformCurrent(), name, sample, min, max, \
+ bucket_count)
+
+#define ANGLE_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \
+ ANGLE_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101)
+
+#define ANGLE_HISTOGRAM_BOOLEAN(name, sample) \
+ ANGLEPlatformCurrent()->histogramBoolean(ANGLEPlatformCurrent(), name, sample)
+
+#define ANGLE_HISTOGRAM_ENUMERATION(name, sample, boundary_value) \
+ ANGLEPlatformCurrent()->histogramEnumeration(ANGLEPlatformCurrent(), name, sample, \
+ boundary_value)
+
+#define ANGLE_HISTOGRAM_MEMORY_KB(name, sample) \
+ ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1000, 500000, 50)
+
+#define ANGLE_HISTOGRAM_MEMORY_MB(name, sample) \
+ ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 1000, 50)
+
+#define ANGLE_HISTOGRAM_SPARSE_SLOWLY(name, sample) \
+ ANGLEPlatformCurrent()->histogramSparse(ANGLEPlatformCurrent(), name, sample)
+
+// Scoped class which logs its time on this earth as a UMA statistic. This is
+// recommended for when you want a histogram which measures the time it takes
+// for a method to execute. This measures up to 10 seconds.
+#define SCOPED_ANGLE_HISTOGRAM_TIMER(name) \
+ SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, false, __COUNTER__)
+
+// Similar scoped histogram timer, but this uses ANGLE_HISTOGRAM_LONG_TIMES_100,
+// which measures up to an hour, and uses 100 buckets. This is more expensive
+// to store, so only use if this often takes >10 seconds.
+#define SCOPED_ANGLE_HISTOGRAM_LONG_TIMER(name) \
+ SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, true, __COUNTER__)
+
+// This nested macro is necessary to expand __COUNTER__ to an actual value.
+#define SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, is_long, key) \
+ SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key)
+
+#define SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) \
+ class [[nodiscard]] ScopedHistogramTimer##key \
+ { \
+ public: \
+ ScopedHistogramTimer##key() \
+ : constructed_(ANGLEPlatformCurrent()->currentTime(ANGLEPlatformCurrent())) \
+ {} \
+ ~ScopedHistogramTimer##key() \
+ { \
+ if (constructed_ == 0) \
+ return; \
+ auto *platform = ANGLEPlatformCurrent(); \
+ double elapsed = platform->currentTime(platform) - constructed_; \
+ int elapsedMS = static_cast<int>(elapsed * 1000.0); \
+ if (is_long) \
+ { \
+ ANGLE_HISTOGRAM_LONG_TIMES_100(name, elapsedMS); \
+ } \
+ else \
+ { \
+ ANGLE_HISTOGRAM_TIMES(name, elapsedMS); \
+ } \
+ } \
+ \
+ private: \
+ double constructed_; \
+ } scoped_histogram_timer_##key
+
+#endif // LIBANGLE_HISTOGRAM_MACROS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/queryconversions.cpp b/gfx/angle/checkout/src/libANGLE/queryconversions.cpp
new file mode 100644
index 0000000000..3c3ab45b7c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/queryconversions.cpp
@@ -0,0 +1,315 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// queryconversions.cpp: Implementation of state query cast conversions
+
+#include "libANGLE/queryconversions.h"
+
+#include <vector>
+
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+
+namespace gl
+{
+
+namespace
+{
+
+GLint64 ExpandFloatToInteger(GLfloat value)
+{
+ return static_cast<GLint64>((static_cast<double>(0xFFFFFFFFULL) * value - 1.0) / 2.0);
+}
+
+template <typename QueryT, typename NativeT>
+QueryT CastFromStateValueToInt(GLenum pname, NativeT value)
+{
+ GLenum nativeType = GLTypeToGLenum<NativeT>::value;
+
+ if (nativeType == GL_FLOAT)
+ {
+ // RGBA color values and DepthRangeF values are converted to integer using Equation 2.4 from
+ // Table 4.5
+ switch (pname)
+ {
+ case GL_DEPTH_RANGE:
+ case GL_COLOR_CLEAR_VALUE:
+ case GL_DEPTH_CLEAR_VALUE:
+ case GL_BLEND_COLOR:
+ // GLES1 emulation:
+ // Also, several GLES1.x values need to be converted to integer with
+ // ExpandFloatToInteger rather than rounding. See GLES 1.1 spec 6.1.2 "Data
+ // Conversions".
+ case GL_ALPHA_TEST_REF:
+ case GL_CURRENT_COLOR:
+ return clampCast<QueryT>(ExpandFloatToInteger(static_cast<GLfloat>(value)));
+ default:
+ return clampCast<QueryT>(std::round(value));
+ }
+ }
+
+ return clampCast<QueryT>(value);
+}
+
+template <typename NativeT, typename QueryT>
+NativeT CastQueryValueToInt(GLenum pname, QueryT value)
+{
+ GLenum queryType = GLTypeToGLenum<QueryT>::value;
+
+ if (queryType == GL_FLOAT)
+ {
+ // ARM devices cast float to uint differently than Intel.
+ // Basically, any negative floating point number becomes 0
+ // when converted to unsigned int. Instead, convert to a signed
+ // int and then convert to unsigned int to "preserve the value"
+ // E.g. common case for tests is to pass in -1 as an invalid query
+ // value. If cast to a unsigned int it becomes 0 (GL_NONE) and is now
+ // a valid enum and negative tests fail. But converting to int
+ // and then to final unsigned int gives us 4294967295 (0xffffffff)
+ // which is what we want.
+ return static_cast<NativeT>(static_cast<GLint64>(std::round(value)));
+ }
+
+ return static_cast<NativeT>(value);
+}
+
+} // anonymous namespace
+
+GLint CastMaskValue(GLuint value)
+{
+ return clampCast<GLint>(value);
+}
+
+template <typename QueryT, typename InternalT>
+QueryT CastFromGLintStateValue(GLenum pname, InternalT value)
+{
+ return CastFromStateValue<QueryT, GLint>(pname, clampCast<GLint, InternalT>(value));
+}
+
+template GLfloat CastFromGLintStateValue<GLfloat, GLenum>(GLenum pname, GLenum value);
+template GLint CastFromGLintStateValue<GLint, GLenum>(GLenum pname, GLenum value);
+template GLint64 CastFromGLintStateValue<GLint64, GLenum>(GLenum pname, GLenum value);
+template GLuint CastFromGLintStateValue<GLuint, GLenum>(GLenum pname, GLenum value);
+template GLuint CastFromGLintStateValue<GLuint, GLint>(GLenum pname, GLint value);
+template GLfloat CastFromGLintStateValue<GLfloat, GLint>(GLenum pname, GLint value);
+template GLint CastFromGLintStateValue<GLint, GLint>(GLenum pname, GLint value);
+template GLfloat CastFromGLintStateValue<GLfloat, bool>(GLenum pname, bool value);
+template GLuint CastFromGLintStateValue<GLuint, bool>(GLenum pname, bool value);
+template GLint CastFromGLintStateValue<GLint, bool>(GLenum pname, bool value);
+
+template <typename QueryT, typename NativeT>
+QueryT CastFromStateValue(GLenum pname, NativeT value)
+{
+ GLenum queryType = GLTypeToGLenum<QueryT>::value;
+
+ switch (queryType)
+ {
+ case GL_INT:
+ case GL_INT_64_ANGLEX:
+ case GL_UNSIGNED_INT:
+ case GL_UINT_64_ANGLEX:
+ return CastFromStateValueToInt<QueryT, NativeT>(pname, value);
+ case GL_FLOAT:
+ return static_cast<QueryT>(value);
+ case GL_BOOL:
+ return static_cast<QueryT>(value == static_cast<NativeT>(0) ? GL_FALSE : GL_TRUE);
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+template GLint CastFromStateValue<GLint, GLint>(GLenum pname, GLint value);
+template GLint CastFromStateValue<GLint, GLint64>(GLenum pname, GLint64 value);
+template GLint64 CastFromStateValue<GLint64, GLint>(GLenum pname, GLint value);
+template GLint64 CastFromStateValue<GLint64, GLint64>(GLenum pname, GLint64 value);
+template GLfloat CastFromStateValue<GLfloat, GLint>(GLenum pname, GLint value);
+template GLfloat CastFromStateValue<GLfloat, GLuint>(GLenum pname, GLuint value);
+template GLfloat CastFromStateValue<GLfloat, GLfloat>(GLenum pname, GLfloat value);
+template GLint CastFromStateValue<GLint, GLfloat>(GLenum pname, GLfloat value);
+template GLuint CastFromStateValue<GLuint, GLfloat>(GLenum pname, GLfloat value);
+template GLuint CastFromStateValue<GLuint, GLint>(GLenum pname, GLint value);
+template GLuint CastFromStateValue<GLuint, GLuint>(GLenum pname, GLuint value);
+template GLint CastFromStateValue<GLint, GLboolean>(GLenum pname, GLboolean value);
+template GLint64 CastFromStateValue<GLint64, GLboolean>(GLenum pname, GLboolean value);
+template GLint CastFromStateValue<GLint, GLuint>(GLenum pname, GLuint value);
+template GLint64 CastFromStateValue<GLint64, GLuint>(GLenum pname, GLuint value);
+template GLuint64 CastFromStateValue<GLuint64, GLuint>(GLenum pname, GLuint value);
+
+template <typename NativeT, typename QueryT>
+NativeT CastQueryValueTo(GLenum pname, QueryT value)
+{
+ GLenum nativeType = GLTypeToGLenum<NativeT>::value;
+
+ switch (nativeType)
+ {
+ case GL_INT:
+ case GL_INT_64_ANGLEX:
+ case GL_UNSIGNED_INT:
+ case GL_UINT_64_ANGLEX:
+ return CastQueryValueToInt<NativeT, QueryT>(pname, value);
+ case GL_FLOAT:
+ return static_cast<NativeT>(value);
+ case GL_BOOL:
+ return static_cast<NativeT>(value == static_cast<QueryT>(0) ? GL_FALSE : GL_TRUE);
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+template GLint CastQueryValueTo<GLint, GLfloat>(GLenum pname, GLfloat value);
+template GLboolean CastQueryValueTo<GLboolean, GLint>(GLenum pname, GLint value);
+template GLint CastQueryValueTo<GLint, GLint>(GLenum pname, GLint value);
+template GLint CastQueryValueTo<GLint, GLuint>(GLenum pname, GLuint value);
+template GLfloat CastQueryValueTo<GLfloat, GLint>(GLenum pname, GLint value);
+template GLfloat CastQueryValueTo<GLfloat, GLuint>(GLenum pname, GLuint value);
+template GLfloat CastQueryValueTo<GLfloat, GLfloat>(GLenum pname, GLfloat value);
+template GLuint CastQueryValueTo<GLuint, GLint>(GLenum pname, GLint value);
+template GLuint CastQueryValueTo<GLuint, GLuint>(GLenum pname, GLuint value);
+template GLuint CastQueryValueTo<GLuint, GLfloat>(GLenum pname, GLfloat value);
+
+template <typename QueryT>
+void CastStateValues(const Context *context,
+ GLenum nativeType,
+ GLenum pname,
+ unsigned int numParams,
+ QueryT *outParams)
+{
+ if (nativeType == GL_INT)
+ {
+ std::vector<GLint> intParams(numParams, 0);
+ context->getIntegervImpl(pname, intParams.data());
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] = CastFromStateValue<QueryT>(pname, intParams[i]);
+ }
+ }
+ else if (nativeType == GL_BOOL)
+ {
+ std::vector<GLboolean> boolParams(numParams, GL_FALSE);
+ context->getBooleanvImpl(pname, boolParams.data());
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] =
+ (boolParams[i] == GL_FALSE ? static_cast<QueryT>(0) : static_cast<QueryT>(1));
+ }
+ }
+ else if (nativeType == GL_FLOAT)
+ {
+ std::vector<GLfloat> floatParams(numParams, 0.0f);
+ context->getFloatvImpl(pname, floatParams.data());
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] = CastFromStateValue<QueryT>(pname, floatParams[i]);
+ }
+ }
+ else if (nativeType == GL_INT_64_ANGLEX)
+ {
+ std::vector<GLint64> int64Params(numParams, 0);
+ context->getInteger64vImpl(pname, int64Params.data());
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] = CastFromStateValue<QueryT>(pname, int64Params[i]);
+ }
+ }
+ else
+ {
+ WARN() << "Application querying parameter that does not exist.";
+ }
+}
+
+// Explicit template instantiation (how we export template functions in different files)
+// The calls below will make CastStateValues successfully link with the GL state query types
+// The GL state query API types are: bool, int, uint, float, int64, uint64
+
+template void CastStateValues<GLboolean>(const Context *,
+ GLenum,
+ GLenum,
+ unsigned int,
+ GLboolean *);
+template void CastStateValues<GLint>(const Context *, GLenum, GLenum, unsigned int, GLint *);
+template void CastStateValues<GLuint>(const Context *, GLenum, GLenum, unsigned int, GLuint *);
+template void CastStateValues<GLfloat>(const Context *, GLenum, GLenum, unsigned int, GLfloat *);
+template void CastStateValues<GLint64>(const Context *, GLenum, GLenum, unsigned int, GLint64 *);
+
+template <typename QueryT>
+void CastIndexedStateValues(Context *context,
+ GLenum nativeType,
+ GLenum pname,
+ GLuint index,
+ unsigned int numParams,
+ QueryT *outParams)
+{
+ if (nativeType == GL_INT)
+ {
+ std::vector<GLint> intParams(numParams, 0);
+ context->getIntegeri_v(pname, index, intParams.data());
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] = CastFromStateValue<QueryT>(pname, intParams[i]);
+ }
+ }
+ else if (nativeType == GL_BOOL)
+ {
+ std::vector<GLboolean> boolParams(numParams, GL_FALSE);
+ context->getBooleani_v(pname, index, boolParams.data());
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] =
+ (boolParams[i] == GL_FALSE ? static_cast<QueryT>(0) : static_cast<QueryT>(1));
+ }
+ }
+ else if (nativeType == GL_INT_64_ANGLEX)
+ {
+ std::vector<GLint64> int64Params(numParams, 0);
+ context->getInteger64i_v(pname, index, int64Params.data());
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ outParams[i] = CastFromStateValue<QueryT>(pname, int64Params[i]);
+ }
+ }
+ else
+ UNREACHABLE();
+}
+
+template void CastIndexedStateValues<GLboolean>(Context *,
+ GLenum,
+ GLenum,
+ GLuint index,
+ unsigned int,
+ GLboolean *);
+template void CastIndexedStateValues<GLint>(Context *,
+ GLenum,
+ GLenum,
+ GLuint index,
+ unsigned int,
+ GLint *);
+template void CastIndexedStateValues<GLuint>(Context *,
+ GLenum,
+ GLenum,
+ GLuint index,
+ unsigned int,
+ GLuint *);
+template void CastIndexedStateValues<GLfloat>(Context *,
+ GLenum,
+ GLenum,
+ GLuint index,
+ unsigned int,
+ GLfloat *);
+template void CastIndexedStateValues<GLint64>(Context *,
+ GLenum,
+ GLenum,
+ GLuint index,
+ unsigned int,
+ GLint64 *);
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/queryconversions.h b/gfx/angle/checkout/src/libANGLE/queryconversions.h
new file mode 100644
index 0000000000..7784c33e73
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/queryconversions.h
@@ -0,0 +1,138 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// queryconversions.h: Declaration of state query cast conversions
+
+#ifndef LIBANGLE_QUERY_CONVERSIONS_H_
+#define LIBANGLE_QUERY_CONVERSIONS_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+
+namespace gl
+{
+class Context;
+
+// Helper class for converting a GL type to a GLenum:
+// We can't use CastStateValueEnum generally, because of GLboolean + GLubyte overlap.
+// We restrict our use to CastFromStateValue and CastQueryValueTo, where it eliminates
+// duplicate parameters.
+
+template <typename GLType>
+struct GLTypeToGLenum
+{
+ // static constexpr GLenum value;
+};
+
+template <>
+struct GLTypeToGLenum<GLint>
+{
+ static constexpr GLenum value = GL_INT;
+};
+template <>
+struct GLTypeToGLenum<GLuint>
+{
+ static constexpr GLenum value = GL_UNSIGNED_INT;
+};
+template <>
+struct GLTypeToGLenum<GLboolean>
+{
+ static constexpr GLenum value = GL_BOOL;
+};
+template <>
+struct GLTypeToGLenum<GLint64>
+{
+ static constexpr GLenum value = GL_INT_64_ANGLEX;
+};
+template <>
+struct GLTypeToGLenum<GLuint64>
+{
+ static constexpr GLenum value = GL_UINT_64_ANGLEX;
+};
+template <>
+struct GLTypeToGLenum<GLfloat>
+{
+ static constexpr GLenum value = GL_FLOAT;
+};
+
+GLint CastMaskValue(GLuint value);
+
+template <typename QueryT, typename InternalT>
+QueryT CastFromGLintStateValue(GLenum pname, InternalT value);
+
+template <typename QueryT, typename NativeT>
+QueryT CastFromStateValue(GLenum pname, NativeT value);
+
+template <typename NativeT, typename QueryT>
+NativeT CastQueryValueTo(GLenum pname, QueryT value);
+
+template <typename ParamType>
+GLenum ConvertToGLenum(GLenum pname, ParamType param)
+{
+ return static_cast<GLenum>(CastQueryValueTo<GLuint>(pname, param));
+}
+
+template <typename ParamType>
+GLenum ConvertToGLenum(ParamType param)
+{
+ return ConvertToGLenum(GL_NONE, param);
+}
+
+template <typename OutType>
+OutType ConvertGLenum(GLenum param)
+{
+ return static_cast<OutType>(param);
+}
+
+template <typename InType, typename OutType>
+void ConvertGLenumValue(InType param, OutType *out)
+{
+ *out = ConvertGLenum<OutType>(static_cast<GLenum>(param));
+}
+
+template <typename PackedEnumType, typename OutType>
+void ConvertPackedEnum(PackedEnumType param, OutType *out)
+{
+ *out = static_cast<OutType>(ToGLenum(param));
+}
+
+template <typename ParamType>
+GLint ConvertToGLint(ParamType param)
+{
+ return CastQueryValueTo<GLint>(GL_NONE, param);
+}
+
+template <typename ParamType>
+bool ConvertToBool(ParamType param)
+{
+ return param != GL_FALSE;
+}
+
+template <typename ParamType>
+GLboolean ConvertToGLBoolean(ParamType param)
+{
+ return param ? GL_TRUE : GL_FALSE;
+}
+
+// The GL state query API types are: bool, int, uint, float, int64, uint64
+template <typename QueryT>
+void CastStateValues(const Context *context,
+ GLenum nativeType,
+ GLenum pname,
+ unsigned int numParams,
+ QueryT *outParams);
+
+// The GL state query API types are: bool, int, uint, float, int64, uint64
+template <typename QueryT>
+void CastIndexedStateValues(Context *context,
+ GLenum nativeType,
+ GLenum pname,
+ GLuint index,
+ unsigned int numParams,
+ QueryT *outParams);
+} // namespace gl
+
+#endif // LIBANGLE_QUERY_CONVERSIONS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/queryutils.cpp b/gfx/angle/checkout/src/libANGLE/queryutils.cpp
new file mode 100644
index 0000000000..56600eae9d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/queryutils.cpp
@@ -0,0 +1,4525 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// queryutils.cpp: Utilities for querying values from GL objects
+
+#include "libANGLE/queryutils.h"
+
+#include <algorithm>
+
+#include "common/utilities.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/EGLSync.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/GLES1State.h"
+#include "libANGLE/MemoryObject.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Sampler.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/queryconversions.h"
+
+namespace gl
+{
+
+namespace
+{
+
+template <bool isPureInteger>
+ColorGeneric ConvertToColor(const GLfloat *params)
+{
+ if (isPureInteger)
+ {
+ UNREACHABLE();
+ return ColorGeneric(ColorI());
+ }
+ else
+ {
+ return ColorGeneric(ColorF::fromData(params));
+ }
+}
+
+template <bool isPureInteger>
+ColorGeneric ConvertToColor(const GLint *params)
+{
+ if (isPureInteger)
+ {
+ return ColorGeneric(ColorI(params[0], params[1], params[2], params[3]));
+ }
+ else
+ {
+ return ColorGeneric(ColorF(normalizedToFloat(params[0]), normalizedToFloat(params[1]),
+ normalizedToFloat(params[2]), normalizedToFloat(params[3])));
+ }
+}
+
+template <bool isPureInteger>
+ColorGeneric ConvertToColor(const GLuint *params)
+{
+ if (isPureInteger)
+ {
+ return ColorGeneric(ColorUI(params[0], params[1], params[2], params[3]));
+ }
+ else
+ {
+ UNREACHABLE();
+ return ColorGeneric(ColorF());
+ }
+}
+
+template <bool isPureInteger>
+void ConvertFromColor(const ColorGeneric &color, GLfloat *outParams)
+{
+ if (isPureInteger)
+ {
+ UNREACHABLE();
+ }
+ else
+ {
+ color.colorF.writeData(outParams);
+ }
+}
+
+template <bool isPureInteger>
+void ConvertFromColor(const ColorGeneric &color, GLint *outParams)
+{
+ if (isPureInteger)
+ {
+ outParams[0] = color.colorI.red;
+ outParams[1] = color.colorI.green;
+ outParams[2] = color.colorI.blue;
+ outParams[3] = color.colorI.alpha;
+ }
+ else
+ {
+ outParams[0] = floatToNormalized<GLint>(color.colorF.red);
+ outParams[1] = floatToNormalized<GLint>(color.colorF.green);
+ outParams[2] = floatToNormalized<GLint>(color.colorF.blue);
+ outParams[3] = floatToNormalized<GLint>(color.colorF.alpha);
+ }
+}
+
+template <bool isPureInteger>
+void ConvertFromColor(const ColorGeneric &color, GLuint *outParams)
+{
+ if (isPureInteger)
+ {
+ constexpr unsigned int kMinValue = 0;
+
+ outParams[0] = std::max(color.colorUI.red, kMinValue);
+ outParams[1] = std::max(color.colorUI.green, kMinValue);
+ outParams[2] = std::max(color.colorUI.blue, kMinValue);
+ outParams[3] = std::max(color.colorUI.alpha, kMinValue);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+}
+
+template <typename ParamType>
+void QueryTexLevelParameterBase(const Texture *texture,
+ TextureTarget target,
+ GLint level,
+ GLenum pname,
+ ParamType *params)
+{
+ ASSERT(texture != nullptr);
+ const InternalFormat *info = texture->getTextureState().getImageDesc(target, level).format.info;
+
+ switch (pname)
+ {
+ case GL_TEXTURE_RED_TYPE:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, info->redBits ? info->componentType : GL_NONE);
+ break;
+ case GL_TEXTURE_GREEN_TYPE:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, info->greenBits ? info->componentType : GL_NONE);
+ break;
+ case GL_TEXTURE_BLUE_TYPE:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, info->blueBits ? info->componentType : GL_NONE);
+ break;
+ case GL_TEXTURE_ALPHA_TYPE:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, info->alphaBits ? info->componentType : GL_NONE);
+ break;
+ case GL_TEXTURE_DEPTH_TYPE:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, info->depthBits ? info->componentType : GL_NONE);
+ break;
+ case GL_TEXTURE_RED_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, info->redBits);
+ break;
+ case GL_TEXTURE_GREEN_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, info->greenBits);
+ break;
+ case GL_TEXTURE_BLUE_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, info->blueBits);
+ break;
+ case GL_TEXTURE_ALPHA_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, info->alphaBits);
+ break;
+ case GL_TEXTURE_DEPTH_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, info->depthBits);
+ break;
+ case GL_TEXTURE_STENCIL_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, info->stencilBits);
+ break;
+ case GL_TEXTURE_SHARED_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, info->sharedBits);
+ break;
+ case GL_TEXTURE_INTERNAL_FORMAT:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, info->internalFormat ? info->internalFormat : GL_RGBA);
+ break;
+ case GL_TEXTURE_WIDTH:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, static_cast<uint32_t>(texture->getWidth(target, level)));
+ break;
+ case GL_TEXTURE_HEIGHT:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, static_cast<uint32_t>(texture->getHeight(target, level)));
+ break;
+ case GL_TEXTURE_DEPTH:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, static_cast<uint32_t>(texture->getDepth(target, level)));
+ break;
+ case GL_TEXTURE_SAMPLES:
+ *params = CastFromStateValue<ParamType>(pname, texture->getSamples(target, level));
+ break;
+ case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
+ *params = CastFromStateValue<ParamType>(
+ pname, static_cast<GLint>(texture->getFixedSampleLocations(target, level)));
+ break;
+ case GL_TEXTURE_COMPRESSED:
+ *params = CastFromStateValue<ParamType>(pname, static_cast<GLint>(info->compressed));
+ break;
+ case GL_MEMORY_SIZE_ANGLE:
+ *params =
+ CastFromStateValue<ParamType>(pname, texture->getLevelMemorySize(target, level));
+ break;
+ case GL_RESOURCE_INITIALIZED_ANGLE:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, texture->initState(GL_NONE, ImageIndex::MakeFromTarget(target, level)) ==
+ InitState::Initialized);
+ break;
+ case GL_TEXTURE_BUFFER_DATA_STORE_BINDING:
+ *params = CastFromStateValue<ParamType>(
+ pname, static_cast<GLint>(texture->getBuffer().id().value));
+ break;
+ case GL_TEXTURE_BUFFER_OFFSET:
+ *params = CastFromStateValue<ParamType>(
+ pname, static_cast<GLint>(texture->getBuffer().getOffset()));
+ break;
+ case GL_TEXTURE_BUFFER_SIZE:
+ *params = CastFromStateValue<ParamType>(
+ pname, static_cast<GLint>(GetBoundBufferAvailableSize(texture->getBuffer())));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+// This function is needed to handle fixed_point data.
+// It can be used when some pname need special conversion from int/float/bool to fixed_point.
+template <bool isGLfixed, typename QueryT, typename ParamType>
+QueryT CastFromSpecialValue(GLenum pname, const ParamType param)
+{
+ if (isGLfixed)
+ {
+ return static_cast<QueryT>(ConvertFloatToFixed(CastFromStateValue<GLfloat>(pname, param)));
+ }
+ else
+ {
+ return CastFromStateValue<QueryT>(pname, param);
+ }
+}
+
+template <bool isPureInteger, bool isGLfixed, typename ParamType>
+void QueryTexParameterBase(const Context *context,
+ const Texture *texture,
+ GLenum pname,
+ ParamType *params)
+{
+ ASSERT(texture != nullptr);
+
+ switch (pname)
+ {
+ case GL_TEXTURE_MAG_FILTER:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getMagFilter());
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getMinFilter());
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getWrapS());
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getWrapT());
+ break;
+ case GL_TEXTURE_WRAP_R:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getWrapR());
+ break;
+ case GL_TEXTURE_IMMUTABLE_FORMAT:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getImmutableFormat());
+ break;
+ case GL_TEXTURE_IMMUTABLE_LEVELS:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getImmutableLevels());
+ break;
+ case GL_TEXTURE_USAGE_ANGLE:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getUsage());
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ *params =
+ CastFromSpecialValue<isGLfixed, ParamType>(pname, texture->getMaxAnisotropy());
+ break;
+ case GL_TEXTURE_SWIZZLE_R:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getSwizzleRed());
+ break;
+ case GL_TEXTURE_SWIZZLE_G:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getSwizzleGreen());
+ break;
+ case GL_TEXTURE_SWIZZLE_B:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getSwizzleBlue());
+ break;
+ case GL_TEXTURE_SWIZZLE_A:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getSwizzleAlpha());
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getBaseLevel());
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getMaxLevel());
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ *params = CastFromSpecialValue<isGLfixed, ParamType>(pname, texture->getMinLod());
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = CastFromSpecialValue<isGLfixed, ParamType>(pname, texture->getMaxLod());
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getCompareMode());
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getCompareFunc());
+ break;
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getSRGBDecode());
+ break;
+ case GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getSRGBOverride());
+ break;
+ case GL_DEPTH_STENCIL_TEXTURE_MODE:
+ *params =
+ CastFromGLintStateValue<ParamType>(pname, texture->getDepthStencilTextureMode());
+ break;
+ case GL_TEXTURE_CROP_RECT_OES:
+ {
+ const gl::Rectangle &crop = texture->getCrop();
+ params[0] = CastFromSpecialValue<isGLfixed, ParamType>(pname, crop.x);
+ params[1] = CastFromSpecialValue<isGLfixed, ParamType>(pname, crop.y);
+ params[2] = CastFromSpecialValue<isGLfixed, ParamType>(pname, crop.width);
+ params[3] = CastFromSpecialValue<isGLfixed, ParamType>(pname, crop.height);
+ break;
+ }
+ case GL_GENERATE_MIPMAP:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->getGenerateMipmapHint());
+ break;
+ case GL_MEMORY_SIZE_ANGLE:
+ *params = CastFromSpecialValue<isGLfixed, ParamType>(pname, texture->getMemorySize());
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ ConvertFromColor<isPureInteger>(texture->getBorderColor(), params);
+ break;
+ case GL_TEXTURE_NATIVE_ID_ANGLE:
+ *params = CastFromSpecialValue<isGLfixed, ParamType>(pname, texture->getNativeID());
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, texture->getImplementationColorReadFormat(context));
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, texture->getImplementationColorReadType(context));
+ break;
+ case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE:
+ *params =
+ CastFromGLintStateValue<ParamType>(pname, GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE);
+ break;
+ case GL_RESOURCE_INITIALIZED_ANGLE:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, texture->initState() == InitState::Initialized);
+ break;
+ case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, texture->getRequiredTextureImageUnits(context));
+ break;
+ case GL_TEXTURE_PROTECTED_EXT:
+ *params = CastFromGLintStateValue<ParamType>(pname, texture->hasProtectedContent());
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+// this function is needed to handle OES_FIXED_POINT.
+// Some pname values can take in GLfixed values and may need to be converted
+template <bool isGLfixed, typename ReturnType, typename ParamType>
+ReturnType ConvertTexParam(GLenum pname, const ParamType param)
+{
+ if (isGLfixed)
+ {
+ return CastQueryValueTo<ReturnType>(pname,
+ ConvertFixedToFloat(static_cast<GLfixed>(param)));
+ }
+ else
+ {
+ return CastQueryValueTo<ReturnType>(pname, param);
+ }
+}
+
+template <bool isPureInteger, bool isGLfixed, typename ParamType>
+void SetTexParameterBase(Context *context, Texture *texture, GLenum pname, const ParamType *params)
+{
+ ASSERT(texture != nullptr);
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ texture->setWrapS(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_WRAP_T:
+ texture->setWrapT(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_WRAP_R:
+ texture->setWrapR(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ texture->setMinFilter(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ texture->setMagFilter(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_USAGE_ANGLE:
+ texture->setUsage(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ texture->setMaxAnisotropy(context,
+ ConvertTexParam<isGLfixed, GLfloat>(pname, params[0]));
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ texture->setCompareMode(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ texture->setCompareFunc(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_SWIZZLE_R:
+ texture->setSwizzleRed(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_SWIZZLE_G:
+ texture->setSwizzleGreen(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_SWIZZLE_B:
+ texture->setSwizzleBlue(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_SWIZZLE_A:
+ texture->setSwizzleAlpha(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ {
+ (void)(texture->setBaseLevel(
+ context, clampCast<GLuint>(CastQueryValueTo<GLint>(pname, params[0]))));
+ break;
+ }
+ case GL_TEXTURE_MAX_LEVEL:
+ texture->setMaxLevel(context,
+ clampCast<GLuint>(CastQueryValueTo<GLint>(pname, params[0])));
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ texture->setMinLod(context, CastQueryValueTo<GLfloat>(pname, params[0]));
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ texture->setMaxLod(context, CastQueryValueTo<GLfloat>(pname, params[0]));
+ break;
+ case GL_DEPTH_STENCIL_TEXTURE_MODE:
+ texture->setDepthStencilTextureMode(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ texture->setSRGBDecode(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT:
+ texture->setSRGBOverride(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_CROP_RECT_OES:
+ texture->setCrop(gl::Rectangle(ConvertTexParam<isGLfixed, GLint>(pname, params[0]),
+ ConvertTexParam<isGLfixed, GLint>(pname, params[1]),
+ ConvertTexParam<isGLfixed, GLint>(pname, params[2]),
+ ConvertTexParam<isGLfixed, GLint>(pname, params[3])));
+ break;
+ case GL_GENERATE_MIPMAP:
+ texture->setGenerateMipmapHint(ConvertToGLenum(params[0]));
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ texture->setBorderColor(context, ConvertToColor<isPureInteger>(params));
+ break;
+ case GL_RESOURCE_INITIALIZED_ANGLE:
+ texture->setInitState(ConvertToBool(params[0]) ? InitState::Initialized
+ : InitState::MayNeedInit);
+ break;
+ case GL_TEXTURE_PROTECTED_EXT:
+ texture->setProtectedContent(context, (params[0] == GL_TRUE));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+template <bool isPureInteger, typename ParamType>
+void QuerySamplerParameterBase(const Sampler *sampler, GLenum pname, ParamType *params)
+{
+ switch (pname)
+ {
+ case GL_TEXTURE_MIN_FILTER:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getMinFilter());
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getMagFilter());
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getWrapS());
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getWrapT());
+ break;
+ case GL_TEXTURE_WRAP_R:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getWrapR());
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ *params = CastFromStateValue<ParamType>(pname, sampler->getMaxAnisotropy());
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ *params = CastFromStateValue<ParamType>(pname, sampler->getMinLod());
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = CastFromStateValue<ParamType>(pname, sampler->getMaxLod());
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getCompareMode());
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getCompareFunc());
+ break;
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ *params = CastFromGLintStateValue<ParamType>(pname, sampler->getSRGBDecode());
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ ConvertFromColor<isPureInteger>(sampler->getBorderColor(), params);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+template <bool isPureInteger, typename ParamType>
+void SetSamplerParameterBase(Context *context,
+ Sampler *sampler,
+ GLenum pname,
+ const ParamType *params)
+{
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ sampler->setWrapS(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_WRAP_T:
+ sampler->setWrapT(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_WRAP_R:
+ sampler->setWrapR(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ sampler->setMinFilter(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ sampler->setMagFilter(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ sampler->setMaxAnisotropy(context, CastQueryValueTo<GLfloat>(pname, params[0]));
+ break;
+ case GL_TEXTURE_COMPARE_MODE:
+ sampler->setCompareMode(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_COMPARE_FUNC:
+ sampler->setCompareFunc(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ sampler->setMinLod(context, CastQueryValueTo<GLfloat>(pname, params[0]));
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ sampler->setMaxLod(context, CastQueryValueTo<GLfloat>(pname, params[0]));
+ break;
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ sampler->setSRGBDecode(context, ConvertToGLenum(pname, params[0]));
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ sampler->setBorderColor(context, ConvertToColor<isPureInteger>(params));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ sampler->onStateChange(angle::SubjectMessage::ContentsChanged);
+}
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+template <typename ParamType, typename CurrentDataType, size_t CurrentValueCount>
+void QueryVertexAttribBase(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const CurrentDataType (&currentValueData)[CurrentValueCount],
+ GLenum pname,
+ ParamType *params)
+{
+ switch (pname)
+ {
+ case GL_CURRENT_VERTEX_ATTRIB:
+ for (size_t i = 0; i < CurrentValueCount; ++i)
+ {
+ params[i] = CastFromStateValue<ParamType>(pname, currentValueData[i]);
+ }
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
+ *params = CastFromStateValue<ParamType>(pname, static_cast<GLint>(attrib.enabled));
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_SIZE:
+ *params = CastFromGLintStateValue<ParamType>(pname, attrib.format->channelCount);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
+ *params = CastFromGLintStateValue<ParamType>(pname, attrib.vertexAttribArrayStride);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_TYPE:
+ *params = CastFromGLintStateValue<ParamType>(
+ pname, gl::ToGLenum(attrib.format->vertexAttribType));
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
+ *params =
+ CastFromStateValue<ParamType>(pname, static_cast<GLint>(attrib.format->isNorm()));
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
+ *params = CastFromGLintStateValue<ParamType>(pname, binding.getBuffer().id().value);
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
+ *params = CastFromStateValue<ParamType>(pname, binding.getDivisor());
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
+ *params = CastFromGLintStateValue<ParamType>(pname, attrib.format->isPureInt());
+ break;
+ case GL_VERTEX_ATTRIB_BINDING:
+ *params = CastFromGLintStateValue<ParamType>(pname, attrib.bindingIndex);
+ break;
+ case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
+ *params = CastFromGLintStateValue<ParamType>(pname, attrib.relativeOffset);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+template <typename ParamType>
+void QueryBufferParameterBase(const Buffer *buffer, GLenum pname, ParamType *params)
+{
+ ASSERT(buffer != nullptr);
+
+ switch (pname)
+ {
+ case GL_BUFFER_USAGE:
+ *params = CastFromGLintStateValue<ParamType>(pname, ToGLenum(buffer->getUsage()));
+ break;
+ case GL_BUFFER_SIZE:
+ *params = CastFromStateValue<ParamType>(pname, buffer->getSize());
+ break;
+ case GL_BUFFER_ACCESS_FLAGS:
+ *params = CastFromGLintStateValue<ParamType>(pname, buffer->getAccessFlags());
+ break;
+ case GL_BUFFER_ACCESS_OES:
+ *params = CastFromGLintStateValue<ParamType>(pname, buffer->getAccess());
+ break;
+ case GL_BUFFER_MAPPED:
+ *params = CastFromStateValue<ParamType>(pname, buffer->isMapped());
+ break;
+ case GL_BUFFER_MAP_OFFSET:
+ *params = CastFromStateValue<ParamType>(pname, buffer->getMapOffset());
+ break;
+ case GL_BUFFER_MAP_LENGTH:
+ *params = CastFromStateValue<ParamType>(pname, buffer->getMapLength());
+ break;
+ case GL_MEMORY_SIZE_ANGLE:
+ *params = CastFromStateValue<ParamType>(pname, buffer->getMemorySize());
+ break;
+ case GL_BUFFER_IMMUTABLE_STORAGE_EXT:
+ *params = CastFromStateValue<ParamType>(pname, buffer->isImmutable());
+ break;
+ case GL_BUFFER_STORAGE_FLAGS_EXT:
+ *params = CastFromGLintStateValue<ParamType>(pname, buffer->getStorageExtUsageFlags());
+ break;
+ case GL_RESOURCE_INITIALIZED_ANGLE:
+ *params = CastFromStateValue<ParamType>(
+ pname, ConvertToGLBoolean(buffer->initState() == InitState::Initialized));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+GLint GetCommonVariableProperty(const sh::ShaderVariable &var, GLenum prop)
+{
+ switch (prop)
+ {
+ case GL_TYPE:
+ return clampCast<GLint>(var.type);
+
+ case GL_ARRAY_SIZE:
+ // Queryable variables are guaranteed not to be arrays of arrays or arrays of structs,
+ // see GLES 3.1 spec section 7.3.1.1 page 77.
+ return clampCast<GLint>(var.getBasicTypeElementCount());
+
+ case GL_NAME_LENGTH:
+ // ES31 spec p84: This counts the terminating null char.
+ return clampCast<GLint>(var.name.size() + 1u);
+
+ default:
+ UNREACHABLE();
+ return GL_INVALID_VALUE;
+ }
+}
+
+GLint GetInputResourceProperty(const Program *program, GLuint index, GLenum prop)
+{
+ const sh::ShaderVariable &variable = program->getInputResource(index);
+
+ switch (prop)
+ {
+ case GL_TYPE:
+ case GL_ARRAY_SIZE:
+ return GetCommonVariableProperty(variable, prop);
+
+ case GL_NAME_LENGTH:
+ return clampCast<GLint>(program->getInputResourceName(index).size() + 1u);
+
+ case GL_LOCATION:
+ return variable.isBuiltIn() ? GL_INVALID_INDEX : variable.location;
+
+ // The query is targeted at the set of active input variables used by the first shader stage
+ // of program. If program contains multiple shader stages then input variables from any
+ // stage other than the first will not be enumerated. Since we found the variable to get
+ // this far, we know it exists in the first attached shader stage.
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ return program->getState().getFirstAttachedShaderStageType() == ShaderType::Vertex;
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ return program->getState().getFirstAttachedShaderStageType() == ShaderType::Fragment;
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ return program->getState().getFirstAttachedShaderStageType() == ShaderType::Compute;
+ case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
+ return program->getState().getFirstAttachedShaderStageType() == ShaderType::Geometry;
+ case GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT:
+ return program->getState().getFirstAttachedShaderStageType() == ShaderType::TessControl;
+ case GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT:
+ return program->getState().getFirstAttachedShaderStageType() ==
+ ShaderType::TessEvaluation;
+ case GL_IS_PER_PATCH_EXT:
+ return variable.isPatch;
+
+ default:
+ UNREACHABLE();
+ return GL_INVALID_VALUE;
+ }
+}
+
+GLint GetOutputResourceProperty(const Program *program, GLuint index, const GLenum prop)
+{
+ const sh::ShaderVariable &outputVariable = program->getOutputResource(index);
+
+ switch (prop)
+ {
+ case GL_TYPE:
+ case GL_ARRAY_SIZE:
+ return GetCommonVariableProperty(outputVariable, prop);
+
+ case GL_NAME_LENGTH:
+ return clampCast<GLint>(program->getOutputResourceName(index).size() + 1u);
+
+ case GL_LOCATION:
+ return outputVariable.location;
+
+ case GL_LOCATION_INDEX_EXT:
+ // EXT_blend_func_extended
+ if (program->getState().getLastAttachedShaderStageType() == gl::ShaderType::Fragment)
+ {
+ return program->getFragDataIndex(outputVariable.name);
+ }
+ return GL_INVALID_INDEX;
+
+ // The set of active user-defined outputs from the final shader stage in this program. If
+ // the final stage is a Fragment Shader, then this represents the fragment outputs that get
+ // written to individual color buffers. If the program only contains a Compute Shader, then
+ // there are no user-defined outputs.
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ return program->getState().getLastAttachedShaderStageType() == ShaderType::Vertex;
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ return program->getState().getLastAttachedShaderStageType() == ShaderType::Fragment;
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ return program->getState().getLastAttachedShaderStageType() == ShaderType::Compute;
+ case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
+ return program->getState().getLastAttachedShaderStageType() == ShaderType::Geometry;
+ case GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT:
+ return program->getState().getLastAttachedShaderStageType() == ShaderType::TessControl;
+ case GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT:
+ return program->getState().getLastAttachedShaderStageType() ==
+ ShaderType::TessEvaluation;
+ case GL_IS_PER_PATCH_EXT:
+ return outputVariable.isPatch;
+
+ default:
+ UNREACHABLE();
+ return GL_INVALID_VALUE;
+ }
+}
+
+GLint GetTransformFeedbackVaryingResourceProperty(const Program *program,
+ GLuint index,
+ const GLenum prop)
+{
+ const auto &tfVariable = program->getTransformFeedbackVaryingResource(index);
+ switch (prop)
+ {
+ case GL_TYPE:
+ return clampCast<GLint>(tfVariable.type);
+
+ case GL_ARRAY_SIZE:
+ return clampCast<GLint>(tfVariable.size());
+
+ case GL_NAME_LENGTH:
+ return clampCast<GLint>(tfVariable.nameWithArrayIndex().size() + 1);
+
+ default:
+ UNREACHABLE();
+ return GL_INVALID_VALUE;
+ }
+}
+
+GLint QueryProgramInterfaceActiveResources(const Program *program, GLenum programInterface)
+{
+ switch (programInterface)
+ {
+ case GL_PROGRAM_INPUT:
+ return clampCast<GLint>(program->getState().getProgramInputs().size());
+
+ case GL_PROGRAM_OUTPUT:
+ return clampCast<GLint>(program->getState().getOutputVariables().size());
+
+ case GL_UNIFORM:
+ return clampCast<GLint>(program->getState().getUniforms().size());
+
+ case GL_UNIFORM_BLOCK:
+ return clampCast<GLint>(program->getState().getUniformBlocks().size());
+
+ case GL_ATOMIC_COUNTER_BUFFER:
+ return clampCast<GLint>(program->getState().getAtomicCounterBuffers().size());
+
+ case GL_BUFFER_VARIABLE:
+ return clampCast<GLint>(program->getState().getBufferVariables().size());
+
+ case GL_SHADER_STORAGE_BLOCK:
+ return clampCast<GLint>(program->getState().getShaderStorageBlocks().size());
+
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ return clampCast<GLint>(program->getTransformFeedbackVaryingCount());
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+template <typename T, typename M>
+GLint FindMaxSize(const std::vector<T> &resources, M member)
+{
+ GLint max = 0;
+ for (const T &resource : resources)
+ {
+ max = std::max(max, clampCast<GLint>((resource.*member).size()));
+ }
+ return max;
+}
+
+GLint QueryProgramInterfaceMaxNameLength(const Program *program, GLenum programInterface)
+{
+ GLint maxNameLength = 0;
+ switch (programInterface)
+ {
+ case GL_PROGRAM_INPUT:
+ maxNameLength = program->getInputResourceMaxNameSize();
+ break;
+
+ case GL_PROGRAM_OUTPUT:
+ maxNameLength = program->getOutputResourceMaxNameSize();
+ break;
+
+ case GL_UNIFORM:
+ maxNameLength = FindMaxSize(program->getState().getUniforms(), &LinkedUniform::name);
+ break;
+
+ case GL_UNIFORM_BLOCK:
+ return program->getActiveUniformBlockMaxNameLength();
+
+ case GL_BUFFER_VARIABLE:
+ maxNameLength =
+ FindMaxSize(program->getState().getBufferVariables(), &BufferVariable::name);
+ break;
+
+ case GL_SHADER_STORAGE_BLOCK:
+ return program->getActiveShaderStorageBlockMaxNameLength();
+
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ return clampCast<GLint>(program->getTransformFeedbackVaryingMaxLength());
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+ // This length includes an extra character for the null terminator.
+ return (maxNameLength == 0 ? 0 : maxNameLength + 1);
+}
+
+GLint QueryProgramInterfaceMaxNumActiveVariables(const Program *program, GLenum programInterface)
+{
+ switch (programInterface)
+ {
+ case GL_UNIFORM_BLOCK:
+ return FindMaxSize(program->getState().getUniformBlocks(),
+ &InterfaceBlock::memberIndexes);
+ case GL_ATOMIC_COUNTER_BUFFER:
+ return FindMaxSize(program->getState().getAtomicCounterBuffers(),
+ &AtomicCounterBuffer::memberIndexes);
+
+ case GL_SHADER_STORAGE_BLOCK:
+ return FindMaxSize(program->getState().getShaderStorageBlocks(),
+ &InterfaceBlock::memberIndexes);
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+GLenum GetUniformPropertyEnum(GLenum prop)
+{
+ switch (prop)
+ {
+ case GL_UNIFORM_TYPE:
+ return GL_TYPE;
+ case GL_UNIFORM_SIZE:
+ return GL_ARRAY_SIZE;
+ case GL_UNIFORM_NAME_LENGTH:
+ return GL_NAME_LENGTH;
+ case GL_UNIFORM_BLOCK_INDEX:
+ return GL_BLOCK_INDEX;
+ case GL_UNIFORM_OFFSET:
+ return GL_OFFSET;
+ case GL_UNIFORM_ARRAY_STRIDE:
+ return GL_ARRAY_STRIDE;
+ case GL_UNIFORM_MATRIX_STRIDE:
+ return GL_MATRIX_STRIDE;
+ case GL_UNIFORM_IS_ROW_MAJOR:
+ return GL_IS_ROW_MAJOR;
+
+ default:
+ return prop;
+ }
+}
+
+GLenum GetUniformBlockPropertyEnum(GLenum prop)
+{
+ switch (prop)
+ {
+ case GL_UNIFORM_BLOCK_BINDING:
+ return GL_BUFFER_BINDING;
+
+ case GL_UNIFORM_BLOCK_DATA_SIZE:
+ return GL_BUFFER_DATA_SIZE;
+
+ case GL_UNIFORM_BLOCK_NAME_LENGTH:
+ return GL_NAME_LENGTH;
+
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+ return GL_NUM_ACTIVE_VARIABLES;
+
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+ return GL_ACTIVE_VARIABLES;
+
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+ return GL_REFERENCED_BY_VERTEX_SHADER;
+
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+ return GL_REFERENCED_BY_FRAGMENT_SHADER;
+
+ default:
+ return prop;
+ }
+}
+
+void GetShaderVariableBufferResourceProperty(const ShaderVariableBuffer &buffer,
+ GLenum pname,
+ GLint *params,
+ GLsizei bufSize,
+ GLsizei *outputPosition)
+
+{
+ switch (pname)
+ {
+ case GL_BUFFER_BINDING:
+ params[(*outputPosition)++] = buffer.binding;
+ break;
+ case GL_BUFFER_DATA_SIZE:
+ params[(*outputPosition)++] = clampCast<GLint>(buffer.dataSize);
+ break;
+ case GL_NUM_ACTIVE_VARIABLES:
+ params[(*outputPosition)++] = buffer.numActiveVariables();
+ break;
+ case GL_ACTIVE_VARIABLES:
+ for (size_t memberIndex = 0;
+ memberIndex < buffer.memberIndexes.size() && *outputPosition < bufSize;
+ ++memberIndex)
+ {
+ params[(*outputPosition)++] = clampCast<GLint>(buffer.memberIndexes[memberIndex]);
+ }
+ break;
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ params[(*outputPosition)++] = static_cast<GLint>(buffer.isActive(ShaderType::Vertex));
+ break;
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ params[(*outputPosition)++] = static_cast<GLint>(buffer.isActive(ShaderType::Fragment));
+ break;
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ params[(*outputPosition)++] = static_cast<GLint>(buffer.isActive(ShaderType::Compute));
+ break;
+ case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
+ params[(*outputPosition)++] = static_cast<GLint>(buffer.isActive(ShaderType::Geometry));
+ break;
+ case GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT:
+ params[(*outputPosition)++] =
+ static_cast<GLint>(buffer.isActive(ShaderType::TessControl));
+ break;
+ case GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT:
+ params[(*outputPosition)++] =
+ static_cast<GLint>(buffer.isActive(ShaderType::TessEvaluation));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void GetInterfaceBlockResourceProperty(const InterfaceBlock &block,
+ GLenum pname,
+ GLint *params,
+ GLsizei bufSize,
+ GLsizei *outputPosition)
+{
+ if (pname == GL_NAME_LENGTH)
+ {
+ params[(*outputPosition)++] = clampCast<GLint>(block.nameWithArrayIndex().size() + 1);
+ return;
+ }
+ GetShaderVariableBufferResourceProperty(block, pname, params, bufSize, outputPosition);
+}
+
+void GetUniformBlockResourceProperty(const Program *program,
+ GLuint blockIndex,
+ GLenum pname,
+ GLint *params,
+ GLsizei bufSize,
+ GLsizei *outputPosition)
+
+{
+ ASSERT(*outputPosition < bufSize);
+ const auto &block = program->getUniformBlockByIndex(blockIndex);
+ GetInterfaceBlockResourceProperty(block, pname, params, bufSize, outputPosition);
+}
+
+void GetShaderStorageBlockResourceProperty(const Program *program,
+ GLuint blockIndex,
+ GLenum pname,
+ GLint *params,
+ GLsizei bufSize,
+ GLsizei *outputPosition)
+
+{
+ ASSERT(*outputPosition < bufSize);
+ const auto &block = program->getShaderStorageBlockByIndex(blockIndex);
+ GetInterfaceBlockResourceProperty(block, pname, params, bufSize, outputPosition);
+}
+
+void GetAtomicCounterBufferResourceProperty(const Program *program,
+ GLuint index,
+ GLenum pname,
+ GLint *params,
+ GLsizei bufSize,
+ GLsizei *outputPosition)
+
+{
+ ASSERT(*outputPosition < bufSize);
+ const auto &buffer = program->getState().getAtomicCounterBuffers()[index];
+ GetShaderVariableBufferResourceProperty(buffer, pname, params, bufSize, outputPosition);
+}
+
+bool IsTextureEnvEnumParameter(TextureEnvParameter pname)
+{
+ switch (pname)
+ {
+ case TextureEnvParameter::Mode:
+ case TextureEnvParameter::CombineRgb:
+ case TextureEnvParameter::CombineAlpha:
+ case TextureEnvParameter::Src0Rgb:
+ case TextureEnvParameter::Src1Rgb:
+ case TextureEnvParameter::Src2Rgb:
+ case TextureEnvParameter::Src0Alpha:
+ case TextureEnvParameter::Src1Alpha:
+ case TextureEnvParameter::Src2Alpha:
+ case TextureEnvParameter::Op0Rgb:
+ case TextureEnvParameter::Op1Rgb:
+ case TextureEnvParameter::Op2Rgb:
+ case TextureEnvParameter::Op0Alpha:
+ case TextureEnvParameter::Op1Alpha:
+ case TextureEnvParameter::Op2Alpha:
+ case TextureEnvParameter::PointCoordReplace:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void GetShaderProgramId(ProgramPipeline *programPipeline, ShaderType shaderType, GLint *params)
+{
+ ASSERT(params);
+
+ *params = 0;
+ if (programPipeline)
+ {
+ const Program *program = programPipeline->getShaderProgram(shaderType);
+ if (program)
+ {
+ *params = program->id().value;
+ }
+ }
+}
+
+} // namespace
+
+void QueryFramebufferAttachmentParameteriv(const Context *context,
+ const Framebuffer *framebuffer,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params)
+{
+ ASSERT(framebuffer);
+
+ const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
+
+ if (attachmentObject == nullptr)
+ {
+ // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
+ // is NONE, then querying any other pname will generate INVALID_ENUM.
+
+ // ES 3.0.2 spec pg 235 states that if the attachment type is none,
+ // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
+ // INVALID_OPERATION for all other pnames
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ *params = GL_NONE;
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ *params = 0;
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ *params = attachmentObject->type();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ *params = attachmentObject->id();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+ *params = attachmentObject->mipLevel();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+ {
+ TextureTarget face = attachmentObject->cubeMapFace();
+ if (face != TextureTarget::InvalidEnum)
+ {
+ *params = ToGLenum(attachmentObject->cubeMapFace());
+ }
+ else
+ {
+ // This happens when the attachment isn't a texture cube map face
+ *params = GL_NONE;
+ }
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
+ *params = attachmentObject->getRedSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
+ *params = attachmentObject->getGreenSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
+ *params = attachmentObject->getBlueSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
+ *params = attachmentObject->getAlphaSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
+ *params = attachmentObject->getDepthSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
+ *params = attachmentObject->getStencilSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
+ *params = attachmentObject->getComponentType();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
+ *params = attachmentObject->getColorEncoding();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
+ *params = attachmentObject->layer();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR:
+ *params = attachmentObject->getNumViews();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR:
+ *params = attachmentObject->getBaseViewIndex();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
+ *params = attachmentObject->isLayered();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT:
+ if (attachmentObject->type() == GL_TEXTURE)
+ {
+ *params = attachmentObject->getSamples();
+ }
+ else
+ {
+ *params = 0;
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryBufferParameteriv(const Buffer *buffer, GLenum pname, GLint *params)
+{
+ QueryBufferParameterBase(buffer, pname, params);
+}
+
+void QueryBufferParameteri64v(const Buffer *buffer, GLenum pname, GLint64 *params)
+{
+ QueryBufferParameterBase(buffer, pname, params);
+}
+
+void QueryBufferPointerv(const Buffer *buffer, GLenum pname, void **params)
+{
+ switch (pname)
+ {
+ case GL_BUFFER_MAP_POINTER:
+ *params = buffer->getMapPointer();
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryProgramiv(Context *context, const Program *program, GLenum pname, GLint *params)
+{
+ ASSERT(program != nullptr || pname == GL_COMPLETION_STATUS_KHR);
+
+ switch (pname)
+ {
+ case GL_DELETE_STATUS:
+ *params = program->isFlaggedForDeletion();
+ return;
+ case GL_LINK_STATUS:
+ *params = program->isLinked();
+ return;
+ case GL_COMPLETION_STATUS_KHR:
+ if (context->isContextLost())
+ {
+ *params = GL_TRUE;
+ }
+ else
+ {
+ *params = program->isLinking() ? GL_FALSE : GL_TRUE;
+ }
+ return;
+ case GL_VALIDATE_STATUS:
+ *params = program->isValidated();
+ return;
+ case GL_INFO_LOG_LENGTH:
+ *params = program->getExecutable().getInfoLogLength();
+ return;
+ case GL_ATTACHED_SHADERS:
+ *params = program->getAttachedShadersCount();
+ return;
+ case GL_ACTIVE_ATTRIBUTES:
+ *params = program->getActiveAttributeCount();
+ return;
+ case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+ *params = program->getActiveAttributeMaxLength();
+ return;
+ case GL_ACTIVE_UNIFORMS:
+ *params = program->getActiveUniformCount();
+ return;
+ case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+ *params = program->getActiveUniformMaxLength();
+ return;
+ case GL_PROGRAM_BINARY_LENGTH_OES:
+ *params = context->getCaps().programBinaryFormats.empty()
+ ? 0
+ : program->getBinaryLength(context);
+ return;
+ case GL_ACTIVE_UNIFORM_BLOCKS:
+ *params = program->getActiveUniformBlockCount();
+ return;
+ case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+ *params = program->getActiveUniformBlockMaxNameLength();
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
+ *params = program->getTransformFeedbackBufferMode();
+ break;
+ case GL_TRANSFORM_FEEDBACK_VARYINGS:
+ *params = clampCast<GLint>(program->getTransformFeedbackVaryingCount());
+ break;
+ case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
+ *params = program->getTransformFeedbackVaryingMaxLength();
+ break;
+ case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
+ *params = program->getBinaryRetrievableHint();
+ break;
+ case GL_PROGRAM_SEPARABLE:
+ // From es31cSeparateShaderObjsTests.cpp:
+ // ProgramParameteri PROGRAM_SEPARABLE
+ // NOTE: The query for PROGRAM_SEPARABLE must query latched
+ // state. In other words, the state of the binary after
+ // it was linked. So in the tests below, the queries
+ // should return the default state GL_FALSE since the
+ // program has no linked binary.
+ *params = program->isSeparable() && program->isLinked();
+ break;
+ case GL_COMPUTE_WORK_GROUP_SIZE:
+ {
+ const sh::WorkGroupSize &localSize = program->getComputeShaderLocalSize();
+ params[0] = localSize[0];
+ params[1] = localSize[1];
+ params[2] = localSize[2];
+ }
+ break;
+ case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
+ *params = program->getActiveAtomicCounterBufferCount();
+ break;
+ case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
+ *params = ToGLenum(program->getGeometryShaderInputPrimitiveType());
+ break;
+ case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
+ *params = ToGLenum(program->getGeometryShaderOutputPrimitiveType());
+ break;
+ case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
+ *params = program->getGeometryShaderMaxVertices();
+ break;
+ case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
+ *params = program->getGeometryShaderInvocations();
+ break;
+ case GL_TESS_CONTROL_OUTPUT_VERTICES_EXT:
+ *params = program->getTessControlShaderVertices();
+ break;
+ case GL_TESS_GEN_MODE_EXT:
+ *params = program->getTessGenMode();
+ break;
+ case GL_TESS_GEN_SPACING_EXT:
+ *params = program->getTessGenSpacing() ? program->getTessGenSpacing() : GL_EQUAL;
+ break;
+ case GL_TESS_GEN_VERTEX_ORDER:
+ *params = program->getTessGenVertexOrder() ? program->getTessGenVertexOrder() : GL_CCW;
+ break;
+ case GL_TESS_GEN_POINT_MODE_EXT:
+ *params = program->getTessGenPointMode() ? GL_TRUE : GL_FALSE;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryRenderbufferiv(const Context *context,
+ const Renderbuffer *renderbuffer,
+ GLenum pname,
+ GLint *params)
+{
+ ASSERT(renderbuffer != nullptr);
+
+ switch (pname)
+ {
+ case GL_RENDERBUFFER_WIDTH:
+ *params = renderbuffer->getWidth();
+ break;
+ case GL_RENDERBUFFER_HEIGHT:
+ *params = renderbuffer->getHeight();
+ break;
+ case GL_RENDERBUFFER_INTERNAL_FORMAT:
+ // Special case the WebGL 1 DEPTH_STENCIL format.
+ if (context->isWebGL1() &&
+ renderbuffer->getFormat().info->internalFormat == GL_DEPTH24_STENCIL8)
+ {
+ *params = GL_DEPTH_STENCIL;
+ }
+ else
+ {
+ *params = renderbuffer->getFormat().info->internalFormat;
+ }
+ break;
+ case GL_RENDERBUFFER_RED_SIZE:
+ *params = renderbuffer->getRedSize();
+ break;
+ case GL_RENDERBUFFER_GREEN_SIZE:
+ *params = renderbuffer->getGreenSize();
+ break;
+ case GL_RENDERBUFFER_BLUE_SIZE:
+ *params = renderbuffer->getBlueSize();
+ break;
+ case GL_RENDERBUFFER_ALPHA_SIZE:
+ *params = renderbuffer->getAlphaSize();
+ break;
+ case GL_RENDERBUFFER_DEPTH_SIZE:
+ *params = renderbuffer->getDepthSize();
+ break;
+ case GL_RENDERBUFFER_STENCIL_SIZE:
+ *params = renderbuffer->getStencilSize();
+ break;
+ case GL_RENDERBUFFER_SAMPLES_ANGLE:
+ *params = renderbuffer->getState().getSamples();
+ break;
+ case GL_MEMORY_SIZE_ANGLE:
+ *params = renderbuffer->getMemorySize();
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+ *params = static_cast<GLint>(renderbuffer->getImplementationColorReadFormat(context));
+ break;
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+ *params = static_cast<GLint>(renderbuffer->getImplementationColorReadType(context));
+ break;
+ case GL_RESOURCE_INITIALIZED_ANGLE:
+ *params = (renderbuffer->initState(GL_NONE, ImageIndex()) == InitState::Initialized);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryShaderiv(const Context *context, Shader *shader, GLenum pname, GLint *params)
+{
+ ASSERT(shader != nullptr || pname == GL_COMPLETION_STATUS_KHR);
+
+ switch (pname)
+ {
+ case GL_SHADER_TYPE:
+ *params = static_cast<GLint>(ToGLenum(shader->getType()));
+ return;
+ case GL_DELETE_STATUS:
+ *params = shader->isFlaggedForDeletion();
+ return;
+ case GL_COMPILE_STATUS:
+ *params = shader->isCompiled(context) ? GL_TRUE : GL_FALSE;
+ return;
+ case GL_COMPLETION_STATUS_KHR:
+ if (context->isContextLost())
+ {
+ *params = GL_TRUE;
+ }
+ else
+ {
+ *params = shader->isCompleted() ? GL_TRUE : GL_FALSE;
+ }
+ return;
+ case GL_INFO_LOG_LENGTH:
+ *params = shader->getInfoLogLength(context);
+ return;
+ case GL_SHADER_SOURCE_LENGTH:
+ *params = shader->getSourceLength();
+ return;
+ case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
+ *params = shader->getTranslatedSourceWithDebugInfoLength(context);
+ return;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryTexLevelParameterfv(const Texture *texture,
+ TextureTarget target,
+ GLint level,
+ GLenum pname,
+ GLfloat *params)
+{
+ QueryTexLevelParameterBase(texture, target, level, pname, params);
+}
+
+void QueryTexLevelParameteriv(const Texture *texture,
+ TextureTarget target,
+ GLint level,
+ GLenum pname,
+ GLint *params)
+{
+ QueryTexLevelParameterBase(texture, target, level, pname, params);
+}
+
+void QueryTexParameterfv(const Context *context,
+ const Texture *texture,
+ GLenum pname,
+ GLfloat *params)
+{
+ QueryTexParameterBase<false, false>(context, texture, pname, params);
+}
+
+void QueryTexParameterxv(const Context *context,
+ const Texture *texture,
+ GLenum pname,
+ GLfixed *params)
+{
+ QueryTexParameterBase<false, true>(context, texture, pname, params);
+}
+
+void QueryTexParameteriv(const Context *context,
+ const Texture *texture,
+ GLenum pname,
+ GLint *params)
+{
+ QueryTexParameterBase<false, false>(context, texture, pname, params);
+}
+
+void QueryTexParameterIiv(const Context *context,
+ const Texture *texture,
+ GLenum pname,
+ GLint *params)
+{
+ QueryTexParameterBase<true, false>(context, texture, pname, params);
+}
+
+void QueryTexParameterIuiv(const Context *context,
+ const Texture *texture,
+ GLenum pname,
+ GLuint *params)
+{
+ QueryTexParameterBase<true, false>(context, texture, pname, params);
+}
+
+void QuerySamplerParameterfv(const Sampler *sampler, GLenum pname, GLfloat *params)
+{
+ QuerySamplerParameterBase<false>(sampler, pname, params);
+}
+
+void QuerySamplerParameteriv(const Sampler *sampler, GLenum pname, GLint *params)
+{
+ QuerySamplerParameterBase<false>(sampler, pname, params);
+}
+
+void QuerySamplerParameterIiv(const Sampler *sampler, GLenum pname, GLint *params)
+{
+ QuerySamplerParameterBase<true>(sampler, pname, params);
+}
+
+void QuerySamplerParameterIuiv(const Sampler *sampler, GLenum pname, GLuint *params)
+{
+ QuerySamplerParameterBase<true>(sampler, pname, params);
+}
+
+void QueryVertexAttribfv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLfloat *params)
+{
+ QueryVertexAttribBase(attrib, binding, currentValueData.Values.FloatValues, pname, params);
+}
+
+void QueryVertexAttribiv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLint *params)
+{
+ QueryVertexAttribBase(attrib, binding, currentValueData.Values.FloatValues, pname, params);
+}
+
+void QueryVertexAttribPointerv(const VertexAttribute &attrib, GLenum pname, void **pointer)
+{
+ switch (pname)
+ {
+ case GL_VERTEX_ATTRIB_ARRAY_POINTER:
+ *pointer = const_cast<void *>(attrib.pointer);
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryVertexAttribIiv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLint *params)
+{
+ QueryVertexAttribBase(attrib, binding, currentValueData.Values.IntValues, pname, params);
+}
+
+void QueryVertexAttribIuiv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLuint *params)
+{
+ QueryVertexAttribBase(attrib, binding, currentValueData.Values.UnsignedIntValues, pname,
+ params);
+}
+
+void QueryActiveUniformBlockiv(const Program *program,
+ UniformBlockIndex uniformBlockIndex,
+ GLenum pname,
+ GLint *params)
+{
+ GLenum prop = GetUniformBlockPropertyEnum(pname);
+ QueryProgramResourceiv(program, GL_UNIFORM_BLOCK, uniformBlockIndex, 1, &prop,
+ std::numeric_limits<GLsizei>::max(), nullptr, params);
+}
+
+void QueryInternalFormativ(const TextureCaps &format, GLenum pname, GLsizei bufSize, GLint *params)
+{
+ switch (pname)
+ {
+ case GL_NUM_SAMPLE_COUNTS:
+ if (bufSize != 0)
+ {
+ *params = clampCast<GLint>(format.sampleCounts.size());
+ }
+ break;
+
+ case GL_SAMPLES:
+ {
+ size_t returnCount = std::min<size_t>(bufSize, format.sampleCounts.size());
+ auto sampleReverseIt = format.sampleCounts.rbegin();
+ for (size_t sampleIndex = 0; sampleIndex < returnCount; ++sampleIndex)
+ {
+ params[sampleIndex] = *sampleReverseIt++;
+ }
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryFramebufferParameteriv(const Framebuffer *framebuffer, GLenum pname, GLint *params)
+{
+ ASSERT(framebuffer);
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+ *params = framebuffer->getDefaultWidth();
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+ *params = framebuffer->getDefaultHeight();
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+ *params = framebuffer->getDefaultSamples();
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+ *params = ConvertToGLBoolean(framebuffer->getDefaultFixedSampleLocations());
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
+ *params = framebuffer->getDefaultLayers();
+ break;
+ case GL_FRAMEBUFFER_FLIP_Y_MESA:
+ *params = ConvertToGLBoolean(framebuffer->getFlipY());
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+angle::Result QuerySynciv(const Context *context,
+ const Sync *sync,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *values)
+{
+ ASSERT(sync != nullptr || pname == GL_SYNC_STATUS);
+
+ // All queries return one value, exit early if the buffer can't fit anything.
+ if (bufSize < 1)
+ {
+ if (length != nullptr)
+ {
+ *length = 0;
+ }
+ return angle::Result::Continue;
+ }
+
+ switch (pname)
+ {
+ case GL_OBJECT_TYPE:
+ *values = clampCast<GLint>(GL_SYNC_FENCE);
+ break;
+ case GL_SYNC_CONDITION:
+ *values = clampCast<GLint>(sync->getCondition());
+ break;
+ case GL_SYNC_FLAGS:
+ *values = clampCast<GLint>(sync->getFlags());
+ break;
+ case GL_SYNC_STATUS:
+ if (context->isContextLost())
+ {
+ *values = GL_SIGNALED;
+ }
+ else
+ {
+ ANGLE_TRY(sync->getStatus(context, values));
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ if (length != nullptr)
+ {
+ *length = 1;
+ }
+
+ return angle::Result::Continue;
+}
+
+void SetTexParameterx(Context *context, Texture *texture, GLenum pname, GLfixed param)
+{
+ SetTexParameterBase<false, true>(context, texture, pname, &param);
+}
+
+void SetTexParameterxv(Context *context, Texture *texture, GLenum pname, const GLfixed *params)
+{
+ SetTexParameterBase<false, true>(context, texture, pname, params);
+}
+
+void SetTexParameterf(Context *context, Texture *texture, GLenum pname, GLfloat param)
+{
+ SetTexParameterBase<false, false>(context, texture, pname, &param);
+}
+
+void SetTexParameterfv(Context *context, Texture *texture, GLenum pname, const GLfloat *params)
+{
+ SetTexParameterBase<false, false>(context, texture, pname, params);
+}
+
+void SetTexParameteri(Context *context, Texture *texture, GLenum pname, GLint param)
+{
+ SetTexParameterBase<false, false>(context, texture, pname, &param);
+}
+
+void SetTexParameteriv(Context *context, Texture *texture, GLenum pname, const GLint *params)
+{
+ SetTexParameterBase<false, false>(context, texture, pname, params);
+}
+
+void SetTexParameterIiv(Context *context, Texture *texture, GLenum pname, const GLint *params)
+{
+ SetTexParameterBase<true, false>(context, texture, pname, params);
+}
+
+void SetTexParameterIuiv(Context *context, Texture *texture, GLenum pname, const GLuint *params)
+{
+ SetTexParameterBase<true, false>(context, texture, pname, params);
+}
+
+void SetSamplerParameterf(Context *context, Sampler *sampler, GLenum pname, GLfloat param)
+{
+ SetSamplerParameterBase<false>(context, sampler, pname, &param);
+}
+
+void SetSamplerParameterfv(Context *context, Sampler *sampler, GLenum pname, const GLfloat *params)
+{
+ SetSamplerParameterBase<false>(context, sampler, pname, params);
+}
+
+void SetSamplerParameteri(Context *context, Sampler *sampler, GLenum pname, GLint param)
+{
+ SetSamplerParameterBase<false>(context, sampler, pname, &param);
+}
+
+void SetSamplerParameteriv(Context *context, Sampler *sampler, GLenum pname, const GLint *params)
+{
+ SetSamplerParameterBase<false>(context, sampler, pname, params);
+}
+
+void SetSamplerParameterIiv(Context *context, Sampler *sampler, GLenum pname, const GLint *params)
+{
+ SetSamplerParameterBase<true>(context, sampler, pname, params);
+}
+
+void SetSamplerParameterIuiv(Context *context, Sampler *sampler, GLenum pname, const GLuint *params)
+{
+ SetSamplerParameterBase<true>(context, sampler, pname, params);
+}
+
+void SetFramebufferParameteri(const Context *context,
+ Framebuffer *framebuffer,
+ GLenum pname,
+ GLint param)
+{
+ ASSERT(framebuffer);
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+ framebuffer->setDefaultWidth(context, param);
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+ framebuffer->setDefaultHeight(context, param);
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+ framebuffer->setDefaultSamples(context, param);
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+ framebuffer->setDefaultFixedSampleLocations(context, ConvertToBool(param));
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
+ framebuffer->setDefaultLayers(param);
+ break;
+ case GL_FRAMEBUFFER_FLIP_Y_MESA:
+ framebuffer->setFlipY(ConvertToBool(param));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void SetProgramParameteri(Program *program, GLenum pname, GLint value)
+{
+ ASSERT(program);
+
+ switch (pname)
+ {
+ case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
+ program->setBinaryRetrievableHint(ConvertToBool(value));
+ break;
+ case GL_PROGRAM_SEPARABLE:
+ program->setSeparable(ConvertToBool(value));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+GLint GetUniformResourceProperty(const Program *program, GLuint index, const GLenum prop)
+{
+ const auto &uniform = program->getUniformByIndex(index);
+ GLenum resourceProp = GetUniformPropertyEnum(prop);
+ switch (resourceProp)
+ {
+ case GL_TYPE:
+ case GL_ARRAY_SIZE:
+ case GL_NAME_LENGTH:
+ return GetCommonVariableProperty(uniform, resourceProp);
+
+ case GL_LOCATION:
+ return program->getUniformLocation(uniform.name).value;
+
+ case GL_BLOCK_INDEX:
+ return (uniform.isAtomicCounter() ? -1 : uniform.bufferIndex);
+
+ case GL_OFFSET:
+ return uniform.blockInfo.offset;
+
+ case GL_ARRAY_STRIDE:
+ return uniform.blockInfo.arrayStride;
+
+ case GL_MATRIX_STRIDE:
+ return uniform.blockInfo.matrixStride;
+
+ case GL_IS_ROW_MAJOR:
+ return static_cast<GLint>(uniform.blockInfo.isRowMajorMatrix);
+
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ return uniform.isActive(ShaderType::Vertex);
+
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ return uniform.isActive(ShaderType::Fragment);
+
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ return uniform.isActive(ShaderType::Compute);
+
+ case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
+ return uniform.isActive(ShaderType::Geometry);
+
+ case GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT:
+ return uniform.isActive(ShaderType::TessControl);
+
+ case GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT:
+ return uniform.isActive(ShaderType::TessEvaluation);
+
+ case GL_ATOMIC_COUNTER_BUFFER_INDEX:
+ return (uniform.isAtomicCounter() ? uniform.bufferIndex : -1);
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+GLint GetBufferVariableResourceProperty(const Program *program, GLuint index, const GLenum prop)
+{
+ const BufferVariable &bufferVariable = program->getBufferVariableByIndex(index);
+ switch (prop)
+ {
+ case GL_TYPE:
+ case GL_ARRAY_SIZE:
+ case GL_NAME_LENGTH:
+ return GetCommonVariableProperty(bufferVariable, prop);
+
+ case GL_BLOCK_INDEX:
+ return bufferVariable.bufferIndex;
+
+ case GL_OFFSET:
+ return bufferVariable.blockInfo.offset;
+
+ case GL_ARRAY_STRIDE:
+ return bufferVariable.blockInfo.arrayStride;
+
+ case GL_MATRIX_STRIDE:
+ return bufferVariable.blockInfo.matrixStride;
+
+ case GL_IS_ROW_MAJOR:
+ return static_cast<GLint>(bufferVariable.blockInfo.isRowMajorMatrix);
+
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ return bufferVariable.isActive(ShaderType::Vertex);
+
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ return bufferVariable.isActive(ShaderType::Fragment);
+
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ return bufferVariable.isActive(ShaderType::Compute);
+
+ case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
+ return bufferVariable.isActive(ShaderType::Geometry);
+
+ case GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT:
+ return bufferVariable.isActive(ShaderType::TessControl);
+
+ case GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT:
+ return bufferVariable.isActive(ShaderType::TessEvaluation);
+
+ case GL_TOP_LEVEL_ARRAY_SIZE:
+ return bufferVariable.topLevelArraySize;
+
+ case GL_TOP_LEVEL_ARRAY_STRIDE:
+ return bufferVariable.blockInfo.topLevelArrayStride;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+GLuint QueryProgramResourceIndex(const Program *program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ switch (programInterface)
+ {
+ case GL_PROGRAM_INPUT:
+ return program->getInputResourceIndex(name);
+
+ case GL_PROGRAM_OUTPUT:
+ return program->getOutputResourceIndex(name);
+
+ case GL_UNIFORM:
+ return program->getState().getUniformIndexFromName(name);
+
+ case GL_BUFFER_VARIABLE:
+ return program->getState().getBufferVariableIndexFromName(name);
+
+ case GL_SHADER_STORAGE_BLOCK:
+ return program->getShaderStorageBlockIndex(name);
+
+ case GL_UNIFORM_BLOCK:
+ return program->getUniformBlockIndex(name);
+
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ return program->getTransformFeedbackVaryingResourceIndex(name);
+
+ default:
+ UNREACHABLE();
+ return GL_INVALID_INDEX;
+ }
+}
+
+void QueryProgramResourceName(const Context *context,
+ const Program *program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name)
+{
+ switch (programInterface)
+ {
+ case GL_PROGRAM_INPUT:
+ program->getInputResourceName(index, bufSize, length, name);
+ break;
+
+ case GL_PROGRAM_OUTPUT:
+ program->getOutputResourceName(index, bufSize, length, name);
+ break;
+
+ case GL_UNIFORM:
+ program->getUniformResourceName(index, bufSize, length, name);
+ break;
+
+ case GL_BUFFER_VARIABLE:
+ program->getBufferVariableResourceName(index, bufSize, length, name);
+ break;
+
+ case GL_SHADER_STORAGE_BLOCK:
+ program->getActiveShaderStorageBlockName(index, bufSize, length, name);
+ break;
+
+ case GL_UNIFORM_BLOCK:
+ program->getActiveUniformBlockName(context, {index}, bufSize, length, name);
+ break;
+
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ program->getTransformFeedbackVarying(index, bufSize, length, nullptr, nullptr, name);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+GLint QueryProgramResourceLocation(const Program *program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ switch (programInterface)
+ {
+ case GL_PROGRAM_INPUT:
+ return program->getInputResourceLocation(name);
+
+ case GL_PROGRAM_OUTPUT:
+ return program->getOutputResourceLocation(name);
+
+ case GL_UNIFORM:
+ return program->getUniformLocation(name).value;
+
+ default:
+ UNREACHABLE();
+ return -1;
+ }
+}
+
+void QueryProgramResourceiv(const Program *program,
+ GLenum programInterface,
+ UniformBlockIndex index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params)
+{
+ if (!program->isLinked())
+ {
+ return;
+ }
+
+ if (length != nullptr)
+ {
+ *length = 0;
+ }
+
+ if (bufSize == 0)
+ {
+ // No room to write the results
+ return;
+ }
+
+ GLsizei pos = 0;
+ for (GLsizei i = 0; i < propCount; i++)
+ {
+ switch (programInterface)
+ {
+ case GL_PROGRAM_INPUT:
+ params[i] = GetInputResourceProperty(program, index.value, props[i]);
+ ++pos;
+ break;
+
+ case GL_PROGRAM_OUTPUT:
+ params[i] = GetOutputResourceProperty(program, index.value, props[i]);
+ ++pos;
+ break;
+
+ case GL_UNIFORM:
+ params[i] = GetUniformResourceProperty(program, index.value, props[i]);
+ ++pos;
+ break;
+
+ case GL_BUFFER_VARIABLE:
+ params[i] = GetBufferVariableResourceProperty(program, index.value, props[i]);
+ ++pos;
+ break;
+
+ case GL_UNIFORM_BLOCK:
+ GetUniformBlockResourceProperty(program, index.value, props[i], params, bufSize,
+ &pos);
+ break;
+
+ case GL_SHADER_STORAGE_BLOCK:
+ GetShaderStorageBlockResourceProperty(program, index.value, props[i], params,
+ bufSize, &pos);
+ break;
+
+ case GL_ATOMIC_COUNTER_BUFFER:
+ GetAtomicCounterBufferResourceProperty(program, index.value, props[i], params,
+ bufSize, &pos);
+ break;
+
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ params[i] =
+ GetTransformFeedbackVaryingResourceProperty(program, index.value, props[i]);
+ ++pos;
+ break;
+
+ default:
+ UNREACHABLE();
+ params[i] = GL_INVALID_VALUE;
+ }
+ if (pos == bufSize)
+ {
+ // Most properties return one value, but GL_ACTIVE_VARIABLES returns an array of values.
+ // This checks not to break buffer bounds for such case.
+ break;
+ }
+ }
+
+ if (length != nullptr)
+ {
+ *length = pos;
+ }
+}
+
+void QueryProgramInterfaceiv(const Program *program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint *params)
+{
+ switch (pname)
+ {
+ case GL_ACTIVE_RESOURCES:
+ *params = QueryProgramInterfaceActiveResources(program, programInterface);
+ break;
+
+ case GL_MAX_NAME_LENGTH:
+ *params = QueryProgramInterfaceMaxNameLength(program, programInterface);
+ break;
+
+ case GL_MAX_NUM_ACTIVE_VARIABLES:
+ *params = QueryProgramInterfaceMaxNumActiveVariables(program, programInterface);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+angle::Result SetMemoryObjectParameteriv(const Context *context,
+ MemoryObject *memoryObject,
+ GLenum pname,
+ const GLint *params)
+{
+ switch (pname)
+ {
+ case GL_DEDICATED_MEMORY_OBJECT_EXT:
+ ANGLE_TRY(memoryObject->setDedicatedMemory(context, ConvertToBool(params[0])));
+ break;
+
+ case GL_PROTECTED_MEMORY_OBJECT_EXT:
+ ANGLE_TRY(memoryObject->setProtectedMemory(context, ConvertToBool(params[0])));
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+
+ return angle::Result::Continue;
+}
+
+void QueryMemoryObjectParameteriv(const MemoryObject *memoryObject, GLenum pname, GLint *params)
+{
+ switch (pname)
+ {
+ case GL_DEDICATED_MEMORY_OBJECT_EXT:
+ *params = memoryObject->isDedicatedMemory();
+ break;
+
+ case GL_PROTECTED_MEMORY_OBJECT_EXT:
+ *params = memoryObject->isProtectedMemory();
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+ClientVertexArrayType ParamToVertexArrayType(GLenum param)
+{
+ switch (param)
+ {
+ case GL_VERTEX_ARRAY:
+ case GL_VERTEX_ARRAY_BUFFER_BINDING:
+ case GL_VERTEX_ARRAY_STRIDE:
+ case GL_VERTEX_ARRAY_SIZE:
+ case GL_VERTEX_ARRAY_TYPE:
+ case GL_VERTEX_ARRAY_POINTER:
+ return ClientVertexArrayType::Vertex;
+ case GL_NORMAL_ARRAY:
+ case GL_NORMAL_ARRAY_BUFFER_BINDING:
+ case GL_NORMAL_ARRAY_STRIDE:
+ case GL_NORMAL_ARRAY_TYPE:
+ case GL_NORMAL_ARRAY_POINTER:
+ return ClientVertexArrayType::Normal;
+ case GL_COLOR_ARRAY:
+ case GL_COLOR_ARRAY_BUFFER_BINDING:
+ case GL_COLOR_ARRAY_STRIDE:
+ case GL_COLOR_ARRAY_SIZE:
+ case GL_COLOR_ARRAY_TYPE:
+ case GL_COLOR_ARRAY_POINTER:
+ return ClientVertexArrayType::Color;
+ case GL_POINT_SIZE_ARRAY_OES:
+ case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
+ case GL_POINT_SIZE_ARRAY_STRIDE_OES:
+ case GL_POINT_SIZE_ARRAY_TYPE_OES:
+ case GL_POINT_SIZE_ARRAY_POINTER_OES:
+ return ClientVertexArrayType::PointSize;
+ case GL_TEXTURE_COORD_ARRAY:
+ case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
+ case GL_TEXTURE_COORD_ARRAY_STRIDE:
+ case GL_TEXTURE_COORD_ARRAY_SIZE:
+ case GL_TEXTURE_COORD_ARRAY_TYPE:
+ case GL_TEXTURE_COORD_ARRAY_POINTER:
+ return ClientVertexArrayType::TextureCoord;
+ default:
+ UNREACHABLE();
+ return ClientVertexArrayType::InvalidEnum;
+ }
+}
+
+void SetLightModelParameters(GLES1State *state, GLenum pname, const GLfloat *params)
+{
+ LightModelParameters &lightModel = state->lightModelParameters();
+
+ switch (pname)
+ {
+ case GL_LIGHT_MODEL_AMBIENT:
+ lightModel.color = ColorF::fromData(params);
+ break;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ lightModel.twoSided = *params == 1.0f ? true : false;
+ break;
+ default:
+ break;
+ }
+}
+
+void GetLightModelParameters(const GLES1State *state, GLenum pname, GLfloat *params)
+{
+ const LightModelParameters &lightModel = state->lightModelParameters();
+
+ switch (pname)
+ {
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ *params = lightModel.twoSided ? 1.0f : 0.0f;
+ break;
+ case GL_LIGHT_MODEL_AMBIENT:
+ lightModel.color.writeData(params);
+ break;
+ default:
+ break;
+ }
+}
+
+bool IsLightModelTwoSided(const GLES1State *state)
+{
+ return state->lightModelParameters().twoSided;
+}
+
+void SetLightParameters(GLES1State *state,
+ GLenum light,
+ LightParameter pname,
+ const GLfloat *params)
+{
+ uint32_t lightIndex = light - GL_LIGHT0;
+
+ LightParameters &lightParams = state->lightParameters(lightIndex);
+
+ switch (pname)
+ {
+ case LightParameter::Ambient:
+ lightParams.ambient = ColorF::fromData(params);
+ break;
+ case LightParameter::Diffuse:
+ lightParams.diffuse = ColorF::fromData(params);
+ break;
+ case LightParameter::Specular:
+ lightParams.specular = ColorF::fromData(params);
+ break;
+ case LightParameter::Position:
+ {
+ angle::Mat4 mv = state->getModelviewMatrix();
+ angle::Vector4 transformedPos =
+ mv.product(angle::Vector4(params[0], params[1], params[2], params[3]));
+ lightParams.position[0] = transformedPos[0];
+ lightParams.position[1] = transformedPos[1];
+ lightParams.position[2] = transformedPos[2];
+ lightParams.position[3] = transformedPos[3];
+ }
+ break;
+ case LightParameter::SpotDirection:
+ {
+ angle::Mat4 mv = state->getModelviewMatrix();
+ angle::Vector4 transformedPos =
+ mv.product(angle::Vector4(params[0], params[1], params[2], 0.0f));
+ lightParams.direction[0] = transformedPos[0];
+ lightParams.direction[1] = transformedPos[1];
+ lightParams.direction[2] = transformedPos[2];
+ }
+ break;
+ case LightParameter::SpotExponent:
+ lightParams.spotlightExponent = *params;
+ break;
+ case LightParameter::SpotCutoff:
+ lightParams.spotlightCutoffAngle = *params;
+ break;
+ case LightParameter::ConstantAttenuation:
+ lightParams.attenuationConst = *params;
+ break;
+ case LightParameter::LinearAttenuation:
+ lightParams.attenuationLinear = *params;
+ break;
+ case LightParameter::QuadraticAttenuation:
+ lightParams.attenuationQuadratic = *params;
+ break;
+ default:
+ return;
+ }
+}
+
+void GetLightParameters(const GLES1State *state,
+ GLenum light,
+ LightParameter pname,
+ GLfloat *params)
+{
+ uint32_t lightIndex = light - GL_LIGHT0;
+ const LightParameters &lightParams = state->lightParameters(lightIndex);
+
+ switch (pname)
+ {
+ case LightParameter::Ambient:
+ lightParams.ambient.writeData(params);
+ break;
+ case LightParameter::Diffuse:
+ lightParams.diffuse.writeData(params);
+ break;
+ case LightParameter::Specular:
+ lightParams.specular.writeData(params);
+ break;
+ case LightParameter::Position:
+ memcpy(params, lightParams.position.data(), 4 * sizeof(GLfloat));
+ break;
+ case LightParameter::SpotDirection:
+ memcpy(params, lightParams.direction.data(), 3 * sizeof(GLfloat));
+ break;
+ case LightParameter::SpotExponent:
+ *params = lightParams.spotlightExponent;
+ break;
+ case LightParameter::SpotCutoff:
+ *params = lightParams.spotlightCutoffAngle;
+ break;
+ case LightParameter::ConstantAttenuation:
+ *params = lightParams.attenuationConst;
+ break;
+ case LightParameter::LinearAttenuation:
+ *params = lightParams.attenuationLinear;
+ break;
+ case LightParameter::QuadraticAttenuation:
+ *params = lightParams.attenuationQuadratic;
+ break;
+ default:
+ break;
+ }
+}
+
+void SetMaterialParameters(GLES1State *state,
+ GLenum face,
+ MaterialParameter pname,
+ const GLfloat *params)
+{
+ // Note: Ambient and diffuse colors are inherited from glColor when COLOR_MATERIAL is enabled,
+ // and can only be modified by this function if that is disabled:
+ //
+ // > the replaced values remain until changed by either sending a new color or by setting a
+ // > new material value when COLOR_MATERIAL is not currently enabled, to override that
+ // particular value.
+
+ MaterialParameters &material = state->materialParameters();
+ switch (pname)
+ {
+ case MaterialParameter::Ambient:
+ if (!state->isColorMaterialEnabled())
+ {
+ material.ambient = ColorF::fromData(params);
+ }
+ break;
+ case MaterialParameter::Diffuse:
+ if (!state->isColorMaterialEnabled())
+ {
+ material.diffuse = ColorF::fromData(params);
+ }
+ break;
+ case MaterialParameter::AmbientAndDiffuse:
+ if (!state->isColorMaterialEnabled())
+ {
+ material.ambient = ColorF::fromData(params);
+ material.diffuse = ColorF::fromData(params);
+ }
+ break;
+ case MaterialParameter::Specular:
+ material.specular = ColorF::fromData(params);
+ break;
+ case MaterialParameter::Emission:
+ material.emissive = ColorF::fromData(params);
+ break;
+ case MaterialParameter::Shininess:
+ material.specularExponent = *params;
+ break;
+ default:
+ return;
+ }
+}
+
+void GetMaterialParameters(const GLES1State *state,
+ GLenum face,
+ MaterialParameter pname,
+ GLfloat *params)
+{
+ const ColorF &currentColor = state->getCurrentColor();
+ const MaterialParameters &material = state->materialParameters();
+ const bool colorMaterialEnabled = state->isColorMaterialEnabled();
+
+ switch (pname)
+ {
+ case MaterialParameter::Ambient:
+ if (colorMaterialEnabled)
+ {
+ currentColor.writeData(params);
+ }
+ else
+ {
+ material.ambient.writeData(params);
+ }
+ break;
+ case MaterialParameter::Diffuse:
+ if (colorMaterialEnabled)
+ {
+ currentColor.writeData(params);
+ }
+ else
+ {
+ material.diffuse.writeData(params);
+ }
+ break;
+ case MaterialParameter::Specular:
+ material.specular.writeData(params);
+ break;
+ case MaterialParameter::Emission:
+ material.emissive.writeData(params);
+ break;
+ case MaterialParameter::Shininess:
+ *params = material.specularExponent;
+ break;
+ default:
+ return;
+ }
+}
+
+unsigned int GetLightModelParameterCount(GLenum pname)
+{
+ switch (pname)
+ {
+ case GL_LIGHT_MODEL_AMBIENT:
+ return 4;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ return 1;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+unsigned int GetLightParameterCount(LightParameter pname)
+{
+ switch (pname)
+ {
+ case LightParameter::Ambient:
+ case LightParameter::Diffuse:
+ case LightParameter::AmbientAndDiffuse:
+ case LightParameter::Specular:
+ case LightParameter::Position:
+ return 4;
+ case LightParameter::SpotDirection:
+ return 3;
+ case LightParameter::SpotExponent:
+ case LightParameter::SpotCutoff:
+ case LightParameter::ConstantAttenuation:
+ case LightParameter::LinearAttenuation:
+ case LightParameter::QuadraticAttenuation:
+ return 1;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+unsigned int GetMaterialParameterCount(MaterialParameter pname)
+{
+ switch (pname)
+ {
+ case MaterialParameter::Ambient:
+ case MaterialParameter::Diffuse:
+ case MaterialParameter::AmbientAndDiffuse:
+ case MaterialParameter::Specular:
+ case MaterialParameter::Emission:
+ return 4;
+ case MaterialParameter::Shininess:
+ return 1;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+void SetFogParameters(GLES1State *state, GLenum pname, const GLfloat *params)
+{
+ FogParameters &fog = state->fogParameters();
+ switch (pname)
+ {
+ case GL_FOG_MODE:
+ fog.mode = FromGLenum<FogMode>(static_cast<GLenum>(params[0]));
+ break;
+ case GL_FOG_DENSITY:
+ fog.density = params[0];
+ break;
+ case GL_FOG_START:
+ fog.start = params[0];
+ break;
+ case GL_FOG_END:
+ fog.end = params[0];
+ break;
+ case GL_FOG_COLOR:
+ fog.color = ColorF::fromData(params);
+ break;
+ default:
+ return;
+ }
+}
+
+void GetFogParameters(const GLES1State *state, GLenum pname, GLfloat *params)
+{
+ const FogParameters &fog = state->fogParameters();
+ switch (pname)
+ {
+ case GL_FOG_MODE:
+ params[0] = static_cast<GLfloat>(ToGLenum(fog.mode));
+ break;
+ case GL_FOG_DENSITY:
+ params[0] = fog.density;
+ break;
+ case GL_FOG_START:
+ params[0] = fog.start;
+ break;
+ case GL_FOG_END:
+ params[0] = fog.end;
+ break;
+ case GL_FOG_COLOR:
+ fog.color.writeData(params);
+ break;
+ default:
+ return;
+ }
+}
+
+unsigned int GetFogParameterCount(GLenum pname)
+{
+ switch (pname)
+ {
+ case GL_FOG_MODE:
+ case GL_FOG_DENSITY:
+ case GL_FOG_START:
+ case GL_FOG_END:
+ return 1;
+ case GL_FOG_COLOR:
+ return 4;
+ default:
+ return 0;
+ }
+}
+
+unsigned int GetTextureEnvParameterCount(TextureEnvParameter pname)
+{
+ switch (pname)
+ {
+ case TextureEnvParameter::Mode:
+ case TextureEnvParameter::CombineRgb:
+ case TextureEnvParameter::CombineAlpha:
+ case TextureEnvParameter::Src0Rgb:
+ case TextureEnvParameter::Src1Rgb:
+ case TextureEnvParameter::Src2Rgb:
+ case TextureEnvParameter::Src0Alpha:
+ case TextureEnvParameter::Src1Alpha:
+ case TextureEnvParameter::Src2Alpha:
+ case TextureEnvParameter::Op0Rgb:
+ case TextureEnvParameter::Op1Rgb:
+ case TextureEnvParameter::Op2Rgb:
+ case TextureEnvParameter::Op0Alpha:
+ case TextureEnvParameter::Op1Alpha:
+ case TextureEnvParameter::Op2Alpha:
+ case TextureEnvParameter::RgbScale:
+ case TextureEnvParameter::AlphaScale:
+ case TextureEnvParameter::PointCoordReplace:
+ return 1;
+ case TextureEnvParameter::Color:
+ return 4;
+ default:
+ return 0;
+ }
+}
+
+void ConvertTextureEnvFromInt(TextureEnvParameter pname, const GLint *input, GLfloat *output)
+{
+ if (IsTextureEnvEnumParameter(pname))
+ {
+ ConvertGLenumValue(input[0], output);
+ return;
+ }
+
+ switch (pname)
+ {
+ case TextureEnvParameter::RgbScale:
+ case TextureEnvParameter::AlphaScale:
+ output[0] = static_cast<GLfloat>(input[0]);
+ break;
+ case TextureEnvParameter::Color:
+ for (int i = 0; i < 4; i++)
+ {
+ output[i] = input[i] / 255.0f;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void ConvertTextureEnvFromFixed(TextureEnvParameter pname, const GLfixed *input, GLfloat *output)
+{
+ if (IsTextureEnvEnumParameter(pname))
+ {
+ ConvertGLenumValue(input[0], output);
+ return;
+ }
+
+ switch (pname)
+ {
+ case TextureEnvParameter::RgbScale:
+ case TextureEnvParameter::AlphaScale:
+ output[0] = ConvertFixedToFloat(input[0]);
+ break;
+ case TextureEnvParameter::Color:
+ for (int i = 0; i < 4; i++)
+ {
+ output[i] = ConvertFixedToFloat(input[i]);
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void ConvertTextureEnvToInt(TextureEnvParameter pname, const GLfloat *input, GLint *output)
+{
+ if (IsTextureEnvEnumParameter(pname))
+ {
+ ConvertGLenumValue(input[0], output);
+ return;
+ }
+
+ switch (pname)
+ {
+ case TextureEnvParameter::RgbScale:
+ case TextureEnvParameter::AlphaScale:
+ output[0] = static_cast<GLint>(input[0]);
+ break;
+ case TextureEnvParameter::Color:
+ for (int i = 0; i < 4; i++)
+ {
+ output[i] = static_cast<GLint>(input[i] * 255.0f);
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void ConvertTextureEnvToFixed(TextureEnvParameter pname, const GLfloat *input, GLfixed *output)
+{
+ if (IsTextureEnvEnumParameter(pname))
+ {
+ ConvertGLenumValue(input[0], output);
+ return;
+ }
+
+ switch (pname)
+ {
+ case TextureEnvParameter::RgbScale:
+ case TextureEnvParameter::AlphaScale:
+ output[0] = ConvertFloatToFixed(input[0]);
+ break;
+ case TextureEnvParameter::Color:
+ for (int i = 0; i < 4; i++)
+ {
+ output[i] = ConvertFloatToFixed(input[i]);
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void SetTextureEnv(unsigned int unit,
+ GLES1State *state,
+ TextureEnvTarget target,
+ TextureEnvParameter pname,
+ const GLfloat *params)
+{
+ TextureEnvironmentParameters &env = state->textureEnvironment(unit);
+ GLenum asEnum = ConvertToGLenum(params[0]);
+
+ switch (target)
+ {
+ case TextureEnvTarget::Env:
+ switch (pname)
+ {
+ case TextureEnvParameter::Mode:
+ env.mode = FromGLenum<TextureEnvMode>(asEnum);
+ break;
+ case TextureEnvParameter::CombineRgb:
+ env.combineRgb = FromGLenum<TextureCombine>(asEnum);
+ break;
+ case TextureEnvParameter::CombineAlpha:
+ env.combineAlpha = FromGLenum<TextureCombine>(asEnum);
+ break;
+ case TextureEnvParameter::Src0Rgb:
+ env.src0Rgb = FromGLenum<TextureSrc>(asEnum);
+ break;
+ case TextureEnvParameter::Src1Rgb:
+ env.src1Rgb = FromGLenum<TextureSrc>(asEnum);
+ break;
+ case TextureEnvParameter::Src2Rgb:
+ env.src2Rgb = FromGLenum<TextureSrc>(asEnum);
+ break;
+ case TextureEnvParameter::Src0Alpha:
+ env.src0Alpha = FromGLenum<TextureSrc>(asEnum);
+ break;
+ case TextureEnvParameter::Src1Alpha:
+ env.src1Alpha = FromGLenum<TextureSrc>(asEnum);
+ break;
+ case TextureEnvParameter::Src2Alpha:
+ env.src2Alpha = FromGLenum<TextureSrc>(asEnum);
+ break;
+ case TextureEnvParameter::Op0Rgb:
+ env.op0Rgb = FromGLenum<TextureOp>(asEnum);
+ break;
+ case TextureEnvParameter::Op1Rgb:
+ env.op1Rgb = FromGLenum<TextureOp>(asEnum);
+ break;
+ case TextureEnvParameter::Op2Rgb:
+ env.op2Rgb = FromGLenum<TextureOp>(asEnum);
+ break;
+ case TextureEnvParameter::Op0Alpha:
+ env.op0Alpha = FromGLenum<TextureOp>(asEnum);
+ break;
+ case TextureEnvParameter::Op1Alpha:
+ env.op1Alpha = FromGLenum<TextureOp>(asEnum);
+ break;
+ case TextureEnvParameter::Op2Alpha:
+ env.op2Alpha = FromGLenum<TextureOp>(asEnum);
+ break;
+ case TextureEnvParameter::Color:
+ env.color = ColorF::fromData(params);
+ break;
+ case TextureEnvParameter::RgbScale:
+ env.rgbScale = params[0];
+ break;
+ case TextureEnvParameter::AlphaScale:
+ env.alphaScale = params[0];
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ break;
+ case TextureEnvTarget::PointSprite:
+ switch (pname)
+ {
+ case TextureEnvParameter::PointCoordReplace:
+ env.pointSpriteCoordReplace = static_cast<bool>(params[0]);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void GetTextureEnv(unsigned int unit,
+ const GLES1State *state,
+ TextureEnvTarget target,
+ TextureEnvParameter pname,
+ GLfloat *params)
+{
+ const TextureEnvironmentParameters &env = state->textureEnvironment(unit);
+
+ switch (target)
+ {
+ case TextureEnvTarget::Env:
+ switch (pname)
+ {
+ case TextureEnvParameter::Mode:
+ ConvertPackedEnum(env.mode, params);
+ break;
+ case TextureEnvParameter::CombineRgb:
+ ConvertPackedEnum(env.combineRgb, params);
+ break;
+ case TextureEnvParameter::CombineAlpha:
+ ConvertPackedEnum(env.combineAlpha, params);
+ break;
+ case TextureEnvParameter::Src0Rgb:
+ ConvertPackedEnum(env.src0Rgb, params);
+ break;
+ case TextureEnvParameter::Src1Rgb:
+ ConvertPackedEnum(env.src1Rgb, params);
+ break;
+ case TextureEnvParameter::Src2Rgb:
+ ConvertPackedEnum(env.src2Rgb, params);
+ break;
+ case TextureEnvParameter::Src0Alpha:
+ ConvertPackedEnum(env.src0Alpha, params);
+ break;
+ case TextureEnvParameter::Src1Alpha:
+ ConvertPackedEnum(env.src1Alpha, params);
+ break;
+ case TextureEnvParameter::Src2Alpha:
+ ConvertPackedEnum(env.src2Alpha, params);
+ break;
+ case TextureEnvParameter::Op0Rgb:
+ ConvertPackedEnum(env.op0Rgb, params);
+ break;
+ case TextureEnvParameter::Op1Rgb:
+ ConvertPackedEnum(env.op1Rgb, params);
+ break;
+ case TextureEnvParameter::Op2Rgb:
+ ConvertPackedEnum(env.op2Rgb, params);
+ break;
+ case TextureEnvParameter::Op0Alpha:
+ ConvertPackedEnum(env.op0Alpha, params);
+ break;
+ case TextureEnvParameter::Op1Alpha:
+ ConvertPackedEnum(env.op1Alpha, params);
+ break;
+ case TextureEnvParameter::Op2Alpha:
+ ConvertPackedEnum(env.op2Alpha, params);
+ break;
+ case TextureEnvParameter::Color:
+ env.color.writeData(params);
+ break;
+ case TextureEnvParameter::RgbScale:
+ *params = env.rgbScale;
+ break;
+ case TextureEnvParameter::AlphaScale:
+ *params = env.alphaScale;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ break;
+ case TextureEnvTarget::PointSprite:
+ switch (pname)
+ {
+ case TextureEnvParameter::PointCoordReplace:
+ *params = static_cast<GLfloat>(env.pointSpriteCoordReplace);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+unsigned int GetPointParameterCount(PointParameter pname)
+{
+ switch (pname)
+ {
+ case PointParameter::PointSizeMin:
+ case PointParameter::PointSizeMax:
+ case PointParameter::PointFadeThresholdSize:
+ return 1;
+ case PointParameter::PointDistanceAttenuation:
+ return 3;
+ default:
+ return 0;
+ }
+}
+
+void SetPointParameter(GLES1State *state, PointParameter pname, const GLfloat *params)
+{
+
+ PointParameters &pointParams = state->pointParameters();
+
+ switch (pname)
+ {
+ case PointParameter::PointSizeMin:
+ pointParams.pointSizeMin = params[0];
+ break;
+ case PointParameter::PointSizeMax:
+ pointParams.pointSizeMax = params[0];
+ break;
+ case PointParameter::PointFadeThresholdSize:
+ pointParams.pointFadeThresholdSize = params[0];
+ break;
+ case PointParameter::PointDistanceAttenuation:
+ for (unsigned int i = 0; i < 3; i++)
+ {
+ pointParams.pointDistanceAttenuation[i] = params[i];
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+void GetPointParameter(const GLES1State *state, PointParameter pname, GLfloat *params)
+{
+ const PointParameters &pointParams = state->pointParameters();
+
+ switch (pname)
+ {
+ case PointParameter::PointSizeMin:
+ params[0] = pointParams.pointSizeMin;
+ break;
+ case PointParameter::PointSizeMax:
+ params[0] = pointParams.pointSizeMax;
+ break;
+ case PointParameter::PointFadeThresholdSize:
+ params[0] = pointParams.pointFadeThresholdSize;
+ break;
+ case PointParameter::PointDistanceAttenuation:
+ for (unsigned int i = 0; i < 3; i++)
+ {
+ params[i] = pointParams.pointDistanceAttenuation[i];
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+void SetPointSize(GLES1State *state, GLfloat size)
+{
+ PointParameters &params = state->pointParameters();
+ params.pointSize = size;
+}
+
+void GetPointSize(const GLES1State *state, GLfloat *sizeOut)
+{
+ const PointParameters &params = state->pointParameters();
+ *sizeOut = params.pointSize;
+}
+
+unsigned int GetTexParameterCount(GLenum pname)
+{
+ switch (pname)
+ {
+ case GL_TEXTURE_CROP_RECT_OES:
+ case GL_TEXTURE_BORDER_COLOR:
+ return 4;
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_USAGE_ANGLE:
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ case GL_TEXTURE_IMMUTABLE_FORMAT:
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_IMMUTABLE_LEVELS:
+ case GL_TEXTURE_SWIZZLE_R:
+ case GL_TEXTURE_SWIZZLE_G:
+ case GL_TEXTURE_SWIZZLE_B:
+ case GL_TEXTURE_SWIZZLE_A:
+ case GL_TEXTURE_BASE_LEVEL:
+ case GL_TEXTURE_MAX_LEVEL:
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ case GL_TEXTURE_COMPARE_MODE:
+ case GL_TEXTURE_COMPARE_FUNC:
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ case GL_DEPTH_STENCIL_TEXTURE_MODE:
+ case GL_TEXTURE_NATIVE_ID_ANGLE:
+ case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+bool GetQueryParameterInfo(const State &glState,
+ GLenum pname,
+ GLenum *type,
+ unsigned int *numParams)
+{
+ const Caps &caps = glState.getCaps();
+ const Extensions &extensions = glState.getExtensions();
+ GLint clientMajorVersion = glState.getClientMajorVersion();
+ EGLenum clientType = glState.getClientType();
+
+ // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
+ // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
+ // to the fact that it is stored internally as a float, and so would require conversion
+ // if returned from Context::getIntegerv. Since this conversion is already implemented
+ // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
+ // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
+ // application.
+ switch (pname)
+ {
+ case GL_COMPRESSED_TEXTURE_FORMATS:
+ {
+ *type = GL_INT;
+ *numParams = static_cast<unsigned int>(caps.compressedTextureFormats.size());
+ return true;
+ }
+ case GL_SHADER_BINARY_FORMATS:
+ {
+ *type = GL_INT;
+ *numParams = static_cast<unsigned int>(caps.shaderBinaryFormats.size());
+ return true;
+ }
+
+ case GL_MAX_VERTEX_ATTRIBS:
+ case GL_MAX_VERTEX_UNIFORM_VECTORS:
+ case GL_MAX_VARYING_VECTORS:
+ case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+ case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
+ case GL_MAX_TEXTURE_IMAGE_UNITS:
+ case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
+ case GL_MAX_RENDERBUFFER_SIZE:
+ case GL_NUM_SHADER_BINARY_FORMATS:
+ case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
+ case GL_ARRAY_BUFFER_BINDING:
+ case GL_FRAMEBUFFER_BINDING: // GL_FRAMEBUFFER_BINDING now equivalent to
+ // GL_DRAW_FRAMEBUFFER_BINDING
+ case GL_RENDERBUFFER_BINDING:
+ case GL_CURRENT_PROGRAM:
+ case GL_PACK_ALIGNMENT:
+ case GL_UNPACK_ALIGNMENT:
+ case GL_GENERATE_MIPMAP_HINT:
+ case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
+ case GL_RED_BITS:
+ case GL_GREEN_BITS:
+ case GL_BLUE_BITS:
+ case GL_ALPHA_BITS:
+ case GL_DEPTH_BITS:
+ case GL_STENCIL_BITS:
+ case GL_ELEMENT_ARRAY_BUFFER_BINDING:
+ case GL_CULL_FACE_MODE:
+ case GL_FRONT_FACE:
+ case GL_ACTIVE_TEXTURE:
+ case GL_STENCIL_FUNC:
+ case GL_STENCIL_VALUE_MASK:
+ case GL_STENCIL_REF:
+ case GL_STENCIL_FAIL:
+ case GL_STENCIL_PASS_DEPTH_FAIL:
+ case GL_STENCIL_PASS_DEPTH_PASS:
+ case GL_STENCIL_BACK_FUNC:
+ case GL_STENCIL_BACK_VALUE_MASK:
+ case GL_STENCIL_BACK_REF:
+ case GL_STENCIL_BACK_FAIL:
+ case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
+ case GL_STENCIL_BACK_PASS_DEPTH_PASS:
+ case GL_DEPTH_FUNC:
+ case GL_BLEND_SRC_RGB:
+ case GL_BLEND_SRC_ALPHA:
+ case GL_BLEND_DST_RGB:
+ case GL_BLEND_DST_ALPHA:
+ case GL_BLEND_EQUATION_RGB:
+ case GL_BLEND_EQUATION_ALPHA:
+ case GL_STENCIL_WRITEMASK:
+ case GL_STENCIL_BACK_WRITEMASK:
+ case GL_STENCIL_CLEAR_VALUE:
+ case GL_SUBPIXEL_BITS:
+ case GL_MAX_TEXTURE_SIZE:
+ case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
+ case GL_SAMPLE_BUFFERS:
+ case GL_SAMPLES:
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+ case GL_TEXTURE_BINDING_2D:
+ case GL_TEXTURE_BINDING_CUBE_MAP:
+ case GL_RESET_NOTIFICATION_STRATEGY_EXT:
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+ {
+ if (!extensions.packReverseRowOrderANGLE)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_MAX_RECTANGLE_TEXTURE_SIZE_ANGLE:
+ case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
+ {
+ if (!extensions.textureRectangleANGLE)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_MAX_DRAW_BUFFERS_EXT:
+ case GL_MAX_COLOR_ATTACHMENTS_EXT:
+ {
+ if ((clientMajorVersion < 3) && !extensions.drawBuffersEXT)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_MAX_VIEWPORT_DIMS:
+ {
+ *type = GL_INT;
+ *numParams = 2;
+ return true;
+ }
+ case GL_VIEWPORT:
+ case GL_SCISSOR_BOX:
+ {
+ *type = GL_INT;
+ *numParams = 4;
+ return true;
+ }
+ case GL_SHADER_COMPILER:
+ case GL_SAMPLE_COVERAGE_INVERT:
+ case GL_DEPTH_WRITEMASK:
+ case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
+ case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
+ case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as
+ // bool-natural
+ case GL_SAMPLE_COVERAGE:
+ case GL_SCISSOR_TEST:
+ case GL_STENCIL_TEST:
+ case GL_DEPTH_TEST:
+ case GL_BLEND:
+ case GL_DITHER:
+ case GL_CONTEXT_ROBUST_ACCESS_EXT:
+ {
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ case GL_COLOR_LOGIC_OP:
+ {
+ if (!extensions.logicOpANGLE)
+ {
+ return false;
+ }
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ case GL_COLOR_WRITEMASK:
+ {
+ *type = GL_BOOL;
+ *numParams = 4;
+ return true;
+ }
+ case GL_POLYGON_OFFSET_FACTOR:
+ case GL_POLYGON_OFFSET_UNITS:
+ case GL_SAMPLE_COVERAGE_VALUE:
+ case GL_DEPTH_CLEAR_VALUE:
+ case GL_LINE_WIDTH:
+ {
+ *type = GL_FLOAT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_ALIASED_LINE_WIDTH_RANGE:
+ case GL_ALIASED_POINT_SIZE_RANGE:
+ case GL_DEPTH_RANGE:
+ {
+ *type = GL_FLOAT;
+ *numParams = 2;
+ return true;
+ }
+ case GL_COLOR_CLEAR_VALUE:
+ case GL_BLEND_COLOR:
+ {
+ *type = GL_FLOAT;
+ *numParams = 4;
+ return true;
+ }
+ case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!extensions.textureFilterAnisotropicEXT)
+ {
+ return false;
+ }
+ *type = GL_FLOAT;
+ *numParams = 1;
+ return true;
+ case GL_TIMESTAMP_EXT:
+ if (!extensions.disjointTimerQueryEXT)
+ {
+ return false;
+ }
+ *type = GL_INT_64_ANGLEX;
+ *numParams = 1;
+ return true;
+ case GL_GPU_DISJOINT_EXT:
+ if (!extensions.disjointTimerQueryEXT)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_COVERAGE_MODULATION_CHROMIUM:
+ if (!extensions.framebufferMixedSamplesCHROMIUM)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_TEXTURE_BINDING_EXTERNAL_OES:
+ if (!extensions.EGLStreamConsumerExternalNV && !extensions.EGLImageExternalOES)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_MAX_CLIP_DISTANCES_EXT: // case GL_MAX_CLIP_PLANES
+ if (clientMajorVersion < 2)
+ {
+ break;
+ }
+ if (!extensions.clipDistanceAPPLE && !extensions.clipCullDistanceEXT)
+ {
+ // NOTE(hqle): if client version is 1. GL_MAX_CLIP_DISTANCES_EXT is equal
+ // to GL_MAX_CLIP_PLANES which is a valid enum.
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_MAX_CULL_DISTANCES_EXT:
+ case GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT:
+ if (!extensions.clipCullDistanceEXT)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_CLIP_ORIGIN_EXT:
+ case GL_CLIP_DEPTH_MODE_EXT:
+ if (!extensions.clipControlEXT)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_PRIMITIVE_BOUNDING_BOX:
+ if (!extensions.primitiveBoundingBoxAny())
+ {
+ return false;
+ }
+ *type = GL_FLOAT;
+ *numParams = 8;
+ return true;
+ case GL_SHADING_RATE_QCOM:
+ if (!extensions.shadingRateQCOM)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
+ if (clientType == EGL_OPENGL_API ||
+ (clientType == EGL_OPENGL_ES_API && glState.getClientVersion() >= Version(3, 2)))
+ {
+ switch (pname)
+ {
+ case GL_CONTEXT_FLAGS:
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ }
+ }
+
+ if (clientType == EGL_OPENGL_API)
+ {
+ switch (pname)
+ {
+ case GL_CONTEXT_PROFILE_MASK:
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ }
+ }
+
+ if (extensions.debugKHR)
+ {
+ switch (pname)
+ {
+ case GL_DEBUG_LOGGED_MESSAGES:
+ case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH:
+ case GL_DEBUG_GROUP_STACK_DEPTH:
+ case GL_MAX_DEBUG_MESSAGE_LENGTH:
+ case GL_MAX_DEBUG_LOGGED_MESSAGES:
+ case GL_MAX_DEBUG_GROUP_STACK_DEPTH:
+ case GL_MAX_LABEL_LENGTH:
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+
+ case GL_DEBUG_OUTPUT_SYNCHRONOUS:
+ case GL_DEBUG_OUTPUT:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (extensions.multisampleCompatibilityEXT)
+ {
+ switch (pname)
+ {
+ case GL_MULTISAMPLE_EXT:
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (extensions.bindGeneratesResourceCHROMIUM)
+ {
+ switch (pname)
+ {
+ case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (extensions.clientArraysANGLE)
+ {
+ switch (pname)
+ {
+ case GL_CLIENT_ARRAYS_ANGLE:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (extensions.sRGBWriteControlEXT)
+ {
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (extensions.robustResourceInitializationANGLE &&
+ pname == GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE)
+ {
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+
+ if (extensions.programCacheControlANGLE && pname == GL_PROGRAM_CACHE_ENABLED_ANGLE)
+ {
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+
+ if (extensions.parallelShaderCompileKHR && pname == GL_MAX_SHADER_COMPILER_THREADS_KHR)
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
+ if (extensions.blendFuncExtendedEXT && pname == GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT)
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
+ if (extensions.robustFragmentShaderOutputANGLE &&
+ pname == GL_ROBUST_FRAGMENT_SHADER_OUTPUT_ANGLE)
+ {
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+
+ // Check for ES3.0+ parameter names which are also exposed as ES2 extensions
+ switch (pname)
+ {
+ // GL_DRAW_FRAMEBUFFER_BINDING equivalent to GL_FRAMEBUFFER_BINDING
+ case GL_READ_FRAMEBUFFER_BINDING:
+ if ((clientMajorVersion < 3) && !extensions.framebufferBlitAny())
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+
+ case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
+ if ((clientMajorVersion < 3) && !extensions.getProgramBinaryOES)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+
+ case GL_PROGRAM_BINARY_FORMATS_OES:
+ if ((clientMajorVersion < 3) && !extensions.getProgramBinaryOES)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = static_cast<unsigned int>(caps.programBinaryFormats.size());
+ return true;
+
+ case GL_PACK_ROW_LENGTH:
+ case GL_PACK_SKIP_ROWS:
+ case GL_PACK_SKIP_PIXELS:
+ if ((clientMajorVersion < 3) && !extensions.packSubimageNV)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_UNPACK_ROW_LENGTH:
+ case GL_UNPACK_SKIP_ROWS:
+ case GL_UNPACK_SKIP_PIXELS:
+ if ((clientMajorVersion < 3) && !extensions.unpackSubimageEXT)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_VERTEX_ARRAY_BINDING:
+ if ((clientMajorVersion < 3) && !extensions.vertexArrayObjectOES)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_PIXEL_PACK_BUFFER_BINDING:
+ case GL_PIXEL_UNPACK_BUFFER_BINDING:
+ if ((clientMajorVersion < 3) && !extensions.pixelBufferObjectNV)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_MAX_SAMPLES:
+ {
+ static_assert(GL_MAX_SAMPLES_ANGLE == GL_MAX_SAMPLES,
+ "GL_MAX_SAMPLES_ANGLE not equal to GL_MAX_SAMPLES");
+ if ((clientMajorVersion < 3) && !(extensions.framebufferMultisampleANGLE ||
+ extensions.multisampledRenderToTextureEXT))
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
+ if ((clientMajorVersion < 3) && !extensions.standardDerivativesOES)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ case GL_TEXTURE_BINDING_3D:
+ if ((clientMajorVersion < 3) && !extensions.texture3DOES)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_MAX_3D_TEXTURE_SIZE:
+ if ((clientMajorVersion < 3) && !extensions.texture3DOES)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
+ if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
+ {
+ if ((glState.getClientVersion() < Version(3, 0)) && !extensions.drawBuffersEXT)
+ {
+ return false;
+ }
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
+ if ((extensions.multiview2OVR || extensions.multiviewOVR) && pname == GL_MAX_VIEWS_OVR)
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
+ if (extensions.provokingVertexANGLE && pname == GL_PROVOKING_VERTEX)
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
+ if (glState.getClientVersion() < Version(2, 0))
+ {
+ switch (pname)
+ {
+ case GL_ALPHA_TEST_FUNC:
+ case GL_CLIENT_ACTIVE_TEXTURE:
+ case GL_MATRIX_MODE:
+ case GL_MAX_TEXTURE_UNITS:
+ case GL_MAX_MODELVIEW_STACK_DEPTH:
+ case GL_MAX_PROJECTION_STACK_DEPTH:
+ case GL_MAX_TEXTURE_STACK_DEPTH:
+ case GL_MAX_LIGHTS:
+ case GL_MAX_CLIP_PLANES:
+ case GL_VERTEX_ARRAY_STRIDE:
+ case GL_NORMAL_ARRAY_STRIDE:
+ case GL_COLOR_ARRAY_STRIDE:
+ case GL_TEXTURE_COORD_ARRAY_STRIDE:
+ case GL_VERTEX_ARRAY_SIZE:
+ case GL_COLOR_ARRAY_SIZE:
+ case GL_TEXTURE_COORD_ARRAY_SIZE:
+ case GL_VERTEX_ARRAY_TYPE:
+ case GL_NORMAL_ARRAY_TYPE:
+ case GL_COLOR_ARRAY_TYPE:
+ case GL_TEXTURE_COORD_ARRAY_TYPE:
+ case GL_VERTEX_ARRAY_BUFFER_BINDING:
+ case GL_NORMAL_ARRAY_BUFFER_BINDING:
+ case GL_COLOR_ARRAY_BUFFER_BINDING:
+ case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING:
+ case GL_POINT_SIZE_ARRAY_STRIDE_OES:
+ case GL_POINT_SIZE_ARRAY_TYPE_OES:
+ case GL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES:
+ case GL_SHADE_MODEL:
+ case GL_MODELVIEW_STACK_DEPTH:
+ case GL_PROJECTION_STACK_DEPTH:
+ case GL_TEXTURE_STACK_DEPTH:
+ case GL_LOGIC_OP_MODE:
+ case GL_BLEND_SRC:
+ case GL_BLEND_DST:
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ case GL_POINT_SMOOTH_HINT:
+ case GL_LINE_SMOOTH_HINT:
+ case GL_FOG_HINT:
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_ALPHA_TEST_REF:
+ case GL_FOG_DENSITY:
+ case GL_FOG_START:
+ case GL_FOG_END:
+ case GL_FOG_MODE:
+ case GL_POINT_SIZE:
+ case GL_POINT_SIZE_MIN:
+ case GL_POINT_SIZE_MAX:
+ case GL_POINT_FADE_THRESHOLD_SIZE:
+ *type = GL_FLOAT;
+ *numParams = 1;
+ return true;
+ case GL_SMOOTH_POINT_SIZE_RANGE:
+ case GL_SMOOTH_LINE_WIDTH_RANGE:
+ *type = GL_FLOAT;
+ *numParams = 2;
+ return true;
+ case GL_CURRENT_COLOR:
+ case GL_CURRENT_TEXTURE_COORDS:
+ case GL_LIGHT_MODEL_AMBIENT:
+ case GL_FOG_COLOR:
+ *type = GL_FLOAT;
+ *numParams = 4;
+ return true;
+ case GL_CURRENT_NORMAL:
+ case GL_POINT_DISTANCE_ATTENUATION:
+ *type = GL_FLOAT;
+ *numParams = 3;
+ return true;
+ case GL_MODELVIEW_MATRIX:
+ case GL_PROJECTION_MATRIX:
+ case GL_TEXTURE_MATRIX:
+ *type = GL_FLOAT;
+ *numParams = 16;
+ return true;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (glState.getClientVersion() < Version(3, 0))
+ {
+ return false;
+ }
+
+ // Check for ES3.0+ parameter names
+ switch (pname)
+ {
+ case GL_MAX_UNIFORM_BUFFER_BINDINGS:
+ case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT:
+ case GL_UNIFORM_BUFFER_BINDING:
+ case GL_TRANSFORM_FEEDBACK_BINDING:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ case GL_COPY_READ_BUFFER_BINDING:
+ case GL_COPY_WRITE_BUFFER_BINDING:
+ case GL_SAMPLER_BINDING:
+ case GL_READ_BUFFER:
+ case GL_TEXTURE_BINDING_3D:
+ case GL_TEXTURE_BINDING_2D_ARRAY:
+ case GL_MAX_ARRAY_TEXTURE_LAYERS:
+ case GL_MAX_VERTEX_UNIFORM_BLOCKS:
+ case GL_MAX_FRAGMENT_UNIFORM_BLOCKS:
+ case GL_MAX_COMBINED_UNIFORM_BLOCKS:
+ case GL_MAX_VERTEX_OUTPUT_COMPONENTS:
+ case GL_MAX_FRAGMENT_INPUT_COMPONENTS:
+ case GL_MAX_VARYING_COMPONENTS:
+ case GL_MAX_VERTEX_UNIFORM_COMPONENTS:
+ case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS:
+ case GL_MIN_PROGRAM_TEXEL_OFFSET:
+ case GL_MAX_PROGRAM_TEXEL_OFFSET:
+ case GL_NUM_EXTENSIONS:
+ case GL_MAJOR_VERSION:
+ case GL_MINOR_VERSION:
+ case GL_MAX_ELEMENTS_INDICES:
+ case GL_MAX_ELEMENTS_VERTICES:
+ case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS:
+ case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS:
+ case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS:
+ case GL_UNPACK_IMAGE_HEIGHT:
+ case GL_UNPACK_SKIP_IMAGES:
+ case GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES:
+ {
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+
+ case GL_MAX_ELEMENT_INDEX:
+ case GL_MAX_UNIFORM_BLOCK_SIZE:
+ case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS:
+ case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS:
+ case GL_MAX_SERVER_WAIT_TIMEOUT:
+ {
+ *type = GL_INT_64_ANGLEX;
+ *numParams = 1;
+ return true;
+ }
+
+ case GL_TRANSFORM_FEEDBACK_ACTIVE:
+ case GL_TRANSFORM_FEEDBACK_PAUSED:
+ case GL_PRIMITIVE_RESTART_FIXED_INDEX:
+ case GL_RASTERIZER_DISCARD:
+ {
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+
+ case GL_MAX_TEXTURE_LOD_BIAS:
+ case GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES:
+ case GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES:
+ {
+ *type = GL_FLOAT;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (extensions.requestExtensionANGLE)
+ {
+ switch (pname)
+ {
+ case GL_NUM_REQUESTABLE_EXTENSIONS_ANGLE:
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (extensions.textureMultisampleANGLE)
+ {
+ switch (pname)
+ {
+ case GL_MAX_COLOR_TEXTURE_SAMPLES_ANGLE:
+ case GL_MAX_INTEGER_SAMPLES_ANGLE:
+ case GL_MAX_DEPTH_TEXTURE_SAMPLES_ANGLE:
+ case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ANGLE:
+ case GL_MAX_SAMPLE_MASK_WORDS:
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (extensions.textureCubeMapArrayAny())
+ {
+ switch (pname)
+ {
+ case GL_TEXTURE_BINDING_CUBE_MAP_ARRAY:
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (extensions.textureBufferAny())
+ {
+ switch (pname)
+ {
+ case GL_TEXTURE_BUFFER_BINDING:
+ case GL_TEXTURE_BINDING_BUFFER:
+ case GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
+ case GL_MAX_TEXTURE_BUFFER_SIZE:
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (extensions.shaderPixelLocalStorageANGLE)
+ {
+ switch (pname)
+ {
+ case GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE:
+ case GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE:
+ case GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE:
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_PIXEL_LOCAL_STORAGE_ACTIVE_ANGLE:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (glState.getClientVersion() < Version(3, 1))
+ {
+ return false;
+ }
+
+ // Check for ES3.1+ parameter names
+ switch (pname)
+ {
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ case GL_DRAW_INDIRECT_BUFFER_BINDING:
+ case GL_DISPATCH_INDIRECT_BUFFER_BINDING:
+ case GL_MAX_FRAMEBUFFER_WIDTH:
+ case GL_MAX_FRAMEBUFFER_HEIGHT:
+ case GL_MAX_FRAMEBUFFER_SAMPLES:
+ case GL_MAX_SAMPLE_MASK_WORDS:
+ case GL_MAX_COLOR_TEXTURE_SAMPLES:
+ case GL_MAX_DEPTH_TEXTURE_SAMPLES:
+ case GL_MAX_INTEGER_SAMPLES:
+ case GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET:
+ case GL_MAX_VERTEX_ATTRIB_BINDINGS:
+ case GL_MAX_VERTEX_ATTRIB_STRIDE:
+ case GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS:
+ case GL_MAX_VERTEX_ATOMIC_COUNTERS:
+ case GL_MAX_VERTEX_IMAGE_UNIFORMS:
+ case GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS:
+ case GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS:
+ case GL_MAX_FRAGMENT_ATOMIC_COUNTERS:
+ case GL_MAX_FRAGMENT_IMAGE_UNIFORMS:
+ case GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS:
+ case GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET:
+ case GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET:
+ case GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS:
+ case GL_MAX_COMPUTE_UNIFORM_BLOCKS:
+ case GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS:
+ case GL_MAX_COMPUTE_SHARED_MEMORY_SIZE:
+ case GL_MAX_COMPUTE_UNIFORM_COMPONENTS:
+ case GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS:
+ case GL_MAX_COMPUTE_ATOMIC_COUNTERS:
+ case GL_MAX_COMPUTE_IMAGE_UNIFORMS:
+ case GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS:
+ case GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS:
+ case GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES:
+ case GL_MAX_UNIFORM_LOCATIONS:
+ case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
+ case GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE:
+ case GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS:
+ case GL_MAX_COMBINED_ATOMIC_COUNTERS:
+ case GL_MAX_IMAGE_UNITS:
+ case GL_MAX_COMBINED_IMAGE_UNIFORMS:
+ case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS:
+ case GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS:
+ case GL_SHADER_STORAGE_BUFFER_BINDING:
+ case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT:
+ case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
+ case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
+ case GL_PROGRAM_PIPELINE_BINDING:
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ case GL_MAX_SHADER_STORAGE_BLOCK_SIZE:
+ *type = GL_INT_64_ANGLEX;
+ *numParams = 1;
+ return true;
+ case GL_SAMPLE_MASK:
+ case GL_SAMPLE_SHADING:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ case GL_MIN_SAMPLE_SHADING_VALUE:
+ *type = GL_FLOAT;
+ *numParams = 1;
+ return true;
+ }
+
+ if (extensions.geometryShaderAny())
+ {
+ switch (pname)
+ {
+ case GL_MAX_FRAMEBUFFER_LAYERS_EXT:
+ case GL_LAYER_PROVOKING_VERTEX_EXT:
+ case GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT:
+ case GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT:
+ case GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT:
+ case GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT:
+ case GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT:
+ case GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT:
+ case GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT:
+ case GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT:
+ case GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT:
+ case GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT:
+ case GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT:
+ case GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT:
+ case GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT:
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ if (extensions.tessellationShaderEXT)
+ {
+ switch (pname)
+ {
+ case GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED:
+ *type = GL_BOOL;
+ *numParams = 1;
+ return true;
+ case GL_PATCH_VERTICES:
+ case GL_MAX_PATCH_VERTICES_EXT:
+ case GL_MAX_TESS_GEN_LEVEL_EXT:
+ case GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT:
+ case GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT:
+ case GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT:
+ case GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT:
+ case GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT:
+ case GL_MAX_TESS_PATCH_COMPONENTS_EXT:
+ case GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT:
+ case GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT:
+ case GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT:
+ case GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT:
+ case GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT:
+ case GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT:
+ case GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT:
+ case GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT:
+ case GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT:
+ case GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT:
+ case GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT:
+ case GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT:
+ case GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT:
+ case GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT:
+ case GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT:
+ case GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT:
+ *type = GL_INT;
+ *numParams = 1;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void QueryProgramPipelineiv(const Context *context,
+ ProgramPipeline *programPipeline,
+ GLenum pname,
+ GLint *params)
+{
+ if (!params)
+ {
+ // Can't write the result anywhere, so just return immediately.
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_ACTIVE_PROGRAM:
+ {
+ // the name of the active program object of the program pipeline object is returned in
+ // params
+ *params = 0;
+ if (programPipeline)
+ {
+ const Program *program = programPipeline->getActiveShaderProgram();
+ if (program)
+ {
+ *params = program->id().value;
+ }
+ }
+ break;
+ }
+
+ case GL_VERTEX_SHADER:
+ {
+ // the name of the current program object for the vertex shader type of the program
+ // pipeline object is returned in params
+ GetShaderProgramId(programPipeline, ShaderType::Vertex, params);
+ break;
+ }
+
+ case GL_FRAGMENT_SHADER:
+ {
+ // the name of the current program object for the fragment shader type of the program
+ // pipeline object is returned in params
+ GetShaderProgramId(programPipeline, ShaderType::Fragment, params);
+ break;
+ }
+
+ case GL_TESS_CONTROL_SHADER:
+ {
+ // the name of the current program object for the tessellation control shader type of
+ // the program pipeline object is returned in params
+ GetShaderProgramId(programPipeline, ShaderType::TessControl, params);
+ break;
+ }
+
+ case GL_TESS_EVALUATION_SHADER:
+ {
+ // the name of the current program object for the tessellation evaluation shader type of
+ // the program pipeline object is returned in params
+ GetShaderProgramId(programPipeline, ShaderType::TessEvaluation, params);
+ break;
+ }
+
+ case GL_COMPUTE_SHADER:
+ {
+ // the name of the current program object for the compute shader type of the program
+ // pipeline object is returned in params
+ GetShaderProgramId(programPipeline, ShaderType::Compute, params);
+ break;
+ }
+
+ case GL_GEOMETRY_SHADER:
+ {
+ // the name of the current program object for the geometry shader type of the program
+ // pipeline object is returned in params
+ GetShaderProgramId(programPipeline, ShaderType::Geometry, params);
+ break;
+ }
+
+ case GL_INFO_LOG_LENGTH:
+ {
+ // the length of the info log, including the null terminator, is returned in params. If
+ // there is no info log, zero is returned.
+ *params = 0;
+ if (programPipeline)
+ {
+ *params = programPipeline->getExecutable().getInfoLogLength();
+ }
+ break;
+ }
+
+ case GL_VALIDATE_STATUS:
+ {
+ // the validation status of pipeline, as determined by glValidateProgramPipeline, is
+ // returned in params
+ *params = 0;
+ if (programPipeline)
+ {
+ *params = programPipeline->isValid();
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+} // namespace gl
+
+namespace egl
+{
+
+void QueryConfigAttrib(const Config *config, EGLint attribute, EGLint *value)
+{
+ ASSERT(config != nullptr);
+ switch (attribute)
+ {
+ case EGL_BUFFER_SIZE:
+ *value = config->bufferSize;
+ break;
+ case EGL_ALPHA_SIZE:
+ *value = config->alphaSize;
+ break;
+ case EGL_BLUE_SIZE:
+ *value = config->blueSize;
+ break;
+ case EGL_GREEN_SIZE:
+ *value = config->greenSize;
+ break;
+ case EGL_RED_SIZE:
+ *value = config->redSize;
+ break;
+ case EGL_DEPTH_SIZE:
+ *value = config->depthSize;
+ break;
+ case EGL_STENCIL_SIZE:
+ *value = config->stencilSize;
+ break;
+ case EGL_CONFIG_CAVEAT:
+ *value = config->configCaveat;
+ break;
+ case EGL_CONFIG_ID:
+ *value = config->configID;
+ break;
+ case EGL_LEVEL:
+ *value = config->level;
+ break;
+ case EGL_NATIVE_RENDERABLE:
+ *value = config->nativeRenderable;
+ break;
+ case EGL_NATIVE_VISUAL_ID:
+ *value = config->nativeVisualID;
+ break;
+ case EGL_NATIVE_VISUAL_TYPE:
+ *value = config->nativeVisualType;
+ break;
+ case EGL_SAMPLES:
+ *value = config->samples;
+ break;
+ case EGL_SAMPLE_BUFFERS:
+ *value = config->sampleBuffers;
+ break;
+ case EGL_SURFACE_TYPE:
+ *value = config->surfaceType;
+ break;
+ case EGL_BIND_TO_TEXTURE_TARGET_ANGLE:
+ *value = config->bindToTextureTarget;
+ break;
+ case EGL_TRANSPARENT_TYPE:
+ *value = config->transparentType;
+ break;
+ case EGL_TRANSPARENT_BLUE_VALUE:
+ *value = config->transparentBlueValue;
+ break;
+ case EGL_TRANSPARENT_GREEN_VALUE:
+ *value = config->transparentGreenValue;
+ break;
+ case EGL_TRANSPARENT_RED_VALUE:
+ *value = config->transparentRedValue;
+ break;
+ case EGL_BIND_TO_TEXTURE_RGB:
+ *value = config->bindToTextureRGB;
+ break;
+ case EGL_BIND_TO_TEXTURE_RGBA:
+ *value = config->bindToTextureRGBA;
+ break;
+ case EGL_MIN_SWAP_INTERVAL:
+ *value = config->minSwapInterval;
+ break;
+ case EGL_MAX_SWAP_INTERVAL:
+ *value = config->maxSwapInterval;
+ break;
+ case EGL_LUMINANCE_SIZE:
+ *value = config->luminanceSize;
+ break;
+ case EGL_ALPHA_MASK_SIZE:
+ *value = config->alphaMaskSize;
+ break;
+ case EGL_COLOR_BUFFER_TYPE:
+ *value = config->colorBufferType;
+ break;
+ case EGL_RENDERABLE_TYPE:
+ *value = config->renderableType;
+ break;
+ case EGL_MATCH_NATIVE_PIXMAP:
+ *value = false;
+ UNIMPLEMENTED();
+ break;
+ case EGL_CONFORMANT:
+ *value = config->conformant;
+ break;
+ case EGL_MAX_PBUFFER_WIDTH:
+ *value = config->maxPBufferWidth;
+ break;
+ case EGL_MAX_PBUFFER_HEIGHT:
+ *value = config->maxPBufferHeight;
+ break;
+ case EGL_MAX_PBUFFER_PIXELS:
+ *value = config->maxPBufferPixels;
+ break;
+ case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
+ *value = config->optimalOrientation;
+ break;
+ case EGL_COLOR_COMPONENT_TYPE_EXT:
+ *value = config->colorComponentType;
+ break;
+ case EGL_RECORDABLE_ANDROID:
+ *value = config->recordable;
+ break;
+ case EGL_FRAMEBUFFER_TARGET_ANDROID:
+ *value = config->framebufferTarget;
+ break;
+ case EGL_MATCH_FORMAT_KHR:
+ *value = config->matchFormat;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+void QueryContextAttrib(const gl::Context *context, EGLint attribute, EGLint *value)
+{
+ switch (attribute)
+ {
+ case EGL_CONFIG_ID:
+ if (context->getConfig() != EGL_NO_CONFIG_KHR)
+ {
+ *value = context->getConfig()->configID;
+ }
+ else
+ {
+ *value = 0;
+ }
+ break;
+ case EGL_CONTEXT_CLIENT_TYPE:
+ *value = context->getClientType();
+ break;
+ case EGL_CONTEXT_CLIENT_VERSION:
+ *value = context->getClientMajorVersion();
+ break;
+ case EGL_RENDER_BUFFER:
+ *value = context->getRenderBuffer();
+ break;
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ *value = context->isRobustResourceInitEnabled();
+ break;
+ case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
+ *value = static_cast<EGLint>(context->getContextPriority());
+ break;
+ case EGL_PROTECTED_CONTENT_EXT:
+ *value = context->getState().hasProtectedContent();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+egl::Error QuerySurfaceAttrib(const Display *display,
+ const gl::Context *context,
+ Surface *surface,
+ EGLint attribute,
+ EGLint *value)
+{
+ switch (attribute)
+ {
+ case EGL_GL_COLORSPACE:
+ *value = surface->getGLColorspace();
+ break;
+ case EGL_VG_ALPHA_FORMAT:
+ *value = surface->getVGAlphaFormat();
+ break;
+ case EGL_VG_COLORSPACE:
+ *value = surface->getVGColorspace();
+ break;
+ case EGL_CONFIG_ID:
+ *value = surface->getConfig()->configID;
+ break;
+ case EGL_HEIGHT:
+ ANGLE_TRY(surface->getUserHeight(display, value));
+ break;
+ case EGL_HORIZONTAL_RESOLUTION:
+ *value = surface->getHorizontalResolution();
+ break;
+ case EGL_LARGEST_PBUFFER:
+ // The EGL spec states that value is not written if the surface is not a pbuffer
+ if (surface->getType() == EGL_PBUFFER_BIT)
+ {
+ *value = surface->getLargestPbuffer();
+ }
+ break;
+ case EGL_MIPMAP_TEXTURE:
+ // The EGL spec states that value is not written if the surface is not a pbuffer
+ if (surface->getType() == EGL_PBUFFER_BIT)
+ {
+ *value = surface->getMipmapTexture();
+ }
+ break;
+ case EGL_MIPMAP_LEVEL:
+ // The EGL spec states that value is not written if the surface is not a pbuffer
+ if (surface->getType() == EGL_PBUFFER_BIT)
+ {
+ *value = surface->getMipmapLevel();
+ }
+ break;
+ case EGL_MULTISAMPLE_RESOLVE:
+ *value = surface->getMultisampleResolve();
+ break;
+ case EGL_PIXEL_ASPECT_RATIO:
+ *value = surface->getPixelAspectRatio();
+ break;
+ case EGL_RENDER_BUFFER:
+ *value = surface->getRenderBuffer();
+ break;
+ case EGL_SWAP_BEHAVIOR:
+ *value = surface->getSwapBehavior();
+ break;
+ case EGL_TEXTURE_FORMAT:
+ // The EGL spec states that value is not written if the surface is not a pbuffer
+ if (surface->getType() == EGL_PBUFFER_BIT)
+ {
+ *value = ToEGLenum(surface->getTextureFormat());
+ }
+ break;
+ case EGL_TEXTURE_TARGET:
+ // The EGL spec states that value is not written if the surface is not a pbuffer
+ if (surface->getType() == EGL_PBUFFER_BIT)
+ {
+ *value = surface->getTextureTarget();
+ }
+ break;
+ case EGL_VERTICAL_RESOLUTION:
+ *value = surface->getVerticalResolution();
+ break;
+ case EGL_WIDTH:
+ ANGLE_TRY(surface->getUserWidth(display, value));
+ break;
+ case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+ *value = surface->isPostSubBufferSupported();
+ break;
+ case EGL_FIXED_SIZE_ANGLE:
+ *value = surface->isFixedSize();
+ break;
+ case EGL_SURFACE_ORIENTATION_ANGLE:
+ *value = surface->getOrientation();
+ break;
+ case EGL_DIRECT_COMPOSITION_ANGLE:
+ *value = surface->directComposition();
+ break;
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ *value = surface->isRobustResourceInitEnabled();
+ break;
+ case EGL_TIMESTAMPS_ANDROID:
+ *value = surface->isTimestampsEnabled();
+ break;
+ case EGL_BUFFER_AGE_EXT:
+ ANGLE_TRY(surface->getBufferAge(context, value));
+ break;
+ case EGL_BITMAP_PITCH_KHR:
+ *value = surface->getBitmapPitch();
+ break;
+ case EGL_BITMAP_ORIGIN_KHR:
+ *value = surface->getBitmapOrigin();
+ break;
+ case EGL_BITMAP_PIXEL_RED_OFFSET_KHR:
+ *value = surface->getRedOffset();
+ break;
+ case EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR:
+ *value = surface->getGreenOffset();
+ break;
+ case EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR:
+ *value = surface->getBlueOffset();
+ break;
+ case EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR:
+ *value = surface->getAlphaOffset();
+ break;
+ case EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR:
+ *value = surface->getLuminanceOffset();
+ break;
+ case EGL_BITMAP_PIXEL_SIZE_KHR:
+ *value = surface->getBitmapPixelSize();
+ break;
+ case EGL_PROTECTED_CONTENT_EXT:
+ *value = surface->hasProtectedContent();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return NoError();
+}
+
+egl::Error QuerySurfaceAttrib64KHR(const Display *display,
+ const gl::Context *context,
+ const Surface *surface,
+ EGLint attribute,
+ EGLAttribKHR *value)
+{
+ switch (attribute)
+ {
+ case EGL_BITMAP_PITCH_KHR:
+ *value = static_cast<EGLAttribKHR>(surface->getBitmapPitch());
+ break;
+ case EGL_BITMAP_ORIGIN_KHR:
+ *value = static_cast<EGLAttribKHR>(surface->getBitmapOrigin());
+ break;
+ case EGL_BITMAP_PIXEL_RED_OFFSET_KHR:
+ *value = static_cast<EGLAttribKHR>(surface->getRedOffset());
+ break;
+ case EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR:
+ *value = static_cast<EGLAttribKHR>(surface->getGreenOffset());
+ break;
+ case EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR:
+ *value = static_cast<EGLAttribKHR>(surface->getBlueOffset());
+ break;
+ case EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR:
+ *value = static_cast<EGLAttribKHR>(surface->getAlphaOffset());
+ break;
+ case EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR:
+ *value = static_cast<EGLAttribKHR>(surface->getLuminanceOffset());
+ break;
+ case EGL_BITMAP_PIXEL_SIZE_KHR:
+ *value = static_cast<EGLAttribKHR>(surface->getBitmapPixelSize());
+ break;
+ case EGL_BITMAP_POINTER_KHR:
+ *value = surface->getBitmapPointer();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return NoError();
+}
+
+egl::Error SetSurfaceAttrib(Surface *surface, EGLint attribute, EGLint value)
+{
+ switch (attribute)
+ {
+ case EGL_MIPMAP_LEVEL:
+ surface->setMipmapLevel(value);
+ break;
+ case EGL_MULTISAMPLE_RESOLVE:
+ surface->setMultisampleResolve(value);
+ break;
+ case EGL_SWAP_BEHAVIOR:
+ surface->setSwapBehavior(value);
+ break;
+ case EGL_WIDTH:
+ surface->setFixedWidth(value);
+ break;
+ case EGL_HEIGHT:
+ surface->setFixedHeight(value);
+ break;
+ case EGL_TIMESTAMPS_ANDROID:
+ surface->setTimestampsEnabled(value != EGL_FALSE);
+ break;
+ case EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID:
+ return surface->setAutoRefreshEnabled(value == EGL_TRUE);
+ case EGL_RENDER_BUFFER:
+ return surface->setRenderBuffer(value);
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return NoError();
+}
+
+Error GetSyncAttrib(Display *display, Sync *sync, EGLint attribute, EGLint *value)
+{
+ switch (attribute)
+ {
+ case EGL_SYNC_TYPE_KHR:
+ *value = sync->getType();
+ return NoError();
+
+ case EGL_SYNC_STATUS_KHR:
+ return sync->getStatus(display, value);
+
+ case EGL_SYNC_CONDITION_KHR:
+ *value = sync->getCondition();
+ return NoError();
+
+ default:
+ break;
+ }
+
+ UNREACHABLE();
+ return NoError();
+}
+} // namespace egl
diff --git a/gfx/angle/checkout/src/libANGLE/queryutils.h b/gfx/angle/checkout/src/libANGLE/queryutils.h
new file mode 100644
index 0000000000..dfb3680e8c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/queryutils.h
@@ -0,0 +1,293 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// queryutils.h: Utilities for querying values from GL objects
+
+#ifndef LIBANGLE_QUERYUTILS_H_
+#define LIBANGLE_QUERYUTILS_H_
+
+#include "angle_gl.h"
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+#include <EGL/egl.h>
+
+namespace gl
+{
+class Buffer;
+class Context;
+class Sync;
+class Framebuffer;
+class GLES1State;
+class Program;
+class Renderbuffer;
+class Sampler;
+class Shader;
+class State;
+class Texture;
+struct TextureCaps;
+struct UniformBlock;
+struct VertexAttribute;
+class VertexBinding;
+struct VertexAttribCurrentValueData;
+
+void QueryFramebufferAttachmentParameteriv(const Context *context,
+ const Framebuffer *framebuffer,
+ GLenum attachment,
+ GLenum pname,
+ GLint *params);
+void QueryBufferParameteriv(const Buffer *buffer, GLenum pname, GLint *params);
+void QueryBufferParameteri64v(const Buffer *buffer, GLenum pname, GLint64 *params);
+void QueryBufferPointerv(const Buffer *buffer, GLenum pname, void **params);
+void QueryProgramiv(Context *context, const Program *program, GLenum pname, GLint *params);
+void QueryRenderbufferiv(const Context *context,
+ const Renderbuffer *renderbuffer,
+ GLenum pname,
+ GLint *params);
+void QueryShaderiv(const Context *context, Shader *shader, GLenum pname, GLint *params);
+void QueryTexLevelParameterfv(const Texture *texture,
+ TextureTarget target,
+ GLint level,
+ GLenum pname,
+ GLfloat *params);
+void QueryTexLevelParameteriv(const Texture *texture,
+ TextureTarget target,
+ GLint level,
+ GLenum pname,
+ GLint *params);
+void QueryTexParameterfv(const Context *context,
+ const Texture *texture,
+ GLenum pname,
+ GLfloat *params);
+void QueryTexParameterxv(const Context *context,
+ const Texture *texture,
+ GLenum pname,
+ GLfixed *params);
+void QueryTexParameteriv(const Context *context,
+ const Texture *texture,
+ GLenum pname,
+ GLint *params);
+void QueryTexParameterIiv(const Context *context,
+ const Texture *texture,
+ GLenum pname,
+ GLint *params);
+void QueryTexParameterIuiv(const Context *context,
+ const Texture *texture,
+ GLenum pname,
+ GLuint *params);
+void QuerySamplerParameterfv(const Sampler *sampler, GLenum pname, GLfloat *params);
+void QuerySamplerParameteriv(const Sampler *sampler, GLenum pname, GLint *params);
+void QuerySamplerParameterIiv(const Sampler *sampler, GLenum pname, GLint *params);
+void QuerySamplerParameterIuiv(const Sampler *sampler, GLenum pname, GLuint *params);
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using the following
+// functions.
+void QueryVertexAttribfv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLfloat *params);
+
+void QueryVertexAttribiv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLint *params);
+
+void QueryVertexAttribPointerv(const VertexAttribute &attrib, GLenum pname, void **pointer);
+
+void QueryVertexAttribIiv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLint *params);
+
+void QueryVertexAttribIuiv(const VertexAttribute &attrib,
+ const VertexBinding &binding,
+ const VertexAttribCurrentValueData &currentValueData,
+ GLenum pname,
+ GLuint *params);
+
+void QueryActiveUniformBlockiv(const Program *program,
+ UniformBlockIndex uniformBlockIndex,
+ GLenum pname,
+ GLint *params);
+
+void QueryInternalFormativ(const TextureCaps &format, GLenum pname, GLsizei bufSize, GLint *params);
+
+void QueryFramebufferParameteriv(const Framebuffer *framebuffer, GLenum pname, GLint *params);
+
+angle::Result QuerySynciv(const Context *context,
+ const Sync *sync,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *values);
+
+void SetTexParameterf(Context *context, Texture *texture, GLenum pname, GLfloat param);
+void SetTexParameterfv(Context *context, Texture *texture, GLenum pname, const GLfloat *params);
+void SetTexParameteri(Context *context, Texture *texture, GLenum pname, GLint param);
+void SetTexParameteriv(Context *context, Texture *texture, GLenum pname, const GLint *params);
+void SetTexParameterIiv(Context *context, Texture *texture, GLenum pname, const GLint *params);
+void SetTexParameterIuiv(Context *context, Texture *texture, GLenum pname, const GLuint *params);
+void SetTexParameterx(Context *context, Texture *texture, GLenum pname, GLfixed param);
+void SetTexParameterxv(Context *context, Texture *texture, GLenum pname, const GLfixed *params);
+
+void SetSamplerParameterf(Context *context, Sampler *sampler, GLenum pname, GLfloat param);
+void SetSamplerParameterfv(Context *context, Sampler *sampler, GLenum pname, const GLfloat *params);
+void SetSamplerParameteri(Context *context, Sampler *sampler, GLenum pname, GLint param);
+void SetSamplerParameteriv(Context *context, Sampler *sampler, GLenum pname, const GLint *params);
+void SetSamplerParameterIiv(Context *context, Sampler *sampler, GLenum pname, const GLint *params);
+void SetSamplerParameterIuiv(Context *context,
+ Sampler *sampler,
+ GLenum pname,
+ const GLuint *params);
+
+void SetFramebufferParameteri(const Context *context,
+ Framebuffer *framebuffer,
+ GLenum pname,
+ GLint param);
+
+void SetProgramParameteri(Program *program, GLenum pname, GLint value);
+
+GLint GetUniformResourceProperty(const Program *program, GLuint index, const GLenum prop);
+
+GLuint QueryProgramResourceIndex(const Program *program,
+ GLenum programInterface,
+ const GLchar *name);
+
+void QueryProgramResourceName(const Context *context,
+ const Program *program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *name);
+
+GLint QueryProgramResourceLocation(const Program *program,
+ GLenum programInterface,
+ const GLchar *name);
+void QueryProgramResourceiv(const Program *program,
+ GLenum programInterface,
+ UniformBlockIndex index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLint *params);
+
+void QueryProgramInterfaceiv(const Program *program,
+ GLenum programInterface,
+ GLenum pname,
+ GLint *params);
+
+angle::Result SetMemoryObjectParameteriv(const Context *context,
+ MemoryObject *memoryObject,
+ GLenum pname,
+ const GLint *params);
+void QueryMemoryObjectParameteriv(const MemoryObject *memoryObject, GLenum pname, GLint *params);
+
+// GLES1 emulation
+
+ClientVertexArrayType ParamToVertexArrayType(GLenum param);
+
+void SetLightParameters(GLES1State *state,
+ GLenum light,
+ LightParameter pname,
+ const GLfloat *params);
+void GetLightParameters(const GLES1State *state,
+ GLenum light,
+ LightParameter pname,
+ GLfloat *params);
+
+void SetLightModelParameters(GLES1State *state, GLenum pname, const GLfloat *params);
+void GetLightModelParameters(const GLES1State *state, GLenum pname, GLfloat *params);
+bool IsLightModelTwoSided(const GLES1State *state);
+
+void SetMaterialParameters(GLES1State *state,
+ GLenum face,
+ MaterialParameter pname,
+ const GLfloat *params);
+void GetMaterialParameters(const GLES1State *state,
+ GLenum face,
+ MaterialParameter pname,
+ GLfloat *params);
+
+unsigned int GetLightModelParameterCount(GLenum pname);
+unsigned int GetLightParameterCount(LightParameter pname);
+unsigned int GetMaterialParameterCount(MaterialParameter pname);
+
+void SetFogParameters(GLES1State *state, GLenum pname, const GLfloat *params);
+void GetFogParameters(const GLES1State *state, GLenum pname, GLfloat *params);
+unsigned int GetFogParameterCount(GLenum pname);
+
+unsigned int GetTextureEnvParameterCount(TextureEnvParameter pname);
+
+void ConvertTextureEnvFromInt(TextureEnvParameter pname, const GLint *input, GLfloat *output);
+void ConvertTextureEnvFromFixed(TextureEnvParameter pname, const GLfixed *input, GLfloat *output);
+void ConvertTextureEnvToInt(TextureEnvParameter pname, const GLfloat *input, GLint *output);
+void ConvertTextureEnvToFixed(TextureEnvParameter pname, const GLfloat *input, GLfixed *output);
+
+void SetTextureEnv(unsigned int unit,
+ GLES1State *state,
+ TextureEnvTarget target,
+ TextureEnvParameter pname,
+ const GLfloat *params);
+void GetTextureEnv(unsigned int unit,
+ const GLES1State *state,
+ TextureEnvTarget target,
+ TextureEnvParameter pname,
+ GLfloat *params);
+
+unsigned int GetPointParameterCount(PointParameter pname);
+
+void SetPointParameter(GLES1State *state, PointParameter pname, const GLfloat *params);
+void GetPointParameter(const GLES1State *state, PointParameter pname, GLfloat *params);
+
+void SetPointSize(GLES1State *state, GLfloat size);
+void GetPointSize(const GLES1State *state, GLfloat *sizeOut);
+
+unsigned int GetTexParameterCount(GLenum pname);
+
+bool GetQueryParameterInfo(const State &glState,
+ GLenum pname,
+ GLenum *type,
+ unsigned int *numParams);
+
+void QueryProgramPipelineiv(const Context *context,
+ ProgramPipeline *programPipeline,
+ GLenum pname,
+ GLint *params);
+} // namespace gl
+
+namespace egl
+{
+struct Config;
+class Display;
+class Surface;
+class Sync;
+
+void QueryConfigAttrib(const Config *config, EGLint attribute, EGLint *value);
+
+void QueryContextAttrib(const gl::Context *context, EGLint attribute, EGLint *value);
+
+egl::Error QuerySurfaceAttrib(const Display *display,
+ const gl::Context *context,
+ Surface *surface,
+ EGLint attribute,
+ EGLint *value);
+egl::Error SetSurfaceAttrib(Surface *surface, EGLint attribute, EGLint value);
+Error GetSyncAttrib(Display *display, Sync *sync, EGLint attribute, EGLint *value);
+egl::Error QuerySurfaceAttrib64KHR(const Display *display,
+ const gl::Context *context,
+ const Surface *surface,
+ EGLint attribute,
+ EGLAttribKHR *value);
+
+} // namespace egl
+
+#endif // LIBANGLE_QUERYUTILS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/BufferImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/BufferImpl.cpp
new file mode 100644
index 0000000000..9cd3c5b6f6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/BufferImpl.cpp
@@ -0,0 +1,39 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BufferImpl.cpp: Implementation methods rx::BufferImpl class.
+
+#include "libANGLE/renderer/BufferImpl.h"
+
+namespace rx
+{
+
+angle::Result BufferImpl::getSubData(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size,
+ void *outData)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+angle::Result BufferImpl::setDataWithUsageFlags(const gl::Context *context,
+ gl::BufferBinding target,
+ GLeglClientBufferEXT clientBuffer,
+ const void *data,
+ size_t size,
+ gl::BufferUsage usage,
+ GLbitfield flags)
+{
+ return setData(context, target, data, size, usage);
+}
+
+angle::Result BufferImpl::onLabelUpdate(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/BufferImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/BufferImpl.h
new file mode 100644
index 0000000000..6238a4def3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/BufferImpl.h
@@ -0,0 +1,98 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BufferImpl.h: Defines the abstract rx::BufferImpl class.
+
+#ifndef LIBANGLE_RENDERER_BUFFERIMPL_H_
+#define LIBANGLE_RENDERER_BUFFERIMPL_H_
+
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Observer.h"
+
+#include <stdint.h>
+
+namespace gl
+{
+class BufferState;
+class Context;
+} // namespace gl
+
+namespace rx
+{
+// We use two set of Subject messages. The CONTENTS_CHANGED message is signaled whenever data
+// changes, to trigger re-translation or other events. Some buffers only need to be updated when the
+// underlying driver object changes - this is notified via the STORAGE_CHANGED message.
+class BufferImpl : public angle::Subject
+{
+ public:
+ BufferImpl(const gl::BufferState &state) : mState(state) {}
+ ~BufferImpl() override {}
+ virtual void destroy(const gl::Context *context) {}
+
+ virtual angle::Result setDataWithUsageFlags(const gl::Context *context,
+ gl::BufferBinding target,
+ GLeglClientBufferEXT clientBuffer,
+ const void *data,
+ size_t size,
+ gl::BufferUsage usage,
+ GLbitfield flags);
+ virtual angle::Result setData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ gl::BufferUsage usage) = 0;
+ virtual angle::Result setSubData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ size_t offset) = 0;
+ virtual angle::Result copySubData(const gl::Context *context,
+ BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size) = 0;
+ virtual angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) = 0;
+ virtual angle::Result mapRange(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ void **mapPtr) = 0;
+ virtual angle::Result unmap(const gl::Context *context, GLboolean *result) = 0;
+
+ virtual angle::Result getIndexRange(const gl::Context *context,
+ gl::DrawElementsType type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ gl::IndexRange *outRange) = 0;
+
+ virtual angle::Result getSubData(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size,
+ void *outData);
+
+ virtual angle::Result onLabelUpdate(const gl::Context *context);
+
+ // Override if accurate native memory size information is available
+ virtual GLint64 getMemorySize() const;
+
+ virtual void onDataChanged() {}
+
+ protected:
+ const gl::BufferState &mState;
+};
+
+inline GLint64 BufferImpl::getMemorySize() const
+{
+ return 0;
+}
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_BUFFERIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/CompilerImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/CompilerImpl.h
new file mode 100644
index 0000000000..0e8c5192f2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/CompilerImpl.h
@@ -0,0 +1,32 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CompilerImpl.h: Defines the rx::CompilerImpl class, an implementation interface
+// for the gl::Compiler object.
+
+#include "GLSLANG/ShaderLang.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+#ifndef LIBANGLE_RENDERER_COMPILERIMPL_H_
+# define LIBANGLE_RENDERER_COMPILERIMPL_H_
+
+namespace rx
+{
+
+class CompilerImpl : angle::NonCopyable
+{
+ public:
+ CompilerImpl() {}
+ virtual ~CompilerImpl() {}
+
+ // TODO(jmadill): Expose translator built-in resources init method.
+ virtual ShShaderOutput getTranslatorOutputType() const = 0;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_COMPILERIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/ContextImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/ContextImpl.cpp
new file mode 100644
index 0000000000..952d4ee37a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/ContextImpl.cpp
@@ -0,0 +1,88 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ContextImpl:
+// Implementation-specific functionality associated with a GL Context.
+//
+
+#include "libANGLE/renderer/ContextImpl.h"
+
+#include "common/third_party/base/anglebase/no_destructor.h"
+#include "libANGLE/Context.h"
+
+namespace rx
+{
+ContextImpl::ContextImpl(const gl::State &state, gl::ErrorSet *errorSet)
+ : mState(state), mMemoryProgramCache(nullptr), mErrors(errorSet)
+{}
+
+ContextImpl::~ContextImpl() {}
+
+void ContextImpl::invalidateTexture(gl::TextureType target)
+{
+ UNREACHABLE();
+}
+
+angle::Result ContextImpl::onUnMakeCurrent(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+angle::Result ContextImpl::handleNoopDrawEvent()
+{
+ return angle::Result::Continue;
+}
+
+void ContextImpl::setMemoryProgramCache(gl::MemoryProgramCache *memoryProgramCache)
+{
+ mMemoryProgramCache = memoryProgramCache;
+}
+
+void ContextImpl::handleError(GLenum errorCode,
+ const char *message,
+ const char *file,
+ const char *function,
+ unsigned int line)
+{
+ std::stringstream errorStream;
+ errorStream << "Internal error: " << gl::FmtHex(errorCode) << ": " << message;
+ mErrors->handleError(errorCode, errorStream.str().c_str(), file, function, line);
+}
+
+egl::ContextPriority ContextImpl::getContextPriority() const
+{
+ return egl::ContextPriority::Medium;
+}
+
+egl::Error ContextImpl::releaseHighPowerGPU(gl::Context *)
+{
+ return egl::NoError();
+}
+
+egl::Error ContextImpl::reacquireHighPowerGPU(gl::Context *)
+{
+ return egl::NoError();
+}
+
+angle::Result ContextImpl::acquireTextures(const gl::Context *context,
+ const gl::TextureBarrierVector &textureBarriers)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+angle::Result ContextImpl::releaseTextures(const gl::Context *context,
+ gl::TextureBarrierVector *textureBarriers)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+const angle::PerfMonitorCounterGroups &ContextImpl::getPerfMonitorCounters()
+{
+ static angle::base::NoDestructor<angle::PerfMonitorCounterGroups> sCounters;
+ return *sCounters;
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/ContextImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/ContextImpl.h
new file mode 100644
index 0000000000..3b167fe8b6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/ContextImpl.h
@@ -0,0 +1,274 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ContextImpl:
+// Implementation-specific functionality associated with a GL Context.
+//
+
+#ifndef LIBANGLE_RENDERER_CONTEXTIMPL_H_
+#define LIBANGLE_RENDERER_CONTEXTIMPL_H_
+
+#include <vector>
+
+#include "common/angleutils.h"
+#include "libANGLE/State.h"
+#include "libANGLE/renderer/GLImplFactory.h"
+
+namespace gl
+{
+class ErrorSet;
+class MemoryProgramCache;
+class Path;
+class Semaphore;
+struct Workarounds;
+} // namespace gl
+
+namespace rx
+{
+class ContextImpl : public GLImplFactory
+{
+ public:
+ ContextImpl(const gl::State &state, gl::ErrorSet *errorSet);
+ ~ContextImpl() override;
+
+ virtual void onDestroy(const gl::Context *context) {}
+
+ virtual angle::Result initialize() = 0;
+
+ // Flush and finish.
+ virtual angle::Result flush(const gl::Context *context) = 0;
+ virtual angle::Result finish(const gl::Context *context) = 0;
+
+ // Drawing methods.
+ virtual angle::Result drawArrays(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count) = 0;
+ virtual angle::Result drawArraysInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount) = 0;
+ // Necessary for Vulkan since gl_InstanceIndex includes baseInstance
+ virtual angle::Result drawArraysInstancedBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount,
+ GLuint baseInstance) = 0;
+
+ virtual angle::Result drawElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices) = 0;
+ virtual angle::Result drawElementsBaseVertex(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLint baseVertex) = 0;
+ virtual angle::Result drawElementsInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances) = 0;
+ virtual angle::Result drawElementsInstancedBaseVertex(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances,
+ GLint baseVertex) = 0;
+ virtual angle::Result drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances,
+ GLint baseVertex,
+ GLuint baseInstance) = 0;
+ virtual angle::Result drawRangeElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices) = 0;
+ virtual angle::Result drawRangeElementsBaseVertex(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLint baseVertex) = 0;
+
+ virtual angle::Result drawArraysIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const void *indirect) = 0;
+ virtual angle::Result drawElementsIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType type,
+ const void *indirect) = 0;
+
+ // MultiDraw* impl added as we need workaround for promoting dynamic attributes in D3D backend
+ virtual angle::Result multiDrawArrays(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ GLsizei drawcount) = 0;
+ virtual angle::Result multiDrawArraysIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride) = 0;
+ virtual angle::Result multiDrawArraysInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount) = 0;
+ virtual angle::Result multiDrawElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ GLsizei drawcount) = 0;
+ virtual angle::Result multiDrawElementsInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount) = 0;
+ virtual angle::Result multiDrawElementsIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType type,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride) = 0;
+ virtual angle::Result multiDrawArraysInstancedBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ const GLuint *baseInstances,
+ GLsizei drawcount) = 0;
+ virtual angle::Result multiDrawElementsInstancedBaseVertexBaseInstance(
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount) = 0;
+
+ // Device loss
+ virtual gl::GraphicsResetStatus getResetStatus() = 0;
+
+ // EXT_debug_marker
+ virtual angle::Result insertEventMarker(GLsizei length, const char *marker) = 0;
+ virtual angle::Result pushGroupMarker(GLsizei length, const char *marker) = 0;
+ virtual angle::Result popGroupMarker() = 0;
+
+ // KHR_debug
+ virtual angle::Result pushDebugGroup(const gl::Context *context,
+ GLenum source,
+ GLuint id,
+ const std::string &message) = 0;
+ virtual angle::Result popDebugGroup(const gl::Context *context) = 0;
+ virtual angle::Result handleNoopDrawEvent();
+
+ // KHR_parallel_shader_compile
+ virtual void setMaxShaderCompilerThreads(GLuint count) {}
+
+ // GL_ANGLE_texture_storage_external
+ virtual void invalidateTexture(gl::TextureType target);
+
+ // EXT_shader_framebuffer_fetch_non_coherent
+ virtual void framebufferFetchBarrier() {}
+
+ // KHR_blend_equation_advanced
+ virtual void blendBarrier() {}
+
+ // State sync with dirty bits.
+ virtual angle::Result syncState(const gl::Context *context,
+ const gl::State::DirtyBits &dirtyBits,
+ const gl::State::DirtyBits &bitMask,
+ gl::Command command) = 0;
+
+ // Disjoint timer queries
+ virtual GLint getGPUDisjoint() = 0;
+ virtual GLint64 getTimestamp() = 0;
+
+ // Context switching
+ virtual angle::Result onMakeCurrent(const gl::Context *context) = 0;
+ virtual angle::Result onUnMakeCurrent(const gl::Context *context);
+
+ // Native capabilities, unmodified by gl::Context.
+ virtual gl::Caps getNativeCaps() const = 0;
+ virtual const gl::TextureCapsMap &getNativeTextureCaps() const = 0;
+ virtual const gl::Extensions &getNativeExtensions() const = 0;
+ virtual const gl::Limitations &getNativeLimitations() const = 0;
+ virtual ShPixelLocalStorageType getNativePixelLocalStorageType() const = 0;
+
+ virtual angle::Result dispatchCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ) = 0;
+ virtual angle::Result dispatchComputeIndirect(const gl::Context *context,
+ GLintptr indirect) = 0;
+
+ virtual angle::Result memoryBarrier(const gl::Context *context, GLbitfield barriers) = 0;
+ virtual angle::Result memoryBarrierByRegion(const gl::Context *context,
+ GLbitfield barriers) = 0;
+
+ const gl::State &getState() const { return mState; }
+ int getClientMajorVersion() const { return mState.getClientMajorVersion(); }
+ int getClientMinorVersion() const { return mState.getClientMinorVersion(); }
+ const gl::Caps &getCaps() const { return mState.getCaps(); }
+ const gl::TextureCapsMap &getTextureCaps() const { return mState.getTextureCaps(); }
+ const gl::Extensions &getExtensions() const { return mState.getExtensions(); }
+ const gl::Limitations &getLimitations() const { return mState.getLimitations(); }
+
+ // A common GL driver behaviour is to trigger dynamic shader recompilation on a draw call,
+ // based on the current render states. We store a mutable pointer to the program cache so
+ // on draw calls we can store the refreshed shaders in the cache.
+ void setMemoryProgramCache(gl::MemoryProgramCache *memoryProgramCache);
+
+ void handleError(GLenum errorCode,
+ const char *message,
+ const char *file,
+ const char *function,
+ unsigned int line);
+
+ virtual egl::ContextPriority getContextPriority() const;
+
+ // EGL_ANGLE_power_preference implementation.
+ virtual egl::Error releaseHighPowerGPU(gl::Context *context);
+ virtual egl::Error reacquireHighPowerGPU(gl::Context *context);
+
+ // GL_ANGLE_vulkan_image
+ virtual angle::Result acquireTextures(const gl::Context *context,
+ const gl::TextureBarrierVector &textureBarriers);
+ virtual angle::Result releaseTextures(const gl::Context *context,
+ gl::TextureBarrierVector *textureBarriers);
+
+ // AMD_performance_monitor
+ virtual const angle::PerfMonitorCounterGroups &getPerfMonitorCounters();
+
+ protected:
+ const gl::State &mState;
+ gl::MemoryProgramCache *mMemoryProgramCache;
+ gl::ErrorSet *mErrors;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_CONTEXTIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/DeviceImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/DeviceImpl.cpp
new file mode 100644
index 0000000000..109fc48477
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/DeviceImpl.cpp
@@ -0,0 +1,18 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DeviceImpl.cpp: Implementation methods of egl::Device
+
+#include "libANGLE/renderer/DeviceImpl.h"
+
+namespace rx
+{
+
+DeviceImpl::DeviceImpl() {}
+
+DeviceImpl::~DeviceImpl() {}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/DeviceImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/DeviceImpl.h
new file mode 100644
index 0000000000..30cee7d514
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/DeviceImpl.h
@@ -0,0 +1,42 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DeviceImpl.h: Implementation methods of egl::Device
+
+#ifndef LIBANGLE_RENDERER_DEVICEIMPL_H_
+#define LIBANGLE_RENDERER_DEVICEIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Error.h"
+
+namespace egl
+{
+class Display;
+}
+
+namespace rx
+{
+class DisplayImpl;
+
+class DeviceImpl : angle::NonCopyable
+{
+ public:
+ DeviceImpl();
+ virtual ~DeviceImpl();
+
+ virtual egl::Error initialize() = 0;
+
+ virtual egl::Error getAttribute(const egl::Display *display,
+ EGLint attribute,
+ void **outValue) = 0;
+ virtual EGLint getType() = 0;
+ virtual void generateExtensions(egl::DeviceExtensions *outExtensions) const = 0;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_DEVICEIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/DisplayImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/DisplayImpl.cpp
new file mode 100644
index 0000000000..f07cd30517
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/DisplayImpl.cpp
@@ -0,0 +1,168 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayImpl.cpp: Implementation methods of egl::Display
+
+#include "libANGLE/renderer/DisplayImpl.h"
+
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/DeviceImpl.h"
+
+namespace rx
+{
+namespace
+{
+// For back-ends that do not implement EGLDevice.
+class MockDevice : public DeviceImpl
+{
+ public:
+ MockDevice() = default;
+ egl::Error initialize() override { return egl::NoError(); }
+ egl::Error getAttribute(const egl::Display *display, EGLint attribute, void **outValue) override
+ {
+ UNREACHABLE();
+ return egl::EglBadAttribute();
+ }
+ EGLint getType() override
+ {
+ UNREACHABLE();
+ return EGL_NONE;
+ }
+ void generateExtensions(egl::DeviceExtensions *outExtensions) const override
+ {
+ *outExtensions = egl::DeviceExtensions();
+ }
+};
+} // anonymous namespace
+
+DisplayImpl::DisplayImpl(const egl::DisplayState &state)
+ : mState(state), mExtensionsInitialized(false), mCapsInitialized(false), mBlobCache(nullptr)
+{}
+
+DisplayImpl::~DisplayImpl()
+{
+ ASSERT(mState.surfaceSet.empty());
+}
+
+egl::Error DisplayImpl::prepareForCall()
+{
+ return egl::NoError();
+}
+
+egl::Error DisplayImpl::releaseThread()
+{
+ return egl::NoError();
+}
+
+const egl::DisplayExtensions &DisplayImpl::getExtensions() const
+{
+ if (!mExtensionsInitialized)
+ {
+ generateExtensions(&mExtensions);
+ mExtensionsInitialized = true;
+ }
+
+ return mExtensions;
+}
+
+egl::Error DisplayImpl::handleGPUSwitch()
+{
+ return egl::NoError();
+}
+
+egl::Error DisplayImpl::forceGPUSwitch(EGLint gpuIDHigh, EGLint gpuIDLow)
+{
+ return egl::NoError();
+}
+
+egl::Error DisplayImpl::validateClientBuffer(const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const
+{
+ UNREACHABLE();
+ return egl::EglBadDisplay() << "DisplayImpl::validateClientBuffer unimplemented.";
+}
+
+egl::Error DisplayImpl::validateImageClientBuffer(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const
+{
+ UNREACHABLE();
+ return egl::EglBadDisplay() << "DisplayImpl::validateImageClientBuffer unimplemented.";
+}
+
+egl::Error DisplayImpl::validatePixmap(const egl::Config *config,
+ EGLNativePixmapType pixmap,
+ const egl::AttributeMap &attributes) const
+{
+ UNREACHABLE();
+ return egl::EglBadDisplay() << "DisplayImpl::valdiatePixmap unimplemented.";
+}
+
+const egl::Caps &DisplayImpl::getCaps() const
+{
+ if (!mCapsInitialized)
+ {
+ generateCaps(&mCaps);
+ mCapsInitialized = true;
+ }
+
+ return mCaps;
+}
+
+DeviceImpl *DisplayImpl::createDevice()
+{
+ return new MockDevice();
+}
+
+bool DisplayImpl::isX11() const
+{
+ return false;
+}
+
+bool DisplayImpl::isWayland() const
+{
+ return false;
+}
+
+bool DisplayImpl::isGBM() const
+{
+ return false;
+}
+
+bool DisplayImpl::supportsDmaBufFormat(EGLint format) const
+{
+ UNREACHABLE();
+ return false;
+}
+
+egl::Error DisplayImpl::queryDmaBufFormats(EGLint max_formats, EGLint *formats, EGLint *num_formats)
+{
+ UNREACHABLE();
+ return egl::NoError();
+}
+
+egl::Error DisplayImpl::queryDmaBufModifiers(EGLint format,
+ EGLint max_modifiers,
+ EGLuint64KHR *modifiers,
+ EGLBoolean *external_only,
+ EGLint *num_modifiers)
+{
+ UNREACHABLE();
+ return egl::NoError();
+}
+
+GLuint DisplayImpl::getNextSurfaceID()
+{
+ uint64_t id = mNextSurfaceID.generate().getValue();
+ ASSERT(id <= 0xfffffffful);
+ return static_cast<GLuint>(id);
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/DisplayImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/DisplayImpl.h
new file mode 100644
index 0000000000..0dea083f9e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/DisplayImpl.h
@@ -0,0 +1,169 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayImpl.h: Implementation methods of egl::Display
+
+#ifndef LIBANGLE_RENDERER_DISPLAYIMPL_H_
+#define LIBANGLE_RENDERER_DISPLAYIMPL_H_
+
+#include "common/Optional.h"
+#include "common/angleutils.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Observer.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/renderer/EGLImplFactory.h"
+#include "platform/Feature.h"
+
+#include <set>
+#include <vector>
+
+namespace angle
+{
+struct FrontendFeatures;
+} // namespace angle
+
+namespace egl
+{
+class AttributeMap;
+class BlobCache;
+class Display;
+struct DisplayState;
+struct Config;
+class Surface;
+class ImageSibling;
+class Thread;
+} // namespace egl
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace rx
+{
+class SurfaceImpl;
+class ImageImpl;
+struct ConfigDesc;
+class DeviceImpl;
+class StreamProducerImpl;
+
+class ShareGroupImpl : angle::NonCopyable
+{
+ public:
+ ShareGroupImpl() : mAnyContextWithRobustness(false) {}
+ virtual ~ShareGroupImpl() {}
+ virtual void onDestroy(const egl::Display *display) {}
+
+ void onRobustContextAdd() { mAnyContextWithRobustness = true; }
+ bool hasAnyContextWithRobustness() const { return mAnyContextWithRobustness; }
+
+ private:
+ // Whether any context in the share group has robustness enabled. If any context in the share
+ // group is robust, any program created in any context of the share group must have robustness
+ // enabled. This is because programs are shared between the share group contexts.
+ bool mAnyContextWithRobustness;
+};
+
+class DisplayImpl : public EGLImplFactory, public angle::Subject
+{
+ public:
+ DisplayImpl(const egl::DisplayState &state);
+ ~DisplayImpl() override;
+
+ virtual egl::Error initialize(egl::Display *display) = 0;
+ virtual void terminate() = 0;
+ virtual egl::Error prepareForCall();
+ virtual egl::Error releaseThread();
+
+ virtual egl::Error makeCurrent(egl::Display *display,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface,
+ gl::Context *context) = 0;
+
+ virtual egl::ConfigSet generateConfigs() = 0;
+
+ virtual bool testDeviceLost() = 0;
+ virtual egl::Error restoreLostDevice(const egl::Display *display) = 0;
+
+ virtual bool isValidNativeWindow(EGLNativeWindowType window) const = 0;
+ virtual egl::Error validateClientBuffer(const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const;
+ virtual egl::Error validateImageClientBuffer(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const;
+ virtual egl::Error validatePixmap(const egl::Config *config,
+ EGLNativePixmapType pixmap,
+ const egl::AttributeMap &attributes) const;
+
+ virtual std::string getRendererDescription() = 0;
+ virtual std::string getVendorString() = 0;
+ virtual std::string getVersionString(bool includeFullVersion) = 0;
+
+ virtual DeviceImpl *createDevice();
+
+ virtual egl::Error waitClient(const gl::Context *context) = 0;
+ virtual egl::Error waitNative(const gl::Context *context, EGLint engine) = 0;
+ virtual gl::Version getMaxSupportedESVersion() const = 0;
+ virtual gl::Version getMaxConformantESVersion() const = 0;
+ // If desktop GL is not supported in any capacity for a given backend, this returns None.
+ virtual Optional<gl::Version> getMaxSupportedDesktopVersion() const = 0;
+ const egl::Caps &getCaps() const;
+
+ virtual void setBlobCacheFuncs(EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get) {}
+
+ const egl::DisplayExtensions &getExtensions() const;
+
+ void setBlobCache(egl::BlobCache *blobCache) { mBlobCache = blobCache; }
+ egl::BlobCache *getBlobCache() const { return mBlobCache; }
+
+ virtual void initializeFrontendFeatures(angle::FrontendFeatures *features) const {}
+
+ virtual void populateFeatureList(angle::FeatureList *features) = 0;
+
+ const egl::DisplayState &getState() const { return mState; }
+
+ virtual egl::Error handleGPUSwitch();
+ virtual egl::Error forceGPUSwitch(EGLint gpuIDHigh, EGLint gpuIDLow);
+
+ virtual bool isX11() const;
+ virtual bool isWayland() const;
+ virtual bool isGBM() const;
+
+ virtual bool supportsDmaBufFormat(EGLint format) const;
+ virtual egl::Error queryDmaBufFormats(EGLint max_formats, EGLint *formats, EGLint *num_formats);
+ virtual egl::Error queryDmaBufModifiers(EGLint format,
+ EGLint max_modifiers,
+ EGLuint64KHR *modifiers,
+ EGLBoolean *external_only,
+ EGLint *num_modifiers);
+ GLuint getNextSurfaceID() override;
+
+ protected:
+ const egl::DisplayState &mState;
+
+ private:
+ virtual void generateExtensions(egl::DisplayExtensions *outExtensions) const = 0;
+ virtual void generateCaps(egl::Caps *outCaps) const = 0;
+
+ mutable bool mExtensionsInitialized;
+ mutable egl::DisplayExtensions mExtensions;
+
+ mutable bool mCapsInitialized;
+ mutable egl::Caps mCaps;
+
+ egl::BlobCache *mBlobCache;
+ rx::AtomicSerialFactory mNextSurfaceID;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_DISPLAYIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/EGLImplFactory.h b/gfx/angle/checkout/src/libANGLE/renderer/EGLImplFactory.h
new file mode 100644
index 0000000000..4d5308dc0e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/EGLImplFactory.h
@@ -0,0 +1,104 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// EGLImplFactory.h:
+// Factory interface for EGL Impl objects.
+//
+
+#ifndef LIBANGLE_RENDERER_EGLIMPLFACTORY_H_
+#define LIBANGLE_RENDERER_EGLIMPLFACTORY_H_
+
+#include "libANGLE/Stream.h"
+
+namespace egl
+{
+class AttributeMap;
+struct Config;
+class ImageSibling;
+struct ImageState;
+struct SurfaceState;
+} // namespace egl
+
+namespace gl
+{
+class Context;
+class ErrorSet;
+class State;
+} // namespace gl
+
+namespace rx
+{
+class ContextImpl;
+class EGLSyncImpl;
+class ImageImpl;
+class ExternalImageSiblingImpl;
+class SurfaceImpl;
+class ShareGroupImpl;
+
+class EGLImplFactory : angle::NonCopyable
+{
+ public:
+ EGLImplFactory() {}
+ virtual ~EGLImplFactory() {}
+
+ virtual SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) = 0;
+ virtual SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::AttributeMap &attribs) = 0;
+ virtual SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) = 0;
+ virtual SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) = 0;
+
+ virtual ImageImpl *createImage(const egl::ImageState &state,
+ const gl::Context *context,
+ EGLenum target,
+ const egl::AttributeMap &attribs) = 0;
+
+ virtual ContextImpl *createContext(const gl::State &state,
+ gl::ErrorSet *errorSet,
+ const egl::Config *configuration,
+ const gl::Context *shareContext,
+ const egl::AttributeMap &attribs) = 0;
+
+ virtual StreamProducerImpl *createStreamProducerD3DTexture(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) = 0;
+
+ virtual ExternalImageSiblingImpl *createExternalImageSibling(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs);
+
+ virtual EGLSyncImpl *createSync(const egl::AttributeMap &attribs);
+
+ virtual ShareGroupImpl *createShareGroup() = 0;
+
+ virtual GLuint getNextSurfaceID() = 0;
+};
+
+inline ExternalImageSiblingImpl *EGLImplFactory::createExternalImageSibling(
+ const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs)
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+inline EGLSyncImpl *EGLImplFactory::createSync(const egl::AttributeMap &attribs)
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_EGLIMPLFACTORY_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/EGLReusableSync.cpp b/gfx/angle/checkout/src/libANGLE/renderer/EGLReusableSync.cpp
new file mode 100644
index 0000000000..8441b028da
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/EGLReusableSync.cpp
@@ -0,0 +1,116 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// EGLReusableSync.cpp: Implements the egl::ReusableSync class.
+
+#include "libANGLE/renderer/EGLReusableSync.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/ContextImpl.h"
+
+namespace rx
+{
+
+ReusableSync::ReusableSync(const egl::AttributeMap &attribs)
+ : EGLSyncImpl(), mStatus(EGL_UNSIGNALED)
+{}
+
+void ReusableSync::onDestroy(const egl::Display *display) {}
+
+ReusableSync::~ReusableSync()
+{
+ // Release any waiting thread.
+ mCondVar.notify_all();
+}
+
+egl::Error ReusableSync::initialize(const egl::Display *display,
+ const gl::Context *context,
+ EGLenum type)
+{
+ return egl::NoError();
+}
+
+egl::Error ReusableSync::clientWait(const egl::Display *display,
+ const gl::Context *context,
+ EGLint flags,
+ EGLTime timeout,
+ EGLint *outResult)
+{
+ if (mStatus == EGL_SIGNALED)
+ {
+ *outResult = EGL_CONDITION_SATISFIED_KHR;
+ return egl::NoError();
+ }
+ if (((flags & EGL_SYNC_FLUSH_COMMANDS_BIT) != 0) && (context != nullptr))
+ {
+ angle::Result result = context->getImplementation()->flush(context);
+ if (result != angle::Result::Continue)
+ {
+ return ResultToEGL(result);
+ }
+ }
+ if (timeout == 0)
+ {
+ *outResult = EGL_TIMEOUT_EXPIRED_KHR;
+ return egl::NoError();
+ }
+
+ using NanoSeconds = std::chrono::duration<int64_t, std::nano>;
+ NanoSeconds duration = (timeout == EGL_FOREVER) ? NanoSeconds::max() : NanoSeconds(timeout);
+ std::cv_status waitStatus = std::cv_status::no_timeout;
+ mMutex.lock();
+ waitStatus = mCondVar.wait_for(mMutex, duration);
+ mMutex.unlock();
+
+ switch (waitStatus)
+ {
+ case std::cv_status::no_timeout: // Signaled.
+ *outResult = EGL_CONDITION_SATISFIED_KHR;
+ break;
+ case std::cv_status::timeout: // Timed-out.
+ *outResult = EGL_TIMEOUT_EXPIRED_KHR;
+ break;
+ default:
+ break;
+ }
+ return egl::NoError();
+}
+
+egl::Error ReusableSync::serverWait(const egl::Display *display,
+ const gl::Context *context,
+ EGLint flags)
+{
+ // Does not support server wait.
+ return egl::EglBadMatch();
+}
+
+egl::Error ReusableSync::signal(const egl::Display *display,
+ const gl::Context *context,
+ EGLint mode)
+{
+ if (mode == EGL_SIGNALED)
+ {
+ if (mStatus == EGL_UNSIGNALED)
+ {
+ // Release all threads.
+ mCondVar.notify_all();
+ }
+ mStatus = EGL_SIGNALED;
+ }
+ else
+ {
+ mStatus = EGL_UNSIGNALED;
+ }
+ return egl::NoError();
+}
+
+egl::Error ReusableSync::getStatus(const egl::Display *display, EGLint *outStatus)
+{
+ *outStatus = mStatus;
+ return egl::NoError();
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/EGLReusableSync.h b/gfx/angle/checkout/src/libANGLE/renderer/EGLReusableSync.h
new file mode 100644
index 0000000000..12c972565d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/EGLReusableSync.h
@@ -0,0 +1,54 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// EGL_KHR_reusable_sync
+
+#ifndef LIBANGLE_RENDERER_EGLREUSABLESYNC_H_
+#define LIBANGLE_RENDERER_EGLREUSABLESYNC_H_
+
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/renderer/EGLSyncImpl.h"
+
+#include "common/angleutils.h"
+
+#include <condition_variable>
+
+namespace rx
+{
+
+class ReusableSync final : public EGLSyncImpl
+{
+ public:
+ ReusableSync(const egl::AttributeMap &attribs);
+ ~ReusableSync() override;
+
+ void onDestroy(const egl::Display *display) override;
+
+ egl::Error initialize(const egl::Display *display,
+ const gl::Context *context,
+ EGLenum type) override;
+ egl::Error clientWait(const egl::Display *display,
+ const gl::Context *context,
+ EGLint flags,
+ EGLTime timeout,
+ EGLint *outResult) override;
+ egl::Error serverWait(const egl::Display *display,
+ const gl::Context *context,
+ EGLint flags) override;
+ egl::Error signal(const egl::Display *display,
+ const gl::Context *context,
+ EGLint mode) override;
+ egl::Error getStatus(const egl::Display *display, EGLint *outStatus) override;
+
+ private:
+ EGLint mStatus;
+ std::condition_variable mCondVar;
+ std::unique_lock<std::mutex> mMutex;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_EGLREUSABLESYNC_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/EGLSyncImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/EGLSyncImpl.cpp
new file mode 100644
index 0000000000..a62edce539
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/EGLSyncImpl.cpp
@@ -0,0 +1,37 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// EGLSyncImpl.cpp: Implements the rx::EGLSyncImpl class.
+
+#include "libANGLE/renderer/EGLReusableSync.h"
+
+#include "angle_gl.h"
+
+#include "common/utilities.h"
+
+namespace rx
+{
+
+egl::Error EGLSyncImpl::signal(const egl::Display *display, const gl::Context *context, EGLint mode)
+{
+ UNREACHABLE();
+ return egl::EglBadMatch();
+}
+
+egl::Error EGLSyncImpl::copyMetalSharedEventANGLE(const egl::Display *display,
+ void **eventOut) const
+{
+ UNREACHABLE();
+ return egl::EglBadMatch();
+}
+
+egl::Error EGLSyncImpl::dupNativeFenceFD(const egl::Display *display, EGLint *fdOut) const
+{
+ UNREACHABLE();
+ return egl::EglBadMatch();
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/EGLSyncImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/EGLSyncImpl.h
new file mode 100644
index 0000000000..1dee6d315b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/EGLSyncImpl.h
@@ -0,0 +1,57 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// EGLSyncImpl.h: Defines the rx::EGLSyncImpl class.
+
+#ifndef LIBANGLE_RENDERER_EGLSYNCIMPL_H_
+#define LIBANGLE_RENDERER_EGLSYNCIMPL_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+namespace egl
+{
+class Display;
+} // namespace egl
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace rx
+{
+class EGLSyncImpl : angle::NonCopyable
+{
+ public:
+ EGLSyncImpl() {}
+ virtual ~EGLSyncImpl() {}
+
+ virtual void onDestroy(const egl::Display *display) {}
+
+ virtual egl::Error initialize(const egl::Display *display,
+ const gl::Context *context,
+ EGLenum type) = 0;
+ virtual egl::Error clientWait(const egl::Display *display,
+ const gl::Context *context,
+ EGLint flags,
+ EGLTime timeout,
+ EGLint *outResult) = 0;
+ virtual egl::Error serverWait(const egl::Display *display,
+ const gl::Context *context,
+ EGLint flags) = 0;
+ virtual egl::Error signal(const egl::Display *display, const gl::Context *context, EGLint mode);
+ virtual egl::Error getStatus(const egl::Display *display, EGLint *outStatus) = 0;
+ virtual egl::Error copyMetalSharedEventANGLE(const egl::Display *display,
+ void **outEvent) const;
+ virtual egl::Error dupNativeFenceFD(const egl::Display *display, EGLint *fdOut) const;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_EGLSYNCIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/FenceNVImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/FenceNVImpl.h
new file mode 100644
index 0000000000..99c002ad2e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/FenceNVImpl.h
@@ -0,0 +1,38 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FenceNVImpl.h: Defines the rx::FenceNVImpl class.
+
+#ifndef LIBANGLE_RENDERER_FENCENVIMPL_H_
+#define LIBANGLE_RENDERER_FENCENVIMPL_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace rx
+{
+class FenceNVImpl : angle::NonCopyable
+{
+ public:
+ FenceNVImpl() {}
+ virtual ~FenceNVImpl() {}
+
+ virtual void onDestroy(const gl::Context *context) = 0;
+ virtual angle::Result set(const gl::Context *context, GLenum condition) = 0;
+ virtual angle::Result test(const gl::Context *context, GLboolean *outFinished) = 0;
+ virtual angle::Result finish(const gl::Context *context) = 0;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_FENCENVIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/Format.h b/gfx/angle/checkout/src/libANGLE/renderer/Format.h
new file mode 100644
index 0000000000..1974381f53
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/Format.h
@@ -0,0 +1,238 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Format:
+// A universal description of typed GPU storage. Across multiple
+// renderer back-ends, there are common formats and some distinct
+// permutations, this enum encapsulates them all. Formats apply to
+// textures, but could also apply to any typed data.
+
+#ifndef LIBANGLE_RENDERER_FORMAT_H_
+#define LIBANGLE_RENDERER_FORMAT_H_
+
+#include "libANGLE/renderer/FormatID_autogen.h"
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace angle
+{
+enum class FormatID;
+
+extern const Format gFormatInfoTable[];
+
+struct Format final : private angle::NonCopyable
+{
+ inline constexpr Format(FormatID id,
+ GLenum glFormat,
+ GLenum fboFormat,
+ rx::MipGenerationFunction mipGen,
+ const rx::FastCopyFunctionMap &fastCopyFunctions,
+ rx::PixelReadFunction colorRead,
+ rx::PixelWriteFunction colorWrite,
+ GLenum componentType,
+ GLuint redBits,
+ GLuint greenBits,
+ GLuint blueBits,
+ GLuint alphaBits,
+ GLuint luminanceBits,
+ GLuint depthBits,
+ GLuint stencilBits,
+ GLuint pixelBytes,
+ GLuint componentAlignmentMask,
+ bool isBlock,
+ bool isFixed,
+ bool isScaled,
+ bool isSRGB,
+ bool isYUV,
+ gl::VertexAttribType vertexAttribType);
+
+ static const Format &Get(FormatID id) { return gFormatInfoTable[static_cast<int>(id)]; }
+
+ static FormatID InternalFormatToID(GLenum internalFormat);
+
+ constexpr bool hasDepthOrStencilBits() const;
+ constexpr bool isLUMA() const;
+ constexpr bool isBGRA() const;
+
+ constexpr bool isSint() const;
+ constexpr bool isUint() const;
+ constexpr bool isSnorm() const;
+ constexpr bool isUnorm() const;
+ constexpr bool isFloat() const;
+ constexpr bool isVertexTypeHalfFloat() const;
+
+ constexpr bool isInt() const { return isSint() || isUint(); }
+ constexpr bool isNorm() const { return isSnorm() || isUnorm(); }
+ constexpr bool isPureInt() const { return isInt() && !isScaled; }
+
+ bool operator==(const Format &other) const { return this->id == other.id; }
+
+ FormatID id;
+
+ // The closest matching GL internal format for the storage this format uses. Note that this
+ // may be a different internal format than the one this ANGLE format is used for.
+ GLenum glInternalFormat;
+
+ // The format we should report to the GL layer when querying implementation formats from a FBO.
+ // This might not be the same as the glInternalFormat, since some DXGI formats don't have
+ // matching GL format enums, like BGRA4, BGR5A1 and B5G6R6.
+ GLenum fboImplementationInternalFormat;
+
+ rx::MipGenerationFunction mipGenerationFunction;
+ rx::PixelReadFunction pixelReadFunction;
+ rx::PixelWriteFunction pixelWriteFunction;
+
+ // A map from a gl::FormatType to a fast pixel copy function for this format.
+ const rx::FastCopyFunctionMap &fastCopyFunctions;
+
+ GLenum componentType;
+
+ GLuint redBits;
+ GLuint greenBits;
+ GLuint blueBits;
+ GLuint alphaBits;
+ GLuint luminanceBits;
+ GLuint depthBits;
+ GLuint stencilBits;
+
+ GLuint pixelBytes;
+
+ // For 1-byte components, is 0x0. For 2-byte, is 0x1. For 4-byte, is 0x3. For all others,
+ // MAX_UINT.
+ GLuint componentAlignmentMask;
+
+ GLuint channelCount;
+
+ bool isBlock;
+ bool isFixed;
+ bool isScaled;
+ bool isSRGB;
+ bool isYUV;
+
+ // For vertex formats only. Returns the "type" value for glVertexAttribPointer etc.
+ gl::VertexAttribType vertexAttribType;
+};
+
+constexpr GLuint GetChannelCount(GLuint redBits,
+ GLuint greenBits,
+ GLuint blueBits,
+ GLuint alphaBits,
+ GLuint luminanceBits,
+ GLuint depthBits,
+ GLuint stencilBits)
+{
+ return (redBits > 0 ? 1 : 0) + (greenBits > 0 ? 1 : 0) + (blueBits > 0 ? 1 : 0) +
+ (alphaBits > 0 ? 1 : 0) + (luminanceBits > 0 ? 1 : 0) + (depthBits > 0 ? 1 : 0) +
+ (stencilBits > 0 ? 1 : 0);
+}
+
+constexpr Format::Format(FormatID id,
+ GLenum glFormat,
+ GLenum fboFormat,
+ rx::MipGenerationFunction mipGen,
+ const rx::FastCopyFunctionMap &fastCopyFunctions,
+ rx::PixelReadFunction colorRead,
+ rx::PixelWriteFunction colorWrite,
+ GLenum componentType,
+ GLuint redBits,
+ GLuint greenBits,
+ GLuint blueBits,
+ GLuint alphaBits,
+ GLuint luminanceBits,
+ GLuint depthBits,
+ GLuint stencilBits,
+ GLuint pixelBytes,
+ GLuint componentAlignmentMask,
+ bool isBlock,
+ bool isFixed,
+ bool isScaled,
+ bool isSRGB,
+ bool isYUV,
+ gl::VertexAttribType vertexAttribType)
+ : id(id),
+ glInternalFormat(glFormat),
+ fboImplementationInternalFormat(fboFormat),
+ mipGenerationFunction(mipGen),
+ pixelReadFunction(colorRead),
+ pixelWriteFunction(colorWrite),
+ fastCopyFunctions(fastCopyFunctions),
+ componentType(componentType),
+ redBits(redBits),
+ greenBits(greenBits),
+ blueBits(blueBits),
+ alphaBits(alphaBits),
+ luminanceBits(luminanceBits),
+ depthBits(depthBits),
+ stencilBits(stencilBits),
+ pixelBytes(pixelBytes),
+ componentAlignmentMask(componentAlignmentMask),
+ channelCount(GetChannelCount(redBits,
+ greenBits,
+ blueBits,
+ alphaBits,
+ luminanceBits,
+ depthBits,
+ stencilBits)),
+ isBlock(isBlock),
+ isFixed(isFixed),
+ isScaled(isScaled),
+ isSRGB(isSRGB),
+ isYUV(isYUV),
+ vertexAttribType(vertexAttribType)
+{}
+
+constexpr bool Format::hasDepthOrStencilBits() const
+{
+ return depthBits > 0 || stencilBits > 0;
+}
+
+constexpr bool Format::isLUMA() const
+{
+ // There's no format with G or B without R
+ ASSERT(redBits > 0 || (greenBits == 0 && blueBits == 0));
+ return redBits == 0 && (luminanceBits > 0 || alphaBits > 0);
+}
+
+constexpr bool Format::isBGRA() const
+{
+ return id == FormatID::B8G8R8A8_UNORM || id == FormatID::B8G8R8A8_UNORM_SRGB ||
+ id == FormatID::B8G8R8A8_TYPELESS || id == FormatID::B8G8R8A8_TYPELESS_SRGB;
+}
+
+constexpr bool Format::isSint() const
+{
+ return componentType == GL_INT;
+}
+
+constexpr bool Format::isUint() const
+{
+ return componentType == GL_UNSIGNED_INT;
+}
+
+constexpr bool Format::isSnorm() const
+{
+ return componentType == GL_SIGNED_NORMALIZED;
+}
+
+constexpr bool Format::isUnorm() const
+{
+ return componentType == GL_UNSIGNED_NORMALIZED;
+}
+
+constexpr bool Format::isFloat() const
+{
+ return componentType == GL_FLOAT;
+}
+
+constexpr bool Format::isVertexTypeHalfFloat() const
+{
+ return vertexAttribType == gl::VertexAttribType::HalfFloat;
+}
+
+template <typename T>
+using FormatMap = PackedEnumMap<FormatID, T, kNumANGLEFormats>;
+
+} // namespace angle
+
+#endif // LIBANGLE_RENDERER_FORMAT_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/FormatID_autogen.h b/gfx/angle/checkout/src/libANGLE/renderer/FormatID_autogen.h
new file mode 100644
index 0000000000..1e6ded8001
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/FormatID_autogen.h
@@ -0,0 +1,264 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_angle_format_table.py using data from angle_format_data.json
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ANGLE format enumeration.
+
+#ifndef LIBANGLE_RENDERER_FORMATID_H_
+#define LIBANGLE_RENDERER_FORMATID_H_
+
+#include <cstdint>
+
+namespace angle
+{
+
+enum class FormatID
+{
+ NONE,
+ D16_UNORM,
+ D24_UNORM_S8_UINT,
+ D24_UNORM_X8_UINT,
+ D32_FLOAT,
+ D32_FLOAT_S8X24_UINT,
+ D32_UNORM,
+ S8_UINT,
+ A16_FLOAT,
+ A1R5G5B5_UNORM,
+ A2R10G10B10_SINT_VERTEX,
+ A2R10G10B10_SNORM_VERTEX,
+ A2R10G10B10_SSCALED_VERTEX,
+ A2R10G10B10_UINT_VERTEX,
+ A2R10G10B10_UNORM_VERTEX,
+ A2R10G10B10_USCALED_VERTEX,
+ A32_FLOAT,
+ A8_UNORM,
+ ASTC_10x10_SRGB_BLOCK,
+ ASTC_10x10_UNORM_BLOCK,
+ ASTC_10x5_SRGB_BLOCK,
+ ASTC_10x5_UNORM_BLOCK,
+ ASTC_10x6_SRGB_BLOCK,
+ ASTC_10x6_UNORM_BLOCK,
+ ASTC_10x8_SRGB_BLOCK,
+ ASTC_10x8_UNORM_BLOCK,
+ ASTC_12x10_SRGB_BLOCK,
+ ASTC_12x10_UNORM_BLOCK,
+ ASTC_12x12_SRGB_BLOCK,
+ ASTC_12x12_UNORM_BLOCK,
+ ASTC_3x3x3_UNORM_BLOCK,
+ ASTC_3x3x3_UNORM_SRGB_BLOCK,
+ ASTC_4x3x3_UNORM_BLOCK,
+ ASTC_4x3x3_UNORM_SRGB_BLOCK,
+ ASTC_4x4_SRGB_BLOCK,
+ ASTC_4x4_UNORM_BLOCK,
+ ASTC_4x4x3_UNORM_BLOCK,
+ ASTC_4x4x3_UNORM_SRGB_BLOCK,
+ ASTC_4x4x4_UNORM_BLOCK,
+ ASTC_4x4x4_UNORM_SRGB_BLOCK,
+ ASTC_5x4_SRGB_BLOCK,
+ ASTC_5x4_UNORM_BLOCK,
+ ASTC_5x4x4_UNORM_BLOCK,
+ ASTC_5x4x4_UNORM_SRGB_BLOCK,
+ ASTC_5x5_SRGB_BLOCK,
+ ASTC_5x5_UNORM_BLOCK,
+ ASTC_5x5x4_UNORM_BLOCK,
+ ASTC_5x5x4_UNORM_SRGB_BLOCK,
+ ASTC_5x5x5_UNORM_BLOCK,
+ ASTC_5x5x5_UNORM_SRGB_BLOCK,
+ ASTC_6x5_SRGB_BLOCK,
+ ASTC_6x5_UNORM_BLOCK,
+ ASTC_6x5x5_UNORM_BLOCK,
+ ASTC_6x5x5_UNORM_SRGB_BLOCK,
+ ASTC_6x6_SRGB_BLOCK,
+ ASTC_6x6_UNORM_BLOCK,
+ ASTC_6x6x5_UNORM_BLOCK,
+ ASTC_6x6x5_UNORM_SRGB_BLOCK,
+ ASTC_6x6x6_UNORM_BLOCK,
+ ASTC_6x6x6_UNORM_SRGB_BLOCK,
+ ASTC_8x5_SRGB_BLOCK,
+ ASTC_8x5_UNORM_BLOCK,
+ ASTC_8x6_SRGB_BLOCK,
+ ASTC_8x6_UNORM_BLOCK,
+ ASTC_8x8_SRGB_BLOCK,
+ ASTC_8x8_UNORM_BLOCK,
+ B10G10R10A2_UNORM,
+ B4G4R4A4_UNORM,
+ B5G5R5A1_UNORM,
+ B5G6R5_UNORM,
+ B8G8R8A8_TYPELESS,
+ B8G8R8A8_TYPELESS_SRGB,
+ B8G8R8A8_UNORM,
+ B8G8R8A8_UNORM_SRGB,
+ B8G8R8X8_UNORM,
+ BC1_RGBA_UNORM_BLOCK,
+ BC1_RGBA_UNORM_SRGB_BLOCK,
+ BC1_RGB_UNORM_BLOCK,
+ BC1_RGB_UNORM_SRGB_BLOCK,
+ BC2_RGBA_UNORM_BLOCK,
+ BC2_RGBA_UNORM_SRGB_BLOCK,
+ BC3_RGBA_UNORM_BLOCK,
+ BC3_RGBA_UNORM_SRGB_BLOCK,
+ BC4_RED_SNORM_BLOCK,
+ BC4_RED_UNORM_BLOCK,
+ BC5_RG_SNORM_BLOCK,
+ BC5_RG_UNORM_BLOCK,
+ BC6H_RGB_SFLOAT_BLOCK,
+ BC6H_RGB_UFLOAT_BLOCK,
+ BC7_RGBA_UNORM_BLOCK,
+ BC7_RGBA_UNORM_SRGB_BLOCK,
+ EAC_R11G11_SNORM_BLOCK,
+ EAC_R11G11_UNORM_BLOCK,
+ EAC_R11_SNORM_BLOCK,
+ EAC_R11_UNORM_BLOCK,
+ ETC1_LOSSY_DECODE_R8G8B8_UNORM_BLOCK,
+ ETC1_R8G8B8_UNORM_BLOCK,
+ ETC2_R8G8B8A1_SRGB_BLOCK,
+ ETC2_R8G8B8A1_UNORM_BLOCK,
+ ETC2_R8G8B8A8_SRGB_BLOCK,
+ ETC2_R8G8B8A8_UNORM_BLOCK,
+ ETC2_R8G8B8_SRGB_BLOCK,
+ ETC2_R8G8B8_UNORM_BLOCK,
+ G8_B8R8_2PLANE_420_UNORM,
+ G8_B8_R8_3PLANE_420_UNORM,
+ L16A16_FLOAT,
+ L16_FLOAT,
+ L32A32_FLOAT,
+ L32_FLOAT,
+ L8A8_UNORM,
+ L8_UNORM,
+ PALETTE4_R4G4B4A4_UNORM,
+ PALETTE4_R5G5B5A1_UNORM,
+ PALETTE4_R5G6B5_UNORM,
+ PALETTE4_R8G8B8A8_UNORM,
+ PALETTE4_R8G8B8_UNORM,
+ PALETTE8_R4G4B4A4_UNORM,
+ PALETTE8_R5G5B5A1_UNORM,
+ PALETTE8_R5G6B5_UNORM,
+ PALETTE8_R8G8B8A8_UNORM,
+ PALETTE8_R8G8B8_UNORM,
+ PVRTC1_RGBA_2BPP_UNORM_BLOCK,
+ PVRTC1_RGBA_2BPP_UNORM_SRGB_BLOCK,
+ PVRTC1_RGBA_4BPP_UNORM_BLOCK,
+ PVRTC1_RGBA_4BPP_UNORM_SRGB_BLOCK,
+ PVRTC1_RGB_2BPP_UNORM_BLOCK,
+ PVRTC1_RGB_2BPP_UNORM_SRGB_BLOCK,
+ PVRTC1_RGB_4BPP_UNORM_BLOCK,
+ PVRTC1_RGB_4BPP_UNORM_SRGB_BLOCK,
+ R10G10B10A2_SINT,
+ R10G10B10A2_SNORM,
+ R10G10B10A2_SSCALED,
+ R10G10B10A2_UINT,
+ R10G10B10A2_UNORM,
+ R10G10B10A2_USCALED,
+ R10G10B10X2_UNORM,
+ R11G11B10_FLOAT,
+ R16G16B16A16_FLOAT,
+ R16G16B16A16_SINT,
+ R16G16B16A16_SNORM,
+ R16G16B16A16_SSCALED,
+ R16G16B16A16_UINT,
+ R16G16B16A16_UNORM,
+ R16G16B16A16_USCALED,
+ R16G16B16_FLOAT,
+ R16G16B16_SINT,
+ R16G16B16_SNORM,
+ R16G16B16_SSCALED,
+ R16G16B16_UINT,
+ R16G16B16_UNORM,
+ R16G16B16_USCALED,
+ R16G16_FLOAT,
+ R16G16_SINT,
+ R16G16_SNORM,
+ R16G16_SSCALED,
+ R16G16_UINT,
+ R16G16_UNORM,
+ R16G16_USCALED,
+ R16_FLOAT,
+ R16_SINT,
+ R16_SNORM,
+ R16_SSCALED,
+ R16_UINT,
+ R16_UNORM,
+ R16_USCALED,
+ R32G32B32A32_FIXED,
+ R32G32B32A32_FLOAT,
+ R32G32B32A32_SINT,
+ R32G32B32A32_SNORM,
+ R32G32B32A32_SSCALED,
+ R32G32B32A32_UINT,
+ R32G32B32A32_UNORM,
+ R32G32B32A32_USCALED,
+ R32G32B32_FIXED,
+ R32G32B32_FLOAT,
+ R32G32B32_SINT,
+ R32G32B32_SNORM,
+ R32G32B32_SSCALED,
+ R32G32B32_UINT,
+ R32G32B32_UNORM,
+ R32G32B32_USCALED,
+ R32G32_FIXED,
+ R32G32_FLOAT,
+ R32G32_SINT,
+ R32G32_SNORM,
+ R32G32_SSCALED,
+ R32G32_UINT,
+ R32G32_UNORM,
+ R32G32_USCALED,
+ R32_FIXED,
+ R32_FLOAT,
+ R32_SINT,
+ R32_SNORM,
+ R32_SSCALED,
+ R32_UINT,
+ R32_UNORM,
+ R32_USCALED,
+ R4G4B4A4_UNORM,
+ R5G5B5A1_UNORM,
+ R5G6B5_UNORM,
+ R8G8B8A8_SINT,
+ R8G8B8A8_SNORM,
+ R8G8B8A8_SSCALED,
+ R8G8B8A8_TYPELESS,
+ R8G8B8A8_TYPELESS_SRGB,
+ R8G8B8A8_UINT,
+ R8G8B8A8_UNORM,
+ R8G8B8A8_UNORM_SRGB,
+ R8G8B8A8_USCALED,
+ R8G8B8X8_UNORM,
+ R8G8B8_SINT,
+ R8G8B8_SNORM,
+ R8G8B8_SSCALED,
+ R8G8B8_UINT,
+ R8G8B8_UNORM,
+ R8G8B8_UNORM_SRGB,
+ R8G8B8_USCALED,
+ R8G8_SINT,
+ R8G8_SNORM,
+ R8G8_SSCALED,
+ R8G8_UINT,
+ R8G8_UNORM,
+ R8G8_UNORM_SRGB,
+ R8G8_USCALED,
+ R8_SINT,
+ R8_SNORM,
+ R8_SSCALED,
+ R8_UINT,
+ R8_UNORM,
+ R8_UNORM_SRGB,
+ R8_USCALED,
+ R9G9B9E5_SHAREDEXP,
+ X2R10G10B10_SINT_VERTEX,
+ X2R10G10B10_SNORM_VERTEX,
+ X2R10G10B10_SSCALED_VERTEX,
+ X2R10G10B10_UINT_VERTEX,
+ X2R10G10B10_UNORM_VERTEX,
+ X2R10G10B10_USCALED_VERTEX
+};
+
+constexpr uint32_t kNumANGLEFormats = 238;
+
+} // namespace angle
+
+#endif // LIBANGLE_RENDERER_FORMATID_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/Format_table_autogen.cpp b/gfx/angle/checkout/src/libANGLE/renderer/Format_table_autogen.cpp
new file mode 100644
index 0000000000..df700ab74f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/Format_table_autogen.cpp
@@ -0,0 +1,762 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_angle_format_table.py using data from angle_format_data.json
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ANGLE Format table:
+// Queries for typed format information from the ANGLE format enum.
+
+#include "libANGLE/renderer/Format.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+namespace angle
+{
+
+static constexpr rx::FastCopyFunctionMap::Entry BGRAEntry = {angle::FormatID::R8G8B8A8_UNORM,
+ CopyBGRA8ToRGBA8};
+static constexpr rx::FastCopyFunctionMap BGRACopyFunctions = {&BGRAEntry, 1};
+static constexpr rx::FastCopyFunctionMap NoCopyFunctions;
+
+const Format gFormatInfoTable[] = {
+ // clang-format off
+ { FormatID::NONE, GL_NONE, GL_NONE, nullptr, NoCopyFunctions, nullptr, nullptr, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::D16_UNORM, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT16, nullptr, NoCopyFunctions, ReadDepthStencil<D16>, WriteDepthStencil<D16>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 16, 0, 2, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, nullptr, NoCopyFunctions, ReadDepthStencil<D24S8>, WriteDepthStencil<D24S8>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 24, 8, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::D24_UNORM_X8_UINT, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT24, nullptr, NoCopyFunctions, ReadDepthStencil<D24X8>, WriteDepthStencil<D24X8>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 24, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::D32_FLOAT, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT32F, nullptr, NoCopyFunctions, ReadDepthStencil<D32F>, WriteDepthStencil<D32F>, GL_FLOAT, 0, 0, 0, 0, 0, 32, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::Float },
+ { FormatID::D32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8, GL_DEPTH32F_STENCIL8, nullptr, NoCopyFunctions, ReadDepthStencil<D32FS8X24>, WriteDepthStencil<D32FS8X24>, GL_FLOAT, 0, 0, 0, 0, 0, 32, 8, 8, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::Float },
+ { FormatID::D32_UNORM, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT32_OES, nullptr, NoCopyFunctions, ReadDepthStencil<D32>, WriteDepthStencil<D32>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 32, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::S8_UINT, GL_STENCIL_INDEX8, GL_STENCIL_INDEX8, nullptr, NoCopyFunctions, ReadDepthStencil<S8>, WriteDepthStencil<S8>, GL_UNSIGNED_INT, 0, 0, 0, 0, 0, 0, 8, 1, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::A16_FLOAT, GL_ALPHA16F_EXT, GL_ALPHA16F_EXT, GenerateMip<A16F>, NoCopyFunctions, ReadColor<A16F, GLfloat>, WriteColor<A16F, GLfloat>, GL_FLOAT, 0, 0, 0, 16, 0, 0, 0, 2, 1, false, false, false, false, false, gl::VertexAttribType::Float },
+ { FormatID::A1R5G5B5_UNORM, GL_A1RGB5_ANGLEX, GL_A1RGB5_ANGLEX, GenerateMip<A1R5G5B5>, NoCopyFunctions, ReadColor<A1R5G5B5, GLfloat>, WriteColor<A1R5G5B5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 5, 5, 1, 0, 0, 0, 2, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::A2R10G10B10_SINT_VERTEX, GL_INT_10_10_10_2_OES, GL_INT_10_10_10_2_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_INT, 10, 10, 10, 2, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::Int1010102 },
+ { FormatID::A2R10G10B10_SNORM_VERTEX, GL_A2_RGB10_SNORM_ANGLEX, GL_A2_RGB10_SNORM_ANGLEX, nullptr, NoCopyFunctions, nullptr, nullptr, GL_SIGNED_NORMALIZED, 10, 10, 10, 2, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::Int1010102 },
+ { FormatID::A2R10G10B10_SSCALED_VERTEX, GL_A2_RGB10_SSCALED_ANGLEX, GL_A2_RGB10_SSCALED_ANGLEX, nullptr, NoCopyFunctions, nullptr, nullptr, GL_INT, 10, 10, 10, 2, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, true, false, false, gl::VertexAttribType::Int1010102 },
+ { FormatID::A2R10G10B10_UINT_VERTEX, GL_UNSIGNED_INT_10_10_10_2_OES, GL_UNSIGNED_INT_10_10_10_2_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_INT, 10, 10, 10, 2, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedInt1010102 },
+ { FormatID::A2R10G10B10_UNORM_VERTEX, GL_A2_RGB10_UNORM_ANGLEX, GL_A2_RGB10_UNORM_ANGLEX, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 10, 10, 10, 2, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedInt1010102 },
+ { FormatID::A2R10G10B10_USCALED_VERTEX, GL_A2_RGB10_USCALED_ANGLEX, GL_A2_RGB10_USCALED_ANGLEX, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_INT, 10, 10, 10, 2, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, true, false, false, gl::VertexAttribType::UnsignedInt1010102 },
+ { FormatID::A32_FLOAT, GL_ALPHA32F_EXT, GL_ALPHA32F_EXT, GenerateMip<A32F>, NoCopyFunctions, ReadColor<A32F, GLfloat>, WriteColor<A32F, GLfloat>, GL_FLOAT, 0, 0, 0, 32, 0, 0, 0, 4, 3, false, false, false, false, false, gl::VertexAttribType::Float },
+ { FormatID::A8_UNORM, GL_ALPHA8_EXT, GL_ALPHA8_EXT, GenerateMip<A8>, NoCopyFunctions, ReadColor<A8, GLfloat>, WriteColor<A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 8, 0, 0, 0, 1, 0, false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_10x10_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_10x10_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_10x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_10x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_10x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_10x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_10x8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_10x8_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_12x10_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_12x10_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_12x12_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_12x12_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_3x3x3_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_3x3x3_OES, GL_COMPRESSED_RGBA_ASTC_3x3x3_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_3x3x3_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_4x3x3_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_4x3x3_OES, GL_COMPRESSED_RGBA_ASTC_4x3x3_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_4x3x3_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_4x4_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_4x4_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_4x4x3_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_4x4x3_OES, GL_COMPRESSED_RGBA_ASTC_4x4x3_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_4x4x3_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_4x4x4_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_4x4x4_OES, GL_COMPRESSED_RGBA_ASTC_4x4x4_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_4x4x4_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_5x4_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_5x4_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_5x4x4_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_5x4x4_OES, GL_COMPRESSED_RGBA_ASTC_5x4x4_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_5x4x4_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_5x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_5x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_5x5x4_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_5x5x4_OES, GL_COMPRESSED_RGBA_ASTC_5x5x4_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_5x5x4_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_5x5x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_5x5x5_OES, GL_COMPRESSED_RGBA_ASTC_5x5x5_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_5x5x5_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_6x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_6x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_6x5x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_6x5x5_OES, GL_COMPRESSED_RGBA_ASTC_6x5x5_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_6x5x5_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_6x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_6x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_6x6x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_6x6x5_OES, GL_COMPRESSED_RGBA_ASTC_6x6x5_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_6x6x5_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_6x6x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_6x6x6_OES, GL_COMPRESSED_RGBA_ASTC_6x6x6_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_6x6x6_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_8x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_8x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_8x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_8x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_8x8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ASTC_8x8_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::B10G10R10A2_UNORM, GL_BGR10_A2_ANGLEX, GL_BGR10_A2_ANGLEX, GenerateMip<B10G10R10A2>, NoCopyFunctions, ReadColor<B10G10R10A2, GLfloat>, WriteColor<B10G10R10A2, GLfloat>, GL_UNSIGNED_NORMALIZED, 10, 10, 10, 2, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedInt2101010 },
+ { FormatID::B4G4R4A4_UNORM, GL_BGRA4_ANGLEX, GL_RGBA4, GenerateMip<A4R4G4B4>, NoCopyFunctions, ReadColor<A4R4G4B4, GLfloat>, WriteColor<A4R4G4B4, GLfloat>, GL_UNSIGNED_NORMALIZED, 4, 4, 4, 4, 0, 0, 0, 2, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::B5G5R5A1_UNORM, GL_BGR5_A1_ANGLEX, GL_RGB5_A1, GenerateMip<A1R5G5B5>, NoCopyFunctions, ReadColor<A1R5G5B5, GLfloat>, WriteColor<A1R5G5B5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 5, 5, 1, 0, 0, 0, 2, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::B5G6R5_UNORM, GL_BGR565_ANGLEX, GL_RGB565, GenerateMip<B5G6R5>, NoCopyFunctions, ReadColor<B5G6R5, GLfloat>, WriteColor<B5G6R5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 6, 5, 0, 0, 0, 0, 2, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::B8G8R8A8_TYPELESS, GL_BGRA8_EXT, GL_BGRA8_EXT, GenerateMip<B8G8R8A8>, NoCopyFunctions, ReadColor<B8G8R8A8, GLfloat>, WriteColor<B8G8R8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::B8G8R8A8_TYPELESS_SRGB, GL_BGRA8_SRGB_ANGLEX, GL_BGRA8_SRGB_ANGLEX, GenerateMip<B8G8R8A8>, NoCopyFunctions, ReadColor<B8G8R8A8, GLfloat>, WriteColor<B8G8R8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, true, false, gl::VertexAttribType::Byte },
+ { FormatID::B8G8R8A8_UNORM, GL_BGRA8_EXT, GL_BGRA8_EXT, GenerateMip<B8G8R8A8>, BGRACopyFunctions, ReadColor<B8G8R8A8, GLfloat>, WriteColor<B8G8R8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::B8G8R8A8_UNORM_SRGB, GL_BGRA8_SRGB_ANGLEX, GL_BGRA8_SRGB_ANGLEX, GenerateMip<B8G8R8A8>, NoCopyFunctions, ReadColor<B8G8R8A8, GLfloat>, WriteColor<B8G8R8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, true, false, gl::VertexAttribType::Byte },
+ { FormatID::B8G8R8X8_UNORM, GL_BGRA8_EXT, GL_BGRA8_EXT, GenerateMip<B8G8R8X8>, NoCopyFunctions, ReadColor<B8G8R8X8, GLfloat>, WriteColor<B8G8R8X8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::BC1_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::BC1_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::BC1_RGB_UNORM_BLOCK, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::BC1_RGB_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::BC2_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::BC2_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::BC3_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::BC3_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::BC4_RED_SNORM_BLOCK, GL_COMPRESSED_SIGNED_RED_RGTC1_EXT, GL_COMPRESSED_SIGNED_RED_RGTC1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_SIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::BC4_RED_UNORM_BLOCK, GL_COMPRESSED_RED_RGTC1_EXT, GL_COMPRESSED_RED_RGTC1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::BC5_RG_SNORM_BLOCK, GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_SIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::BC5_RG_UNORM_BLOCK, GL_COMPRESSED_RED_GREEN_RGTC2_EXT, GL_COMPRESSED_RED_GREEN_RGTC2_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::BC6H_RGB_SFLOAT_BLOCK, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_FLOAT, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::BC6H_RGB_UFLOAT_BLOCK, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_FLOAT, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::BC7_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::BC7_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::EAC_R11G11_SNORM_BLOCK, GL_COMPRESSED_SIGNED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_SIGNED_NORMALIZED, 11, 11, 0, 0, 0, 0, 0, 16, 0, true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::EAC_R11G11_UNORM_BLOCK, GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_RG11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 11, 11, 0, 0, 0, 0, 0, 16, 0, true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::EAC_R11_SNORM_BLOCK, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_SIGNED_NORMALIZED, 11, 0, 0, 0, 0, 0, 0, 8, 0, true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::EAC_R11_UNORM_BLOCK, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 11, 0, 0, 0, 0, 0, 0, 8, 0, true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::ETC1_LOSSY_DECODE_R8G8B8_UNORM_BLOCK, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 8, 0, true, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::ETC1_R8G8B8_UNORM_BLOCK, GL_ETC1_RGB8_OES, GL_ETC1_RGB8_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 8, 0, true, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::ETC2_R8G8B8A1_SRGB_BLOCK, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 1, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::Byte },
+ { FormatID::ETC2_R8G8B8A1_UNORM_BLOCK, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 1, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::ETC2_R8G8B8A8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 16, 0, true, false, false, true, false, gl::VertexAttribType::Byte },
+ { FormatID::ETC2_R8G8B8A8_UNORM_BLOCK, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 16, 0, true, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::ETC2_R8G8B8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 8, 0, true, false, false, true, false, gl::VertexAttribType::Byte },
+ { FormatID::ETC2_R8G8B8_UNORM_BLOCK, GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 8, 0, true, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::G8_B8R8_2PLANE_420_UNORM, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLfloat>, WriteColor<R8G8B8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 3, 0, false, false, false, false, true, gl::VertexAttribType::UnsignedByte },
+ { FormatID::G8_B8_R8_3PLANE_420_UNORM, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLfloat>, WriteColor<R8G8B8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 3, 0, false, false, false, false, true, gl::VertexAttribType::UnsignedByte },
+ { FormatID::L16A16_FLOAT, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA16F_EXT, GenerateMip<L16A16F>, NoCopyFunctions, ReadColor<L16A16F, GLfloat>, WriteColor<L16A16F, GLfloat>, GL_FLOAT, 0, 0, 0, 16, 16, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::Float },
+ { FormatID::L16_FLOAT, GL_LUMINANCE16F_EXT, GL_LUMINANCE16F_EXT, GenerateMip<L16F>, NoCopyFunctions, ReadColor<L16F, GLfloat>, WriteColor<L16F, GLfloat>, GL_FLOAT, 0, 0, 0, 0, 16, 0, 0, 2, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::Float },
+ { FormatID::L32A32_FLOAT, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA32F_EXT, GenerateMip<L32A32F>, NoCopyFunctions, ReadColor<L32A32F, GLfloat>, WriteColor<L32A32F, GLfloat>, GL_FLOAT, 0, 0, 0, 32, 32, 0, 0, 8, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::Float },
+ { FormatID::L32_FLOAT, GL_LUMINANCE32F_EXT, GL_LUMINANCE32F_EXT, GenerateMip<L32F>, NoCopyFunctions, ReadColor<L32F, GLfloat>, WriteColor<L32F, GLfloat>, GL_FLOAT, 0, 0, 0, 0, 32, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::Float },
+ { FormatID::L8A8_UNORM, GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip<L8A8>, NoCopyFunctions, ReadColor<L8A8, GLfloat>, WriteColor<L8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 8, 8, 0, 0, 2, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::L8_UNORM, GL_LUMINANCE8_EXT, GL_LUMINANCE8_EXT, GenerateMip<L8>, NoCopyFunctions, ReadColor<L8, GLfloat>, WriteColor<L8, GLfloat>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 8, 0, 0, 1, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::PALETTE4_R4G4B4A4_UNORM, GL_PALETTE4_RGBA4_OES, GL_PALETTE4_RGBA4_OES, GenerateMip<R4G4B4A4>, NoCopyFunctions, ReadColor<R4G4B4A4, GLfloat>, WriteColor<R4G4B4A4, GLfloat>, GL_UNSIGNED_NORMALIZED, 4, 4, 4, 4, 0, 0, 0, 3, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::PALETTE4_R5G5B5A1_UNORM, GL_PALETTE4_RGB5_A1_OES, GL_PALETTE4_RGB5_A1_OES, GenerateMip<R5G5B5A1>, NoCopyFunctions, ReadColor<R5G5B5A1, GLfloat>, WriteColor<R5G5B5A1, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 5, 5, 1, 0, 0, 0, 3, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::PALETTE4_R5G6B5_UNORM, GL_PALETTE4_R5_G6_B5_OES, GL_PALETTE4_R5_G6_B5_OES, GenerateMip<R5G6B5>, NoCopyFunctions, ReadColor<R5G6B5, GLfloat>, WriteColor<R5G6B5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 6, 5, 0, 0, 0, 0, 3, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::PALETTE4_R8G8B8A8_UNORM, GL_PALETTE4_RGBA8_OES, GL_PALETTE4_RGBA8_OES, GenerateMip<R8G8B8A8>, NoCopyFunctions, ReadColor<R8G8B8A8, GLfloat>, WriteColor<R8G8B8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 5, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::PALETTE4_R8G8B8_UNORM, GL_PALETTE4_RGB8_OES, GL_PALETTE4_RGB8_OES, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLfloat>, WriteColor<R8G8B8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::PALETTE8_R4G4B4A4_UNORM, GL_PALETTE8_RGBA4_OES, GL_PALETTE8_RGBA4_OES, GenerateMip<R4G4B4A4>, NoCopyFunctions, ReadColor<R4G4B4A4, GLfloat>, WriteColor<R4G4B4A4, GLfloat>, GL_UNSIGNED_NORMALIZED, 4, 4, 4, 4, 0, 0, 0, 3, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::PALETTE8_R5G5B5A1_UNORM, GL_PALETTE8_RGB5_A1_OES, GL_PALETTE8_RGB5_A1_OES, GenerateMip<R5G5B5A1>, NoCopyFunctions, ReadColor<R5G5B5A1, GLfloat>, WriteColor<R5G5B5A1, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 5, 5, 1, 0, 0, 0, 3, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::PALETTE8_R5G6B5_UNORM, GL_PALETTE8_R5_G6_B5_OES, GL_PALETTE8_R5_G6_B5_OES, GenerateMip<R5G6B5>, NoCopyFunctions, ReadColor<R5G6B5, GLfloat>, WriteColor<R5G6B5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 6, 5, 0, 0, 0, 0, 3, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::PALETTE8_R8G8B8A8_UNORM, GL_PALETTE8_RGBA8_OES, GL_PALETTE8_RGBA8_OES, GenerateMip<R8G8B8A8>, NoCopyFunctions, ReadColor<R8G8B8A8, GLfloat>, WriteColor<R8G8B8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 5, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::PALETTE8_R8G8B8_UNORM, GL_PALETTE8_RGB8_OES, GL_PALETTE8_RGB8_OES, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLfloat>, WriteColor<R8G8B8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::PVRTC1_RGBA_2BPP_UNORM_BLOCK, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::PVRTC1_RGBA_2BPP_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT, GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::PVRTC1_RGBA_4BPP_UNORM_BLOCK, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::PVRTC1_RGBA_4BPP_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT, GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::PVRTC1_RGB_2BPP_UNORM_BLOCK, GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::PVRTC1_RGB_2BPP_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT, GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::PVRTC1_RGB_4BPP_UNORM_BLOCK, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::PVRTC1_RGB_4BPP_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT, GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false, false, true, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::R10G10B10A2_SINT, GL_RGB10_A2_SINT_ANGLEX, GL_RGB10_A2_SINT_ANGLEX, GenerateMip<R10G10B10A2S>, NoCopyFunctions, ReadColor<R10G10B10A2S, GLint>, WriteColor<R10G10B10A2S, GLint>, GL_INT, 10, 10, 10, 2, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::Int2101010 },
+ { FormatID::R10G10B10A2_SNORM, GL_RGB10_A2_SNORM_ANGLEX, GL_RGB10_A2_SNORM_ANGLEX, GenerateMip<R10G10B10A2S>, NoCopyFunctions, ReadColor<R10G10B10A2S, GLfloat>, WriteColor<R10G10B10A2S, GLfloat>, GL_SIGNED_NORMALIZED, 10, 10, 10, 2, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::Int2101010 },
+ { FormatID::R10G10B10A2_SSCALED, GL_RGB10_A2_SSCALED_ANGLEX, GL_RGB10_A2_SSCALED_ANGLEX, GenerateMip<R10G10B10A2S>, NoCopyFunctions, ReadColor<R10G10B10A2S, GLint>, WriteColor<R10G10B10A2S, GLint>, GL_INT, 10, 10, 10, 2, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, true, false, false, gl::VertexAttribType::Int2101010 },
+ { FormatID::R10G10B10A2_UINT, GL_RGB10_A2UI, GL_RGB10_A2UI, GenerateMip<R10G10B10A2>, NoCopyFunctions, ReadColor<R10G10B10A2, GLuint>, WriteColor<R10G10B10A2, GLuint>, GL_UNSIGNED_INT, 10, 10, 10, 2, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedInt2101010 },
+ { FormatID::R10G10B10A2_UNORM, GL_RGB10_A2, GL_RGB10_A2, GenerateMip<R10G10B10A2>, NoCopyFunctions, ReadColor<R10G10B10A2, GLfloat>, WriteColor<R10G10B10A2, GLfloat>, GL_UNSIGNED_NORMALIZED, 10, 10, 10, 2, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedInt2101010 },
+ { FormatID::R10G10B10A2_USCALED, GL_RGB10_A2_USCALED_ANGLEX, GL_RGB10_A2_USCALED_ANGLEX, GenerateMip<R10G10B10A2>, NoCopyFunctions, ReadColor<R10G10B10A2, GLuint>, WriteColor<R10G10B10A2, GLuint>, GL_UNSIGNED_INT, 10, 10, 10, 2, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, true, false, false, gl::VertexAttribType::UnsignedInt2101010 },
+ { FormatID::R10G10B10X2_UNORM, GL_RGB10_UNORM_ANGLEX, GL_RGB10_UNORM_ANGLEX, GenerateMip<R10G10B10X2>, NoCopyFunctions, ReadColor<R10G10B10X2, GLfloat>, WriteColor<R10G10B10X2, GLfloat>, GL_UNSIGNED_NORMALIZED, 10, 10, 10, 0, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedInt2101010 },
+ { FormatID::R11G11B10_FLOAT, GL_R11F_G11F_B10F, GL_R11F_G11F_B10F, GenerateMip<R11G11B10F>, NoCopyFunctions, ReadColor<R11G11B10F, GLfloat>, WriteColor<R11G11B10F, GLfloat>, GL_FLOAT, 11, 11, 10, 0, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::Float },
+ { FormatID::R16G16B16A16_FLOAT, GL_RGBA16F, GL_RGBA16F, GenerateMip<R16G16B16A16F>, NoCopyFunctions, ReadColor<R16G16B16A16F, GLfloat>, WriteColor<R16G16B16A16F, GLfloat>, GL_FLOAT, 16, 16, 16, 16, 0, 0, 0, 8, 1, false, false, false, false, false, gl::VertexAttribType::HalfFloat },
+ { FormatID::R16G16B16A16_SINT, GL_RGBA16I, GL_RGBA16I, GenerateMip<R16G16B16A16S>, NoCopyFunctions, ReadColor<R16G16B16A16S, GLint>, WriteColor<R16G16B16A16S, GLint>, GL_INT, 16, 16, 16, 16, 0, 0, 0, 8, 1, false, false, false, false, false, gl::VertexAttribType::Short },
+ { FormatID::R16G16B16A16_SNORM, GL_RGBA16_SNORM_EXT, GL_RGBA16_SNORM_EXT, GenerateMip<R16G16B16A16S>, NoCopyFunctions, ReadColor<R16G16B16A16S, GLfloat>, WriteColor<R16G16B16A16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 16, 16, 16, 0, 0, 0, 8, 1, false, false, false, false, false, gl::VertexAttribType::Short },
+ { FormatID::R16G16B16A16_SSCALED, GL_RGBA16_SSCALED_ANGLEX, GL_RGBA16_SSCALED_ANGLEX, GenerateMip<R16G16B16A16S>, NoCopyFunctions, ReadColor<R16G16B16A16S, GLint>, WriteColor<R16G16B16A16S, GLint>, GL_INT, 16, 16, 16, 16, 0, 0, 0, 8, 1, false, false, true, false, false, gl::VertexAttribType::Short },
+ { FormatID::R16G16B16A16_UINT, GL_RGBA16UI, GL_RGBA16UI, GenerateMip<R16G16B16A16>, NoCopyFunctions, ReadColor<R16G16B16A16, GLuint>, WriteColor<R16G16B16A16, GLuint>, GL_UNSIGNED_INT, 16, 16, 16, 16, 0, 0, 0, 8, 1, false, false, false, false, false, gl::VertexAttribType::UnsignedShort },
+ { FormatID::R16G16B16A16_UNORM, GL_RGBA16_EXT, GL_RGBA16_EXT, GenerateMip<R16G16B16A16>, NoCopyFunctions, ReadColor<R16G16B16A16, GLfloat>, WriteColor<R16G16B16A16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 16, 16, 16, 0, 0, 0, 8, 1, false, false, false, false, false, gl::VertexAttribType::UnsignedShort },
+ { FormatID::R16G16B16A16_USCALED, GL_RGBA16_USCALED_ANGLEX, GL_RGBA16_USCALED_ANGLEX, GenerateMip<R16G16B16A16>, NoCopyFunctions, ReadColor<R16G16B16A16, GLuint>, WriteColor<R16G16B16A16, GLuint>, GL_UNSIGNED_INT, 16, 16, 16, 16, 0, 0, 0, 8, 1, false, false, true, false, false, gl::VertexAttribType::UnsignedShort },
+ { FormatID::R16G16B16_FLOAT, GL_RGB16F, GL_RGB16F, GenerateMip<R16G16B16F>, NoCopyFunctions, ReadColor<R16G16B16F, GLfloat>, WriteColor<R16G16B16F, GLfloat>, GL_FLOAT, 16, 16, 16, 0, 0, 0, 0, 6, 1, false, false, false, false, false, gl::VertexAttribType::HalfFloat },
+ { FormatID::R16G16B16_SINT, GL_RGB16I, GL_RGB16I, GenerateMip<R16G16B16S>, NoCopyFunctions, ReadColor<R16G16B16S, GLint>, WriteColor<R16G16B16S, GLint>, GL_INT, 16, 16, 16, 0, 0, 0, 0, 6, 1, false, false, false, false, false, gl::VertexAttribType::Short },
+ { FormatID::R16G16B16_SNORM, GL_RGB16_SNORM_EXT, GL_RGB16_SNORM_EXT, GenerateMip<R16G16B16S>, NoCopyFunctions, ReadColor<R16G16B16S, GLfloat>, WriteColor<R16G16B16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 16, 16, 0, 0, 0, 0, 6, 1, false, false, false, false, false, gl::VertexAttribType::Short },
+ { FormatID::R16G16B16_SSCALED, GL_RGB16_SSCALED_ANGLEX, GL_RGB16_SSCALED_ANGLEX, GenerateMip<R16G16B16S>, NoCopyFunctions, ReadColor<R16G16B16S, GLint>, WriteColor<R16G16B16S, GLint>, GL_INT, 16, 16, 16, 0, 0, 0, 0, 6, 1, false, false, true, false, false, gl::VertexAttribType::Short },
+ { FormatID::R16G16B16_UINT, GL_RGB16UI, GL_RGB16UI, GenerateMip<R16G16B16>, NoCopyFunctions, ReadColor<R16G16B16, GLuint>, WriteColor<R16G16B16, GLuint>, GL_UNSIGNED_INT, 16, 16, 16, 0, 0, 0, 0, 6, 1, false, false, false, false, false, gl::VertexAttribType::UnsignedShort },
+ { FormatID::R16G16B16_UNORM, GL_RGB16_EXT, GL_RGB16_EXT, GenerateMip<R16G16B16>, NoCopyFunctions, ReadColor<R16G16B16, GLfloat>, WriteColor<R16G16B16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 16, 16, 0, 0, 0, 0, 6, 1, false, false, false, false, false, gl::VertexAttribType::UnsignedShort },
+ { FormatID::R16G16B16_USCALED, GL_RGB16_USCALED_ANGLEX, GL_RGB16_USCALED_ANGLEX, GenerateMip<R16G16B16>, NoCopyFunctions, ReadColor<R16G16B16, GLuint>, WriteColor<R16G16B16, GLuint>, GL_UNSIGNED_INT, 16, 16, 16, 0, 0, 0, 0, 6, 1, false, false, true, false, false, gl::VertexAttribType::UnsignedShort },
+ { FormatID::R16G16_FLOAT, GL_RG16F, GL_RG16F, GenerateMip<R16G16F>, NoCopyFunctions, ReadColor<R16G16F, GLfloat>, WriteColor<R16G16F, GLfloat>, GL_FLOAT, 16, 16, 0, 0, 0, 0, 0, 4, 1, false, false, false, false, false, gl::VertexAttribType::HalfFloat },
+ { FormatID::R16G16_SINT, GL_RG16I, GL_RG16I, GenerateMip<R16G16S>, NoCopyFunctions, ReadColor<R16G16S, GLint>, WriteColor<R16G16S, GLint>, GL_INT, 16, 16, 0, 0, 0, 0, 0, 4, 1, false, false, false, false, false, gl::VertexAttribType::Short },
+ { FormatID::R16G16_SNORM, GL_RG16_SNORM_EXT, GL_RG16_SNORM_EXT, GenerateMip<R16G16S>, NoCopyFunctions, ReadColor<R16G16S, GLfloat>, WriteColor<R16G16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 16, 0, 0, 0, 0, 0, 4, 1, false, false, false, false, false, gl::VertexAttribType::Short },
+ { FormatID::R16G16_SSCALED, GL_RG16_SSCALED_ANGLEX, GL_RG16_SSCALED_ANGLEX, GenerateMip<R16G16S>, NoCopyFunctions, ReadColor<R16G16S, GLint>, WriteColor<R16G16S, GLint>, GL_INT, 16, 16, 0, 0, 0, 0, 0, 4, 1, false, false, true, false, false, gl::VertexAttribType::Short },
+ { FormatID::R16G16_UINT, GL_RG16UI, GL_RG16UI, GenerateMip<R16G16>, NoCopyFunctions, ReadColor<R16G16, GLuint>, WriteColor<R16G16, GLuint>, GL_UNSIGNED_INT, 16, 16, 0, 0, 0, 0, 0, 4, 1, false, false, false, false, false, gl::VertexAttribType::UnsignedShort },
+ { FormatID::R16G16_UNORM, GL_RG16_EXT, GL_RG16_EXT, GenerateMip<R16G16>, NoCopyFunctions, ReadColor<R16G16, GLfloat>, WriteColor<R16G16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 16, 0, 0, 0, 0, 0, 4, 1, false, false, false, false, false, gl::VertexAttribType::UnsignedShort },
+ { FormatID::R16G16_USCALED, GL_RG16_USCALED_ANGLEX, GL_RG16_USCALED_ANGLEX, GenerateMip<R16G16>, NoCopyFunctions, ReadColor<R16G16, GLuint>, WriteColor<R16G16, GLuint>, GL_UNSIGNED_INT, 16, 16, 0, 0, 0, 0, 0, 4, 1, false, false, true, false, false, gl::VertexAttribType::UnsignedShort },
+ { FormatID::R16_FLOAT, GL_R16F, GL_R16F, GenerateMip<R16F>, NoCopyFunctions, ReadColor<R16F, GLfloat>, WriteColor<R16F, GLfloat>, GL_FLOAT, 16, 0, 0, 0, 0, 0, 0, 2, 1, false, false, false, false, false, gl::VertexAttribType::HalfFloat },
+ { FormatID::R16_SINT, GL_R16I, GL_R16I, GenerateMip<R16S>, NoCopyFunctions, ReadColor<R16S, GLint>, WriteColor<R16S, GLint>, GL_INT, 16, 0, 0, 0, 0, 0, 0, 2, 1, false, false, false, false, false, gl::VertexAttribType::Short },
+ { FormatID::R16_SNORM, GL_R16_SNORM_EXT, GL_R16_SNORM_EXT, GenerateMip<R16S>, NoCopyFunctions, ReadColor<R16S, GLfloat>, WriteColor<R16S, GLfloat>, GL_SIGNED_NORMALIZED, 16, 0, 0, 0, 0, 0, 0, 2, 1, false, false, false, false, false, gl::VertexAttribType::Short },
+ { FormatID::R16_SSCALED, GL_R16_SSCALED_ANGLEX, GL_R16_SSCALED_ANGLEX, GenerateMip<R16S>, NoCopyFunctions, ReadColor<R16S, GLint>, WriteColor<R16S, GLint>, GL_INT, 16, 0, 0, 0, 0, 0, 0, 2, 1, false, false, true, false, false, gl::VertexAttribType::Short },
+ { FormatID::R16_UINT, GL_R16UI, GL_R16UI, GenerateMip<R16>, NoCopyFunctions, ReadColor<R16, GLuint>, WriteColor<R16, GLuint>, GL_UNSIGNED_INT, 16, 0, 0, 0, 0, 0, 0, 2, 1, false, false, false, false, false, gl::VertexAttribType::UnsignedShort },
+ { FormatID::R16_UNORM, GL_R16_EXT, GL_R16_EXT, GenerateMip<R16>, NoCopyFunctions, ReadColor<R16, GLfloat>, WriteColor<R16, GLfloat>, GL_UNSIGNED_NORMALIZED, 16, 0, 0, 0, 0, 0, 0, 2, 1, false, false, false, false, false, gl::VertexAttribType::UnsignedShort },
+ { FormatID::R16_USCALED, GL_R16_USCALED_ANGLEX, GL_R16_USCALED_ANGLEX, GenerateMip<R16>, NoCopyFunctions, ReadColor<R16, GLuint>, WriteColor<R16, GLuint>, GL_UNSIGNED_INT, 16, 0, 0, 0, 0, 0, 0, 2, 1, false, false, true, false, false, gl::VertexAttribType::UnsignedShort },
+ { FormatID::R32G32B32A32_FIXED, GL_RGBA32_FIXED_ANGLEX, GL_RGBA32_FIXED_ANGLEX, GenerateMip<R32G32B32A32F>, NoCopyFunctions, ReadColor<R32G32B32A32F, GLfloat>, WriteColor<R32G32B32A32F, GLfloat>, GL_FLOAT, 32, 32, 32, 32, 0, 0, 0, 16, 3, false, true, false, false, false, gl::VertexAttribType::Fixed },
+ { FormatID::R32G32B32A32_FLOAT, GL_RGBA32F, GL_RGBA32F, GenerateMip<R32G32B32A32F>, NoCopyFunctions, ReadColor<R32G32B32A32F, GLfloat>, WriteColor<R32G32B32A32F, GLfloat>, GL_FLOAT, 32, 32, 32, 32, 0, 0, 0, 16, 3, false, false, false, false, false, gl::VertexAttribType::Float },
+ { FormatID::R32G32B32A32_SINT, GL_RGBA32I, GL_RGBA32I, GenerateMip<R32G32B32A32S>, NoCopyFunctions, ReadColor<R32G32B32A32S, GLint>, WriteColor<R32G32B32A32S, GLint>, GL_INT, 32, 32, 32, 32, 0, 0, 0, 16, 3, false, false, false, false, false, gl::VertexAttribType::Int },
+ { FormatID::R32G32B32A32_SNORM, GL_RGBA32_SNORM_ANGLEX, GL_RGBA32_SNORM_ANGLEX, GenerateMip<R32G32B32A32S>, NoCopyFunctions, ReadColor<R32G32B32A32S, GLfloat>, WriteColor<R32G32B32A32S, GLfloat>, GL_SIGNED_NORMALIZED, 32, 32, 32, 32, 0, 0, 0, 16, 3, false, false, false, false, false, gl::VertexAttribType::Int },
+ { FormatID::R32G32B32A32_SSCALED, GL_RGBA32_SSCALED_ANGLEX, GL_RGBA32_SSCALED_ANGLEX, GenerateMip<R32G32B32A32S>, NoCopyFunctions, ReadColor<R32G32B32A32S, GLint>, WriteColor<R32G32B32A32S, GLint>, GL_INT, 32, 32, 32, 32, 0, 0, 0, 16, 3, false, false, true, false, false, gl::VertexAttribType::Int },
+ { FormatID::R32G32B32A32_UINT, GL_RGBA32UI, GL_RGBA32UI, GenerateMip<R32G32B32A32>, NoCopyFunctions, ReadColor<R32G32B32A32, GLuint>, WriteColor<R32G32B32A32, GLuint>, GL_UNSIGNED_INT, 32, 32, 32, 32, 0, 0, 0, 16, 3, false, false, false, false, false, gl::VertexAttribType::UnsignedInt },
+ { FormatID::R32G32B32A32_UNORM, GL_RGBA32_UNORM_ANGLEX, GL_RGBA32_UNORM_ANGLEX, GenerateMip<R32G32B32A32>, NoCopyFunctions, ReadColor<R32G32B32A32, GLfloat>, WriteColor<R32G32B32A32, GLfloat>, GL_UNSIGNED_NORMALIZED, 32, 32, 32, 32, 0, 0, 0, 16, 3, false, false, false, false, false, gl::VertexAttribType::UnsignedInt },
+ { FormatID::R32G32B32A32_USCALED, GL_RGBA32_USCALED_ANGLEX, GL_RGBA32_USCALED_ANGLEX, GenerateMip<R32G32B32A32>, NoCopyFunctions, ReadColor<R32G32B32A32, GLuint>, WriteColor<R32G32B32A32, GLuint>, GL_UNSIGNED_INT, 32, 32, 32, 32, 0, 0, 0, 16, 3, false, false, true, false, false, gl::VertexAttribType::UnsignedInt },
+ { FormatID::R32G32B32_FIXED, GL_RGB32_FIXED_ANGLEX, GL_RGB32_FIXED_ANGLEX, GenerateMip<R32G32B32F>, NoCopyFunctions, ReadColor<R32G32B32F, GLfloat>, WriteColor<R32G32B32F, GLfloat>, GL_FLOAT, 32, 32, 32, 0, 0, 0, 0, 12, 3, false, true, false, false, false, gl::VertexAttribType::Fixed },
+ { FormatID::R32G32B32_FLOAT, GL_RGB32F, GL_RGB32F, GenerateMip<R32G32B32F>, NoCopyFunctions, ReadColor<R32G32B32F, GLfloat>, WriteColor<R32G32B32F, GLfloat>, GL_FLOAT, 32, 32, 32, 0, 0, 0, 0, 12, 3, false, false, false, false, false, gl::VertexAttribType::Float },
+ { FormatID::R32G32B32_SINT, GL_RGB32I, GL_RGB32I, GenerateMip<R32G32B32S>, NoCopyFunctions, ReadColor<R32G32B32S, GLint>, WriteColor<R32G32B32S, GLint>, GL_INT, 32, 32, 32, 0, 0, 0, 0, 12, 3, false, false, false, false, false, gl::VertexAttribType::Int },
+ { FormatID::R32G32B32_SNORM, GL_RGB32_SNORM_ANGLEX, GL_RGB32_SNORM_ANGLEX, GenerateMip<R32G32B32S>, NoCopyFunctions, ReadColor<R32G32B32S, GLfloat>, WriteColor<R32G32B32S, GLfloat>, GL_SIGNED_NORMALIZED, 32, 32, 32, 0, 0, 0, 0, 12, 3, false, false, false, false, false, gl::VertexAttribType::Int },
+ { FormatID::R32G32B32_SSCALED, GL_RGB32_SSCALED_ANGLEX, GL_RGB32_SSCALED_ANGLEX, GenerateMip<R32G32B32S>, NoCopyFunctions, ReadColor<R32G32B32S, GLint>, WriteColor<R32G32B32S, GLint>, GL_INT, 32, 32, 32, 0, 0, 0, 0, 12, 3, false, false, true, false, false, gl::VertexAttribType::Int },
+ { FormatID::R32G32B32_UINT, GL_RGB32UI, GL_RGB32UI, GenerateMip<R32G32B32>, NoCopyFunctions, ReadColor<R32G32B32, GLuint>, WriteColor<R32G32B32, GLuint>, GL_UNSIGNED_INT, 32, 32, 32, 0, 0, 0, 0, 12, 3, false, false, false, false, false, gl::VertexAttribType::UnsignedInt },
+ { FormatID::R32G32B32_UNORM, GL_RGB32_UNORM_ANGLEX, GL_RGB32_UNORM_ANGLEX, GenerateMip<R32G32B32>, NoCopyFunctions, ReadColor<R32G32B32, GLfloat>, WriteColor<R32G32B32, GLfloat>, GL_UNSIGNED_NORMALIZED, 32, 32, 32, 0, 0, 0, 0, 12, 3, false, false, false, false, false, gl::VertexAttribType::UnsignedInt },
+ { FormatID::R32G32B32_USCALED, GL_RGB32_USCALED_ANGLEX, GL_RGB32_USCALED_ANGLEX, GenerateMip<R32G32B32>, NoCopyFunctions, ReadColor<R32G32B32, GLuint>, WriteColor<R32G32B32, GLuint>, GL_UNSIGNED_INT, 32, 32, 32, 0, 0, 0, 0, 12, 3, false, false, true, false, false, gl::VertexAttribType::UnsignedInt },
+ { FormatID::R32G32_FIXED, GL_RG32_FIXED_ANGLEX, GL_RG32_FIXED_ANGLEX, GenerateMip<R32G32F>, NoCopyFunctions, ReadColor<R32G32F, GLfloat>, WriteColor<R32G32F, GLfloat>, GL_FLOAT, 32, 32, 0, 0, 0, 0, 0, 8, 3, false, true, false, false, false, gl::VertexAttribType::Fixed },
+ { FormatID::R32G32_FLOAT, GL_RG32F, GL_RG32F, GenerateMip<R32G32F>, NoCopyFunctions, ReadColor<R32G32F, GLfloat>, WriteColor<R32G32F, GLfloat>, GL_FLOAT, 32, 32, 0, 0, 0, 0, 0, 8, 3, false, false, false, false, false, gl::VertexAttribType::Float },
+ { FormatID::R32G32_SINT, GL_RG32I, GL_RG32I, GenerateMip<R32G32S>, NoCopyFunctions, ReadColor<R32G32S, GLint>, WriteColor<R32G32S, GLint>, GL_INT, 32, 32, 0, 0, 0, 0, 0, 8, 3, false, false, false, false, false, gl::VertexAttribType::Int },
+ { FormatID::R32G32_SNORM, GL_RG32_SNORM_ANGLEX, GL_RG32_SNORM_ANGLEX, GenerateMip<R32G32S>, NoCopyFunctions, ReadColor<R32G32S, GLfloat>, WriteColor<R32G32S, GLfloat>, GL_SIGNED_NORMALIZED, 32, 32, 0, 0, 0, 0, 0, 8, 3, false, false, false, false, false, gl::VertexAttribType::Int },
+ { FormatID::R32G32_SSCALED, GL_RG32_SSCALED_ANGLEX, GL_RG32_SSCALED_ANGLEX, GenerateMip<R32G32S>, NoCopyFunctions, ReadColor<R32G32S, GLint>, WriteColor<R32G32S, GLint>, GL_INT, 32, 32, 0, 0, 0, 0, 0, 8, 3, false, false, true, false, false, gl::VertexAttribType::Int },
+ { FormatID::R32G32_UINT, GL_RG32UI, GL_RG32UI, GenerateMip<R32G32>, NoCopyFunctions, ReadColor<R32G32, GLuint>, WriteColor<R32G32, GLuint>, GL_UNSIGNED_INT, 32, 32, 0, 0, 0, 0, 0, 8, 3, false, false, false, false, false, gl::VertexAttribType::UnsignedInt },
+ { FormatID::R32G32_UNORM, GL_RG32_UNORM_ANGLEX, GL_RG32_UNORM_ANGLEX, GenerateMip<R32G32>, NoCopyFunctions, ReadColor<R32G32, GLfloat>, WriteColor<R32G32, GLfloat>, GL_UNSIGNED_NORMALIZED, 32, 32, 0, 0, 0, 0, 0, 8, 3, false, false, false, false, false, gl::VertexAttribType::UnsignedInt },
+ { FormatID::R32G32_USCALED, GL_RG32_USCALED_ANGLEX, GL_RG32_USCALED_ANGLEX, GenerateMip<R32G32>, NoCopyFunctions, ReadColor<R32G32, GLuint>, WriteColor<R32G32, GLuint>, GL_UNSIGNED_INT, 32, 32, 0, 0, 0, 0, 0, 8, 3, false, false, true, false, false, gl::VertexAttribType::UnsignedInt },
+ { FormatID::R32_FIXED, GL_R32_FIXED_ANGLEX, GL_R32_FIXED_ANGLEX, GenerateMip<R32F>, NoCopyFunctions, ReadColor<R32F, GLfloat>, WriteColor<R32F, GLfloat>, GL_FLOAT, 32, 0, 0, 0, 0, 0, 0, 4, 3, false, true, false, false, false, gl::VertexAttribType::Fixed },
+ { FormatID::R32_FLOAT, GL_R32F, GL_R32F, GenerateMip<R32F>, NoCopyFunctions, ReadColor<R32F, GLfloat>, WriteColor<R32F, GLfloat>, GL_FLOAT, 32, 0, 0, 0, 0, 0, 0, 4, 3, false, false, false, false, false, gl::VertexAttribType::Float },
+ { FormatID::R32_SINT, GL_R32I, GL_R32I, GenerateMip<R32S>, NoCopyFunctions, ReadColor<R32S, GLint>, WriteColor<R32S, GLint>, GL_INT, 32, 0, 0, 0, 0, 0, 0, 4, 3, false, false, false, false, false, gl::VertexAttribType::Int },
+ { FormatID::R32_SNORM, GL_R32_SNORM_ANGLEX, GL_R32_SNORM_ANGLEX, GenerateMip<R32S>, NoCopyFunctions, ReadColor<R32S, GLfloat>, WriteColor<R32S, GLfloat>, GL_SIGNED_NORMALIZED, 32, 0, 0, 0, 0, 0, 0, 4, 3, false, false, false, false, false, gl::VertexAttribType::Int },
+ { FormatID::R32_SSCALED, GL_R32_SSCALED_ANGLEX, GL_R32_SSCALED_ANGLEX, GenerateMip<R32S>, NoCopyFunctions, ReadColor<R32S, GLint>, WriteColor<R32S, GLint>, GL_INT, 32, 0, 0, 0, 0, 0, 0, 4, 3, false, false, true, false, false, gl::VertexAttribType::Int },
+ { FormatID::R32_UINT, GL_R32UI, GL_R32UI, GenerateMip<R32>, NoCopyFunctions, ReadColor<R32, GLuint>, WriteColor<R32, GLuint>, GL_UNSIGNED_INT, 32, 0, 0, 0, 0, 0, 0, 4, 3, false, false, false, false, false, gl::VertexAttribType::UnsignedInt },
+ { FormatID::R32_UNORM, GL_R32_UNORM_ANGLEX, GL_R32_UNORM_ANGLEX, GenerateMip<R32>, NoCopyFunctions, ReadColor<R32, GLfloat>, WriteColor<R32, GLfloat>, GL_UNSIGNED_NORMALIZED, 32, 0, 0, 0, 0, 0, 0, 4, 3, false, false, false, false, false, gl::VertexAttribType::UnsignedInt },
+ { FormatID::R32_USCALED, GL_R32_USCALED_ANGLEX, GL_R32_USCALED_ANGLEX, GenerateMip<R32>, NoCopyFunctions, ReadColor<R32, GLuint>, WriteColor<R32, GLuint>, GL_UNSIGNED_INT, 32, 0, 0, 0, 0, 0, 0, 4, 3, false, false, true, false, false, gl::VertexAttribType::UnsignedInt },
+ { FormatID::R4G4B4A4_UNORM, GL_RGBA4, GL_RGBA4, GenerateMip<R4G4B4A4>, NoCopyFunctions, ReadColor<R4G4B4A4, GLfloat>, WriteColor<R4G4B4A4, GLfloat>, GL_UNSIGNED_NORMALIZED, 4, 4, 4, 4, 0, 0, 0, 2, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::R5G5B5A1_UNORM, GL_RGB5_A1, GL_RGB5_A1, GenerateMip<R5G5B5A1>, NoCopyFunctions, ReadColor<R5G5B5A1, GLfloat>, WriteColor<R5G5B5A1, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 5, 5, 1, 0, 0, 0, 2, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::R5G6B5_UNORM, GL_RGB565, GL_RGB565, GenerateMip<R5G6B5>, NoCopyFunctions, ReadColor<R5G6B5, GLfloat>, WriteColor<R5G6B5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 6, 5, 0, 0, 0, 0, 2, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::R8G8B8A8_SINT, GL_RGBA8I, GL_RGBA8I, GenerateMip<R8G8B8A8S>, NoCopyFunctions, ReadColor<R8G8B8A8S, GLint>, WriteColor<R8G8B8A8S, GLint>, GL_INT, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, false, false, gl::VertexAttribType::Byte },
+ { FormatID::R8G8B8A8_SNORM, GL_RGBA8_SNORM, GL_RGBA8_SNORM, GenerateMip<R8G8B8A8S>, NoCopyFunctions, ReadColor<R8G8B8A8S, GLfloat>, WriteColor<R8G8B8A8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, false, false, gl::VertexAttribType::Byte },
+ { FormatID::R8G8B8A8_SSCALED, GL_RGBA8_SSCALED_ANGLEX, GL_RGBA8_SSCALED_ANGLEX, GenerateMip<R8G8B8A8S>, NoCopyFunctions, ReadColor<R8G8B8A8S, GLint>, WriteColor<R8G8B8A8S, GLint>, GL_INT, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, true, false, false, gl::VertexAttribType::Byte },
+ { FormatID::R8G8B8A8_TYPELESS, GL_RGBA8, GL_RGBA8, GenerateMip<R8G8B8A8>, NoCopyFunctions, ReadColor<R8G8B8A8, GLfloat>, WriteColor<R8G8B8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::R8G8B8A8_TYPELESS_SRGB, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GenerateMip<R8G8B8A8>, NoCopyFunctions, ReadColor<R8G8B8A8, GLfloat>, WriteColor<R8G8B8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, true, false, gl::VertexAttribType::Byte },
+ { FormatID::R8G8B8A8_UINT, GL_RGBA8UI, GL_RGBA8UI, GenerateMip<R8G8B8A8>, NoCopyFunctions, ReadColor<R8G8B8A8, GLuint>, WriteColor<R8G8B8A8, GLuint>, GL_UNSIGNED_INT, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::R8G8B8A8_UNORM, GL_RGBA8, GL_RGBA8, GenerateMip<R8G8B8A8>, NoCopyFunctions, ReadColor<R8G8B8A8, GLfloat>, WriteColor<R8G8B8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::R8G8B8A8_UNORM_SRGB, GL_SRGB8_ALPHA8, GL_SRGB8_ALPHA8, GenerateMip<R8G8B8A8SRGB>, NoCopyFunctions, ReadColor<R8G8B8A8SRGB, GLfloat>, WriteColor<R8G8B8A8SRGB, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, false, true, false, gl::VertexAttribType::Byte },
+ { FormatID::R8G8B8A8_USCALED, GL_RGBA8_USCALED_ANGLEX, GL_RGBA8_USCALED_ANGLEX, GenerateMip<R8G8B8A8>, NoCopyFunctions, ReadColor<R8G8B8A8, GLuint>, WriteColor<R8G8B8A8, GLuint>, GL_UNSIGNED_INT, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false, true, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::R8G8B8X8_UNORM, GL_RGBA8, GL_RGBA8, GenerateMip<R8G8B8X8>, NoCopyFunctions, ReadColor<R8G8B8X8, GLfloat>, WriteColor<R8G8B8X8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::R8G8B8_SINT, GL_RGB8I, GL_RGB8I, GenerateMip<R8G8B8S>, NoCopyFunctions, ReadColor<R8G8B8S, GLint>, WriteColor<R8G8B8S, GLint>, GL_INT, 8, 8, 8, 0, 0, 0, 0, 3, 0, false, false, false, false, false, gl::VertexAttribType::Byte },
+ { FormatID::R8G8B8_SNORM, GL_RGB8_SNORM, GL_RGB8_SNORM, GenerateMip<R8G8B8S>, NoCopyFunctions, ReadColor<R8G8B8S, GLfloat>, WriteColor<R8G8B8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 3, 0, false, false, false, false, false, gl::VertexAttribType::Byte },
+ { FormatID::R8G8B8_SSCALED, GL_RGB8_SSCALED_ANGLEX, GL_RGB8_SSCALED_ANGLEX, GenerateMip<R8G8B8S>, NoCopyFunctions, ReadColor<R8G8B8S, GLint>, WriteColor<R8G8B8S, GLint>, GL_INT, 8, 8, 8, 0, 0, 0, 0, 3, 0, false, false, true, false, false, gl::VertexAttribType::Byte },
+ { FormatID::R8G8B8_UINT, GL_RGB8UI, GL_RGB8UI, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLuint>, WriteColor<R8G8B8, GLuint>, GL_UNSIGNED_INT, 8, 8, 8, 0, 0, 0, 0, 3, 0, false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::R8G8B8_UNORM, GL_RGB8, GL_RGB8, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLfloat>, WriteColor<R8G8B8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 3, 0, false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::R8G8B8_UNORM_SRGB, GL_SRGB8, GL_SRGB8, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLfloat>, WriteColor<R8G8B8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 3, 0, false, false, false, true, false, gl::VertexAttribType::Byte },
+ { FormatID::R8G8B8_USCALED, GL_RGB8_USCALED_ANGLEX, GL_RGB8_USCALED_ANGLEX, GenerateMip<R8G8B8>, NoCopyFunctions, ReadColor<R8G8B8, GLuint>, WriteColor<R8G8B8, GLuint>, GL_UNSIGNED_INT, 8, 8, 8, 0, 0, 0, 0, 3, 0, false, false, true, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::R8G8_SINT, GL_RG8I, GL_RG8I, GenerateMip<R8G8S>, NoCopyFunctions, ReadColor<R8G8S, GLint>, WriteColor<R8G8S, GLint>, GL_INT, 8, 8, 0, 0, 0, 0, 0, 2, 0, false, false, false, false, false, gl::VertexAttribType::Byte },
+ { FormatID::R8G8_SNORM, GL_RG8_SNORM, GL_RG8_SNORM, GenerateMip<R8G8S>, NoCopyFunctions, ReadColor<R8G8S, GLfloat>, WriteColor<R8G8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 8, 0, 0, 0, 0, 0, 2, 0, false, false, false, false, false, gl::VertexAttribType::Byte },
+ { FormatID::R8G8_SSCALED, GL_RG8_SSCALED_ANGLEX, GL_RG8_SSCALED_ANGLEX, GenerateMip<R8G8S>, NoCopyFunctions, ReadColor<R8G8S, GLint>, WriteColor<R8G8S, GLint>, GL_INT, 8, 8, 0, 0, 0, 0, 0, 2, 0, false, false, true, false, false, gl::VertexAttribType::Byte },
+ { FormatID::R8G8_UINT, GL_RG8UI, GL_RG8UI, GenerateMip<R8G8>, NoCopyFunctions, ReadColor<R8G8, GLuint>, WriteColor<R8G8, GLuint>, GL_UNSIGNED_INT, 8, 8, 0, 0, 0, 0, 0, 2, 0, false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::R8G8_UNORM, GL_RG8, GL_RG8, GenerateMip<R8G8>, NoCopyFunctions, ReadColor<R8G8, GLfloat>, WriteColor<R8G8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 0, 0, 0, 0, 0, 2, 0, false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::R8G8_UNORM_SRGB, GL_SRG8_EXT, GL_SRG8_EXT, GenerateMip<R8G8>, NoCopyFunctions, ReadColor<R8G8, GLfloat>, WriteColor<R8G8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 0, 0, 0, 0, 0, 2, 0, false, false, false, true, false, gl::VertexAttribType::Byte },
+ { FormatID::R8G8_USCALED, GL_RG8_USCALED_ANGLEX, GL_RG8_USCALED_ANGLEX, GenerateMip<R8G8>, NoCopyFunctions, ReadColor<R8G8, GLuint>, WriteColor<R8G8, GLuint>, GL_UNSIGNED_INT, 8, 8, 0, 0, 0, 0, 0, 2, 0, false, false, true, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::R8_SINT, GL_R8I, GL_R8I, GenerateMip<R8S>, NoCopyFunctions, ReadColor<R8S, GLint>, WriteColor<R8S, GLint>, GL_INT, 8, 0, 0, 0, 0, 0, 0, 1, 0, false, false, false, false, false, gl::VertexAttribType::Byte },
+ { FormatID::R8_SNORM, GL_R8_SNORM, GL_R8_SNORM, GenerateMip<R8S>, NoCopyFunctions, ReadColor<R8S, GLfloat>, WriteColor<R8S, GLfloat>, GL_SIGNED_NORMALIZED, 8, 0, 0, 0, 0, 0, 0, 1, 0, false, false, false, false, false, gl::VertexAttribType::Byte },
+ { FormatID::R8_SSCALED, GL_R8_SSCALED_ANGLEX, GL_R8_SSCALED_ANGLEX, GenerateMip<R8S>, NoCopyFunctions, ReadColor<R8S, GLint>, WriteColor<R8S, GLint>, GL_INT, 8, 0, 0, 0, 0, 0, 0, 1, 0, false, false, true, false, false, gl::VertexAttribType::Byte },
+ { FormatID::R8_UINT, GL_R8UI, GL_R8UI, GenerateMip<R8>, NoCopyFunctions, ReadColor<R8, GLuint>, WriteColor<R8, GLuint>, GL_UNSIGNED_INT, 8, 0, 0, 0, 0, 0, 0, 1, 0, false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::R8_UNORM, GL_R8, GL_R8, GenerateMip<R8>, NoCopyFunctions, ReadColor<R8, GLfloat>, WriteColor<R8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 0, 0, 0, 0, 0, 0, 1, 0, false, false, false, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::R8_UNORM_SRGB, GL_SR8_EXT, GL_SR8_EXT, GenerateMip<R8>, NoCopyFunctions, ReadColor<R8, GLfloat>, WriteColor<R8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 0, 0, 0, 0, 0, 0, 1, 0, false, false, false, true, false, gl::VertexAttribType::Byte },
+ { FormatID::R8_USCALED, GL_R8_USCALED_ANGLEX, GL_R8_USCALED_ANGLEX, GenerateMip<R8>, NoCopyFunctions, ReadColor<R8, GLuint>, WriteColor<R8, GLuint>, GL_UNSIGNED_INT, 8, 0, 0, 0, 0, 0, 0, 1, 0, false, false, true, false, false, gl::VertexAttribType::UnsignedByte },
+ { FormatID::R9G9B9E5_SHAREDEXP, GL_RGB9_E5, GL_RGB9_E5, GenerateMip<R9G9B9E5>, NoCopyFunctions, ReadColor<R9G9B9E5, GLfloat>, WriteColor<R9G9B9E5, GLfloat>, GL_FLOAT, 9, 9, 9, 0, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::InvalidEnum },
+ { FormatID::X2R10G10B10_SINT_VERTEX, GL_X2_RGB10_SINT_ANGLEX, GL_X2_RGB10_SINT_ANGLEX, nullptr, NoCopyFunctions, nullptr, nullptr, GL_INT, 10, 10, 10, 0, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::Int1010102 },
+ { FormatID::X2R10G10B10_SNORM_VERTEX, GL_X2_RGB10_SNORM_ANGLEX, GL_X2_RGB10_SNORM_ANGLEX, nullptr, NoCopyFunctions, nullptr, nullptr, GL_SIGNED_NORMALIZED, 10, 10, 10, 0, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::Int1010102 },
+ { FormatID::X2R10G10B10_SSCALED_VERTEX, GL_X2_RGB10_SSCALED_ANGLEX, GL_X2_RGB10_SSCALED_ANGLEX, nullptr, NoCopyFunctions, nullptr, nullptr, GL_INT, 10, 10, 10, 0, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, true, false, false, gl::VertexAttribType::Int1010102 },
+ { FormatID::X2R10G10B10_UINT_VERTEX, GL_X2_RGB10_UINT_ANGLEX, GL_X2_RGB10_UINT_ANGLEX, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_INT, 10, 10, 10, 0, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedInt1010102 },
+ { FormatID::X2R10G10B10_UNORM_VERTEX, GL_X2_RGB10_UNORM_ANGLEX, GL_X2_RGB10_UNORM_ANGLEX, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 10, 10, 10, 0, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, false, false, false, gl::VertexAttribType::UnsignedInt1010102 },
+ { FormatID::X2R10G10B10_USCALED_VERTEX, GL_X2_RGB10_USCALED_ANGLEX, GL_X2_RGB10_USCALED_ANGLEX, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_INT, 10, 10, 10, 0, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false, true, false, false, gl::VertexAttribType::UnsignedInt1010102 },
+ // clang-format on
+};
+
+// static
+FormatID Format::InternalFormatToID(GLenum internalFormat)
+{
+ switch (internalFormat)
+ {
+ case GL_A1RGB5_ANGLEX:
+ return FormatID::A1R5G5B5_UNORM;
+ case GL_A2_RGB10_SNORM_ANGLEX:
+ return FormatID::A2R10G10B10_SNORM_VERTEX;
+ case GL_A2_RGB10_SSCALED_ANGLEX:
+ return FormatID::A2R10G10B10_SSCALED_VERTEX;
+ case GL_A2_RGB10_UNORM_ANGLEX:
+ return FormatID::A2R10G10B10_UNORM_VERTEX;
+ case GL_A2_RGB10_USCALED_ANGLEX:
+ return FormatID::A2R10G10B10_USCALED_VERTEX;
+ case GL_ALPHA16F_EXT:
+ return FormatID::A16_FLOAT;
+ case GL_ALPHA32F_EXT:
+ return FormatID::A32_FLOAT;
+ case GL_ALPHA8_EXT:
+ return FormatID::A8_UNORM;
+ case GL_BGR10_A2_ANGLEX:
+ return FormatID::B10G10R10A2_UNORM;
+ case GL_BGR565_ANGLEX:
+ return FormatID::B5G6R5_UNORM;
+ case GL_BGR5_A1_ANGLEX:
+ return FormatID::B5G5R5A1_UNORM;
+ case GL_BGRA4_ANGLEX:
+ return FormatID::B4G4R4A4_UNORM;
+ case GL_BGRA8_EXT:
+ return FormatID::B8G8R8A8_UNORM;
+ case GL_BGRA8_SRGB_ANGLEX:
+ return FormatID::B8G8R8A8_UNORM_SRGB;
+ case GL_BGRA8_TYPELESS_ANGLEX:
+ return FormatID::B8G8R8A8_TYPELESS;
+ case GL_BGRA8_TYPELESS_SRGB_ANGLEX:
+ return FormatID::B8G8R8A8_TYPELESS_SRGB;
+ case GL_BGRX8_ANGLEX:
+ return FormatID::B8G8R8X8_UNORM;
+ case GL_COMPRESSED_R11_EAC:
+ return FormatID::EAC_R11_UNORM_BLOCK;
+ case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
+ return FormatID::BC5_RG_UNORM_BLOCK;
+ case GL_COMPRESSED_RED_RGTC1_EXT:
+ return FormatID::BC4_RED_UNORM_BLOCK;
+ case GL_COMPRESSED_RG11_EAC:
+ return FormatID::EAC_R11G11_UNORM_BLOCK;
+ case GL_COMPRESSED_RGB8_ETC2:
+ return FormatID::ETC2_R8G8B8_UNORM_BLOCK;
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ return FormatID::ETC2_R8G8B8A1_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA8_ETC2_EAC:
+ return FormatID::ETC2_R8G8B8A8_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
+ return FormatID::ASTC_10x10_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
+ return FormatID::ASTC_10x5_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
+ return FormatID::ASTC_10x6_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
+ return FormatID::ASTC_10x8_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
+ return FormatID::ASTC_12x10_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
+ return FormatID::ASTC_12x12_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_3x3x3_OES:
+ return FormatID::ASTC_3x3x3_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_4x3x3_OES:
+ return FormatID::ASTC_4x3x3_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
+ return FormatID::ASTC_4x4_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_4x4x3_OES:
+ return FormatID::ASTC_4x4x3_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_4x4x4_OES:
+ return FormatID::ASTC_4x4x4_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
+ return FormatID::ASTC_5x4_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_5x4x4_OES:
+ return FormatID::ASTC_5x4x4_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
+ return FormatID::ASTC_5x5_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_5x5x4_OES:
+ return FormatID::ASTC_5x5x4_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_5x5x5_OES:
+ return FormatID::ASTC_5x5x5_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
+ return FormatID::ASTC_6x5_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_6x5x5_OES:
+ return FormatID::ASTC_6x5x5_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
+ return FormatID::ASTC_6x6_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_6x6x5_OES:
+ return FormatID::ASTC_6x6x5_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_6x6x6_OES:
+ return FormatID::ASTC_6x6x6_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
+ return FormatID::ASTC_8x5_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
+ return FormatID::ASTC_8x6_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
+ return FormatID::ASTC_8x8_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
+ return FormatID::BC7_RGBA_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
+ return FormatID::PVRTC1_RGBA_2BPP_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
+ return FormatID::PVRTC1_RGBA_4BPP_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return FormatID::BC1_RGBA_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ return FormatID::BC2_RGBA_UNORM_BLOCK;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ return FormatID::BC3_RGBA_UNORM_BLOCK;
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
+ return FormatID::BC6H_RGB_SFLOAT_BLOCK;
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
+ return FormatID::BC6H_RGB_UFLOAT_BLOCK;
+ case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
+ return FormatID::PVRTC1_RGB_2BPP_UNORM_BLOCK;
+ case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
+ return FormatID::PVRTC1_RGB_4BPP_UNORM_BLOCK;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ return FormatID::BC1_RGB_UNORM_BLOCK;
+ case GL_COMPRESSED_SIGNED_R11_EAC:
+ return FormatID::EAC_R11_SNORM_BLOCK;
+ case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
+ return FormatID::BC5_RG_SNORM_BLOCK;
+ case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
+ return FormatID::BC4_RED_SNORM_BLOCK;
+ case GL_COMPRESSED_SIGNED_RG11_EAC:
+ return FormatID::EAC_R11G11_SNORM_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+ return FormatID::ASTC_10x10_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+ return FormatID::ASTC_10x5_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+ return FormatID::ASTC_10x6_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+ return FormatID::ASTC_10x8_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+ return FormatID::ASTC_12x10_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+ return FormatID::ASTC_12x12_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES:
+ return FormatID::ASTC_3x3x3_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES:
+ return FormatID::ASTC_4x3x3_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+ return FormatID::ASTC_4x4_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES:
+ return FormatID::ASTC_4x4x3_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES:
+ return FormatID::ASTC_4x4x4_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+ return FormatID::ASTC_5x4_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES:
+ return FormatID::ASTC_5x4x4_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+ return FormatID::ASTC_5x5_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES:
+ return FormatID::ASTC_5x5x4_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES:
+ return FormatID::ASTC_5x5x5_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+ return FormatID::ASTC_6x5_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES:
+ return FormatID::ASTC_6x5x5_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+ return FormatID::ASTC_6x6_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES:
+ return FormatID::ASTC_6x6x5_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES:
+ return FormatID::ASTC_6x6x6_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+ return FormatID::ASTC_8x5_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+ return FormatID::ASTC_8x6_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+ return FormatID::ASTC_8x8_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ return FormatID::ETC2_R8G8B8A8_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_ETC2:
+ return FormatID::ETC2_R8G8B8_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ return FormatID::ETC2_R8G8B8A1_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
+ return FormatID::BC7_RGBA_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
+ return FormatID::PVRTC1_RGBA_2BPP_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
+ return FormatID::PVRTC1_RGBA_4BPP_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ return FormatID::BC1_RGBA_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ return FormatID::BC2_RGBA_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ return FormatID::BC3_RGBA_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
+ return FormatID::PVRTC1_RGB_2BPP_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
+ return FormatID::PVRTC1_RGB_4BPP_UNORM_SRGB_BLOCK;
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ return FormatID::BC1_RGB_UNORM_SRGB_BLOCK;
+ case GL_DEPTH24_STENCIL8:
+ return FormatID::D24_UNORM_S8_UINT;
+ case GL_DEPTH32F_STENCIL8:
+ return FormatID::D32_FLOAT_S8X24_UINT;
+ case GL_DEPTH_COMPONENT16:
+ return FormatID::D16_UNORM;
+ case GL_DEPTH_COMPONENT24:
+ return FormatID::D24_UNORM_X8_UINT;
+ case GL_DEPTH_COMPONENT32F:
+ return FormatID::D32_FLOAT;
+ case GL_DEPTH_COMPONENT32_OES:
+ return FormatID::D32_UNORM;
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ return FormatID::ETC1_LOSSY_DECODE_R8G8B8_UNORM_BLOCK;
+ case GL_ETC1_RGB8_OES:
+ return FormatID::ETC1_R8G8B8_UNORM_BLOCK;
+ case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE:
+ return FormatID::G8_B8R8_2PLANE_420_UNORM;
+ case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE:
+ return FormatID::G8_B8_R8_3PLANE_420_UNORM;
+ case GL_INT_10_10_10_2_OES:
+ return FormatID::A2R10G10B10_SINT_VERTEX;
+ case GL_LUMINANCE16F_EXT:
+ return FormatID::L16_FLOAT;
+ case GL_LUMINANCE32F_EXT:
+ return FormatID::L32_FLOAT;
+ case GL_LUMINANCE8_ALPHA8_EXT:
+ return FormatID::L8A8_UNORM;
+ case GL_LUMINANCE8_EXT:
+ return FormatID::L8_UNORM;
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ return FormatID::L16A16_FLOAT;
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ return FormatID::L32A32_FLOAT;
+ case GL_NONE:
+ return FormatID::NONE;
+ case GL_PALETTE4_R5_G6_B5_OES:
+ return FormatID::PALETTE4_R5G6B5_UNORM;
+ case GL_PALETTE4_RGB5_A1_OES:
+ return FormatID::PALETTE4_R5G5B5A1_UNORM;
+ case GL_PALETTE4_RGB8_OES:
+ return FormatID::PALETTE4_R8G8B8_UNORM;
+ case GL_PALETTE4_RGBA4_OES:
+ return FormatID::PALETTE4_R4G4B4A4_UNORM;
+ case GL_PALETTE4_RGBA8_OES:
+ return FormatID::PALETTE4_R8G8B8A8_UNORM;
+ case GL_PALETTE8_R5_G6_B5_OES:
+ return FormatID::PALETTE8_R5G6B5_UNORM;
+ case GL_PALETTE8_RGB5_A1_OES:
+ return FormatID::PALETTE8_R5G5B5A1_UNORM;
+ case GL_PALETTE8_RGB8_OES:
+ return FormatID::PALETTE8_R8G8B8_UNORM;
+ case GL_PALETTE8_RGBA4_OES:
+ return FormatID::PALETTE8_R4G4B4A4_UNORM;
+ case GL_PALETTE8_RGBA8_OES:
+ return FormatID::PALETTE8_R8G8B8A8_UNORM;
+ case GL_R11F_G11F_B10F:
+ return FormatID::R11G11B10_FLOAT;
+ case GL_R16F:
+ return FormatID::R16_FLOAT;
+ case GL_R16I:
+ return FormatID::R16_SINT;
+ case GL_R16UI:
+ return FormatID::R16_UINT;
+ case GL_R16_EXT:
+ return FormatID::R16_UNORM;
+ case GL_R16_SNORM_EXT:
+ return FormatID::R16_SNORM;
+ case GL_R16_SSCALED_ANGLEX:
+ return FormatID::R16_SSCALED;
+ case GL_R16_USCALED_ANGLEX:
+ return FormatID::R16_USCALED;
+ case GL_R32F:
+ return FormatID::R32_FLOAT;
+ case GL_R32I:
+ return FormatID::R32_SINT;
+ case GL_R32UI:
+ return FormatID::R32_UINT;
+ case GL_R32_FIXED_ANGLEX:
+ return FormatID::R32_FIXED;
+ case GL_R32_SNORM_ANGLEX:
+ return FormatID::R32_SNORM;
+ case GL_R32_SSCALED_ANGLEX:
+ return FormatID::R32_SSCALED;
+ case GL_R32_UNORM_ANGLEX:
+ return FormatID::R32_UNORM;
+ case GL_R32_USCALED_ANGLEX:
+ return FormatID::R32_USCALED;
+ case GL_R8:
+ return FormatID::R8_UNORM;
+ case GL_R8I:
+ return FormatID::R8_SINT;
+ case GL_R8UI:
+ return FormatID::R8_UINT;
+ case GL_R8_SNORM:
+ return FormatID::R8_SNORM;
+ case GL_R8_SSCALED_ANGLEX:
+ return FormatID::R8_SSCALED;
+ case GL_R8_USCALED_ANGLEX:
+ return FormatID::R8_USCALED;
+ case GL_RG16F:
+ return FormatID::R16G16_FLOAT;
+ case GL_RG16I:
+ return FormatID::R16G16_SINT;
+ case GL_RG16UI:
+ return FormatID::R16G16_UINT;
+ case GL_RG16_EXT:
+ return FormatID::R16G16_UNORM;
+ case GL_RG16_SNORM_EXT:
+ return FormatID::R16G16_SNORM;
+ case GL_RG16_SSCALED_ANGLEX:
+ return FormatID::R16G16_SSCALED;
+ case GL_RG16_USCALED_ANGLEX:
+ return FormatID::R16G16_USCALED;
+ case GL_RG32F:
+ return FormatID::R32G32_FLOAT;
+ case GL_RG32I:
+ return FormatID::R32G32_SINT;
+ case GL_RG32UI:
+ return FormatID::R32G32_UINT;
+ case GL_RG32_FIXED_ANGLEX:
+ return FormatID::R32G32_FIXED;
+ case GL_RG32_SNORM_ANGLEX:
+ return FormatID::R32G32_SNORM;
+ case GL_RG32_SSCALED_ANGLEX:
+ return FormatID::R32G32_SSCALED;
+ case GL_RG32_UNORM_ANGLEX:
+ return FormatID::R32G32_UNORM;
+ case GL_RG32_USCALED_ANGLEX:
+ return FormatID::R32G32_USCALED;
+ case GL_RG8:
+ return FormatID::R8G8_UNORM;
+ case GL_RG8I:
+ return FormatID::R8G8_SINT;
+ case GL_RG8UI:
+ return FormatID::R8G8_UINT;
+ case GL_RG8_SNORM:
+ return FormatID::R8G8_SNORM;
+ case GL_RG8_SSCALED_ANGLEX:
+ return FormatID::R8G8_SSCALED;
+ case GL_RG8_USCALED_ANGLEX:
+ return FormatID::R8G8_USCALED;
+ case GL_RGB:
+ return FormatID::R8G8B8_UNORM;
+ case GL_RGB10_A2:
+ return FormatID::R10G10B10A2_UNORM;
+ case GL_RGB10_A2UI:
+ return FormatID::R10G10B10A2_UINT;
+ case GL_RGB10_A2_SINT_ANGLEX:
+ return FormatID::R10G10B10A2_SINT;
+ case GL_RGB10_A2_SNORM_ANGLEX:
+ return FormatID::R10G10B10A2_SNORM;
+ case GL_RGB10_A2_SSCALED_ANGLEX:
+ return FormatID::R10G10B10A2_SSCALED;
+ case GL_RGB10_A2_USCALED_ANGLEX:
+ return FormatID::R10G10B10A2_USCALED;
+ case GL_RGB10_UNORM_ANGLEX:
+ return FormatID::R10G10B10X2_UNORM;
+ case GL_RGB16F:
+ return FormatID::R16G16B16_FLOAT;
+ case GL_RGB16I:
+ return FormatID::R16G16B16_SINT;
+ case GL_RGB16UI:
+ return FormatID::R16G16B16_UINT;
+ case GL_RGB16_EXT:
+ return FormatID::R16G16B16_UNORM;
+ case GL_RGB16_SNORM_EXT:
+ return FormatID::R16G16B16_SNORM;
+ case GL_RGB16_SSCALED_ANGLEX:
+ return FormatID::R16G16B16_SSCALED;
+ case GL_RGB16_USCALED_ANGLEX:
+ return FormatID::R16G16B16_USCALED;
+ case GL_RGB32F:
+ return FormatID::R32G32B32_FLOAT;
+ case GL_RGB32I:
+ return FormatID::R32G32B32_SINT;
+ case GL_RGB32UI:
+ return FormatID::R32G32B32_UINT;
+ case GL_RGB32_FIXED_ANGLEX:
+ return FormatID::R32G32B32_FIXED;
+ case GL_RGB32_SNORM_ANGLEX:
+ return FormatID::R32G32B32_SNORM;
+ case GL_RGB32_SSCALED_ANGLEX:
+ return FormatID::R32G32B32_SSCALED;
+ case GL_RGB32_UNORM_ANGLEX:
+ return FormatID::R32G32B32_UNORM;
+ case GL_RGB32_USCALED_ANGLEX:
+ return FormatID::R32G32B32_USCALED;
+ case GL_RGB565:
+ return FormatID::R5G6B5_UNORM;
+ case GL_RGB5_A1:
+ return FormatID::R5G5B5A1_UNORM;
+ case GL_RGB8:
+ return FormatID::R8G8B8_UNORM;
+ case GL_RGB8I:
+ return FormatID::R8G8B8_SINT;
+ case GL_RGB8UI:
+ return FormatID::R8G8B8_UINT;
+ case GL_RGB8_SNORM:
+ return FormatID::R8G8B8_SNORM;
+ case GL_RGB8_SSCALED_ANGLEX:
+ return FormatID::R8G8B8_SSCALED;
+ case GL_RGB8_USCALED_ANGLEX:
+ return FormatID::R8G8B8_USCALED;
+ case GL_RGB9_E5:
+ return FormatID::R9G9B9E5_SHAREDEXP;
+ case GL_RGBA:
+ return FormatID::R8G8B8A8_UNORM;
+ case GL_RGBA16F:
+ return FormatID::R16G16B16A16_FLOAT;
+ case GL_RGBA16I:
+ return FormatID::R16G16B16A16_SINT;
+ case GL_RGBA16UI:
+ return FormatID::R16G16B16A16_UINT;
+ case GL_RGBA16_EXT:
+ return FormatID::R16G16B16A16_UNORM;
+ case GL_RGBA16_SNORM_EXT:
+ return FormatID::R16G16B16A16_SNORM;
+ case GL_RGBA16_SSCALED_ANGLEX:
+ return FormatID::R16G16B16A16_SSCALED;
+ case GL_RGBA16_USCALED_ANGLEX:
+ return FormatID::R16G16B16A16_USCALED;
+ case GL_RGBA32F:
+ return FormatID::R32G32B32A32_FLOAT;
+ case GL_RGBA32I:
+ return FormatID::R32G32B32A32_SINT;
+ case GL_RGBA32UI:
+ return FormatID::R32G32B32A32_UINT;
+ case GL_RGBA32_FIXED_ANGLEX:
+ return FormatID::R32G32B32A32_FIXED;
+ case GL_RGBA32_SNORM_ANGLEX:
+ return FormatID::R32G32B32A32_SNORM;
+ case GL_RGBA32_SSCALED_ANGLEX:
+ return FormatID::R32G32B32A32_SSCALED;
+ case GL_RGBA32_UNORM_ANGLEX:
+ return FormatID::R32G32B32A32_UNORM;
+ case GL_RGBA32_USCALED_ANGLEX:
+ return FormatID::R32G32B32A32_USCALED;
+ case GL_RGBA4:
+ return FormatID::R4G4B4A4_UNORM;
+ case GL_RGBA8:
+ return FormatID::R8G8B8A8_UNORM;
+ case GL_RGBA8I:
+ return FormatID::R8G8B8A8_SINT;
+ case GL_RGBA8UI:
+ return FormatID::R8G8B8A8_UINT;
+ case GL_RGBA8_SNORM:
+ return FormatID::R8G8B8A8_SNORM;
+ case GL_RGBA8_SSCALED_ANGLEX:
+ return FormatID::R8G8B8A8_SSCALED;
+ case GL_RGBA8_TYPELESS_ANGLEX:
+ return FormatID::R8G8B8A8_TYPELESS;
+ case GL_RGBA8_TYPELESS_SRGB_ANGLEX:
+ return FormatID::R8G8B8A8_TYPELESS_SRGB;
+ case GL_RGBA8_USCALED_ANGLEX:
+ return FormatID::R8G8B8A8_USCALED;
+ case GL_RGBX8_ANGLE:
+ return FormatID::R8G8B8X8_UNORM;
+ case GL_SR8_EXT:
+ return FormatID::R8_UNORM_SRGB;
+ case GL_SRG8_EXT:
+ return FormatID::R8G8_UNORM_SRGB;
+ case GL_SRGB8:
+ return FormatID::R8G8B8_UNORM_SRGB;
+ case GL_SRGB8_ALPHA8:
+ return FormatID::R8G8B8A8_UNORM_SRGB;
+ case GL_STENCIL_INDEX8:
+ return FormatID::S8_UINT;
+ case GL_UNSIGNED_INT_10_10_10_2_OES:
+ return FormatID::A2R10G10B10_UINT_VERTEX;
+ case GL_X2_RGB10_SINT_ANGLEX:
+ return FormatID::X2R10G10B10_SINT_VERTEX;
+ case GL_X2_RGB10_SNORM_ANGLEX:
+ return FormatID::X2R10G10B10_SNORM_VERTEX;
+ case GL_X2_RGB10_SSCALED_ANGLEX:
+ return FormatID::X2R10G10B10_SSCALED_VERTEX;
+ case GL_X2_RGB10_UINT_ANGLEX:
+ return FormatID::X2R10G10B10_UINT_VERTEX;
+ case GL_X2_RGB10_UNORM_ANGLEX:
+ return FormatID::X2R10G10B10_UNORM_VERTEX;
+ case GL_X2_RGB10_USCALED_ANGLEX:
+ return FormatID::X2R10G10B10_USCALED_VERTEX;
+ default:
+ return FormatID::NONE;
+ }
+}
+
+const Format *GetFormatInfoTable()
+{
+ return gFormatInfoTable;
+}
+} // namespace angle
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h
new file mode 100644
index 0000000000..0b5223ae5d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/FramebufferAttachmentObjectImpl.h
@@ -0,0 +1,65 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FramebufferAttachmentObjectImpl.h:
+// Common ancenstor for all implementations of FBO attachable-objects.
+// This means Surfaces, Textures and Renderbuffers.
+//
+
+#ifndef LIBANGLE_RENDERER_FRAMEBUFFER_ATTACHMENT_OBJECT_IMPL_H_
+#define LIBANGLE_RENDERER_FRAMEBUFFER_ATTACHMENT_OBJECT_IMPL_H_
+
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/Observer.h"
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace rx
+{
+class FramebufferAttachmentRenderTarget;
+
+class FramebufferAttachmentObjectImpl : public angle::Subject
+{
+ public:
+ FramebufferAttachmentObjectImpl() {}
+ ~FramebufferAttachmentObjectImpl() override {}
+
+ virtual angle::Result getAttachmentRenderTarget(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
+ GLsizei samples,
+ FramebufferAttachmentRenderTarget **rtOut);
+
+ virtual angle::Result initializeContents(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex);
+};
+
+inline angle::Result FramebufferAttachmentObjectImpl::getAttachmentRenderTarget(
+ const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
+ GLsizei samples,
+ FramebufferAttachmentRenderTarget **rtOut)
+{
+ UNIMPLEMENTED();
+ return angle::Result::Stop;
+}
+
+inline angle::Result FramebufferAttachmentObjectImpl::initializeContents(
+ const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex)
+{
+ UNIMPLEMENTED();
+ return angle::Result::Stop;
+}
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_FRAMEBUFFER_ATTACHMENT_OBJECT_IMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/FramebufferImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/FramebufferImpl.cpp
new file mode 100644
index 0000000000..1cef167d9d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/FramebufferImpl.cpp
@@ -0,0 +1,18 @@
+//
+// Copyright 2022 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FramebufferImpl.cpp: Implements the class methods for FramebufferImpl.
+
+#include "libANGLE/renderer/FramebufferImpl.h"
+
+namespace rx
+{
+
+angle::Result FramebufferImpl::onLabelUpdate(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/FramebufferImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/FramebufferImpl.h
new file mode 100644
index 0000000000..0ecfaba4f2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/FramebufferImpl.h
@@ -0,0 +1,123 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FramebufferImpl.h: Defines the abstract rx::FramebufferImpl class.
+
+#ifndef LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_
+#define LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/State.h"
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+class Buffer;
+class Framebuffer;
+class FramebufferAttachment;
+struct PixelPackState;
+} // namespace gl
+
+namespace rx
+{
+class DisplayImpl;
+
+class FramebufferImpl : angle::NonCopyable
+{
+ public:
+ explicit FramebufferImpl(const gl::FramebufferState &state) : mState(state) {}
+ virtual ~FramebufferImpl() {}
+ virtual void destroy(const gl::Context *context) {}
+
+ virtual angle::Result discard(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments) = 0;
+ virtual angle::Result invalidate(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments) = 0;
+ virtual angle::Result invalidateSub(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area) = 0;
+
+ virtual angle::Result clear(const gl::Context *context, GLbitfield mask) = 0;
+ virtual angle::Result clearBufferfv(const gl::Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values) = 0;
+ virtual angle::Result clearBufferuiv(const gl::Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values) = 0;
+ virtual angle::Result clearBufferiv(const gl::Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values) = 0;
+ virtual angle::Result clearBufferfi(const gl::Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil) = 0;
+
+ virtual const gl::InternalFormat &getImplementationColorReadFormat(
+ const gl::Context *context) const;
+ virtual angle::Result readPixels(const gl::Context *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelPackState &pack,
+ gl::Buffer *packBuffer,
+ void *pixels) = 0;
+
+ virtual angle::Result blit(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter) = 0;
+
+ virtual gl::FramebufferStatus checkStatus(const gl::Context *context) const = 0;
+
+ virtual angle::Result syncState(const gl::Context *context,
+ GLenum binding,
+ const gl::Framebuffer::DirtyBits &dirtyBits,
+ gl::Command command) = 0;
+
+ virtual angle::Result getSamplePosition(const gl::Context *context,
+ size_t index,
+ GLfloat *xy) const = 0;
+
+ // Special configuration option for checkStatus(). Some back-ends don't require a syncState
+ // before calling checkStatus. In practice the GL back-end is the only config that needs
+ // syncState because it depends on the behaviour of the driver. Allowing the Vulkan and
+ // D3D back-ends to skip syncState lets us do more work in the syncState call.
+ virtual bool shouldSyncStateBeforeCheckStatus() const;
+
+ virtual angle::Result onLabelUpdate(const gl::Context *context);
+
+ const gl::FramebufferState &getState() const { return mState; }
+
+ protected:
+ const gl::FramebufferState &mState;
+};
+
+inline bool FramebufferImpl::shouldSyncStateBeforeCheckStatus() const
+{
+ return false;
+}
+
+// Default implementation returns the format specified in the attachment.
+inline const gl::InternalFormat &FramebufferImpl::getImplementationColorReadFormat(
+ const gl::Context *context) const
+{
+ const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment();
+ return *readAttachment->getFormat().info;
+}
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/GLImplFactory.h b/gfx/angle/checkout/src/libANGLE/renderer/GLImplFactory.h
new file mode 100644
index 0000000000..1995197b06
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/GLImplFactory.h
@@ -0,0 +1,116 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// GLImplFactory.h:
+// Factory interface for OpenGL ES Impl objects.
+//
+
+#ifndef LIBANGLE_RENDERER_GLIMPLFACTORY_H_
+#define LIBANGLE_RENDERER_GLIMPLFACTORY_H_
+
+#include <vector>
+
+#include "angle_gl.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Overlay.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/ProgramPipeline.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/renderer/serial_utils.h"
+
+namespace gl
+{
+class State;
+} // namespace gl
+
+namespace rx
+{
+class BufferImpl;
+class CompilerImpl;
+class ContextImpl;
+class FenceNVImpl;
+class SyncImpl;
+class FramebufferImpl;
+class MemoryObjectImpl;
+class OverlayImpl;
+class PathImpl;
+class ProgramImpl;
+class ProgramPipelineImpl;
+class QueryImpl;
+class RenderbufferImpl;
+class SamplerImpl;
+class SemaphoreImpl;
+class ShaderImpl;
+class TextureImpl;
+class TransformFeedbackImpl;
+class VertexArrayImpl;
+
+class GLImplFactory : angle::NonCopyable
+{
+ public:
+ GLImplFactory();
+ virtual ~GLImplFactory();
+
+ // Shader creation
+ virtual CompilerImpl *createCompiler() = 0;
+ virtual ShaderImpl *createShader(const gl::ShaderState &data) = 0;
+ virtual ProgramImpl *createProgram(const gl::ProgramState &data) = 0;
+
+ // Framebuffer creation
+ virtual FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) = 0;
+
+ // Texture creation
+ virtual TextureImpl *createTexture(const gl::TextureState &state) = 0;
+
+ // Renderbuffer creation
+ virtual RenderbufferImpl *createRenderbuffer(const gl::RenderbufferState &state) = 0;
+
+ // Buffer creation
+ virtual BufferImpl *createBuffer(const gl::BufferState &state) = 0;
+
+ // Vertex Array creation
+ virtual VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) = 0;
+
+ // Query and Fence creation
+ virtual QueryImpl *createQuery(gl::QueryType type) = 0;
+ virtual FenceNVImpl *createFenceNV() = 0;
+ virtual SyncImpl *createSync() = 0;
+
+ // Transform Feedback creation
+ virtual TransformFeedbackImpl *createTransformFeedback(
+ const gl::TransformFeedbackState &state) = 0;
+
+ // Sampler object creation
+ virtual SamplerImpl *createSampler(const gl::SamplerState &state) = 0;
+
+ // Program Pipeline object creation
+ virtual ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) = 0;
+
+ // Memory object creation
+ virtual MemoryObjectImpl *createMemoryObject() = 0;
+
+ // Semaphore creation
+ virtual SemaphoreImpl *createSemaphore() = 0;
+
+ // Overlay creation
+ virtual OverlayImpl *createOverlay(const gl::OverlayState &state) = 0;
+
+ rx::Serial generateSerial() { return mSerialFactory.generate(); }
+
+ private:
+ rx::SerialFactory mSerialFactory;
+};
+
+inline GLImplFactory::GLImplFactory() = default;
+
+inline GLImplFactory::~GLImplFactory() = default;
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GLIMPLFACTORY_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/ImageImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/ImageImpl.cpp
new file mode 100644
index 0000000000..014b1d634d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/ImageImpl.cpp
@@ -0,0 +1,30 @@
+//
+// Copyright 2021 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ImageImpl.cpp: Defines the rx::ImageImpl class representing the EGLimage object.
+
+#include "libANGLE/renderer/ImageImpl.h"
+
+namespace rx
+{
+
+bool ExternalImageSiblingImpl::isCubeMap() const
+{
+ return false;
+}
+
+uint32_t ExternalImageSiblingImpl::getLevelCount() const
+{
+ return 1;
+}
+
+egl::Error ImageImpl::exportVkImage(void *vkImage, void *vkImageCreateInfo)
+{
+ UNIMPLEMENTED();
+ return egl::EglBadAccess();
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/ImageImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/ImageImpl.h
new file mode 100644
index 0000000000..2a316610b3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/ImageImpl.h
@@ -0,0 +1,68 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ImageImpl.h: Defines the rx::ImageImpl class representing the EGLimage object.
+
+#ifndef LIBANGLE_RENDERER_IMAGEIMPL_H_
+#define LIBANGLE_RENDERER_IMAGEIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace egl
+{
+class Display;
+class ImageSibling;
+struct ImageState;
+} // namespace egl
+
+namespace rx
+{
+class ExternalImageSiblingImpl : public FramebufferAttachmentObjectImpl
+{
+ public:
+ ~ExternalImageSiblingImpl() override {}
+
+ virtual egl::Error initialize(const egl::Display *display) = 0;
+ virtual void onDestroy(const egl::Display *display) {}
+
+ virtual gl::Format getFormat() const = 0;
+ virtual bool isRenderable(const gl::Context *context) const = 0;
+ virtual bool isTexturable(const gl::Context *context) const = 0;
+ virtual bool isYUV() const = 0;
+ virtual bool isCubeMap() const;
+ virtual bool hasProtectedContent() const = 0;
+ virtual gl::Extents getSize() const = 0;
+ virtual size_t getSamples() const = 0;
+ virtual uint32_t getLevelCount() const;
+};
+
+class ImageImpl : angle::NonCopyable
+{
+ public:
+ ImageImpl(const egl::ImageState &state) : mState(state) {}
+ virtual ~ImageImpl() {}
+ virtual void onDestroy(const egl::Display *display) {}
+
+ virtual egl::Error initialize(const egl::Display *display) = 0;
+
+ virtual angle::Result orphan(const gl::Context *context, egl::ImageSibling *sibling) = 0;
+
+ virtual egl::Error exportVkImage(void *vkImage, void *vkImageCreateInfo);
+
+ protected:
+ const egl::ImageState &mState;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_IMAGEIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/MemoryObjectImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/MemoryObjectImpl.h
new file mode 100644
index 0000000000..ce37dd3545
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/MemoryObjectImpl.h
@@ -0,0 +1,47 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// MemoryObjectImpl.h: Implements the rx::MemoryObjectImpl class [EXT_external_objects]
+
+#ifndef LIBANGLE_RENDERER_MEMORYOBJECTIMPL_H_
+#define LIBANGLE_RENDERER_MEMORYOBJECTIMPL_H_
+
+#include "angle_gl.h"
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+namespace gl
+{
+class Context;
+class MemoryObject;
+} // namespace gl
+
+namespace rx
+{
+
+class MemoryObjectImpl : angle::NonCopyable
+{
+ public:
+ virtual ~MemoryObjectImpl() {}
+
+ virtual void onDestroy(const gl::Context *context) = 0;
+
+ virtual angle::Result setDedicatedMemory(const gl::Context *context, bool dedicatedMemory) = 0;
+ virtual angle::Result setProtectedMemory(const gl::Context *context, bool protectedMemory) = 0;
+
+ virtual angle::Result importFd(gl::Context *context,
+ GLuint64 size,
+ gl::HandleType handleType,
+ GLint fd) = 0;
+ virtual angle::Result importZirconHandle(gl::Context *context,
+ GLuint64 size,
+ gl::HandleType handleType,
+ GLuint handle) = 0;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_MEMORYOBJECTIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/OverlayImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/OverlayImpl.h
new file mode 100644
index 0000000000..fc1b1b0d58
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/OverlayImpl.h
@@ -0,0 +1,42 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// OverlayImpl.h: Defines the abstract rx::OverlayImpl class.
+
+#ifndef LIBANGLE_RENDERER_OVERLAYIMPL_H_
+#define LIBANGLE_RENDERER_OVERLAYIMPL_H_
+
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Observer.h"
+
+#include <stdint.h>
+
+namespace gl
+{
+class Context;
+class OverlayState;
+} // namespace gl
+
+namespace rx
+{
+class OverlayImpl : angle::NonCopyable
+{
+ public:
+ OverlayImpl(const gl::OverlayState &state) : mState(state) {}
+ virtual ~OverlayImpl() {}
+
+ virtual void onDestroy(const gl::Context *context) {}
+
+ protected:
+ const gl::OverlayState &mState;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_OVERLAYIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/ProgramImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/ProgramImpl.cpp
new file mode 100644
index 0000000000..9ede4a882d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/ProgramImpl.cpp
@@ -0,0 +1,18 @@
+//
+// Copyright 2022 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ProgramImpl.cpp: Implements the class methods for ProgramImpl.
+
+#include "libANGLE/renderer/ProgramImpl.h"
+
+namespace rx
+{
+
+angle::Result ProgramImpl::onLabelUpdate(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/ProgramImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/ProgramImpl.h
new file mode 100644
index 0000000000..22bd304856
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/ProgramImpl.h
@@ -0,0 +1,176 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramImpl.h: Defines the abstract rx::ProgramImpl class.
+
+#ifndef LIBANGLE_RENDERER_PROGRAMIMPL_H_
+#define LIBANGLE_RENDERER_PROGRAMIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/BinaryStream.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Shader.h"
+
+#include <map>
+
+namespace gl
+{
+class Context;
+struct ProgramLinkedResources;
+} // namespace gl
+
+namespace sh
+{
+struct BlockMemberInfo;
+}
+
+namespace rx
+{
+
+// Provides a mechanism to access the result of asynchronous linking.
+class LinkEvent : angle::NonCopyable
+{
+ public:
+ virtual ~LinkEvent() {}
+
+ // Please be aware that these methods may be called under a gl::Context other
+ // than the one where the LinkEvent was created.
+ //
+ // Waits until the linking is actually done. Returns true if the linking
+ // succeeded, false otherwise.
+ virtual angle::Result wait(const gl::Context *context) = 0;
+ // Peeks whether the linking is still ongoing.
+ virtual bool isLinking() = 0;
+};
+
+// Wraps an already done linking.
+class LinkEventDone final : public LinkEvent
+{
+ public:
+ LinkEventDone(angle::Result result) : mResult(result) {}
+ angle::Result wait(const gl::Context *context) override;
+ bool isLinking() override;
+
+ private:
+ angle::Result mResult;
+};
+
+inline angle::Result LinkEventDone::wait(const gl::Context *context)
+{
+ return mResult;
+}
+inline bool LinkEventDone::isLinking()
+{
+ return false;
+}
+
+class ProgramImpl : angle::NonCopyable
+{
+ public:
+ ProgramImpl(const gl::ProgramState &state) : mState(state) {}
+ virtual ~ProgramImpl() {}
+ virtual void destroy(const gl::Context *context) {}
+
+ virtual std::unique_ptr<LinkEvent> load(const gl::Context *context,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog) = 0;
+ virtual void save(const gl::Context *context, gl::BinaryOutputStream *stream) = 0;
+ virtual void setBinaryRetrievableHint(bool retrievable) = 0;
+ virtual void setSeparable(bool separable) = 0;
+
+ virtual std::unique_ptr<LinkEvent> link(const gl::Context *context,
+ const gl::ProgramLinkedResources &resources,
+ gl::InfoLog &infoLog,
+ const gl::ProgramMergedVaryings &mergedVaryings) = 0;
+ virtual GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) = 0;
+
+ virtual void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) = 0;
+ virtual void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) = 0;
+ virtual void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) = 0;
+ virtual void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) = 0;
+ virtual void setUniform1iv(GLint location, GLsizei count, const GLint *v) = 0;
+ virtual void setUniform2iv(GLint location, GLsizei count, const GLint *v) = 0;
+ virtual void setUniform3iv(GLint location, GLsizei count, const GLint *v) = 0;
+ virtual void setUniform4iv(GLint location, GLsizei count, const GLint *v) = 0;
+ virtual void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) = 0;
+ virtual void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) = 0;
+ virtual void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) = 0;
+ virtual void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) = 0;
+ virtual void setUniformMatrix2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) = 0;
+ virtual void setUniformMatrix3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) = 0;
+ virtual void setUniformMatrix4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) = 0;
+ virtual void setUniformMatrix2x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) = 0;
+ virtual void setUniformMatrix3x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) = 0;
+ virtual void setUniformMatrix2x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) = 0;
+ virtual void setUniformMatrix4x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) = 0;
+ virtual void setUniformMatrix3x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) = 0;
+ virtual void setUniformMatrix4x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) = 0;
+
+ // Done in the back-end to avoid having to keep a system copy of uniform data.
+ virtual void getUniformfv(const gl::Context *context,
+ GLint location,
+ GLfloat *params) const = 0;
+ virtual void getUniformiv(const gl::Context *context, GLint location, GLint *params) const = 0;
+ virtual void getUniformuiv(const gl::Context *context,
+ GLint location,
+ GLuint *params) const = 0;
+
+ // Implementation-specific method for ignoring unreferenced uniforms. Some implementations may
+ // perform more extensive analysis and ignore some locations that ANGLE doesn't detect as
+ // unreferenced. This method is not required to be overriden by a back-end.
+ virtual void markUnusedUniformLocations(std::vector<gl::VariableLocation> *uniformLocations,
+ std::vector<gl::SamplerBinding> *samplerBindings,
+ std::vector<gl::ImageBinding> *imageBindings)
+ {}
+
+ const gl::ProgramState &getState() const { return mState; }
+
+ virtual angle::Result syncState(const gl::Context *context,
+ const gl::Program::DirtyBits &dirtyBits);
+
+ virtual angle::Result onLabelUpdate(const gl::Context *context);
+
+ protected:
+ const gl::ProgramState &mState;
+};
+
+inline angle::Result ProgramImpl::syncState(const gl::Context *context,
+ const gl::Program::DirtyBits &dirtyBits)
+{
+ return angle::Result::Continue;
+}
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_PROGRAMIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/ProgramPipelineImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/ProgramPipelineImpl.cpp
new file mode 100644
index 0000000000..c90fb11da0
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/ProgramPipelineImpl.cpp
@@ -0,0 +1,26 @@
+//
+// Copyright 2022 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramPipelineImpl.cpp: Defines the abstract rx::ProgramPipelineImpl class.
+
+#include "libANGLE/renderer/ProgramPipelineImpl.h"
+
+namespace rx
+{
+
+angle::Result ProgramPipelineImpl::link(const gl::Context *context,
+ const gl::ProgramMergedVaryings &mergedVaryings,
+ const gl::ProgramVaryingPacking &varyingPacking)
+{
+ return angle::Result::Continue;
+}
+
+angle::Result ProgramPipelineImpl::onLabelUpdate(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/ProgramPipelineImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/ProgramPipelineImpl.h
new file mode 100644
index 0000000000..7f69571a9f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/ProgramPipelineImpl.h
@@ -0,0 +1,42 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramPipelineImpl.h: Defines the abstract rx::ProgramPipelineImpl class.
+
+#ifndef LIBANGLE_RENDERER_PROGRAMPIPELINEIMPL_H_
+#define LIBANGLE_RENDERER_PROGRAMPIPELINEIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/ProgramPipeline.h"
+
+namespace rx
+{
+class ContextImpl;
+
+class ProgramPipelineImpl : public angle::NonCopyable
+{
+ public:
+ ProgramPipelineImpl(const gl::ProgramPipelineState &state) : mState(state) {}
+ virtual ~ProgramPipelineImpl() {}
+ virtual void destroy(const gl::Context *context) {}
+
+ virtual angle::Result link(const gl::Context *context,
+ const gl::ProgramMergedVaryings &mergedVaryings,
+ const gl::ProgramVaryingPacking &varyingPacking);
+
+ virtual void onProgramUniformUpdate(gl::ShaderType shaderType) {}
+
+ virtual angle::Result onLabelUpdate(const gl::Context *context);
+
+ const gl::ProgramPipelineState &getState() const { return mState; }
+
+ protected:
+ const gl::ProgramPipelineState &mState;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_PROGRAMPIPELINEIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/QueryImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/QueryImpl.cpp
new file mode 100644
index 0000000000..ed9497e2a3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/QueryImpl.cpp
@@ -0,0 +1,21 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// QueryImpl.cpp: Defines the abstract rx::QueryImpl classes.
+
+#include "libANGLE/renderer/QueryImpl.h"
+
+namespace rx
+{
+
+void QueryImpl::onDestroy(const gl::Context *context) {}
+
+angle::Result QueryImpl::onLabelUpdate(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/QueryImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/QueryImpl.h
new file mode 100644
index 0000000000..8e5e351418
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/QueryImpl.h
@@ -0,0 +1,49 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// QueryImpl.h: Defines the abstract rx::QueryImpl class.
+
+#ifndef LIBANGLE_RENDERER_QUERYIMPL_H_
+#define LIBANGLE_RENDERER_QUERYIMPL_H_
+
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace rx
+{
+class QueryImpl : angle::NonCopyable
+{
+ public:
+ explicit QueryImpl(gl::QueryType type) : mType(type) {}
+ virtual ~QueryImpl() {}
+
+ virtual void onDestroy(const gl::Context *context);
+
+ virtual angle::Result begin(const gl::Context *context) = 0;
+ virtual angle::Result end(const gl::Context *context) = 0;
+ virtual angle::Result queryCounter(const gl::Context *context) = 0;
+ virtual angle::Result getResult(const gl::Context *context, GLint *params) = 0;
+ virtual angle::Result getResult(const gl::Context *context, GLuint *params) = 0;
+ virtual angle::Result getResult(const gl::Context *context, GLint64 *params) = 0;
+ virtual angle::Result getResult(const gl::Context *context, GLuint64 *params) = 0;
+ virtual angle::Result isResultAvailable(const gl::Context *context, bool *available) = 0;
+
+ virtual angle::Result onLabelUpdate(const gl::Context *context);
+
+ gl::QueryType getType() const { return mType; }
+
+ protected:
+ gl::QueryType mType;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_QUERYIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/RenderTargetCache.h b/gfx/angle/checkout/src/libANGLE/renderer/RenderTargetCache.h
new file mode 100644
index 0000000000..ffc2a04492
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/RenderTargetCache.h
@@ -0,0 +1,186 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// RenderTargetCache:
+// The RenderTargetCache pattern is used in the D3D9, D3D11 and Vulkan back-ends. It is a
+// cache of the various back-end objects (RenderTargets) associated with each Framebuffer
+// attachment, be they Textures, Renderbuffers, or Surfaces. The cache is updated in Framebuffer's
+// syncState method.
+//
+
+#ifndef LIBANGLE_RENDERER_RENDER_TARGET_CACHE_H_
+#define LIBANGLE_RENDERER_RENDER_TARGET_CACHE_H_
+
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+
+namespace rx
+{
+
+template <typename RenderTargetT>
+class RenderTargetCache final : angle::NonCopyable
+{
+ public:
+ RenderTargetCache();
+ ~RenderTargetCache();
+
+ // Update all RenderTargets from the dirty bits.
+ angle::Result update(const gl::Context *context,
+ const gl::FramebufferState &state,
+ const gl::Framebuffer::DirtyBits &dirtyBits);
+
+ // Update individual RenderTargets.
+ angle::Result updateReadColorRenderTarget(const gl::Context *context,
+ const gl::FramebufferState &state);
+ angle::Result updateColorRenderTarget(const gl::Context *context,
+ const gl::FramebufferState &state,
+ size_t colorIndex);
+ angle::Result updateDepthStencilRenderTarget(const gl::Context *context,
+ const gl::FramebufferState &state);
+
+ using RenderTargetArray = gl::AttachmentArray<RenderTargetT *>;
+
+ const RenderTargetArray &getColors() const;
+ RenderTargetT *getDepthStencil() const;
+
+ RenderTargetT *getColorDraw(const gl::FramebufferState &state, size_t colorIndex) const;
+ RenderTargetT *getColorRead(const gl::FramebufferState &state) const;
+
+ private:
+ angle::Result updateCachedRenderTarget(const gl::Context *context,
+ const gl::FramebufferAttachment *attachment,
+ RenderTargetT **cachedRenderTarget);
+
+ RenderTargetT *mReadRenderTarget = nullptr;
+ gl::AttachmentArray<RenderTargetT *> mColorRenderTargets = {};
+ // We only support a single Depth/Stencil RenderTarget currently.
+ RenderTargetT *mDepthStencilRenderTarget = nullptr;
+};
+
+template <typename RenderTargetT>
+RenderTargetCache<RenderTargetT>::RenderTargetCache() = default;
+
+template <typename RenderTargetT>
+RenderTargetCache<RenderTargetT>::~RenderTargetCache() = default;
+
+template <typename RenderTargetT>
+angle::Result RenderTargetCache<RenderTargetT>::update(const gl::Context *context,
+ const gl::FramebufferState &state,
+ const gl::Framebuffer::DirtyBits &dirtyBits)
+{
+ for (auto dirtyBit : dirtyBits)
+ {
+ switch (dirtyBit)
+ {
+ case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
+ case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
+ ANGLE_TRY(updateDepthStencilRenderTarget(context, state));
+ break;
+ case gl::Framebuffer::DIRTY_BIT_READ_BUFFER:
+ ANGLE_TRY(updateReadColorRenderTarget(context, state));
+ break;
+ case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
+ case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
+ case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
+ case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
+ case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+ break;
+ default:
+ {
+ static_assert(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0, "FB dirty bits");
+ if (dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX)
+ {
+ size_t colorIndex = static_cast<size_t>(
+ dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
+ ANGLE_TRY(updateColorRenderTarget(context, state, colorIndex));
+ }
+ break;
+ }
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+template <typename RenderTargetT>
+const gl::AttachmentArray<RenderTargetT *> &RenderTargetCache<RenderTargetT>::getColors() const
+{
+ return mColorRenderTargets;
+}
+
+template <typename RenderTargetT>
+RenderTargetT *RenderTargetCache<RenderTargetT>::getDepthStencil() const
+{
+ return mDepthStencilRenderTarget;
+}
+
+template <typename RenderTargetT>
+angle::Result RenderTargetCache<RenderTargetT>::updateReadColorRenderTarget(
+ const gl::Context *context,
+ const gl::FramebufferState &state)
+{
+ return updateCachedRenderTarget(context, state.getReadAttachment(), &mReadRenderTarget);
+}
+
+template <typename RenderTargetT>
+angle::Result RenderTargetCache<RenderTargetT>::updateColorRenderTarget(
+ const gl::Context *context,
+ const gl::FramebufferState &state,
+ size_t colorIndex)
+{
+ // If the color render target we're updating is also the read buffer, make sure we update the
+ // read render target also so it's not stale.
+ if (state.getReadBufferState() != GL_NONE && state.getReadIndex() == colorIndex)
+ {
+ ANGLE_TRY(updateReadColorRenderTarget(context, state));
+ }
+
+ return updateCachedRenderTarget(context, state.getColorAttachment(colorIndex),
+ &mColorRenderTargets[colorIndex]);
+}
+
+template <typename RenderTargetT>
+angle::Result RenderTargetCache<RenderTargetT>::updateDepthStencilRenderTarget(
+ const gl::Context *context,
+ const gl::FramebufferState &state)
+{
+ return updateCachedRenderTarget(context, state.getDepthOrStencilAttachment(),
+ &mDepthStencilRenderTarget);
+}
+
+template <typename RenderTargetT>
+angle::Result RenderTargetCache<RenderTargetT>::updateCachedRenderTarget(
+ const gl::Context *context,
+ const gl::FramebufferAttachment *attachment,
+ RenderTargetT **cachedRenderTarget)
+{
+ RenderTargetT *newRenderTarget = nullptr;
+ if (attachment)
+ {
+ ASSERT(attachment->isAttached());
+ ANGLE_TRY(attachment->getRenderTarget(context, attachment->getRenderToTextureSamples(),
+ &newRenderTarget));
+ }
+ *cachedRenderTarget = newRenderTarget;
+ return angle::Result::Continue;
+}
+
+template <typename RenderTargetT>
+RenderTargetT *RenderTargetCache<RenderTargetT>::getColorDraw(const gl::FramebufferState &state,
+ size_t colorIndex) const
+{
+ return mColorRenderTargets[colorIndex];
+}
+
+template <typename RenderTargetT>
+RenderTargetT *RenderTargetCache<RenderTargetT>::getColorRead(
+ const gl::FramebufferState &state) const
+{
+ return mReadRenderTarget;
+}
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_RENDER_TARGET_CACHE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/RenderbufferImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/RenderbufferImpl.cpp
new file mode 100644
index 0000000000..c25f87e13e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/RenderbufferImpl.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright 2022 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferImpl.cpp: Defines the abstract rx::RenderbufferImpl class.
+
+#include "libANGLE/renderer/RenderbufferImpl.h"
+
+namespace rx
+{
+
+angle::Result RenderbufferImpl::onLabelUpdate(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/RenderbufferImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/RenderbufferImpl.h
new file mode 100644
index 0000000000..94dd7b9da7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/RenderbufferImpl.h
@@ -0,0 +1,164 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferImpl.h: Defines the abstract class gl::RenderbufferImpl
+
+#ifndef LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_
+#define LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
+
+namespace gl
+{
+struct PixelPackState;
+class RenderbufferState;
+} // namespace gl
+
+namespace egl
+{
+class Image;
+} // namespace egl
+
+namespace rx
+{
+
+class RenderbufferImpl : public FramebufferAttachmentObjectImpl
+{
+ public:
+ RenderbufferImpl(const gl::RenderbufferState &state) : mState(state) {}
+ ~RenderbufferImpl() override {}
+ virtual void onDestroy(const gl::Context *context) {}
+
+ virtual angle::Result setStorage(const gl::Context *context,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height) = 0;
+ virtual angle::Result setStorageMultisample(const gl::Context *context,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ gl::MultisamplingMode mode) = 0;
+ virtual angle::Result setStorageEGLImageTarget(const gl::Context *context,
+ egl::Image *image) = 0;
+
+ virtual angle::Result copyRenderbufferSubData(const gl::Context *context,
+ const gl::Renderbuffer *srcBuffer,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth);
+
+ virtual angle::Result copyTextureSubData(const gl::Context *context,
+ const gl::Texture *srcTexture,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth);
+
+ virtual GLenum getColorReadFormat(const gl::Context *context);
+ virtual GLenum getColorReadType(const gl::Context *context);
+
+ virtual angle::Result getRenderbufferImage(const gl::Context *context,
+ const gl::PixelPackState &packState,
+ gl::Buffer *packBuffer,
+ GLenum format,
+ GLenum type,
+ void *pixels);
+
+ // Override if accurate native memory size information is available
+ virtual GLint getMemorySize() const;
+
+ virtual angle::Result onLabelUpdate(const gl::Context *context);
+
+ protected:
+ const gl::RenderbufferState &mState;
+};
+
+inline angle::Result RenderbufferImpl::copyRenderbufferSubData(const gl::Context *context,
+ const gl::Renderbuffer *srcBuffer,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+inline angle::Result RenderbufferImpl::copyTextureSubData(const gl::Context *context,
+ const gl::Texture *srcTexture,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+inline GLint RenderbufferImpl::getMemorySize() const
+{
+ return 0;
+}
+
+inline GLenum RenderbufferImpl::getColorReadFormat(const gl::Context *context)
+{
+ UNREACHABLE();
+ return GL_NONE;
+}
+
+inline GLenum RenderbufferImpl::getColorReadType(const gl::Context *context)
+{
+ UNREACHABLE();
+ return GL_NONE;
+}
+
+inline angle::Result RenderbufferImpl::getRenderbufferImage(const gl::Context *context,
+ const gl::PixelPackState &packState,
+ gl::Buffer *packBuffer,
+ GLenum format,
+ GLenum type,
+ void *pixels)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/SamplerImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/SamplerImpl.h
new file mode 100644
index 0000000000..2d0af8b0cc
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/SamplerImpl.h
@@ -0,0 +1,44 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SamplerImpl.h: Defines the abstract rx::SamplerImpl class.
+
+#ifndef LIBANGLE_RENDERER_SAMPLERIMPL_H_
+#define LIBANGLE_RENDERER_SAMPLERIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Sampler.h"
+
+namespace gl
+{
+class Context;
+class SamplerState;
+} // namespace gl
+
+namespace rx
+{
+
+class SamplerImpl : angle::NonCopyable
+{
+ public:
+ SamplerImpl(const gl::SamplerState &state) : mState(state) {}
+ virtual ~SamplerImpl() {}
+
+ virtual void onDestroy(const gl::Context *context)
+ {
+ // Default implementation: no-op.
+ }
+ virtual angle::Result syncState(const gl::Context *context, const bool dirty) = 0;
+
+ angle::Result onLabelUpdate(const gl::Context *context) { return angle::Result::Continue; }
+
+ protected:
+ const gl::SamplerState &mState;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_SAMPLERIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/SemaphoreImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/SemaphoreImpl.h
new file mode 100644
index 0000000000..5beeba0d0a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/SemaphoreImpl.h
@@ -0,0 +1,50 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SemaphoreImpl.h: Implements the rx::SemaphoreImpl class [EXT_external_objects]
+
+#ifndef LIBANGLE_RENDERER_SEMAPHOREIMPL_H_
+#define LIBANGLE_RENDERER_SEMAPHOREIMPL_H_
+
+#include "angle_gl.h"
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+class Context;
+class Semaphore;
+} // namespace gl
+
+namespace rx
+{
+
+class SemaphoreImpl : angle::NonCopyable
+{
+ public:
+ virtual ~SemaphoreImpl() {}
+
+ virtual void onDestroy(const gl::Context *context) = 0;
+
+ virtual angle::Result importFd(gl::Context *context, gl::HandleType handleType, GLint fd) = 0;
+
+ virtual angle::Result importZirconHandle(gl::Context *context,
+ gl::HandleType handleType,
+ GLuint handle) = 0;
+
+ virtual angle::Result wait(gl::Context *context,
+ const gl::BufferBarrierVector &bufferBarriers,
+ const gl::TextureBarrierVector &textureBarriers) = 0;
+
+ virtual angle::Result signal(gl::Context *context,
+ const gl::BufferBarrierVector &bufferBarriers,
+ const gl::TextureBarrierVector &textureBarriers) = 0;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_SEMAPHOREIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/ShaderImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/ShaderImpl.cpp
new file mode 100644
index 0000000000..eb20adcfde
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/ShaderImpl.cpp
@@ -0,0 +1,105 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderImpl.cpp: Implementation methods of ShaderImpl
+
+#include "libANGLE/renderer/ShaderImpl.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/trace.h"
+
+namespace rx
+{
+
+WaitableCompileEvent::WaitableCompileEvent(std::shared_ptr<angle::WaitableEvent> waitableEvent)
+ : mWaitableEvent(waitableEvent)
+{}
+
+WaitableCompileEvent::~WaitableCompileEvent()
+{
+ mWaitableEvent.reset();
+}
+
+void WaitableCompileEvent::wait()
+{
+ mWaitableEvent->wait();
+}
+
+bool WaitableCompileEvent::isReady()
+{
+ return mWaitableEvent->isReady();
+}
+
+const std::string &WaitableCompileEvent::getInfoLog()
+{
+ return mInfoLog;
+}
+
+class TranslateTask : public angle::Closure
+{
+ public:
+ TranslateTask(ShHandle handle, const ShCompileOptions &options, const std::string &source)
+ : mHandle(handle), mOptions(options), mSource(source), mResult(false)
+ {}
+
+ void operator()() override
+ {
+ ANGLE_TRACE_EVENT1("gpu.angle", "TranslateTask::run", "source", mSource);
+ const char *source = mSource.c_str();
+ mResult = sh::Compile(mHandle, &source, 1, mOptions);
+ }
+
+ bool getResult() { return mResult; }
+
+ ShHandle getHandle() { return mHandle; }
+
+ private:
+ ShHandle mHandle;
+ ShCompileOptions mOptions;
+ std::string mSource;
+ bool mResult;
+};
+
+class WaitableCompileEventImpl final : public WaitableCompileEvent
+{
+ public:
+ WaitableCompileEventImpl(std::shared_ptr<angle::WaitableEvent> waitableEvent,
+ std::shared_ptr<TranslateTask> translateTask)
+ : WaitableCompileEvent(waitableEvent), mTranslateTask(translateTask)
+ {}
+
+ bool getResult() override { return mTranslateTask->getResult(); }
+
+ bool postTranslate(std::string *infoLog) override { return true; }
+
+ private:
+ std::shared_ptr<TranslateTask> mTranslateTask;
+};
+
+std::shared_ptr<WaitableCompileEvent> ShaderImpl::compileImpl(
+ const gl::Context *context,
+ gl::ShCompilerInstance *compilerInstance,
+ const std::string &source,
+ ShCompileOptions *compileOptions)
+{
+#if defined(ANGLE_ENABLE_ASSERTS)
+ compileOptions->validateAST = true;
+#endif
+
+ auto workerThreadPool = context->getShaderCompileThreadPool();
+ auto translateTask =
+ std::make_shared<TranslateTask>(compilerInstance->getHandle(), *compileOptions, source);
+
+ return std::make_shared<WaitableCompileEventImpl>(
+ angle::WorkerThreadPool::PostWorkerTask(workerThreadPool, translateTask), translateTask);
+}
+
+angle::Result ShaderImpl::onLabelUpdate(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/ShaderImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/ShaderImpl.h
new file mode 100644
index 0000000000..be50cc754b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/ShaderImpl.h
@@ -0,0 +1,77 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderImpl.h: Defines the abstract rx::ShaderImpl class.
+
+#ifndef LIBANGLE_RENDERER_SHADERIMPL_H_
+#define LIBANGLE_RENDERER_SHADERIMPL_H_
+
+#include <functional>
+
+#include "common/angleutils.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/WorkerThread.h"
+
+namespace gl
+{
+class ShCompilerInstance;
+} // namespace gl
+
+namespace rx
+{
+
+using UpdateShaderStateFunctor = std::function<void(bool compiled, ShHandle handle)>;
+class WaitableCompileEvent : public angle::WaitableEvent
+{
+ public:
+ WaitableCompileEvent(std::shared_ptr<angle::WaitableEvent> waitableEvent);
+ ~WaitableCompileEvent() override;
+
+ void wait() override;
+
+ bool isReady() override;
+
+ virtual bool getResult() = 0;
+
+ virtual bool postTranslate(std::string *infoLog) = 0;
+
+ const std::string &getInfoLog();
+
+ protected:
+ std::shared_ptr<angle::WaitableEvent> mWaitableEvent;
+ std::string mInfoLog;
+};
+
+class ShaderImpl : angle::NonCopyable
+{
+ public:
+ ShaderImpl(const gl::ShaderState &state) : mState(state) {}
+ virtual ~ShaderImpl() {}
+
+ virtual void destroy() {}
+
+ virtual std::shared_ptr<WaitableCompileEvent> compile(const gl::Context *context,
+ gl::ShCompilerInstance *compilerInstance,
+ ShCompileOptions *options) = 0;
+
+ virtual std::string getDebugInfo() const = 0;
+
+ const gl::ShaderState &getState() const { return mState; }
+
+ virtual angle::Result onLabelUpdate(const gl::Context *context);
+
+ protected:
+ std::shared_ptr<WaitableCompileEvent> compileImpl(const gl::Context *context,
+ gl::ShCompilerInstance *compilerInstance,
+ const std::string &source,
+ ShCompileOptions *compileOptions);
+
+ const gl::ShaderState &mState;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_SHADERIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/StreamProducerImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/StreamProducerImpl.h
new file mode 100644
index 0000000000..e4a65e2812
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/StreamProducerImpl.h
@@ -0,0 +1,40 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StreamProducerImpl.h: Defines the abstract rx::StreamProducerImpl class.
+
+#ifndef LIBANGLE_RENDERER_STREAMPRODUCERIMPL_H_
+#define LIBANGLE_RENDERER_STREAMPRODUCERIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Stream.h"
+
+namespace rx
+{
+
+class StreamProducerImpl : angle::NonCopyable
+{
+ public:
+ explicit StreamProducerImpl() {}
+ virtual ~StreamProducerImpl() {}
+
+ // Validates the ability for the producer to accept an arbitrary pointer to a frame. All
+ // pointers should be validated through this function before being used to produce a frame.
+ virtual egl::Error validateD3DTexture(const void *pointer,
+ const egl::AttributeMap &attributes) const = 0;
+
+ // Constructs a frame from an arbitrary external pointer that points to producer specific frame
+ // data. Replaces the internal frame with the new one.
+ virtual void postD3DTexture(void *pointer, const egl::AttributeMap &attributes) = 0;
+
+ // Returns an OpenGL texture interpretation of some frame attributes for the purpose of
+ // constructing an OpenGL texture from a frame. Depending on the producer and consumer, some
+ // frames may have multiple "planes" with different OpenGL texture representations.
+ virtual egl::Stream::GLTextureDescription getGLFrameDescription(int planeIndex) = 0;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_STREAMPRODUCERIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/SurfaceImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/SurfaceImpl.cpp
new file mode 100644
index 0000000000..469ef6119f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/SurfaceImpl.cpp
@@ -0,0 +1,158 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SurfaceImpl.cpp: Implementation of Surface stub method class
+
+#include "libANGLE/renderer/SurfaceImpl.h"
+
+namespace rx
+{
+
+SurfaceImpl::SurfaceImpl(const egl::SurfaceState &state) : mState(state) {}
+
+SurfaceImpl::~SurfaceImpl() {}
+
+egl::Error SurfaceImpl::makeCurrent(const gl::Context *context)
+{
+ return egl::NoError();
+}
+
+egl::Error SurfaceImpl::unMakeCurrent(const gl::Context *context)
+{
+ return egl::NoError();
+}
+
+egl::Error SurfaceImpl::prepareSwap(const gl::Context *)
+{
+ return angle::ResultToEGL(angle::Result::Continue);
+}
+
+egl::Error SurfaceImpl::swapWithDamage(const gl::Context *context,
+ const EGLint *rects,
+ EGLint n_rects)
+{
+ UNREACHABLE();
+ return egl::EglBadSurface() << "swapWithDamage implementation missing.";
+}
+
+egl::Error SurfaceImpl::setPresentationTime(EGLnsecsANDROID time)
+{
+ UNREACHABLE();
+ return egl::EglBadSurface() << "setPresentationTime implementation missing.";
+}
+
+void SurfaceImpl::setFixedWidth(EGLint width)
+{
+ UNREACHABLE();
+}
+
+void SurfaceImpl::setFixedHeight(EGLint height)
+{
+ UNREACHABLE();
+}
+
+void SurfaceImpl::setTimestampsEnabled(bool enabled)
+{
+ UNREACHABLE();
+}
+
+const angle::Format *SurfaceImpl::getD3DTextureColorFormat() const
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+egl::SupportedCompositorTimings SurfaceImpl::getSupportedCompositorTimings() const
+{
+ UNREACHABLE();
+ return egl::SupportedCompositorTimings();
+}
+
+egl::Error SurfaceImpl::getCompositorTiming(EGLint numTimestamps,
+ const EGLint *names,
+ EGLnsecsANDROID *values) const
+{
+ UNREACHABLE();
+ return egl::EglBadDisplay();
+}
+
+egl::Error SurfaceImpl::getNextFrameId(EGLuint64KHR *frameId) const
+{
+ UNREACHABLE();
+ return egl::EglBadDisplay();
+}
+
+egl::SupportedTimestamps SurfaceImpl::getSupportedTimestamps() const
+{
+ UNREACHABLE();
+ return egl::SupportedTimestamps();
+}
+
+egl::Error SurfaceImpl::getFrameTimestamps(EGLuint64KHR frameId,
+ EGLint numTimestamps,
+ const EGLint *timestamps,
+ EGLnsecsANDROID *values) const
+{
+ UNREACHABLE();
+ return egl::EglBadDisplay();
+}
+
+egl::Error SurfaceImpl::swapWithFrameToken(const gl::Context *context,
+ EGLFrameTokenANGLE frameToken)
+{
+ UNREACHABLE();
+ return egl::EglBadDisplay();
+}
+
+egl::Error SurfaceImpl::getUserWidth(const egl::Display *display, EGLint *value) const
+{
+ *value = getWidth();
+ return egl::NoError();
+}
+
+egl::Error SurfaceImpl::getUserHeight(const egl::Display *display, EGLint *value) const
+{
+ *value = getHeight();
+ return egl::NoError();
+}
+
+egl::Error SurfaceImpl::getBufferAge(const gl::Context *context, EGLint *age)
+{
+ *age = 0;
+ return egl::NoError();
+}
+
+egl::Error SurfaceImpl::setAutoRefreshEnabled(bool enabled)
+{
+ return egl::EglBadMatch();
+}
+
+egl::Error SurfaceImpl::lockSurface(const egl::Display *display,
+ EGLint usageHint,
+ bool preservePixels,
+ uint8_t **bufferPtrOut,
+ EGLint *bufferPitchOut)
+{
+ UNREACHABLE();
+ return egl::EglBadMatch();
+}
+
+egl::Error SurfaceImpl::unlockSurface(const egl::Display *display, bool preservePixels)
+{
+ UNREACHABLE();
+ return egl::EglBadMatch();
+}
+
+EGLint SurfaceImpl::origin() const
+{
+ return EGL_LOWER_LEFT_KHR;
+}
+
+egl::Error SurfaceImpl::setRenderBuffer(EGLint renderBuffer)
+{
+ return egl::NoError();
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/SurfaceImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/SurfaceImpl.h
new file mode 100644
index 0000000000..95952d096c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/SurfaceImpl.h
@@ -0,0 +1,136 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SurfaceImpl.h: Implementation methods of egl::Surface
+
+#ifndef LIBANGLE_RENDERER_SURFACEIMPL_H_
+#define LIBANGLE_RENDERER_SURFACEIMPL_H_
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
+
+namespace angle
+{
+struct Format;
+}
+
+namespace gl
+{
+class Context;
+class FramebufferState;
+} // namespace gl
+
+namespace egl
+{
+class Display;
+struct Config;
+struct SurfaceState;
+class Thread;
+
+using SupportedTimestamps = angle::PackedEnumBitSet<Timestamp>;
+using SupportedCompositorTimings = angle::PackedEnumBitSet<CompositorTiming>;
+} // namespace egl
+
+namespace rx
+{
+class SurfaceImpl : public FramebufferAttachmentObjectImpl
+{
+ public:
+ SurfaceImpl(const egl::SurfaceState &surfaceState);
+ ~SurfaceImpl() override;
+ virtual void destroy(const egl::Display *display) {}
+
+ virtual egl::Error initialize(const egl::Display *display) = 0;
+ virtual egl::Error makeCurrent(const gl::Context *context);
+ virtual egl::Error unMakeCurrent(const gl::Context *context);
+ virtual egl::Error prepareSwap(const gl::Context *);
+ virtual egl::Error swap(const gl::Context *context) = 0;
+ virtual egl::Error swapWithDamage(const gl::Context *context,
+ const EGLint *rects,
+ EGLint n_rects);
+ virtual egl::Error swapWithFrameToken(const gl::Context *context,
+ EGLFrameTokenANGLE frameToken);
+ virtual egl::Error postSubBuffer(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height) = 0;
+ virtual egl::Error setPresentationTime(EGLnsecsANDROID time);
+ virtual egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) = 0;
+ virtual egl::Error bindTexImage(const gl::Context *context,
+ gl::Texture *texture,
+ EGLint buffer) = 0;
+ virtual egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) = 0;
+ virtual egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) = 0;
+ virtual egl::Error getMscRate(EGLint *numerator, EGLint *denominator) = 0;
+ virtual void setSwapInterval(EGLint interval) = 0;
+ virtual void setFixedWidth(EGLint width);
+ virtual void setFixedHeight(EGLint height);
+
+ // width and height can change with client window resizing
+ virtual EGLint getWidth() const = 0;
+ virtual EGLint getHeight() const = 0;
+ // Note: windows cannot be resized on Android. The approach requires
+ // calling vkGetPhysicalDeviceSurfaceCapabilitiesKHR. However, that is
+ // expensive; and there are troublesome timing issues for other parts of
+ // ANGLE (which cause test failures and crashes). Therefore, a
+ // special-Android-only path is created just for the querying of EGL_WIDTH
+ // and EGL_HEIGHT.
+ // https://issuetracker.google.com/issues/153329980
+ virtual egl::Error getUserWidth(const egl::Display *display, EGLint *value) const;
+ virtual egl::Error getUserHeight(const egl::Display *display, EGLint *value) const;
+
+ virtual EGLint isPostSubBufferSupported() const = 0;
+ virtual EGLint getSwapBehavior() const = 0;
+
+ virtual egl::Error attachToFramebuffer(const gl::Context *context,
+ gl::Framebuffer *framebuffer) = 0;
+ virtual egl::Error detachFromFramebuffer(const gl::Context *context,
+ gl::Framebuffer *framebuffer) = 0;
+
+ // Used to query color format from pbuffers created from D3D textures.
+ virtual const angle::Format *getD3DTextureColorFormat() const;
+
+ // EGL_ANDROID_get_frame_timestamps
+ virtual void setTimestampsEnabled(bool enabled);
+ virtual egl::SupportedCompositorTimings getSupportedCompositorTimings() const;
+ virtual egl::Error getCompositorTiming(EGLint numTimestamps,
+ const EGLint *names,
+ EGLnsecsANDROID *values) const;
+ virtual egl::Error getNextFrameId(EGLuint64KHR *frameId) const;
+ virtual egl::SupportedTimestamps getSupportedTimestamps() const;
+ virtual egl::Error getFrameTimestamps(EGLuint64KHR frameId,
+ EGLint numTimestamps,
+ const EGLint *timestamps,
+ EGLnsecsANDROID *values) const;
+ virtual egl::Error getBufferAge(const gl::Context *context, EGLint *age);
+
+ // EGL_ANDROID_front_buffer_auto_refresh
+ virtual egl::Error setAutoRefreshEnabled(bool enabled);
+
+ // EGL_KHR_lock_surface3
+ virtual egl::Error lockSurface(const egl::Display *display,
+ EGLint usageHint,
+ bool preservePixels,
+ uint8_t **bufferPtrOut,
+ EGLint *bufferPitchOut);
+ virtual egl::Error unlockSurface(const egl::Display *display, bool preservePixels);
+ virtual EGLint origin() const;
+
+ virtual egl::Error setRenderBuffer(EGLint renderBuffer);
+
+ protected:
+ const egl::SurfaceState &mState;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_SURFACEIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/SyncImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/SyncImpl.h
new file mode 100644
index 0000000000..59811a62d7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/SyncImpl.h
@@ -0,0 +1,45 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SyncImpl.h: Defines the rx::SyncImpl class.
+
+#ifndef LIBANGLE_RENDERER_FENCESYNCIMPL_H_
+#define LIBANGLE_RENDERER_FENCESYNCIMPL_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace rx
+{
+class SyncImpl : angle::NonCopyable
+{
+ public:
+ SyncImpl() {}
+ virtual ~SyncImpl() {}
+
+ virtual void onDestroy(const gl::Context *context) {}
+
+ virtual angle::Result set(const gl::Context *context, GLenum condition, GLbitfield flags) = 0;
+ virtual angle::Result clientWait(const gl::Context *context,
+ GLbitfield flags,
+ GLuint64 timeout,
+ GLenum *outResult) = 0;
+ virtual angle::Result serverWait(const gl::Context *context,
+ GLbitfield flags,
+ GLuint64 timeout) = 0;
+ virtual angle::Result getStatus(const gl::Context *context, GLint *outResult) = 0;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_FENCESYNCIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/TextureImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/TextureImpl.cpp
new file mode 100644
index 0000000000..7e69330e27
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/TextureImpl.cpp
@@ -0,0 +1,200 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureImpl.cpp: Defines the abstract rx::TextureImpl classes.
+
+#include "libANGLE/renderer/TextureImpl.h"
+
+namespace rx
+{
+TextureImpl::TextureImpl(const gl::TextureState &state) : mState(state) {}
+
+TextureImpl::~TextureImpl() {}
+
+void TextureImpl::onDestroy(const gl::Context *context) {}
+
+angle::Result TextureImpl::copyTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ GLenum type,
+ GLint sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+angle::Result TextureImpl::copySubTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ GLint sourceLevel,
+ const gl::Box &sourceBox,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+angle::Result TextureImpl::copyRenderbufferSubData(const gl::Context *context,
+ const gl::Renderbuffer *srcBuffer,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+angle::Result TextureImpl::copyTextureSubData(const gl::Context *context,
+ const gl::Texture *srcTexture,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+angle::Result TextureImpl::copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+angle::Result TextureImpl::copy3DTexture(const gl::Context *context,
+ gl::TextureTarget target,
+ GLenum internalFormat,
+ GLenum type,
+ GLint sourceLevel,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+angle::Result TextureImpl::copy3DSubTexture(const gl::Context *context,
+ const gl::TextureTarget target,
+ const gl::Offset &destOffset,
+ GLint sourceLevel,
+ GLint destLevel,
+ const gl::Box &srcBox,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+angle::Result TextureImpl::setImageExternal(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+angle::Result TextureImpl::setBuffer(const gl::Context *context, GLenum internalFormat)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+GLint TextureImpl::getMemorySize() const
+{
+ return 0;
+}
+
+GLint TextureImpl::getLevelMemorySize(gl::TextureTarget target, GLint level)
+{
+ return 0;
+}
+
+GLint TextureImpl::getNativeID() const
+{
+ UNREACHABLE();
+ return 0;
+}
+
+GLenum TextureImpl::getColorReadFormat(const gl::Context *context)
+{
+ UNREACHABLE();
+ return GL_NONE;
+}
+
+GLenum TextureImpl::getColorReadType(const gl::Context *context)
+{
+ UNREACHABLE();
+ return GL_NONE;
+}
+
+angle::Result TextureImpl::getTexImage(const gl::Context *context,
+ const gl::PixelPackState &packState,
+ gl::Buffer *packBuffer,
+ gl::TextureTarget target,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ void *pixels)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+angle::Result TextureImpl::getCompressedTexImage(const gl::Context *context,
+ const gl::PixelPackState &packState,
+ gl::Buffer *packBuffer,
+ gl::TextureTarget target,
+ GLint level,
+ void *pixels)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+GLint TextureImpl::getRequiredExternalTextureImageUnits(const gl::Context *context)
+{
+ UNREACHABLE();
+ return 0;
+}
+
+angle::Result TextureImpl::onLabelUpdate(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/TextureImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/TextureImpl.h
new file mode 100644
index 0000000000..368fba09c5
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/TextureImpl.h
@@ -0,0 +1,254 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureImpl.h: Defines the abstract rx::TextureImpl classes.
+
+#ifndef LIBANGLE_RENDERER_TEXTUREIMPL_H_
+#define LIBANGLE_RENDERER_TEXTUREIMPL_H_
+
+#include <stdint.h>
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
+
+namespace egl
+{
+class Surface;
+class Image;
+} // namespace egl
+
+namespace gl
+{
+class Framebuffer;
+class MemoryObject;
+struct PixelUnpackState;
+class TextureState;
+} // namespace gl
+
+namespace rx
+{
+class ContextImpl;
+
+class TextureImpl : public FramebufferAttachmentObjectImpl
+{
+ public:
+ TextureImpl(const gl::TextureState &state);
+ ~TextureImpl() override;
+
+ virtual void onDestroy(const gl::Context *context);
+
+ virtual angle::Result setImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels) = 0;
+ virtual angle::Result setSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels) = 0;
+
+ virtual angle::Result setCompressedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) = 0;
+ virtual angle::Result setCompressedSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) = 0;
+
+ virtual angle::Result copyImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ gl::Framebuffer *source) = 0;
+ virtual angle::Result copySubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ gl::Framebuffer *source) = 0;
+
+ virtual angle::Result copyTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ GLenum type,
+ GLint sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source);
+ virtual angle::Result copySubTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ GLint sourceLevel,
+ const gl::Box &sourceBox,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source);
+
+ virtual angle::Result copyRenderbufferSubData(const gl::Context *context,
+ const gl::Renderbuffer *srcBuffer,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth);
+
+ virtual angle::Result copyTextureSubData(const gl::Context *context,
+ const gl::Texture *srcTexture,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth);
+
+ virtual angle::Result copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source);
+
+ virtual angle::Result copy3DTexture(const gl::Context *context,
+ gl::TextureTarget target,
+ GLenum internalFormat,
+ GLenum type,
+ GLint sourceLevel,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source);
+ virtual angle::Result copy3DSubTexture(const gl::Context *context,
+ const gl::TextureTarget target,
+ const gl::Offset &destOffset,
+ GLint sourceLevel,
+ GLint destLevel,
+ const gl::Box &srcBox,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source);
+
+ virtual angle::Result setStorage(const gl::Context *context,
+ gl::TextureType type,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) = 0;
+
+ virtual angle::Result setStorageMultisample(const gl::Context *context,
+ gl::TextureType type,
+ GLsizei samples,
+ GLint internalformat,
+ const gl::Extents &size,
+ bool fixedSampleLocations) = 0;
+
+ virtual angle::Result setStorageExternalMemory(const gl::Context *context,
+ gl::TextureType type,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ gl::MemoryObject *memoryObject,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext) = 0;
+
+ virtual angle::Result setImageExternal(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type);
+
+ virtual angle::Result setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image) = 0;
+
+ virtual angle::Result setImageExternal(const gl::Context *context,
+ gl::TextureType type,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) = 0;
+
+ virtual angle::Result setBuffer(const gl::Context *context, GLenum internalFormat);
+
+ virtual angle::Result generateMipmap(const gl::Context *context) = 0;
+
+ virtual angle::Result setBaseLevel(const gl::Context *context, GLuint baseLevel) = 0;
+
+ virtual angle::Result bindTexImage(const gl::Context *context, egl::Surface *surface) = 0;
+ virtual angle::Result releaseTexImage(const gl::Context *context) = 0;
+
+ virtual angle::Result onLabelUpdate(const gl::Context *context);
+
+ // Override if accurate native memory size information is available
+ virtual GLint getMemorySize() const;
+ virtual GLint getLevelMemorySize(gl::TextureTarget target, GLint level);
+
+ virtual GLint getNativeID() const;
+
+ virtual angle::Result syncState(const gl::Context *context,
+ const gl::Texture::DirtyBits &dirtyBits,
+ gl::Command source) = 0;
+
+ virtual GLenum getColorReadFormat(const gl::Context *context);
+ virtual GLenum getColorReadType(const gl::Context *context);
+
+ virtual angle::Result getTexImage(const gl::Context *context,
+ const gl::PixelPackState &packState,
+ gl::Buffer *packBuffer,
+ gl::TextureTarget target,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ void *pixels);
+
+ virtual angle::Result getCompressedTexImage(const gl::Context *context,
+ const gl::PixelPackState &packState,
+ gl::Buffer *packBuffer,
+ gl::TextureTarget target,
+ GLint level,
+ void *pixels);
+
+ virtual GLint getRequiredExternalTextureImageUnits(const gl::Context *context);
+
+ const gl::TextureState &getState() const { return mState; }
+
+ protected:
+ const gl::TextureState &mState;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_TEXTUREIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/TransformFeedbackImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/TransformFeedbackImpl.cpp
new file mode 100644
index 0000000000..183c496025
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/TransformFeedbackImpl.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright 2022 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TransformFeedbackImpl.cpp: Defines the abstract rx::TransformFeedbackImpl class.
+
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+
+namespace rx
+{
+
+angle::Result TransformFeedbackImpl::onLabelUpdate(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/TransformFeedbackImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/TransformFeedbackImpl.h
new file mode 100644
index 0000000000..75ef6fdbf8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/TransformFeedbackImpl.h
@@ -0,0 +1,42 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TransformFeedbackImpl.h: Defines the abstract rx::TransformFeedbackImpl class.
+
+#ifndef LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_
+#define LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/TransformFeedback.h"
+
+namespace rx
+{
+
+class TransformFeedbackImpl : angle::NonCopyable
+{
+ public:
+ TransformFeedbackImpl(const gl::TransformFeedbackState &state) : mState(state) {}
+ virtual ~TransformFeedbackImpl() {}
+ virtual void onDestroy(const gl::Context *context) {}
+
+ virtual angle::Result begin(const gl::Context *context, gl::PrimitiveMode primitiveMode) = 0;
+ virtual angle::Result end(const gl::Context *context) = 0;
+ virtual angle::Result pause(const gl::Context *context) = 0;
+ virtual angle::Result resume(const gl::Context *context) = 0;
+
+ virtual angle::Result bindIndexedBuffer(
+ const gl::Context *context,
+ size_t index,
+ const gl::OffsetBindingPointer<gl::Buffer> &binding) = 0;
+
+ virtual angle::Result onLabelUpdate(const gl::Context *context);
+
+ protected:
+ const gl::TransformFeedbackState &mState;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/VertexArrayImpl.cpp b/gfx/angle/checkout/src/libANGLE/renderer/VertexArrayImpl.cpp
new file mode 100644
index 0000000000..b7cac20f78
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/VertexArrayImpl.cpp
@@ -0,0 +1,18 @@
+//
+// Copyright 2022 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// VertexArrayImpl.cpp: Implements the class methods for VertexArrayImpl.
+
+#include "libANGLE/renderer/VertexArrayImpl.h"
+
+namespace rx
+{
+
+angle::Result VertexArrayImpl::onLabelUpdate(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/VertexArrayImpl.h b/gfx/angle/checkout/src/libANGLE/renderer/VertexArrayImpl.h
new file mode 100644
index 0000000000..8e33c901c2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/VertexArrayImpl.h
@@ -0,0 +1,70 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexAttribImpl.h: Defines the abstract rx::VertexAttribImpl class.
+
+#ifndef LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_
+#define LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/VertexArray.h"
+
+// This is a helper X macro for iterating over all dirty attribs/bindings. Useful for dirty bits.
+static_assert(gl::MAX_VERTEX_ATTRIBS == 16, "Invalid max vertex attribs");
+static_assert(gl::MAX_VERTEX_ATTRIB_BINDINGS == 16, "Invalid max vertex bindings");
+#define ANGLE_VERTEX_INDEX_CASES(FUNC) \
+ FUNC(0) \
+ FUNC(1) \
+ FUNC(2) \
+ FUNC(3) \
+ FUNC(4) \
+ FUNC(5) FUNC(6) FUNC(7) FUNC(8) FUNC(9) FUNC(10) FUNC(11) FUNC(12) FUNC(13) FUNC(14) FUNC(15)
+
+namespace rx
+{
+class ContextImpl;
+
+class VertexArrayImpl : angle::NonCopyable
+{
+ public:
+ VertexArrayImpl(const gl::VertexArrayState &state) : mState(state) {}
+
+ // It's up to the implementation to reset the attrib and binding dirty bits.
+ // This is faster than the front-end having to clear all the bits after they have been scanned.
+ virtual angle::Result syncState(const gl::Context *context,
+ const gl::VertexArray::DirtyBits &dirtyBits,
+ gl::VertexArray::DirtyAttribBitsArray *attribBits,
+ gl::VertexArray::DirtyBindingBitsArray *bindingBits);
+
+ virtual void destroy(const gl::Context *context) {}
+ virtual ~VertexArrayImpl() {}
+
+ const gl::VertexArrayState &getState() const { return mState; }
+
+ void setContentsObservers(gl::VertexArrayBufferContentsObservers *observers)
+ {
+ mContentsObservers = observers;
+ }
+
+ virtual angle::Result onLabelUpdate(const gl::Context *context);
+
+ protected:
+ const gl::VertexArrayState &mState;
+ gl::VertexArrayBufferContentsObservers *mContentsObservers = nullptr;
+};
+
+inline angle::Result VertexArrayImpl::syncState(const gl::Context *context,
+ const gl::VertexArray::DirtyBits &dirtyBits,
+ gl::VertexArray::DirtyAttribBitsArray *attribBits,
+ gl::VertexArray::DirtyBindingBitsArray *bindingBits)
+{
+ return angle::Result::Continue;
+}
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/copyvertex.h b/gfx/angle/checkout/src/libANGLE/renderer/copyvertex.h
new file mode 100644
index 0000000000..54624bb29b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/copyvertex.h
@@ -0,0 +1,80 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// copyvertex.h: Defines vertex buffer copying and conversion functions
+
+#ifndef LIBANGLE_RENDERER_COPYVERTEX_H_
+#define LIBANGLE_RENDERER_COPYVERTEX_H_
+
+#include "common/mathutil.h"
+
+namespace rx
+{
+
+using VertexCopyFunction = void (*)(const uint8_t *input,
+ size_t stride,
+ size_t count,
+ uint8_t *output);
+
+// 'alphaDefaultValueBits' gives the default value for the alpha channel (4th component)
+template <typename T,
+ size_t inputComponentCount,
+ size_t outputComponentCount,
+ uint32_t alphaDefaultValueBits>
+void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+void Copy8SintTo16SintVertexData(const uint8_t *input,
+ size_t stride,
+ size_t count,
+ uint8_t *output);
+
+template <size_t componentCount>
+void Copy8SnormTo16SnormVertexData(const uint8_t *input,
+ size_t stride,
+ size_t count,
+ uint8_t *output);
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <typename T,
+ size_t inputComponentCount,
+ size_t outputComponentCount,
+ bool normalized,
+ bool toHalf>
+void CopyToFloatVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+void Copy32FTo16FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+void CopyXYZ32FToXYZ9E5(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+void CopyXYZ32FToX11Y11B10F(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <bool isSigned, bool normalized, bool toFloat, bool toHalf>
+void CopyXYZ10W2ToXYZWFloatVertexData(const uint8_t *input,
+ size_t stride,
+ size_t count,
+ uint8_t *output);
+
+template <bool isSigned, bool normalized, bool toHalf>
+void CopyXYZ10ToXYZWFloatVertexData(const uint8_t *input,
+ size_t stride,
+ size_t count,
+ uint8_t *output);
+
+template <bool isSigned, bool normalized, bool toHalf>
+void CopyW2XYZ10ToXYZWFloatVertexData(const uint8_t *input,
+ size_t stride,
+ size_t count,
+ uint8_t *output);
+
+} // namespace rx
+
+#include "copyvertex.inc.h"
+
+#endif // LIBANGLE_RENDERER_COPYVERTEX_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/copyvertex.inc.h b/gfx/angle/checkout/src/libANGLE/renderer/copyvertex.inc.h
new file mode 100644
index 0000000000..3f1844e91c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/copyvertex.inc.h
@@ -0,0 +1,635 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// copyvertex.inc.h: Implementation of vertex buffer copying and conversion functions
+
+namespace rx
+{
+
+// Returns an aligned buffer to read the input from
+template <typename T, size_t inputComponentCount>
+inline const T *GetAlignedOffsetInput(const T *offsetInput, T *alignedElement)
+{
+ if (reinterpret_cast<uintptr_t>(offsetInput) % sizeof(T) != 0)
+ {
+ // Applications may pass in arbitrarily aligned buffers as input.
+ // Certain architectures have restrictions regarding unaligned reads. Specifically, we crash
+ // on armeabi-v7a devices with a SIGBUS error when performing such operations. arm64 and
+ // x86-64 devices do not appear to have such issues.
+ //
+ // The workaround is to detect if the input buffer is unaligned and if so, perform a
+ // byte-wise copy of the unaligned portion and a memcpy of the rest of the buffer.
+ uint8_t *alignedBuffer = reinterpret_cast<uint8_t *>(&alignedElement[0]);
+ uintptr_t unalignedInputStartAddress = reinterpret_cast<uintptr_t>(offsetInput);
+ constexpr size_t kAlignmentMinusOne = sizeof(T) - 1;
+ uintptr_t alignedInputStartAddress =
+ (reinterpret_cast<uintptr_t>(offsetInput) + kAlignmentMinusOne) & ~(kAlignmentMinusOne);
+ ASSERT(alignedInputStartAddress >= unalignedInputStartAddress);
+
+ const size_t totalBytesToCopy = sizeof(T) * inputComponentCount;
+ const size_t unalignedBytesToCopy = alignedInputStartAddress - unalignedInputStartAddress;
+ ASSERT(totalBytesToCopy >= unalignedBytesToCopy);
+
+ // byte-wise copy of unaligned portion
+ for (size_t i = 0; i < unalignedBytesToCopy; i++)
+ {
+ alignedBuffer[i] = reinterpret_cast<const uint8_t *>(&offsetInput[0])[i];
+ }
+
+ // memcpy remaining buffer
+ memcpy(&alignedBuffer[unalignedBytesToCopy],
+ &reinterpret_cast<const uint8_t *>(&offsetInput[0])[unalignedBytesToCopy],
+ totalBytesToCopy - unalignedBytesToCopy);
+
+ return alignedElement;
+ }
+ else
+ {
+ return offsetInput;
+ }
+}
+
+template <typename T,
+ size_t inputComponentCount,
+ size_t outputComponentCount,
+ uint32_t alphaDefaultValueBits>
+inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
+{
+ const size_t attribSize = sizeof(T) * inputComponentCount;
+
+ if (attribSize == stride && inputComponentCount == outputComponentCount)
+ {
+ memcpy(output, input, count * attribSize);
+ return;
+ }
+
+ if (inputComponentCount == outputComponentCount)
+ {
+ for (size_t i = 0; i < count; i++)
+ {
+ const T *offsetInput = reinterpret_cast<const T *>(input + (i * stride));
+ T offsetInputAligned[inputComponentCount];
+ offsetInput =
+ GetAlignedOffsetInput<T, inputComponentCount>(offsetInput, &offsetInputAligned[0]);
+
+ T *offsetOutput = reinterpret_cast<T *>(output) + i * outputComponentCount;
+
+ memcpy(offsetOutput, offsetInput, attribSize);
+ }
+ return;
+ }
+
+ const T defaultAlphaValue = gl::bitCast<T>(alphaDefaultValueBits);
+ const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3);
+
+ for (size_t i = 0; i < count; i++)
+ {
+ const T *offsetInput = reinterpret_cast<const T *>(input + (i * stride));
+ T offsetInputAligned[inputComponentCount];
+ ASSERT(sizeof(offsetInputAligned) == attribSize);
+ offsetInput =
+ GetAlignedOffsetInput<T, inputComponentCount>(offsetInput, &offsetInputAligned[0]);
+
+ T *offsetOutput = reinterpret_cast<T *>(output) + i * outputComponentCount;
+
+ memcpy(offsetOutput, offsetInput, attribSize);
+
+ if (inputComponentCount < lastNonAlphaOutputComponent)
+ {
+ // Set the remaining G/B channels to 0.
+ size_t numComponents = (lastNonAlphaOutputComponent - inputComponentCount);
+ memset(&offsetOutput[inputComponentCount], 0, numComponents * sizeof(T));
+ }
+
+ if (inputComponentCount < outputComponentCount && outputComponentCount == 4)
+ {
+ // Set the remaining alpha channel to the defaultAlphaValue.
+ offsetOutput[3] = defaultAlphaValue;
+ }
+ }
+}
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+inline void Copy8SintTo16SintVertexData(const uint8_t *input,
+ size_t stride,
+ size_t count,
+ uint8_t *output)
+{
+ const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3);
+
+ for (size_t i = 0; i < count; i++)
+ {
+ const GLbyte *offsetInput = reinterpret_cast<const GLbyte *>(input + i * stride);
+ GLshort *offsetOutput = reinterpret_cast<GLshort *>(output) + i * outputComponentCount;
+
+ for (size_t j = 0; j < inputComponentCount; j++)
+ {
+ offsetOutput[j] = static_cast<GLshort>(offsetInput[j]);
+ }
+
+ for (size_t j = inputComponentCount; j < lastNonAlphaOutputComponent; j++)
+ {
+ // Set remaining G/B channels to 0.
+ offsetOutput[j] = 0;
+ }
+
+ if (inputComponentCount < outputComponentCount && outputComponentCount == 4)
+ {
+ // On integer formats, we must set the Alpha channel to 1 if it's unused.
+ offsetOutput[3] = 1;
+ }
+ }
+}
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+inline void Copy8SnormTo16SnormVertexData(const uint8_t *input,
+ size_t stride,
+ size_t count,
+ uint8_t *output)
+{
+ for (size_t i = 0; i < count; i++)
+ {
+ const GLbyte *offsetInput = reinterpret_cast<const GLbyte *>(input + i * stride);
+ GLshort *offsetOutput = reinterpret_cast<GLshort *>(output) + i * outputComponentCount;
+
+ for (size_t j = 0; j < inputComponentCount; j++)
+ {
+ // The original GLbyte value ranges from -128 to +127 (INT8_MAX).
+ // When converted to GLshort, the value must be scaled to between -32768 and +32767
+ // (INT16_MAX).
+ if (offsetInput[j] > 0)
+ {
+ offsetOutput[j] =
+ offsetInput[j] << 8 | offsetInput[j] << 1 | ((offsetInput[j] & 0x40) >> 6);
+ }
+ else
+ {
+ offsetOutput[j] = offsetInput[j] << 8;
+ }
+ }
+
+ for (size_t j = inputComponentCount; j < std::min<size_t>(outputComponentCount, 3); j++)
+ {
+ // Set remaining G/B channels to 0.
+ offsetOutput[j] = 0;
+ }
+
+ if (inputComponentCount < outputComponentCount && outputComponentCount == 4)
+ {
+ // On normalized formats, we must set the Alpha channel to the max value if it's unused.
+ offsetOutput[3] = INT16_MAX;
+ }
+ }
+}
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+inline void Copy32FixedTo32FVertexData(const uint8_t *input,
+ size_t stride,
+ size_t count,
+ uint8_t *output)
+{
+ static const float divisor = 1.0f / (1 << 16);
+
+ for (size_t i = 0; i < count; i++)
+ {
+ const uint8_t *offsetInput = input + i * stride;
+ float *offsetOutput = reinterpret_cast<float *>(output) + i * outputComponentCount;
+
+ // GLfixed access must be 4-byte aligned on arm32, input and stride sometimes are not
+ if (reinterpret_cast<uintptr_t>(offsetInput) % sizeof(GLfixed) == 0)
+ {
+ for (size_t j = 0; j < inputComponentCount; j++)
+ {
+ offsetOutput[j] =
+ static_cast<float>(reinterpret_cast<const GLfixed *>(offsetInput)[j]) * divisor;
+ }
+ }
+ else
+ {
+ for (size_t j = 0; j < inputComponentCount; j++)
+ {
+ GLfixed alignedInput;
+ memcpy(&alignedInput, offsetInput + j * sizeof(GLfixed), sizeof(GLfixed));
+ offsetOutput[j] = static_cast<float>(alignedInput) * divisor;
+ }
+ }
+
+ // 4-component output formats would need special padding in the alpha channel.
+ static_assert(!(inputComponentCount < 4 && outputComponentCount == 4),
+ "An inputComponentCount less than 4 and an outputComponentCount equal to 4 "
+ "is not supported.");
+
+ for (size_t j = inputComponentCount; j < outputComponentCount; j++)
+ {
+ offsetOutput[j] = 0.0f;
+ }
+ }
+}
+
+template <typename T,
+ size_t inputComponentCount,
+ size_t outputComponentCount,
+ bool normalized,
+ bool toHalf>
+inline void CopyToFloatVertexData(const uint8_t *input,
+ size_t stride,
+ size_t count,
+ uint8_t *output)
+{
+ typedef std::numeric_limits<T> NL;
+ typedef typename std::conditional<toHalf, GLhalf, float>::type outputType;
+
+ for (size_t i = 0; i < count; i++)
+ {
+ const T *offsetInput = reinterpret_cast<const T *>(input + (stride * i));
+ outputType *offsetOutput =
+ reinterpret_cast<outputType *>(output) + i * outputComponentCount;
+
+ T offsetInputAligned[inputComponentCount];
+ offsetInput =
+ GetAlignedOffsetInput<T, inputComponentCount>(offsetInput, &offsetInputAligned[0]);
+
+ for (size_t j = 0; j < inputComponentCount; j++)
+ {
+ float result = 0;
+
+ if (normalized)
+ {
+ if (NL::is_signed)
+ {
+ result = static_cast<float>(offsetInput[j]) / static_cast<float>(NL::max());
+ result = result >= -1.0f ? result : -1.0f;
+ }
+ else
+ {
+ result = static_cast<float>(offsetInput[j]) / static_cast<float>(NL::max());
+ }
+ }
+ else
+ {
+ result = static_cast<float>(offsetInput[j]);
+ }
+
+ if (toHalf)
+ {
+ offsetOutput[j] = gl::float32ToFloat16(result);
+ }
+ else
+ {
+ offsetOutput[j] = static_cast<outputType>(result);
+ }
+ }
+
+ for (size_t j = inputComponentCount; j < outputComponentCount; j++)
+ {
+ offsetOutput[j] = 0;
+ }
+
+ if (inputComponentCount < 4 && outputComponentCount == 4)
+ {
+ if (toHalf)
+ {
+ offsetOutput[3] = gl::Float16One;
+ }
+ else
+ {
+ offsetOutput[3] = static_cast<outputType>(gl::Float32One);
+ }
+ }
+ }
+}
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+void Copy32FTo16FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
+{
+ const unsigned short kZero = gl::float32ToFloat16(0.0f);
+ const unsigned short kOne = gl::float32ToFloat16(1.0f);
+
+ for (size_t i = 0; i < count; i++)
+ {
+ const float *offsetInput = reinterpret_cast<const float *>(input + (stride * i));
+ unsigned short *offsetOutput =
+ reinterpret_cast<unsigned short *>(output) + i * outputComponentCount;
+
+ for (size_t j = 0; j < inputComponentCount; j++)
+ {
+ offsetOutput[j] = gl::float32ToFloat16(offsetInput[j]);
+ }
+
+ for (size_t j = inputComponentCount; j < outputComponentCount; j++)
+ {
+ offsetOutput[j] = (j == 3) ? kOne : kZero;
+ }
+ }
+}
+
+inline void CopyXYZ32FToXYZ9E5(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
+{
+ for (size_t i = 0; i < count; i++)
+ {
+ const float *offsetInput = reinterpret_cast<const float *>(input + (stride * i));
+ unsigned int *offsetOutput = reinterpret_cast<unsigned int *>(output) + i;
+
+ *offsetOutput = gl::convertRGBFloatsTo999E5(offsetInput[0], offsetInput[1], offsetInput[2]);
+ }
+}
+
+inline void CopyXYZ32FToX11Y11B10F(const uint8_t *input,
+ size_t stride,
+ size_t count,
+ uint8_t *output)
+{
+ for (size_t i = 0; i < count; i++)
+ {
+ const float *offsetInput = reinterpret_cast<const float *>(input + (stride * i));
+ unsigned int *offsetOutput = reinterpret_cast<unsigned int *>(output) + i;
+
+ *offsetOutput = gl::float32ToFloat11(offsetInput[0]) << 0 |
+ gl::float32ToFloat11(offsetInput[1]) << 11 |
+ gl::float32ToFloat10(offsetInput[2]) << 22;
+ }
+}
+
+namespace priv
+{
+
+template <bool isSigned, bool normalized, bool toFloat, bool toHalf>
+static inline void CopyPackedRGB(uint32_t data, uint8_t *output)
+{
+ const uint32_t rgbSignMask = 0x200; // 1 set at the 9 bit
+ const uint32_t negativeMask = 0xFFFFFC00; // All bits from 10 to 31 set to 1
+
+ if (toFloat || toHalf)
+ {
+ GLfloat finalValue = static_cast<GLfloat>(data);
+ if (isSigned)
+ {
+ if (data & rgbSignMask)
+ {
+ int negativeNumber = data | negativeMask;
+ finalValue = static_cast<GLfloat>(negativeNumber);
+ }
+
+ if (normalized)
+ {
+ const int32_t maxValue = 0x1FF; // 1 set in bits 0 through 8
+ const int32_t minValue = 0xFFFFFE01; // Inverse of maxValue
+
+ // A 10-bit two's complement number has the possibility of being minValue - 1 but
+ // OpenGL's normalization rules dictate that it should be clamped to minValue in
+ // this case.
+ if (finalValue < minValue)
+ {
+ finalValue = minValue;
+ }
+
+ const int32_t halfRange = (maxValue - minValue) >> 1;
+ finalValue = ((finalValue - minValue) / halfRange) - 1.0f;
+ }
+ }
+ else
+ {
+ if (normalized)
+ {
+ const uint32_t maxValue = 0x3FF; // 1 set in bits 0 through 9
+ finalValue /= static_cast<GLfloat>(maxValue);
+ }
+ }
+
+ if (toHalf)
+ {
+ *reinterpret_cast<GLhalf *>(output) = gl::float32ToFloat16(finalValue);
+ }
+ else
+ {
+ *reinterpret_cast<GLfloat *>(output) = finalValue;
+ }
+ }
+ else
+ {
+ if (isSigned)
+ {
+ GLshort *intOutput = reinterpret_cast<GLshort *>(output);
+
+ if (data & rgbSignMask)
+ {
+ *intOutput = static_cast<GLshort>(data | negativeMask);
+ }
+ else
+ {
+ *intOutput = static_cast<GLshort>(data);
+ }
+ }
+ else
+ {
+ GLushort *uintOutput = reinterpret_cast<GLushort *>(output);
+ *uintOutput = static_cast<GLushort>(data);
+ }
+ }
+}
+
+template <bool isSigned, bool normalized, bool toFloat, bool toHalf>
+inline void CopyPackedAlpha(uint32_t data, uint8_t *output)
+{
+ ASSERT(data >= 0 && data <= 3);
+
+ if (toFloat || toHalf)
+ {
+ GLfloat finalValue = 0;
+ if (isSigned)
+ {
+ if (normalized)
+ {
+ switch (data)
+ {
+ case 0x0:
+ finalValue = 0.0f;
+ break;
+ case 0x1:
+ finalValue = 1.0f;
+ break;
+ case 0x2:
+ finalValue = -1.0f;
+ break;
+ case 0x3:
+ finalValue = -1.0f;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ switch (data)
+ {
+ case 0x0:
+ finalValue = 0.0f;
+ break;
+ case 0x1:
+ finalValue = 1.0f;
+ break;
+ case 0x2:
+ finalValue = -2.0f;
+ break;
+ case 0x3:
+ finalValue = -1.0f;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ }
+ else
+ {
+ if (normalized)
+ {
+ finalValue = data / 3.0f;
+ }
+ else
+ {
+ finalValue = static_cast<float>(data);
+ }
+ }
+
+ if (toHalf)
+ {
+ *reinterpret_cast<GLhalf *>(output) = gl::float32ToFloat16(finalValue);
+ }
+ else
+ {
+ *reinterpret_cast<GLfloat *>(output) = finalValue;
+ }
+ }
+ else
+ {
+ if (isSigned)
+ {
+ GLshort *intOutput = reinterpret_cast<GLshort *>(output);
+ switch (data)
+ {
+ case 0x0:
+ *intOutput = 0;
+ break;
+ case 0x1:
+ *intOutput = 1;
+ break;
+ case 0x2:
+ *intOutput = -2;
+ break;
+ case 0x3:
+ *intOutput = -1;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ *reinterpret_cast<GLushort *>(output) = static_cast<GLushort>(data);
+ }
+ }
+}
+
+} // namespace priv
+
+template <bool isSigned, bool normalized, bool toFloat, bool toHalf>
+inline void CopyXYZ10W2ToXYZWFloatVertexData(const uint8_t *input,
+ size_t stride,
+ size_t count,
+ uint8_t *output)
+{
+ const size_t outputComponentSize = toFloat && !toHalf ? 4 : 2;
+ const size_t componentCount = 4;
+
+ const uint32_t rgbMask = 0x3FF; // 1 set in bits 0 through 9
+ const size_t redShift = 0; // red is bits 0 through 9
+ const size_t greenShift = 10; // green is bits 10 through 19
+ const size_t blueShift = 20; // blue is bits 20 through 29
+
+ const uint32_t alphaMask = 0x3; // 1 set in bits 0 and 1
+ const size_t alphaShift = 30; // Alpha is the 30 and 31 bits
+
+ for (size_t i = 0; i < count; i++)
+ {
+ GLuint packedValue = *reinterpret_cast<const GLuint *>(input + (i * stride));
+ uint8_t *offsetOutput = output + (i * outputComponentSize * componentCount);
+
+ priv::CopyPackedRGB<isSigned, normalized, toFloat, toHalf>(
+ (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize));
+ priv::CopyPackedRGB<isSigned, normalized, toFloat, toHalf>(
+ (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize));
+ priv::CopyPackedRGB<isSigned, normalized, toFloat, toHalf>(
+ (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize));
+ priv::CopyPackedAlpha<isSigned, normalized, toFloat, toHalf>(
+ (packedValue >> alphaShift) & alphaMask, offsetOutput + (3 * outputComponentSize));
+ }
+}
+
+template <bool isSigned, bool normalized, bool toHalf>
+inline void CopyXYZ10ToXYZWFloatVertexData(const uint8_t *input,
+ size_t stride,
+ size_t count,
+ uint8_t *output)
+{
+ const size_t outputComponentSize = toHalf ? 2 : 4;
+ const size_t componentCount = 4;
+
+ const uint32_t rgbMask = 0x3FF; // 1 set in bits 0 through 9
+ const size_t redShift = 22; // red is bits 22 through 31
+ const size_t greenShift = 12; // green is bits 12 through 21
+ const size_t blueShift = 2; // blue is bits 2 through 11
+
+ const uint32_t alphaDefaultValueBits = normalized ? (isSigned ? 0x1 : 0x3) : 0x1;
+
+ for (size_t i = 0; i < count; i++)
+ {
+ GLuint packedValue = *reinterpret_cast<const GLuint *>(input + (i * stride));
+ uint8_t *offsetOutput = output + (i * outputComponentSize * componentCount);
+
+ priv::CopyPackedRGB<isSigned, normalized, true, toHalf>(
+ (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize));
+ priv::CopyPackedRGB<isSigned, normalized, true, toHalf>(
+ (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize));
+ priv::CopyPackedRGB<isSigned, normalized, true, toHalf>(
+ (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize));
+ priv::CopyPackedAlpha<isSigned, normalized, true, toHalf>(
+ alphaDefaultValueBits, offsetOutput + (3 * outputComponentSize));
+ }
+}
+
+template <bool isSigned, bool normalized, bool toHalf>
+inline void CopyW2XYZ10ToXYZWFloatVertexData(const uint8_t *input,
+ size_t stride,
+ size_t count,
+ uint8_t *output)
+{
+ const size_t outputComponentSize = toHalf ? 2 : 4;
+ const size_t componentCount = 4;
+
+ const uint32_t rgbMask = 0x3FF; // 1 set in bits 0 through 9
+ const size_t redShift = 22; // red is bits 22 through 31
+ const size_t greenShift = 12; // green is bits 12 through 21
+ const size_t blueShift = 2; // blue is bits 2 through 11
+
+ const uint32_t alphaMask = 0x3; // 1 set in bits 0 and 1
+ const size_t alphaShift = 0; // Alpha is the 30 and 31 bits
+
+ for (size_t i = 0; i < count; i++)
+ {
+ GLuint packedValue = *reinterpret_cast<const GLuint *>(input + (i * stride));
+ uint8_t *offsetOutput = output + (i * outputComponentSize * componentCount);
+
+ priv::CopyPackedRGB<isSigned, normalized, true, toHalf>(
+ (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize));
+ priv::CopyPackedRGB<isSigned, normalized, true, toHalf>(
+ (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize));
+ priv::CopyPackedRGB<isSigned, normalized, true, toHalf>(
+ (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize));
+ priv::CopyPackedAlpha<isSigned, normalized, true, toHalf>(
+ (packedValue >> alphaShift) & alphaMask, offsetOutput + (3 * outputComponentSize));
+ }
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/BufferD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/BufferD3D.cpp
new file mode 100644
index 0000000000..464bd6d4a8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/BufferD3D.cpp
@@ -0,0 +1,191 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BufferD3D.cpp Defines common functionality between the Buffer9 and Buffer11 classes.
+
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
+
+namespace rx
+{
+
+unsigned int BufferD3D::mNextSerial = 1;
+
+BufferD3D::BufferD3D(const gl::BufferState &state, BufferFactoryD3D *factory)
+ : BufferImpl(state),
+ mFactory(factory),
+ mStaticIndexBuffer(nullptr),
+ mStaticBufferCacheTotalSize(0),
+ mStaticVertexBufferOutOfDate(false),
+ mUnmodifiedDataUse(0),
+ mUsage(D3DBufferUsage::STATIC)
+{
+ updateSerial();
+}
+
+BufferD3D::~BufferD3D()
+{
+ SafeDelete(mStaticIndexBuffer);
+}
+
+void BufferD3D::emptyStaticBufferCache()
+{
+ mStaticVertexBuffers.clear();
+ mStaticBufferCacheTotalSize = 0;
+}
+
+void BufferD3D::updateSerial()
+{
+ mSerial = mNextSerial++;
+}
+
+void BufferD3D::updateD3DBufferUsage(const gl::Context *context, gl::BufferUsage usage)
+{
+ switch (usage)
+ {
+ case gl::BufferUsage::StaticCopy:
+ case gl::BufferUsage::StaticDraw:
+ case gl::BufferUsage::StaticRead:
+ case gl::BufferUsage::DynamicCopy:
+ case gl::BufferUsage::DynamicRead:
+ case gl::BufferUsage::StreamCopy:
+ case gl::BufferUsage::StreamRead:
+ mUsage = D3DBufferUsage::STATIC;
+ initializeStaticData(context);
+ break;
+
+ case gl::BufferUsage::DynamicDraw:
+ case gl::BufferUsage::StreamDraw:
+ mUsage = D3DBufferUsage::DYNAMIC;
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+void BufferD3D::initializeStaticData(const gl::Context *context)
+{
+ if (mStaticVertexBuffers.empty())
+ {
+ StaticVertexBufferInterface *newStaticBuffer = new StaticVertexBufferInterface(mFactory);
+ mStaticVertexBuffers.push_back(
+ std::unique_ptr<StaticVertexBufferInterface>(newStaticBuffer));
+ }
+ if (!mStaticIndexBuffer)
+ {
+ mStaticIndexBuffer = new StaticIndexBufferInterface(mFactory);
+ }
+}
+
+StaticIndexBufferInterface *BufferD3D::getStaticIndexBuffer()
+{
+ return mStaticIndexBuffer;
+}
+
+StaticVertexBufferInterface *BufferD3D::getStaticVertexBuffer(const gl::VertexAttribute &attribute,
+ const gl::VertexBinding &binding)
+{
+ if (mStaticVertexBuffers.empty())
+ {
+ // Early out if there aren't any static buffers at all
+ return nullptr;
+ }
+
+ // Early out, the attribute can be added to mStaticVertexBuffer.
+ if (mStaticVertexBuffers.size() == 1 && mStaticVertexBuffers[0]->empty())
+ {
+ return mStaticVertexBuffers[0].get();
+ }
+
+ // Cache size limiting: track the total allocated buffer sizes.
+ size_t currentTotalSize = 0;
+
+ // At this point, see if any of the existing static buffers contains the attribute data
+ // If there is a cached static buffer that already contains the attribute, then return it
+ for (const auto &staticBuffer : mStaticVertexBuffers)
+ {
+ if (staticBuffer->matchesAttribute(attribute, binding))
+ {
+ return staticBuffer.get();
+ }
+
+ currentTotalSize += staticBuffer->getBufferSize();
+ }
+
+ // Cache size limiting: Clean-up threshold is four times the base buffer size, with a minimum.
+ ASSERT(getSize() < std::numeric_limits<size_t>::max() / 4u);
+ size_t sizeThreshold = std::max(getSize() * 4u, static_cast<size_t>(0x1000u));
+
+ // If we're past the threshold, clear the buffer cache. Note that this will release buffers
+ // that are currenly bound, and in an edge case can even translate the same attribute twice
+ // in the same draw call. It will not delete currently bound buffers, however, because they
+ // are ref counted.
+ if (currentTotalSize > sizeThreshold)
+ {
+ emptyStaticBufferCache();
+ }
+
+ // At this point, we must create a new static buffer for the attribute data.
+ StaticVertexBufferInterface *newStaticBuffer = new StaticVertexBufferInterface(mFactory);
+ newStaticBuffer->setAttribute(attribute, binding);
+ mStaticVertexBuffers.push_back(std::unique_ptr<StaticVertexBufferInterface>(newStaticBuffer));
+ return newStaticBuffer;
+}
+
+void BufferD3D::invalidateStaticData(const gl::Context *context)
+{
+ emptyStaticBufferCache();
+
+ if (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)
+ {
+ SafeDelete(mStaticIndexBuffer);
+ }
+
+ // If the buffer was created with a static usage then we recreate the static
+ // buffers so that they are populated the next time we use this buffer.
+ if (mUsage == D3DBufferUsage::STATIC)
+ {
+ initializeStaticData(context);
+ }
+
+ mUnmodifiedDataUse = 0;
+}
+
+// Creates static buffers if sufficient used data has been left unmodified
+void BufferD3D::promoteStaticUsage(const gl::Context *context, size_t dataSize)
+{
+ if (mUsage == D3DBufferUsage::DYNAMIC)
+ {
+ // Note: This is not a safe math operation. 'dataSize' can come from the app.
+ mUnmodifiedDataUse += dataSize;
+
+ if (mUnmodifiedDataUse > 3 * getSize())
+ {
+ updateD3DBufferUsage(context, gl::BufferUsage::StaticDraw);
+ }
+ }
+}
+
+angle::Result BufferD3D::getIndexRange(const gl::Context *context,
+ gl::DrawElementsType type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ gl::IndexRange *outRange)
+{
+ const uint8_t *data = nullptr;
+ ANGLE_TRY(getData(context, &data));
+
+ *outRange = gl::ComputeIndexRange(type, data + offset, count, primitiveRestartEnabled);
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/BufferD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/BufferD3D.h
new file mode 100644
index 0000000000..19ea78c6eb
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/BufferD3D.h
@@ -0,0 +1,89 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BufferD3D.h: Defines the rx::BufferD3D class, an implementation of BufferImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_BUFFERD3D_H_
+#define LIBANGLE_RENDERER_D3D_BUFFERD3D_H_
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/BufferImpl.h"
+
+#include <stdint.h>
+#include <vector>
+
+namespace gl
+{
+struct VertexAttribute;
+class VertexBinding;
+} // namespace gl
+
+namespace rx
+{
+class BufferFactoryD3D;
+class StaticIndexBufferInterface;
+class StaticVertexBufferInterface;
+
+enum class D3DBufferUsage
+{
+ STATIC,
+ DYNAMIC,
+};
+
+class BufferD3D : public BufferImpl
+{
+ public:
+ BufferD3D(const gl::BufferState &state, BufferFactoryD3D *factory);
+ ~BufferD3D() override;
+
+ unsigned int getSerial() const { return mSerial; }
+
+ virtual size_t getSize() const = 0;
+ virtual bool supportsDirectBinding() const = 0;
+ virtual angle::Result markTransformFeedbackUsage(const gl::Context *context) = 0;
+ virtual angle::Result getData(const gl::Context *context, const uint8_t **outData) = 0;
+
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+ // function.
+ StaticVertexBufferInterface *getStaticVertexBuffer(const gl::VertexAttribute &attribute,
+ const gl::VertexBinding &binding);
+ StaticIndexBufferInterface *getStaticIndexBuffer();
+
+ virtual void initializeStaticData(const gl::Context *context);
+ virtual void invalidateStaticData(const gl::Context *context);
+
+ void promoteStaticUsage(const gl::Context *context, size_t dataSize);
+
+ angle::Result getIndexRange(const gl::Context *context,
+ gl::DrawElementsType type,
+ size_t offset,
+ size_t count,
+ bool primitiveRestartEnabled,
+ gl::IndexRange *outRange) override;
+
+ BufferFactoryD3D *getFactory() const { return mFactory; }
+ D3DBufferUsage getUsage() const { return mUsage; }
+
+ protected:
+ void updateSerial();
+ void updateD3DBufferUsage(const gl::Context *context, gl::BufferUsage usage);
+ void emptyStaticBufferCache();
+
+ BufferFactoryD3D *mFactory;
+ unsigned int mSerial;
+ static unsigned int mNextSerial;
+
+ std::vector<std::unique_ptr<StaticVertexBufferInterface>> mStaticVertexBuffers;
+ StaticIndexBufferInterface *mStaticIndexBuffer;
+ unsigned int mStaticBufferCacheTotalSize;
+ unsigned int mStaticVertexBufferOutOfDate;
+ size_t mUnmodifiedDataUse;
+ D3DBufferUsage mUsage;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_BUFFERD3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/CompilerD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/CompilerD3D.cpp
new file mode 100644
index 0000000000..4656cf4d80
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/CompilerD3D.cpp
@@ -0,0 +1,24 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// CompilerD3D:
+// Implementation of the D3D compiler methods.
+//
+
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+
+namespace rx
+{
+
+CompilerD3D::CompilerD3D(ShShaderOutput translatorOutputType)
+ : mTranslatorOutputType(translatorOutputType)
+{}
+
+ShShaderOutput CompilerD3D::getTranslatorOutputType() const
+{
+ return mTranslatorOutputType;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/CompilerD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/CompilerD3D.h
new file mode 100644
index 0000000000..3e1d01a0b9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/CompilerD3D.h
@@ -0,0 +1,32 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CompilerD3D.h: Defines the rx::CompilerD3D class, an implementation of rx::CompilerImpl.
+
+#ifndef LIBANGLE_RENDERER_COMPILERD3D_H_
+#define LIBANGLE_RENDERER_COMPILERD3D_H_
+
+#include "libANGLE/renderer/CompilerImpl.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+
+class CompilerD3D : public CompilerImpl
+{
+ public:
+ CompilerD3D(ShShaderOutput translatorOutputType);
+ ~CompilerD3D() override {}
+
+ ShShaderOutput getTranslatorOutputType() const override;
+
+ private:
+ ShShaderOutput mTranslatorOutputType;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_COMPILERD3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/ContextD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ContextD3D.h
new file mode 100644
index 0000000000..d563672e67
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ContextD3D.h
@@ -0,0 +1,24 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ContextD3D: Shared common class for Context9 and Context11.
+
+#ifndef LIBANGLE_RENDERER_CONTEXTD3D_H_
+#define LIBANGLE_RENDERER_CONTEXTD3D_H_
+
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+class ContextD3D : public ContextImpl, public d3d::Context
+{
+ public:
+ ContextD3D(const gl::State &state, gl::ErrorSet *errorSet) : ContextImpl(state, errorSet) {}
+ ~ContextD3D() override {}
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_CONTEXTD3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/DeviceD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DeviceD3D.cpp
new file mode 100644
index 0000000000..79dfb094e3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DeviceD3D.cpp
@@ -0,0 +1,84 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DeviceD3D.cpp: D3D implementation of egl::Device
+
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
+
+#include "libANGLE/Device.h"
+#include "libANGLE/Display.h"
+
+#include <EGL/eglext.h>
+
+namespace rx
+{
+
+DeviceD3D::DeviceD3D(GLint deviceType, void *nativeDevice)
+ : mDevice(nativeDevice), mDeviceType(deviceType), mIsInitialized(false)
+{}
+
+DeviceD3D::~DeviceD3D()
+{
+#if defined(ANGLE_ENABLE_D3D11)
+ if (mIsInitialized && mDeviceType == EGL_D3D11_DEVICE_ANGLE)
+ {
+ // DeviceD3D holds a ref to an externally-sourced D3D11 device. We must release it.
+ ID3D11Device *device = static_cast<ID3D11Device *>(mDevice);
+ device->Release();
+ }
+#endif
+}
+
+egl::Error DeviceD3D::getAttribute(const egl::Display *display, EGLint attribute, void **outValue)
+{
+ ASSERT(mIsInitialized);
+ ANGLE_UNUSED_VARIABLE(display);
+ // Validated at higher levels.
+ ASSERT(getType() == attribute);
+ *outValue = mDevice;
+ return egl::NoError();
+}
+
+egl::Error DeviceD3D::initialize()
+{
+ ASSERT(!mIsInitialized);
+
+#if defined(ANGLE_ENABLE_D3D11)
+ if (mDeviceType == EGL_D3D11_DEVICE_ANGLE)
+ {
+ // Validate the device
+ IUnknown *iunknown = static_cast<IUnknown *>(mDevice);
+
+ ID3D11Device *d3dDevice = nullptr;
+ HRESULT hr =
+ iunknown->QueryInterface(__uuidof(ID3D11Device), reinterpret_cast<void **>(&d3dDevice));
+ if (FAILED(hr))
+ {
+ return egl::EglBadAttribute() << "Invalid D3D device passed into EGLDeviceEXT";
+ }
+
+ // The QI to ID3D11Device adds a ref to the D3D11 device.
+ // Deliberately don't release the ref here, so that the DeviceD3D holds a ref to the
+ // D3D11 device.
+ }
+#endif
+
+ mIsInitialized = true;
+
+ return egl::NoError();
+}
+
+EGLint DeviceD3D::getType()
+{
+ return mDeviceType;
+}
+
+void DeviceD3D::generateExtensions(egl::DeviceExtensions *outExtensions) const
+{
+ outExtensions->deviceD3D = true;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/DeviceD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DeviceD3D.h
new file mode 100644
index 0000000000..c169eb7de5
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DeviceD3D.h
@@ -0,0 +1,39 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DeviceD3D.h: D3D implementation of egl::Device
+
+#ifndef LIBANGLE_RENDERER_D3D_DEVICED3D_H_
+#define LIBANGLE_RENDERER_D3D_DEVICED3D_H_
+
+#include "libANGLE/Device.h"
+#include "libANGLE/renderer/DeviceImpl.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+class DeviceD3D : public DeviceImpl
+{
+ public:
+ DeviceD3D(EGLint deviceType, void *nativeDevice);
+ ~DeviceD3D() override;
+
+ egl::Error initialize() override;
+ egl::Error getAttribute(const egl::Display *display,
+ EGLint attribute,
+ void **outValue) override;
+ EGLint getType() override;
+ void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
+
+ private:
+ void *mDevice;
+ EGLint mDeviceType;
+ bool mIsInitialized;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_DEVICED3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DisplayD3D.cpp
new file mode 100644
index 0000000000..35216fd4d2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DisplayD3D.cpp
@@ -0,0 +1,462 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayD3D.cpp: D3D implementation of egl::Display
+
+#include "libANGLE/renderer/d3d/DisplayD3D.h"
+
+#include <EGL/eglext.h>
+
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Thread.h"
+#include "libANGLE/histogram_macros.h"
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
+#include "libANGLE/renderer/d3d/EGLImageD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+
+#if !defined(ANGLE_DEFAULT_D3D11)
+// Enables use of the Direct3D 11 API for a default display, when available
+# define ANGLE_DEFAULT_D3D11 1
+#endif
+
+namespace rx
+{
+
+using CreateRendererD3DFunction = RendererD3D *(*)(egl::Display *);
+
+egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
+{
+ ASSERT(outRenderer != nullptr);
+
+ std::vector<CreateRendererD3DFunction> rendererCreationFunctions;
+
+ if (display->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
+ {
+ const auto &attribMap = display->getAttributeMap();
+ EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId();
+
+ EGLint requestedDisplayType = static_cast<EGLint>(
+ attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE));
+
+#if defined(ANGLE_ENABLE_D3D11)
+ const auto addD3D11 = nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
+ nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE ||
+ requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE;
+#endif
+
+#if defined(ANGLE_ENABLE_D3D9)
+ const auto addD3D9 = nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
+ requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE;
+#endif
+
+#if ANGLE_DEFAULT_D3D11
+# if defined(ANGLE_ENABLE_D3D11)
+ if (addD3D11)
+ {
+ rendererCreationFunctions.push_back(CreateRenderer11);
+ }
+# endif
+
+# if defined(ANGLE_ENABLE_D3D9)
+ if (addD3D9)
+ {
+ rendererCreationFunctions.push_back(CreateRenderer9);
+ }
+# endif
+#else
+# if defined(ANGLE_ENABLE_D3D9)
+ if (addD3D9)
+ {
+ rendererCreationFunctions.push_back(CreateRenderer9);
+ }
+# endif
+
+# if defined(ANGLE_ENABLE_D3D11)
+ if (addD3D11)
+ {
+ rendererCreationFunctions.push_back(CreateRenderer11);
+ }
+# endif
+#endif
+
+ if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE &&
+ nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE &&
+ requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
+ {
+ // The default display is requested, try the D3D9 and D3D11 renderers, order them using
+ // the definition of ANGLE_DEFAULT_D3D11
+#if ANGLE_DEFAULT_D3D11
+# if defined(ANGLE_ENABLE_D3D11)
+ rendererCreationFunctions.push_back(CreateRenderer11);
+# endif
+# if defined(ANGLE_ENABLE_D3D9)
+ rendererCreationFunctions.push_back(CreateRenderer9);
+# endif
+#else
+# if defined(ANGLE_ENABLE_D3D9)
+ rendererCreationFunctions.push_back(CreateRenderer9);
+# endif
+# if defined(ANGLE_ENABLE_D3D11)
+ rendererCreationFunctions.push_back(CreateRenderer11);
+# endif
+#endif
+ }
+ }
+ else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
+ {
+#if defined(ANGLE_ENABLE_D3D11)
+ if (display->getDevice()->getType() == EGL_D3D11_DEVICE_ANGLE)
+ {
+ rendererCreationFunctions.push_back(CreateRenderer11);
+ }
+#endif
+ }
+ else
+ {
+ UNIMPLEMENTED();
+ }
+
+ for (size_t i = 0; i < rendererCreationFunctions.size(); i++)
+ {
+ RendererD3D *renderer = rendererCreationFunctions[i](display);
+ egl::Error result = renderer->initialize();
+
+#if defined(ANGLE_ENABLE_D3D11)
+ if (renderer->getRendererClass() == RENDERER_D3D11)
+ {
+ ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D11_INIT_ERRORS);
+ ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11InitializeResult", result.getID(),
+ NUM_D3D11_INIT_ERRORS);
+ }
+#endif
+
+#if defined(ANGLE_ENABLE_D3D9)
+ if (renderer->getRendererClass() == RENDERER_D3D9)
+ {
+ ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D9_INIT_ERRORS);
+ ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D9InitializeResult", result.getID(),
+ NUM_D3D9_INIT_ERRORS);
+ }
+#endif
+
+ if (!result.isError())
+ {
+ *outRenderer = renderer;
+ return result;
+ }
+
+ // Failed to create the renderer, try the next
+ SafeDelete(renderer);
+ ERR() << "Failed to create D3D renderer: " << result.getMessage();
+ }
+
+ return egl::EglNotInitialized() << "No available renderers.";
+}
+
+DisplayD3D::DisplayD3D(const egl::DisplayState &state) : DisplayImpl(state), mRenderer(nullptr) {}
+
+SurfaceImpl *DisplayD3D::createWindowSurface(const egl::SurfaceState &state,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(mRenderer != nullptr);
+ return new WindowSurfaceD3D(state, mRenderer, mDisplay, window, attribs);
+}
+
+SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::SurfaceState &state,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(mRenderer != nullptr);
+ return new PbufferSurfaceD3D(state, mRenderer, mDisplay, 0, nullptr, attribs);
+}
+
+SurfaceImpl *DisplayD3D::createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(mRenderer != nullptr);
+ return new PbufferSurfaceD3D(state, mRenderer, mDisplay, buftype, clientBuffer, attribs);
+}
+
+SurfaceImpl *DisplayD3D::createPixmapSurface(const egl::SurfaceState &state,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+ImageImpl *DisplayD3D::createImage(const egl::ImageState &state,
+ const gl::Context *context,
+ EGLenum target,
+ const egl::AttributeMap &attribs)
+{
+ return new EGLImageD3D(state, target, attribs, mRenderer);
+}
+
+DeviceImpl *DisplayD3D::createDevice()
+{
+ return mRenderer->createEGLDevice();
+}
+
+rx::ContextImpl *DisplayD3D::createContext(const gl::State &state,
+ gl::ErrorSet *errorSet,
+ const egl::Config *configuration,
+ const gl::Context *shareContext,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(mRenderer != nullptr);
+ return mRenderer->createContext(state, errorSet);
+}
+
+StreamProducerImpl *DisplayD3D::createStreamProducerD3DTexture(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(mRenderer != nullptr);
+ return mRenderer->createStreamProducerD3DTexture(consumerType, attribs);
+}
+
+ExternalImageSiblingImpl *DisplayD3D::createExternalImageSibling(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs)
+{
+ ASSERT(mRenderer != nullptr);
+ return mRenderer->createExternalImageSibling(context, target, buffer, attribs);
+}
+
+ShareGroupImpl *DisplayD3D::createShareGroup()
+{
+ return new ShareGroupD3D();
+}
+
+egl::Error DisplayD3D::makeCurrent(egl::Display *display,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface,
+ gl::Context *context)
+{
+ // Ensure the appropriate global DebugAnnotator is used
+ ASSERT(mRenderer != nullptr);
+ mRenderer->setGlobalDebugAnnotator();
+
+ return egl::NoError();
+}
+
+egl::Error DisplayD3D::initialize(egl::Display *display)
+{
+ ASSERT(mRenderer == nullptr && display != nullptr);
+ mDisplay = display;
+ ANGLE_TRY(CreateRendererD3D(display, &mRenderer));
+ return egl::NoError();
+}
+
+void DisplayD3D::terminate()
+{
+ SafeDelete(mRenderer);
+}
+
+egl::ConfigSet DisplayD3D::generateConfigs()
+{
+ ASSERT(mRenderer != nullptr);
+ return mRenderer->generateConfigs();
+}
+
+bool DisplayD3D::testDeviceLost()
+{
+ ASSERT(mRenderer != nullptr);
+ return mRenderer->testDeviceLost();
+}
+
+egl::Error DisplayD3D::restoreLostDevice(const egl::Display *display)
+{
+ // Release surface resources to make the Reset() succeed
+ for (egl::Surface *surface : mState.surfaceSet)
+ {
+ ASSERT(!surface->getBoundTexture());
+ SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+ surfaceD3D->releaseSwapChain();
+ }
+
+ if (!mRenderer->resetDevice())
+ {
+ return egl::EglBadAlloc();
+ }
+
+ // Restore any surfaces that may have been lost
+ for (const egl::Surface *surface : mState.surfaceSet)
+ {
+ SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+
+ ANGLE_TRY(surfaceD3D->resetSwapChain(display));
+ }
+
+ return egl::NoError();
+}
+
+bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ return mRenderer->isValidNativeWindow(window);
+}
+
+egl::Error DisplayD3D::validateClientBuffer(const egl::Config *config,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const
+{
+ switch (buftype)
+ {
+ case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+ return mRenderer->validateShareHandle(config, static_cast<HANDLE>(clientBuffer),
+ attribs);
+
+ case EGL_D3D_TEXTURE_ANGLE:
+ return mRenderer->getD3DTextureInfo(config, static_cast<IUnknown *>(clientBuffer),
+ attribs, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr);
+
+ default:
+ return DisplayImpl::validateClientBuffer(config, buftype, clientBuffer, attribs);
+ }
+}
+
+egl::Error DisplayD3D::validateImageClientBuffer(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const
+{
+ switch (target)
+ {
+ case EGL_D3D11_TEXTURE_ANGLE:
+ {
+ return mRenderer->getD3DTextureInfo(nullptr, static_cast<IUnknown *>(clientBuffer),
+ attribs, nullptr, nullptr, nullptr, nullptr,
+ nullptr, nullptr);
+ }
+
+ default:
+ return DisplayImpl::validateImageClientBuffer(context, target, clientBuffer, attribs);
+ }
+}
+
+void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+ mRenderer->generateDisplayExtensions(outExtensions);
+}
+
+std::string DisplayD3D::getRendererDescription()
+{
+ if (mRenderer)
+ {
+ return mRenderer->getRendererDescription();
+ }
+ return std::string();
+}
+
+std::string DisplayD3D::getVendorString()
+{
+ if (mRenderer)
+ {
+ return mRenderer->getVendorString();
+ }
+ return std::string();
+}
+
+std::string DisplayD3D::getVersionString(bool includeFullVersion)
+{
+ if (mRenderer)
+ {
+ return mRenderer->getVersionString(includeFullVersion);
+ }
+ return std::string();
+}
+
+void DisplayD3D::generateCaps(egl::Caps *outCaps) const
+{
+ // Display must be initialized to generate caps
+ ASSERT(mRenderer != nullptr);
+
+ outCaps->textureNPOT = mRenderer->getNativeExtensions().textureNpotOES;
+}
+
+egl::Error DisplayD3D::waitClient(const gl::Context *context)
+{
+ for (egl::Surface *surface : mState.surfaceSet)
+ {
+ SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+ ANGLE_TRY(surfaceD3D->checkForOutOfDateSwapChain(this));
+ }
+
+ return egl::NoError();
+}
+
+egl::Error DisplayD3D::waitNative(const gl::Context *context, EGLint engine)
+{
+ egl::Surface *drawSurface = context->getCurrentDrawSurface();
+ egl::Surface *readSurface = context->getCurrentReadSurface();
+
+ if (drawSurface != nullptr)
+ {
+ SurfaceD3D *drawSurfaceD3D = GetImplAs<SurfaceD3D>(drawSurface);
+ ANGLE_TRY(drawSurfaceD3D->checkForOutOfDateSwapChain(this));
+ }
+
+ if (readSurface != nullptr)
+ {
+ SurfaceD3D *readSurfaceD3D = GetImplAs<SurfaceD3D>(readSurface);
+ ANGLE_TRY(readSurfaceD3D->checkForOutOfDateSwapChain(this));
+ }
+
+ return egl::NoError();
+}
+
+gl::Version DisplayD3D::getMaxSupportedESVersion() const
+{
+ return mRenderer->getMaxSupportedESVersion();
+}
+
+gl::Version DisplayD3D::getMaxConformantESVersion() const
+{
+ return mRenderer->getMaxConformantESVersion();
+}
+
+Optional<gl::Version> DisplayD3D::getMaxSupportedDesktopVersion() const
+{
+ return Optional<gl::Version>::Invalid();
+}
+
+void DisplayD3D::handleResult(HRESULT hr,
+ const char *message,
+ const char *file,
+ const char *function,
+ unsigned int line)
+{
+ ASSERT(FAILED(hr));
+
+ std::stringstream errorStream;
+ errorStream << "Internal D3D11 error: " << gl::FmtHR(hr) << ", in " << file << ", " << function
+ << ":" << line << ". " << message;
+
+ mStoredErrorString = errorStream.str();
+}
+
+void DisplayD3D::initializeFrontendFeatures(angle::FrontendFeatures *features) const
+{
+ mRenderer->initializeFrontendFeatures(features);
+}
+
+void DisplayD3D::populateFeatureList(angle::FeatureList *features)
+{
+ mRenderer->getFeatures().populateFeatureList(features);
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/DisplayD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DisplayD3D.h
new file mode 100644
index 0000000000..890658f5ea
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DisplayD3D.h
@@ -0,0 +1,179 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayD3D.h: D3D implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_
+#define LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_
+
+#include "libANGLE/Device.h"
+#include "libANGLE/renderer/DisplayImpl.h"
+
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+class ShareGroupD3D : public ShareGroupImpl
+{};
+
+class DisplayD3D : public DisplayImpl, public d3d::Context
+{
+ public:
+ DisplayD3D(const egl::DisplayState &state);
+
+ egl::Error initialize(egl::Display *display) override;
+ void terminate() override;
+
+ // Surface creation
+ SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) override;
+ SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
+ NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs) override;
+
+ ImageImpl *createImage(const egl::ImageState &state,
+ const gl::Context *context,
+ EGLenum target,
+ const egl::AttributeMap &attribs) override;
+
+ ContextImpl *createContext(const gl::State &state,
+ gl::ErrorSet *errorSet,
+ const egl::Config *configuration,
+ const gl::Context *shareContext,
+ const egl::AttributeMap &attribs) override;
+
+ StreamProducerImpl *createStreamProducerD3DTexture(egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) override;
+
+ ExternalImageSiblingImpl *createExternalImageSibling(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs) override;
+
+ ShareGroupImpl *createShareGroup() override;
+
+ egl::Error makeCurrent(egl::Display *display,
+ egl::Surface *drawSurface,
+ egl::Surface *readSurface,
+ gl::Context *context) override;
+
+ egl::ConfigSet generateConfigs() override;
+
+ bool testDeviceLost() override;
+ egl::Error restoreLostDevice(const egl::Display *display) override;
+
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+ egl::Error validateClientBuffer(const egl::Config *configuration,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const override;
+ egl::Error validateImageClientBuffer(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const override;
+
+ DeviceImpl *createDevice() override;
+
+ std::string getRendererDescription() override;
+ std::string getVendorString() override;
+ std::string getVersionString(bool includeFullVersion) override;
+
+ egl::Error waitClient(const gl::Context *context) override;
+ egl::Error waitNative(const gl::Context *context, EGLint engine) override;
+ gl::Version getMaxSupportedESVersion() const override;
+ gl::Version getMaxConformantESVersion() const override;
+ Optional<gl::Version> getMaxSupportedDesktopVersion() const override;
+
+ void handleResult(HRESULT hr,
+ const char *message,
+ const char *file,
+ const char *function,
+ unsigned int line) override;
+
+ const std::string &getStoredErrorString() const { return mStoredErrorString; }
+
+ void initializeFrontendFeatures(angle::FrontendFeatures *features) const override;
+
+ void populateFeatureList(angle::FeatureList *features) override;
+
+ private:
+ void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+ void generateCaps(egl::Caps *outCaps) const override;
+
+ egl::Display *mDisplay;
+
+ rx::RendererD3D *mRenderer;
+ std::string mStoredErrorString;
+};
+
+// Possible reasons RendererD3D initialize can fail
+enum D3D11InitError
+{
+ // The renderer loaded successfully
+ D3D11_INIT_SUCCESS = 0,
+ // Failed to load the ANGLE & D3D compiler libraries
+ D3D11_INIT_COMPILER_ERROR,
+ // Failed to load a necessary DLL (non-compiler)
+ D3D11_INIT_MISSING_DEP,
+ // CreateDevice returned E_INVALIDARG
+ D3D11_INIT_CREATEDEVICE_INVALIDARG,
+ // CreateDevice failed with an error other than invalid arg
+ D3D11_INIT_CREATEDEVICE_ERROR,
+ // DXGI 1.2 required but not found
+ D3D11_INIT_INCOMPATIBLE_DXGI,
+ // Other initialization error
+ D3D11_INIT_OTHER_ERROR,
+ // CreateDevice returned E_FAIL
+ D3D11_INIT_CREATEDEVICE_FAIL,
+ // CreateDevice returned E_NOTIMPL
+ D3D11_INIT_CREATEDEVICE_NOTIMPL,
+ // CreateDevice returned E_OUTOFMEMORY
+ D3D11_INIT_CREATEDEVICE_OUTOFMEMORY,
+ // CreateDevice returned DXGI_ERROR_INVALID_CALL
+ D3D11_INIT_CREATEDEVICE_INVALIDCALL,
+ // CreateDevice returned DXGI_ERROR_SDK_COMPONENT_MISSING
+ D3D11_INIT_CREATEDEVICE_COMPONENTMISSING,
+ // CreateDevice returned DXGI_ERROR_WAS_STILL_DRAWING
+ D3D11_INIT_CREATEDEVICE_WASSTILLDRAWING,
+ // CreateDevice returned DXGI_ERROR_NOT_CURRENTLY_AVAILABLE
+ D3D11_INIT_CREATEDEVICE_NOTAVAILABLE,
+ // CreateDevice returned DXGI_ERROR_DEVICE_HUNG
+ D3D11_INIT_CREATEDEVICE_DEVICEHUNG,
+ // CreateDevice returned NULL
+ D3D11_INIT_CREATEDEVICE_NULL,
+ NUM_D3D11_INIT_ERRORS
+};
+
+enum D3D9InitError
+{
+ D3D9_INIT_SUCCESS = 0,
+ // Failed to load the D3D or ANGLE compiler
+ D3D9_INIT_COMPILER_ERROR,
+ // Failed to load a necessary DLL
+ D3D9_INIT_MISSING_DEP,
+ // Device creation error
+ D3D9_INIT_CREATE_DEVICE_ERROR,
+ // System does not meet minimum shader spec
+ D3D9_INIT_UNSUPPORTED_VERSION,
+ // System does not support stretchrect from textures
+ D3D9_INIT_UNSUPPORTED_STRETCHRECT,
+ // A call returned out of memory or device lost
+ D3D9_INIT_OUT_OF_MEMORY,
+ // Other unspecified error
+ D3D9_INIT_OTHER_ERROR,
+ NUM_D3D9_INIT_ERRORS
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
new file mode 100644
index 0000000000..b83c8bac6e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
@@ -0,0 +1,1537 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DynamicHLSL.cpp: Implementation for link and run-time HLSL generation
+//
+
+#include "libANGLE/renderer/d3d/DynamicHLSL.h"
+
+#include "common/string_utils.h"
+#include "common/utilities.h"
+#include "compiler/translator/blocklayoutHLSL.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/VaryingPacking.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+
+using namespace gl;
+
+namespace rx
+{
+
+namespace
+{
+
+// kShaderStorageDeclarationString must be the same as outputHLSL.
+constexpr const char kShaderStorageDeclarationString[] =
+ "// @@ SHADER STORAGE DECLARATION STRING @@";
+
+const char *HLSLComponentTypeString(GLenum componentType)
+{
+ switch (componentType)
+ {
+ case GL_UNSIGNED_INT:
+ return "uint";
+ case GL_INT:
+ return "int";
+ case GL_UNSIGNED_NORMALIZED:
+ case GL_SIGNED_NORMALIZED:
+ case GL_FLOAT:
+ return "float";
+ default:
+ UNREACHABLE();
+ return "not-component-type";
+ }
+}
+
+void HLSLComponentTypeString(std::ostringstream &ostream, GLenum componentType, int componentCount)
+{
+ ostream << HLSLComponentTypeString(componentType);
+ if (componentCount > 1)
+ {
+ ostream << componentCount;
+ }
+}
+
+const char *HLSLMatrixTypeString(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT_MAT2:
+ return "float2x2";
+ case GL_FLOAT_MAT3:
+ return "float3x3";
+ case GL_FLOAT_MAT4:
+ return "float4x4";
+ case GL_FLOAT_MAT2x3:
+ return "float2x3";
+ case GL_FLOAT_MAT3x2:
+ return "float3x2";
+ case GL_FLOAT_MAT2x4:
+ return "float2x4";
+ case GL_FLOAT_MAT4x2:
+ return "float4x2";
+ case GL_FLOAT_MAT3x4:
+ return "float3x4";
+ case GL_FLOAT_MAT4x3:
+ return "float4x3";
+ default:
+ UNREACHABLE();
+ return "not-matrix-type";
+ }
+}
+
+void HLSLTypeString(std::ostringstream &ostream, GLenum type)
+{
+ if (gl::IsMatrixType(type))
+ {
+ ostream << HLSLMatrixTypeString(type);
+ return;
+ }
+
+ HLSLComponentTypeString(ostream, gl::VariableComponentType(type),
+ gl::VariableComponentCount(type));
+}
+
+const PixelShaderOutputVariable *FindOutputAtLocation(
+ const std::vector<PixelShaderOutputVariable> &outputVariables,
+ unsigned int location,
+ size_t index = 0)
+{
+ for (auto &outputVar : outputVariables)
+ {
+ if (outputVar.outputLocation == location && outputVar.outputIndex == index)
+ {
+ return &outputVar;
+ }
+ }
+
+ return nullptr;
+}
+
+void WriteArrayString(std::ostringstream &strstr, unsigned int i)
+{
+ static_assert(GL_INVALID_INDEX == UINT_MAX,
+ "GL_INVALID_INDEX must be equal to the max unsigned int.");
+ if (i == UINT_MAX)
+ {
+ return;
+ }
+
+ strstr << "[";
+ strstr << i;
+ strstr << "]";
+}
+
+bool ReplaceShaderStorageDeclaration(const std::vector<ShaderStorageBlock> &shaderStorageBlocks,
+ std::string *hlsl,
+ size_t baseUAVRegister,
+ gl::ShaderType shaderType)
+{
+ std::string ssboHeader;
+ std::ostringstream out(ssboHeader);
+ for (const ShaderStorageBlock &ssbo : shaderStorageBlocks)
+ {
+ size_t uavRegister = baseUAVRegister + ssbo.registerIndex;
+ std::string name = ssbo.name;
+ if (ssbo.arraySize > 0)
+ {
+ for (unsigned int arrayIndex = 0; arrayIndex < ssbo.arraySize; arrayIndex++)
+ {
+ out << "RWByteAddressBuffer "
+ << "dx_" << name << "_" << arrayIndex << ": register(u"
+ << uavRegister + arrayIndex << ");\n";
+ }
+ }
+ else
+ {
+ out << "RWByteAddressBuffer "
+ << "_" << name << ": register(u" << uavRegister << ");\n";
+ }
+ }
+ if (out.str().empty())
+ {
+ return true;
+ }
+ return angle::ReplaceSubstring(hlsl, kShaderStorageDeclarationString, out.str());
+}
+
+constexpr const char *VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
+constexpr const char *VERTEX_OUTPUT_STUB_STRING = "@@ VERTEX OUTPUT @@";
+constexpr const char *PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@";
+constexpr const char *PIXEL_MAIN_PARAMETERS_STUB_STRING = "@@ PIXEL MAIN PARAMETERS @@";
+constexpr const char *MAIN_PROLOGUE_STUB_STRING = "@@ MAIN PROLOGUE @@";
+} // anonymous namespace
+
+// BuiltinInfo implementation
+
+BuiltinInfo::BuiltinInfo() = default;
+BuiltinInfo::~BuiltinInfo() = default;
+
+// DynamicHLSL implementation
+
+DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer) {}
+
+std::string DynamicHLSL::generateVertexShaderForInputLayout(
+ const std::string &sourceShader,
+ const InputLayout &inputLayout,
+ const std::vector<sh::ShaderVariable> &shaderAttributes,
+ const std::vector<rx::ShaderStorageBlock> &shaderStorageBlocks,
+ size_t baseUAVRegister) const
+{
+ std::ostringstream structStream;
+ std::ostringstream initStream;
+
+ structStream << "struct VS_INPUT\n"
+ << "{\n";
+
+ int semanticIndex = 0;
+ unsigned int inputIndex = 0;
+
+ // If gl_PointSize is used in the shader then pointsprites rendering is expected.
+ // If the renderer does not support Geometry shaders then Instanced PointSprite emulation
+ // must be used.
+ bool usesPointSize = sourceShader.find("GL_USES_POINT_SIZE") != std::string::npos;
+ bool useInstancedPointSpriteEmulation =
+ usesPointSize && mRenderer->getFeatures().useInstancedPointSpriteEmulation.enabled;
+
+ // Instanced PointSprite emulation requires additional entries in the
+ // VS_INPUT structure to support the vertices that make up the quad vertices.
+ // These values must be in sync with the cooresponding values added during inputlayout creation
+ // in InputLayoutCache::applyVertexBuffers().
+ //
+ // The additional entries must appear first in the VS_INPUT layout because
+ // Windows Phone 8 era devices require per vertex data to physically come
+ // before per instance data in the shader.
+ if (useInstancedPointSpriteEmulation)
+ {
+ structStream << " float3 spriteVertexPos : SPRITEPOSITION0;\n"
+ << " float2 spriteTexCoord : SPRITETEXCOORD0;\n";
+ }
+
+ for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); ++attributeIndex)
+ {
+ const sh::ShaderVariable &shaderAttribute = shaderAttributes[attributeIndex];
+ if (!shaderAttribute.name.empty())
+ {
+ ASSERT(inputIndex < MAX_VERTEX_ATTRIBS);
+ angle::FormatID vertexFormatID =
+ inputIndex < inputLayout.size() ? inputLayout[inputIndex] : angle::FormatID::NONE;
+
+ // HLSL code for input structure
+ if (IsMatrixType(shaderAttribute.type))
+ {
+ // Matrix types are always transposed
+ structStream << " "
+ << HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type));
+ }
+ else
+ {
+ if (shaderAttribute.name == "gl_InstanceID" ||
+ shaderAttribute.name == "gl_VertexID")
+ {
+ // The input types of the instance ID and vertex ID in HLSL (uint) differs from
+ // the ones in ESSL (int).
+ structStream << " uint";
+ }
+ else
+ {
+ GLenum componentType = mRenderer->getVertexComponentType(vertexFormatID);
+
+ structStream << " ";
+ HLSLComponentTypeString(structStream, componentType,
+ VariableComponentCount(shaderAttribute.type));
+ }
+ }
+
+ structStream << " " << DecorateVariable(shaderAttribute.name) << " : ";
+
+ if (shaderAttribute.name == "gl_InstanceID")
+ {
+ structStream << "SV_InstanceID";
+ }
+ else if (shaderAttribute.name == "gl_VertexID")
+ {
+ structStream << "SV_VertexID";
+ }
+ else
+ {
+ structStream << "TEXCOORD" << semanticIndex;
+ semanticIndex += VariableRegisterCount(shaderAttribute.type);
+ }
+
+ structStream << ";\n";
+
+ // HLSL code for initialization
+ initStream << " " << DecorateVariable(shaderAttribute.name) << " = ";
+
+ // Mismatched vertex attribute to vertex input may result in an undefined
+ // data reinterpretation (eg for pure integer->float, float->pure integer)
+ // TODO: issue warning with gl debug info extension, when supported
+ if (IsMatrixType(shaderAttribute.type) ||
+ (mRenderer->getVertexConversionType(vertexFormatID) & VERTEX_CONVERT_GPU) != 0)
+ {
+ GenerateAttributeConversionHLSL(vertexFormatID, shaderAttribute, initStream);
+ }
+ else
+ {
+ initStream << "input." << DecorateVariable(shaderAttribute.name);
+ }
+
+ if (shaderAttribute.name == "gl_VertexID")
+ {
+ // dx_VertexID contains the firstVertex offset
+ initStream << " + dx_VertexID";
+ }
+
+ initStream << ";\n";
+
+ inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.type));
+ }
+ }
+
+ structStream << "};\n"
+ "\n"
+ "void initAttributes(VS_INPUT input)\n"
+ "{\n"
+ << initStream.str() << "}\n";
+
+ std::string vertexHLSL(sourceShader);
+
+ bool success =
+ angle::ReplaceSubstring(&vertexHLSL, VERTEX_ATTRIBUTE_STUB_STRING, structStream.str());
+ ASSERT(success);
+
+ success = ReplaceShaderStorageDeclaration(shaderStorageBlocks, &vertexHLSL, baseUAVRegister,
+ gl::ShaderType::Vertex);
+ ASSERT(success);
+
+ return vertexHLSL;
+}
+
+std::string DynamicHLSL::generatePixelShaderForOutputSignature(
+ const std::string &sourceShader,
+ const std::vector<PixelShaderOutputVariable> &outputVariables,
+ bool usesFragDepth,
+ const std::vector<GLenum> &outputLayout,
+ const std::vector<ShaderStorageBlock> &shaderStorageBlocks,
+ size_t baseUAVRegister) const
+{
+ const int shaderModel = mRenderer->getMajorShaderModel();
+ std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR";
+ std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH";
+
+ std::ostringstream declarationStream;
+ std::ostringstream copyStream;
+
+ declarationStream << "struct PS_OUTPUT\n"
+ "{\n";
+
+ size_t numOutputs = outputLayout.size();
+
+ // Workaround for HLSL 3.x: We can't do a depth/stencil only render, the runtime will complain.
+ if (numOutputs == 0 && (shaderModel == 3 || !mRenderer->getShaderModelSuffix().empty()))
+ {
+ numOutputs = 1u;
+ }
+ const PixelShaderOutputVariable defaultOutput(GL_FLOAT_VEC4, "unused", "float4(0, 0, 0, 1)", 0,
+ 0);
+ size_t outputIndex = 0;
+
+ for (size_t layoutIndex = 0; layoutIndex < numOutputs; ++layoutIndex)
+ {
+ GLenum binding = outputLayout.empty() ? GL_COLOR_ATTACHMENT0 : outputLayout[layoutIndex];
+
+ if (binding != GL_NONE)
+ {
+ unsigned int location = (binding - GL_COLOR_ATTACHMENT0);
+ outputIndex =
+ layoutIndex > 0 && binding == outputLayout[layoutIndex - 1] ? outputIndex + 1 : 0;
+
+ const PixelShaderOutputVariable *outputVariable =
+ outputLayout.empty() ? &defaultOutput
+ : FindOutputAtLocation(outputVariables, location, outputIndex);
+
+ // OpenGL ES 3.0 spec $4.2.1
+ // If [...] not all user-defined output variables are written, the values of fragment
+ // colors corresponding to unwritten variables are similarly undefined.
+ if (outputVariable)
+ {
+ declarationStream << " ";
+ HLSLTypeString(declarationStream, outputVariable->type);
+ declarationStream << " " << outputVariable->name << " : " << targetSemantic
+ << static_cast<int>(layoutIndex) << ";\n";
+
+ copyStream << " output." << outputVariable->name << " = "
+ << outputVariable->source << ";\n";
+ }
+ }
+ }
+
+ if (usesFragDepth)
+ {
+ declarationStream << " float gl_Depth : " << depthSemantic << ";\n";
+ copyStream << " output.gl_Depth = gl_Depth; \n";
+ }
+
+ declarationStream << "};\n"
+ "\n"
+ "PS_OUTPUT generateOutput()\n"
+ "{\n"
+ " PS_OUTPUT output;\n"
+ << copyStream.str()
+ << " return output;\n"
+ "}\n";
+
+ std::string pixelHLSL(sourceShader);
+
+ bool success =
+ angle::ReplaceSubstring(&pixelHLSL, PIXEL_OUTPUT_STUB_STRING, declarationStream.str());
+ ASSERT(success);
+
+ success = ReplaceShaderStorageDeclaration(shaderStorageBlocks, &pixelHLSL, baseUAVRegister,
+ gl::ShaderType::Fragment);
+ ASSERT(success);
+
+ return pixelHLSL;
+}
+
+std::string DynamicHLSL::generateShaderForImage2DBindSignature(
+ ProgramD3D &programD3D,
+ const gl::ProgramState &programData,
+ gl::ShaderType shaderType,
+ const std::string &shaderHLSL,
+ std::vector<sh::ShaderVariable> &image2DUniforms,
+ const gl::ImageUnitTextureTypeMap &image2DBindLayout,
+ unsigned int baseUAVRegister) const
+{
+ if (image2DUniforms.empty())
+ {
+ return shaderHLSL;
+ }
+
+ return GenerateShaderForImage2DBindSignature(programD3D, programData, shaderType, shaderHLSL,
+ image2DUniforms, image2DBindLayout,
+ baseUAVRegister);
+}
+
+void DynamicHLSL::generateVaryingLinkHLSL(const VaryingPacking &varyingPacking,
+ const BuiltinInfo &builtins,
+ bool programUsesPointSize,
+ std::ostringstream &hlslStream) const
+{
+ ASSERT(builtins.dxPosition.enabled);
+ hlslStream << "{\n"
+ << " float4 dx_Position : " << builtins.dxPosition.str() << ";\n";
+
+ if (builtins.glPosition.enabled)
+ {
+ hlslStream << " float4 gl_Position : " << builtins.glPosition.str() << ";\n";
+ }
+
+ if (builtins.glFragCoord.enabled)
+ {
+ hlslStream << " float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n";
+ }
+
+ if (builtins.glPointCoord.enabled)
+ {
+ hlslStream << " float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n";
+ }
+
+ if (builtins.glPointSize.enabled)
+ {
+ hlslStream << " float gl_PointSize : " << builtins.glPointSize.str() << ";\n";
+ }
+
+ if (builtins.glViewIDOVR.enabled)
+ {
+ hlslStream << " nointerpolation uint gl_ViewID_OVR : " << builtins.glViewIDOVR.str()
+ << ";\n";
+ }
+
+ std::string varyingSemantic =
+ GetVaryingSemantic(mRenderer->getMajorShaderModel(), programUsesPointSize);
+
+ const auto &registerInfos = varyingPacking.getRegisterList();
+ for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
+ {
+ const PackedVaryingRegister &registerInfo = registerInfos[registerIndex];
+ const auto &varying = registerInfo.packedVarying->varying();
+ ASSERT(!varying.isStruct());
+
+ // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many
+ // registers being used.
+ // For example, if there are N registers, and we have N vec3 varyings and 1 float
+ // varying, then D3D will pack them into N registers.
+ // If the float varying has the 'nointerpolation' modifier on it then we would need
+ // N + 1 registers, and D3D compilation will fail.
+
+ switch (registerInfo.packedVarying->interpolation)
+ {
+ case sh::INTERPOLATION_SMOOTH:
+ hlslStream << " ";
+ break;
+ case sh::INTERPOLATION_FLAT:
+ hlslStream << " nointerpolation ";
+ break;
+ case sh::INTERPOLATION_CENTROID:
+ hlslStream << " centroid ";
+ break;
+ case sh::INTERPOLATION_SAMPLE:
+ hlslStream << " sample ";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ GLenum transposedType = gl::TransposeMatrixType(varying.type);
+ GLenum componentType = gl::VariableComponentType(transposedType);
+ int columnCount = gl::VariableColumnCount(transposedType);
+ HLSLComponentTypeString(hlslStream, componentType, columnCount);
+ hlslStream << " v" << registerIndex << " : " << varyingSemantic << registerIndex << ";\n";
+ }
+
+ // Note that the following outputs need to be declared after the others. They are not included
+ // in pixel shader inputs even when they are in vertex/geometry shader outputs, and the pixel
+ // shader input struct must be a prefix of the vertex/geometry shader output struct.
+
+ if (builtins.glViewportIndex.enabled)
+ {
+ hlslStream << " nointerpolation uint gl_ViewportIndex : "
+ << builtins.glViewportIndex.str() << ";\n";
+ }
+
+ if (builtins.glLayer.enabled)
+ {
+ hlslStream << " nointerpolation uint gl_Layer : " << builtins.glLayer.str() << ";\n";
+ }
+
+ hlslStream << "};\n";
+}
+
+void DynamicHLSL::generateShaderLinkHLSL(const gl::Context *context,
+ const gl::Caps &caps,
+ const gl::ProgramState &programData,
+ const ProgramD3DMetadata &programMetadata,
+ const VaryingPacking &varyingPacking,
+ const BuiltinVaryingsD3D &builtinsD3D,
+ gl::ShaderMap<std::string> *shaderHLSL) const
+{
+ ASSERT(shaderHLSL);
+ ASSERT((*shaderHLSL)[gl::ShaderType::Vertex].empty() &&
+ (*shaderHLSL)[gl::ShaderType::Fragment].empty());
+
+ gl::Shader *vertexShaderGL = programData.getAttachedShader(ShaderType::Vertex);
+ gl::Shader *fragmentShaderGL = programData.getAttachedShader(ShaderType::Fragment);
+ const int shaderModel = mRenderer->getMajorShaderModel();
+
+ const ShaderD3D *fragmentShader = nullptr;
+ if (fragmentShaderGL)
+ {
+ fragmentShader = GetImplAs<ShaderD3D>(fragmentShaderGL);
+ }
+
+ // usesViewScale() isn't supported in the D3D9 renderer
+ ASSERT(shaderModel >= 4 || !programMetadata.usesViewScale());
+
+ bool useInstancedPointSpriteEmulation =
+ programMetadata.usesPointSize() &&
+ mRenderer->getFeatures().useInstancedPointSpriteEmulation.enabled;
+
+ // Validation done in the compiler
+ ASSERT(!fragmentShader || !fragmentShader->usesFragColor() || !fragmentShader->usesFragData());
+
+ std::ostringstream vertexStream;
+ vertexStream << "struct VS_OUTPUT\n";
+ const auto &vertexBuiltins = builtinsD3D[gl::ShaderType::Vertex];
+ generateVaryingLinkHLSL(varyingPacking, vertexBuiltins, builtinsD3D.usesPointSize(),
+ vertexStream);
+
+ // Instanced PointSprite emulation requires additional entries originally generated in the
+ // GeometryShader HLSL. These include pointsize clamp values.
+ if (useInstancedPointSpriteEmulation)
+ {
+ vertexStream << "static float minPointSize = " << static_cast<int>(caps.minAliasedPointSize)
+ << ".0f;\n"
+ << "static float maxPointSize = " << static_cast<int>(caps.maxAliasedPointSize)
+ << ".0f;\n";
+ }
+
+ std::ostringstream vertexGenerateOutput;
+ vertexGenerateOutput << "VS_OUTPUT generateOutput(VS_INPUT input)\n"
+ << "{\n"
+ << " VS_OUTPUT output;\n";
+
+ if (vertexBuiltins.glPosition.enabled)
+ {
+ vertexGenerateOutput << " output.gl_Position = gl_Position;\n";
+ }
+
+ if (vertexBuiltins.glViewIDOVR.enabled)
+ {
+ vertexGenerateOutput << " output.gl_ViewID_OVR = ViewID_OVR;\n";
+ }
+ if (programMetadata.hasANGLEMultiviewEnabled() && programMetadata.canSelectViewInVertexShader())
+ {
+ ASSERT(vertexBuiltins.glViewportIndex.enabled && vertexBuiltins.glLayer.enabled);
+ vertexGenerateOutput << " if (multiviewSelectViewportIndex)\n"
+ << " {\n"
+ << " output.gl_ViewportIndex = ViewID_OVR;\n"
+ << " } else {\n"
+ << " output.gl_ViewportIndex = 0;\n"
+ << " output.gl_Layer = ViewID_OVR;\n"
+ << " }\n";
+ }
+
+ // On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust.
+ if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
+ {
+ vertexGenerateOutput << " output.dx_Position.x = gl_Position.x;\n";
+
+ if (programMetadata.usesViewScale())
+ {
+ // This code assumes that dx_ViewScale.y = -1.0f when rendering to texture, and +1.0f
+ // when rendering to the default framebuffer. No other values are valid.
+ vertexGenerateOutput << " output.dx_Position.y = dx_ViewScale.y * gl_Position.y;\n";
+ }
+ else
+ {
+ vertexGenerateOutput
+ << " output.dx_Position.y = clipControlOrigin * gl_Position.y;\n";
+ }
+
+ vertexGenerateOutput
+ << " if (clipControlZeroToOne)\n"
+ << " {\n"
+ << " output.dx_Position.z = gl_Position.z;\n"
+ << " } else {\n"
+ << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
+ << " }\n";
+
+ vertexGenerateOutput << " output.dx_Position.w = gl_Position.w;\n";
+ }
+ else
+ {
+ vertexGenerateOutput << " output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + "
+ "dx_ViewAdjust.x * gl_Position.w;\n";
+
+ // If usesViewScale() is true and we're using the D3D11 renderer via Feature Level 9_*,
+ // then we need to multiply the gl_Position.y by the viewScale.
+ // usesViewScale() isn't supported when using the D3D9 renderer.
+ if (programMetadata.usesViewScale() &&
+ (shaderModel >= 4 && mRenderer->getShaderModelSuffix() != ""))
+ {
+ vertexGenerateOutput << " output.dx_Position.y = dx_ViewScale.y * (gl_Position.y * "
+ "dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n";
+ }
+ else
+ {
+ vertexGenerateOutput << " output.dx_Position.y = clipControlOrigin * (gl_Position.y "
+ "* dx_ViewAdjust.w + "
+ "dx_ViewAdjust.y * gl_Position.w);\n";
+ }
+
+ vertexGenerateOutput
+ << " if (clipControlZeroToOne)\n"
+ << " {\n"
+ << " output.dx_Position.z = gl_Position.z;\n"
+ << " } else {\n"
+ << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
+ << " }\n";
+
+ vertexGenerateOutput << " output.dx_Position.w = gl_Position.w;\n";
+ }
+
+ // We don't need to output gl_PointSize if we use are emulating point sprites via instancing.
+ if (vertexBuiltins.glPointSize.enabled)
+ {
+ vertexGenerateOutput << " output.gl_PointSize = gl_PointSize;\n";
+ }
+
+ if (vertexBuiltins.glFragCoord.enabled)
+ {
+ vertexGenerateOutput << " output.gl_FragCoord = gl_Position;\n";
+ }
+
+ const auto &registerInfos = varyingPacking.getRegisterList();
+ for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
+ {
+ const PackedVaryingRegister &registerInfo = registerInfos[registerIndex];
+ const auto &packedVarying = *registerInfo.packedVarying;
+ const auto &varying = *packedVarying.frontVarying.varying;
+ ASSERT(!varying.isStruct());
+
+ vertexGenerateOutput << " output.v" << registerIndex << " = ";
+
+ if (packedVarying.isStructField())
+ {
+ vertexGenerateOutput << DecorateVariable(packedVarying.frontVarying.parentStructName)
+ << ".";
+ }
+
+ vertexGenerateOutput << DecorateVariable(varying.name);
+
+ if (varying.isArray())
+ {
+ WriteArrayString(vertexGenerateOutput, registerInfo.varyingArrayIndex);
+ }
+
+ if (VariableRowCount(varying.type) > 1)
+ {
+ WriteArrayString(vertexGenerateOutput, registerInfo.varyingRowIndex);
+ }
+
+ vertexGenerateOutput << ";\n";
+ }
+
+ // Instanced PointSprite emulation requires additional entries to calculate
+ // the final output vertex positions of the quad that represents each sprite.
+ if (useInstancedPointSpriteEmulation)
+ {
+ vertexGenerateOutput
+ << "\n"
+ << " gl_PointSize = clamp(gl_PointSize, minPointSize, maxPointSize);\n";
+
+ vertexGenerateOutput
+ << " output.dx_Position.x += (input.spriteVertexPos.x * gl_PointSize / "
+ "(dx_ViewCoords.x*2)) * output.dx_Position.w;";
+
+ if (programMetadata.usesViewScale())
+ {
+ // Multiply by ViewScale to invert the rendering when appropriate
+ vertexGenerateOutput
+ << " output.dx_Position.y += (-dx_ViewScale.y * "
+ "input.spriteVertexPos.y * gl_PointSize / (dx_ViewCoords.y*2)) * "
+ "output.dx_Position.w;";
+ }
+ else
+ {
+ vertexGenerateOutput
+ << " output.dx_Position.y += (input.spriteVertexPos.y * gl_PointSize / "
+ "(dx_ViewCoords.y*2)) * output.dx_Position.w;";
+ }
+
+ vertexGenerateOutput
+ << " output.dx_Position.z += input.spriteVertexPos.z * output.dx_Position.w;\n";
+
+ if (programMetadata.usesPointCoord())
+ {
+ vertexGenerateOutput << "\n"
+ << " output.gl_PointCoord = input.spriteTexCoord;\n";
+ }
+ }
+
+ // Renderers that enable instanced pointsprite emulation require the vertex shader output member
+ // gl_PointCoord to be set to a default value if used without gl_PointSize. 0.5,0.5 is the same
+ // default value used in the generated pixel shader.
+ if (programMetadata.usesInsertedPointCoordValue())
+ {
+ ASSERT(!useInstancedPointSpriteEmulation);
+ vertexGenerateOutput << "\n"
+ << " output.gl_PointCoord = float2(0.5, 0.5);\n";
+ }
+
+ vertexGenerateOutput << "\n"
+ << " return output;\n"
+ << "}";
+
+ if (vertexShaderGL)
+ {
+ std::string vertexSource = vertexShaderGL->getTranslatedSource(context);
+ angle::ReplaceSubstring(&vertexSource, std::string(MAIN_PROLOGUE_STUB_STRING),
+ " initAttributes(input);\n");
+ angle::ReplaceSubstring(&vertexSource, std::string(VERTEX_OUTPUT_STUB_STRING),
+ vertexGenerateOutput.str());
+ vertexStream << vertexSource;
+ }
+
+ const auto &pixelBuiltins = builtinsD3D[gl::ShaderType::Fragment];
+
+ std::ostringstream pixelStream;
+ pixelStream << "struct PS_INPUT\n";
+ generateVaryingLinkHLSL(varyingPacking, pixelBuiltins, builtinsD3D.usesPointSize(),
+ pixelStream);
+ pixelStream << "\n";
+
+ std::ostringstream pixelPrologue;
+ if (fragmentShader && fragmentShader->usesViewID())
+ {
+ ASSERT(pixelBuiltins.glViewIDOVR.enabled);
+ pixelPrologue << " ViewID_OVR = input.gl_ViewID_OVR;\n";
+ }
+
+ if (pixelBuiltins.glFragCoord.enabled)
+ {
+ pixelPrologue << " float rhw = 1.0 / input.gl_FragCoord.w;\n";
+
+ // Certain Shader Models (4_0+ and 3_0) allow reading from dx_Position in the pixel shader.
+ // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using
+ // dx_ViewCoords.
+ // DComp usually gives us an offset at (0, 0), but this is not always the case. It is
+ // valid for DComp to give us an offset into the texture atlas. In that scenario, we
+ // need to offset gl_FragCoord using dx_FragCoordOffset to point to the correct location
+ // of the pixel.
+ if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
+ {
+ pixelPrologue << " gl_FragCoord.x = input.dx_Position.x - dx_FragCoordOffset.x;\n"
+ << " gl_FragCoord.y = input.dx_Position.y - dx_FragCoordOffset.y;\n";
+ }
+ else if (shaderModel == 3)
+ {
+ pixelPrologue
+ << " gl_FragCoord.x = input.dx_Position.x + 0.5 - dx_FragCoordOffset.x;\n"
+ << " gl_FragCoord.y = input.dx_Position.y + 0.5 - dx_FragCoordOffset.y;\n";
+ }
+ else
+ {
+ // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See
+ // Renderer::setViewport()
+ pixelPrologue
+ << " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + "
+ "dx_ViewCoords.z - dx_FragCoordOffset.x;\n"
+ << " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + "
+ "dx_ViewCoords.w - dx_FragCoordOffset.y;\n";
+ }
+
+ if (programMetadata.usesViewScale())
+ {
+ // For Feature Level 9_3 and below, we need to correct gl_FragCoord.y to account
+ // for dx_ViewScale. On Feature Level 10_0+, gl_FragCoord.y is calculated above using
+ // dx_ViewCoords and is always correct irrespective of dx_ViewScale's value.
+ // NOTE: usesViewScale() can only be true on D3D11 (i.e. Shader Model 4.0+).
+ if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
+ {
+ // Some assumptions:
+ // - dx_ViewScale.y = -1.0f when rendering to texture
+ // - dx_ViewScale.y = +1.0f when rendering to the default framebuffer
+ // - gl_FragCoord.y has been set correctly above.
+ //
+ // When rendering to the backbuffer, the code inverts gl_FragCoord's y coordinate.
+ // This involves subtracting the y coordinate from the height of the area being
+ // rendered to.
+ //
+ // First we calculate the height of the area being rendered to:
+ // render_area_height = (2.0f / (1.0f - input.gl_FragCoord.y * rhw)) *
+ // gl_FragCoord.y
+ //
+ // Note that when we're rendering to default FB, we want our output to be
+ // equivalent to:
+ // "gl_FragCoord.y = render_area_height - gl_FragCoord.y"
+ //
+ // When we're rendering to a texture, we want our output to be equivalent to:
+ // "gl_FragCoord.y = gl_FragCoord.y;"
+ //
+ // If we set scale_factor = ((1.0f + dx_ViewScale.y) / 2.0f), then notice that
+ // - When rendering to default FB: scale_factor = 1.0f
+ // - When rendering to texture: scale_factor = 0.0f
+ //
+ // Therefore, we can get our desired output by setting:
+ // "gl_FragCoord.y = scale_factor * render_area_height - dx_ViewScale.y *
+ // gl_FragCoord.y"
+ //
+ // Simplifying, this becomes:
+ pixelPrologue
+ << " gl_FragCoord.y = (1.0f + dx_ViewScale.y) * gl_FragCoord.y /"
+ "(1.0f - input.gl_FragCoord.y * rhw) - dx_ViewScale.y * gl_FragCoord.y;\n";
+ }
+ }
+
+ pixelPrologue << " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + "
+ "dx_DepthFront.y;\n"
+ << " gl_FragCoord.w = rhw;\n";
+ }
+
+ if (pixelBuiltins.glPointCoord.enabled && shaderModel >= 3)
+ {
+ pixelPrologue << " gl_PointCoord.x = input.gl_PointCoord.x;\n"
+ << " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n";
+ }
+
+ if (fragmentShader && fragmentShader->usesFrontFacing())
+ {
+ if (shaderModel <= 3)
+ {
+ pixelPrologue << " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n";
+ }
+ else
+ {
+ pixelPrologue << " gl_FrontFacing = isFrontFace;\n";
+ }
+ }
+
+ for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
+ {
+ const PackedVaryingRegister &registerInfo = registerInfos[registerIndex];
+ const auto &packedVarying = *registerInfo.packedVarying;
+
+ // Don't reference VS-only transform feedback varyings in the PS.
+ if (packedVarying.vertexOnly())
+ {
+ continue;
+ }
+
+ const auto &varying = *packedVarying.backVarying.varying;
+ ASSERT(!varying.isBuiltIn() && !varying.isStruct());
+
+ // Note that we're relying on that the active flag is set according to usage in the fragment
+ // shader.
+ if (!varying.active)
+ {
+ continue;
+ }
+
+ pixelPrologue << " ";
+
+ if (packedVarying.isStructField())
+ {
+ pixelPrologue << DecorateVariable(packedVarying.backVarying.parentStructName) << ".";
+ }
+
+ pixelPrologue << DecorateVariable(varying.name);
+
+ if (varying.isArray())
+ {
+ WriteArrayString(pixelPrologue, registerInfo.varyingArrayIndex);
+ }
+
+ GLenum transposedType = TransposeMatrixType(varying.type);
+ if (VariableRowCount(transposedType) > 1)
+ {
+ WriteArrayString(pixelPrologue, registerInfo.varyingRowIndex);
+ }
+
+ pixelPrologue << " = input.v" << registerIndex;
+
+ switch (VariableColumnCount(transposedType))
+ {
+ case 1:
+ pixelPrologue << ".x";
+ break;
+ case 2:
+ pixelPrologue << ".xy";
+ break;
+ case 3:
+ pixelPrologue << ".xyz";
+ break;
+ case 4:
+ break;
+ default:
+ UNREACHABLE();
+ }
+ pixelPrologue << ";\n";
+ }
+
+ if (fragmentShaderGL)
+ {
+ std::string pixelSource = fragmentShaderGL->getTranslatedSource(context);
+
+ if (fragmentShader->usesFrontFacing())
+ {
+ if (shaderModel >= 4)
+ {
+ angle::ReplaceSubstring(&pixelSource,
+ std::string(PIXEL_MAIN_PARAMETERS_STUB_STRING),
+ "PS_INPUT input, bool isFrontFace : SV_IsFrontFace");
+ }
+ else
+ {
+ angle::ReplaceSubstring(&pixelSource,
+ std::string(PIXEL_MAIN_PARAMETERS_STUB_STRING),
+ "PS_INPUT input, float vFace : VFACE");
+ }
+ }
+ else
+ {
+ angle::ReplaceSubstring(&pixelSource, std::string(PIXEL_MAIN_PARAMETERS_STUB_STRING),
+ "PS_INPUT input");
+ }
+
+ angle::ReplaceSubstring(&pixelSource, std::string(MAIN_PROLOGUE_STUB_STRING),
+ pixelPrologue.str());
+ pixelStream << pixelSource;
+ }
+
+ (*shaderHLSL)[gl::ShaderType::Vertex] = vertexStream.str();
+ (*shaderHLSL)[gl::ShaderType::Fragment] = pixelStream.str();
+}
+
+std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &varyingPacking,
+ const BuiltinVaryingsD3D &builtinsD3D,
+ const bool hasANGLEMultiviewEnabled,
+ const bool selectViewInVS) const
+{
+ ASSERT(mRenderer->getMajorShaderModel() >= 4);
+
+ std::ostringstream preambleStream;
+
+ const auto &vertexBuiltins = builtinsD3D[gl::ShaderType::Vertex];
+
+ preambleStream << "struct GS_INPUT\n";
+ generateVaryingLinkHLSL(varyingPacking, vertexBuiltins, builtinsD3D.usesPointSize(),
+ preambleStream);
+ preambleStream << "\n"
+ << "struct GS_OUTPUT\n";
+ generateVaryingLinkHLSL(varyingPacking, builtinsD3D[gl::ShaderType::Geometry],
+ builtinsD3D.usesPointSize(), preambleStream);
+ preambleStream
+ << "\n"
+ << "void copyVertex(inout GS_OUTPUT output, GS_INPUT input, GS_INPUT flatinput)\n"
+ << "{\n"
+ << " output.gl_Position = input.gl_Position;\n";
+
+ if (vertexBuiltins.glPointSize.enabled)
+ {
+ preambleStream << " output.gl_PointSize = input.gl_PointSize;\n";
+ }
+
+ if (hasANGLEMultiviewEnabled)
+ {
+ preambleStream << " output.gl_ViewID_OVR = input.gl_ViewID_OVR;\n";
+ if (selectViewInVS)
+ {
+ ASSERT(builtinsD3D[gl::ShaderType::Geometry].glViewportIndex.enabled &&
+ builtinsD3D[gl::ShaderType::Geometry].glLayer.enabled);
+
+ // If the view is already selected in the VS, then we just pass the gl_ViewportIndex and
+ // gl_Layer to the output.
+ preambleStream << " output.gl_ViewportIndex = input.gl_ViewportIndex;\n"
+ << " output.gl_Layer = input.gl_Layer;\n";
+ }
+ }
+
+ const auto &registerInfos = varyingPacking.getRegisterList();
+ for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
+ {
+ const PackedVaryingRegister &varyingRegister = registerInfos[registerIndex];
+ preambleStream << " output.v" << registerIndex << " = ";
+ if (varyingRegister.packedVarying->interpolation == sh::INTERPOLATION_FLAT)
+ {
+ preambleStream << "flat";
+ }
+ preambleStream << "input.v" << registerIndex << "; \n";
+ }
+
+ if (vertexBuiltins.glFragCoord.enabled)
+ {
+ preambleStream << " output.gl_FragCoord = input.gl_FragCoord;\n";
+ }
+
+ // Only write the dx_Position if we aren't using point sprites
+ preambleStream << "#ifndef ANGLE_POINT_SPRITE_SHADER\n"
+ << " output.dx_Position = input.dx_Position;\n"
+ << "#endif // ANGLE_POINT_SPRITE_SHADER\n"
+ << "}\n";
+
+ if (hasANGLEMultiviewEnabled && !selectViewInVS)
+ {
+ ASSERT(builtinsD3D[gl::ShaderType::Geometry].glViewportIndex.enabled &&
+ builtinsD3D[gl::ShaderType::Geometry].glLayer.enabled);
+
+ // According to the HLSL reference, using SV_RenderTargetArrayIndex is only valid if the
+ // render target is an array resource. Because of this we do not write to gl_Layer if we are
+ // taking the side-by-side code path. We still select the viewport index in the layered code
+ // path as that is always valid. See:
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/bb509647(v=vs.85).aspx
+ preambleStream << "\n"
+ << "void selectView(inout GS_OUTPUT output, GS_INPUT input)\n"
+ << "{\n"
+ << " if (multiviewSelectViewportIndex)\n"
+ << " {\n"
+ << " output.gl_ViewportIndex = input.gl_ViewID_OVR;\n"
+ << " } else {\n"
+ << " output.gl_ViewportIndex = 0;\n"
+ << " output.gl_Layer = input.gl_ViewID_OVR;\n"
+ << " }\n"
+ << "}\n";
+ }
+
+ return preambleStream.str();
+}
+
+std::string DynamicHLSL::generateGeometryShaderHLSL(const gl::Caps &caps,
+ gl::PrimitiveMode primitiveType,
+ const gl::ProgramState &programData,
+ const bool useViewScale,
+ const bool hasANGLEMultiviewEnabled,
+ const bool selectViewInVS,
+ const bool pointSpriteEmulation,
+ const std::string &preambleString) const
+{
+ ASSERT(mRenderer->getMajorShaderModel() >= 4);
+
+ std::stringstream shaderStream;
+
+ const bool pointSprites = (primitiveType == gl::PrimitiveMode::Points) && pointSpriteEmulation;
+ const bool usesPointCoord = preambleString.find("gl_PointCoord") != std::string::npos;
+
+ const char *inputPT = nullptr;
+ const char *outputPT = nullptr;
+ int inputSize = 0;
+ int maxVertexOutput = 0;
+
+ switch (primitiveType)
+ {
+ case gl::PrimitiveMode::Points:
+ inputPT = "point";
+ inputSize = 1;
+
+ if (pointSprites)
+ {
+ outputPT = "Triangle";
+ maxVertexOutput = 4;
+ }
+ else
+ {
+ outputPT = "Point";
+ maxVertexOutput = 1;
+ }
+
+ break;
+
+ case gl::PrimitiveMode::Lines:
+ case gl::PrimitiveMode::LineStrip:
+ case gl::PrimitiveMode::LineLoop:
+ inputPT = "line";
+ outputPT = "Line";
+ inputSize = 2;
+ maxVertexOutput = 2;
+ break;
+
+ case gl::PrimitiveMode::Triangles:
+ case gl::PrimitiveMode::TriangleStrip:
+ case gl::PrimitiveMode::TriangleFan:
+ inputPT = "triangle";
+ outputPT = "Triangle";
+ inputSize = 3;
+ maxVertexOutput = 3;
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ if (pointSprites || hasANGLEMultiviewEnabled)
+ {
+ shaderStream << "cbuffer DriverConstants : register(b0)\n"
+ "{\n";
+
+ if (pointSprites)
+ {
+ shaderStream << " float4 dx_ViewCoords : packoffset(c1);\n";
+ if (useViewScale)
+ {
+ shaderStream << " float2 dx_ViewScale : packoffset(c3.z);\n";
+ }
+ }
+
+ if (hasANGLEMultiviewEnabled)
+ {
+ // We have to add a value which we can use to keep track of which multi-view code path
+ // is to be selected in the GS.
+ shaderStream << " float multiviewSelectViewportIndex : packoffset(c4.x);\n";
+ }
+
+ shaderStream << "};\n\n";
+ }
+
+ if (pointSprites)
+ {
+ shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n"
+ "\n"
+ "static float2 pointSpriteCorners[] = \n"
+ "{\n"
+ " float2( 0.5f, -0.5f),\n"
+ " float2( 0.5f, 0.5f),\n"
+ " float2(-0.5f, -0.5f),\n"
+ " float2(-0.5f, 0.5f)\n"
+ "};\n"
+ "\n"
+ "static float2 pointSpriteTexcoords[] = \n"
+ "{\n"
+ " float2(1.0f, 1.0f),\n"
+ " float2(1.0f, 0.0f),\n"
+ " float2(0.0f, 1.0f),\n"
+ " float2(0.0f, 0.0f)\n"
+ "};\n"
+ "\n"
+ "static float minPointSize = "
+ << static_cast<int>(caps.minAliasedPointSize)
+ << ".0f;\n"
+ "static float maxPointSize = "
+ << static_cast<int>(caps.maxAliasedPointSize) << ".0f;\n"
+ << "\n";
+ }
+
+ shaderStream << preambleString << "\n"
+ << "[maxvertexcount(" << maxVertexOutput << ")]\n"
+ << "void main(" << inputPT << " GS_INPUT input[" << inputSize << "], ";
+
+ if (primitiveType == gl::PrimitiveMode::TriangleStrip)
+ {
+ shaderStream << "uint primitiveID : SV_PrimitiveID, ";
+ }
+
+ shaderStream << " inout " << outputPT << "Stream<GS_OUTPUT> outStream)\n"
+ << "{\n"
+ << " GS_OUTPUT output = (GS_OUTPUT)0;\n";
+
+ if (primitiveType == gl::PrimitiveMode::TriangleStrip)
+ {
+ shaderStream << " uint lastVertexIndex = (primitiveID % 2 == 0 ? 2 : 1);\n";
+ }
+ else
+ {
+ shaderStream << " uint lastVertexIndex = " << (inputSize - 1) << ";\n";
+ }
+
+ for (int vertexIndex = 0; vertexIndex < inputSize; ++vertexIndex)
+ {
+ shaderStream << " copyVertex(output, input[" << vertexIndex
+ << "], input[lastVertexIndex]);\n";
+ if (hasANGLEMultiviewEnabled && !selectViewInVS)
+ {
+ shaderStream << " selectView(output, input[" << vertexIndex << "]);\n";
+ }
+ if (!pointSprites)
+ {
+ ASSERT(inputSize == maxVertexOutput);
+ shaderStream << " outStream.Append(output);\n";
+ }
+ }
+
+ if (pointSprites)
+ {
+ shaderStream << "\n"
+ " float4 dx_Position = input[0].dx_Position;\n"
+ " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, "
+ "maxPointSize);\n"
+ " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / "
+ "dx_ViewCoords.y) * dx_Position.w;\n";
+
+ for (int corner = 0; corner < 4; corner++)
+ {
+ if (useViewScale)
+ {
+ shaderStream << " \n"
+ " output.dx_Position = dx_Position + float4(1.0f, "
+ "-dx_ViewScale.y, 1.0f, 1.0f)"
+ " * float4(pointSpriteCorners["
+ << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
+ }
+ else
+ {
+ shaderStream << "\n"
+ " output.dx_Position = dx_Position + float4(pointSpriteCorners["
+ << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n";
+ }
+
+ if (usesPointCoord)
+ {
+ shaderStream << " output.gl_PointCoord = pointSpriteTexcoords[" << corner
+ << "];\n";
+ }
+
+ shaderStream << " outStream.Append(output);\n";
+ }
+ }
+
+ shaderStream << " \n"
+ " outStream.RestartStrip();\n"
+ "}\n";
+
+ return shaderStream.str();
+}
+
+// static
+void DynamicHLSL::GenerateAttributeConversionHLSL(angle::FormatID vertexFormatID,
+ const sh::ShaderVariable &shaderAttrib,
+ std::ostringstream &outStream)
+{
+ // Matrix
+ if (IsMatrixType(shaderAttrib.type))
+ {
+ outStream << "transpose(input." << DecorateVariable(shaderAttrib.name) << ")";
+ return;
+ }
+
+ GLenum shaderComponentType = VariableComponentType(shaderAttrib.type);
+ int shaderComponentCount = VariableComponentCount(shaderAttrib.type);
+ const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromID(vertexFormatID);
+
+ // Perform integer to float conversion (if necessary)
+ if (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT)
+ {
+ // TODO: normalization for 32-bit integer formats
+ ASSERT(!vertexFormat.normalized && !vertexFormat.pureInteger);
+ outStream << "float" << shaderComponentCount << "(input."
+ << DecorateVariable(shaderAttrib.name) << ")";
+ return;
+ }
+
+ // No conversion necessary
+ outStream << "input." << DecorateVariable(shaderAttrib.name);
+}
+
+void DynamicHLSL::getPixelShaderOutputKey(const gl::State &data,
+ const gl::ProgramState &programData,
+ const ProgramD3DMetadata &metadata,
+ std::vector<PixelShaderOutputVariable> *outPixelShaderKey)
+{
+ // Two cases when writing to gl_FragColor and using ESSL 1.0:
+ // - with a 3.0 context, the output color is copied to channel 0
+ // - with a 2.0 context, the output color is broadcast to all channels
+ bool broadcast = metadata.usesBroadcast(data);
+ const unsigned int numRenderTargets =
+ (broadcast || metadata.usesMultipleFragmentOuts()
+ ? static_cast<unsigned int>(data.getCaps().maxDrawBuffers)
+ : 1);
+
+ if (!metadata.usesCustomOutVars())
+ {
+ for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets;
+ renderTargetIndex++)
+ {
+ PixelShaderOutputVariable outputKeyVariable;
+ outputKeyVariable.type = GL_FLOAT_VEC4;
+ outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex);
+ outputKeyVariable.source =
+ broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]";
+ outputKeyVariable.outputLocation = renderTargetIndex;
+
+ outPixelShaderKey->push_back(outputKeyVariable);
+ }
+
+ if (metadata.usesSecondaryColor())
+ {
+ for (unsigned int secondaryIndex = 0;
+ secondaryIndex < data.getCaps().maxDualSourceDrawBuffers; secondaryIndex++)
+ {
+ PixelShaderOutputVariable outputKeyVariable;
+ outputKeyVariable.type = GL_FLOAT_VEC4;
+ outputKeyVariable.name = "gl_SecondaryColor" + Str(secondaryIndex);
+ outputKeyVariable.source = "gl_SecondaryColor[" + Str(secondaryIndex) + "]";
+ outputKeyVariable.outputLocation = secondaryIndex;
+ outputKeyVariable.outputIndex = 1;
+
+ outPixelShaderKey->push_back(outputKeyVariable);
+ }
+ }
+ }
+ else
+ {
+ const ShaderD3D *fragmentShader = metadata.getFragmentShader();
+
+ if (!fragmentShader)
+ {
+ return;
+ }
+
+ const auto &shaderOutputVars = fragmentShader->getState().getActiveOutputVariables();
+
+ for (size_t outputLocationIndex = 0u;
+ outputLocationIndex < programData.getOutputLocations().size(); ++outputLocationIndex)
+ {
+ const VariableLocation &outputLocation =
+ programData.getOutputLocations().at(outputLocationIndex);
+ if (!outputLocation.used())
+ {
+ continue;
+ }
+ const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
+ const std::string &variableName = "out_" + outputVariable.name;
+
+ // Fragment outputs can't be arrays of arrays. ESSL 3.10 section 4.3.6.
+ const std::string &elementString =
+ (outputVariable.isArray() ? Str(outputLocation.arrayIndex) : "");
+
+ ASSERT(outputVariable.active);
+
+ PixelShaderOutputVariable outputKeyVariable;
+ outputKeyVariable.type = outputVariable.type;
+ outputKeyVariable.name = variableName + elementString;
+ outputKeyVariable.source =
+ variableName +
+ (outputVariable.isArray() ? ArrayString(outputLocation.arrayIndex) : "");
+ outputKeyVariable.outputLocation = outputLocationIndex;
+
+ outPixelShaderKey->push_back(outputKeyVariable);
+ }
+
+ // Now generate any secondary outputs...
+ for (size_t outputLocationIndex = 0u;
+ outputLocationIndex < programData.getSecondaryOutputLocations().size();
+ ++outputLocationIndex)
+ {
+ const VariableLocation &outputLocation =
+ programData.getSecondaryOutputLocations().at(outputLocationIndex);
+ if (!outputLocation.used())
+ {
+ continue;
+ }
+ const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index];
+ const std::string &variableName = "out_" + outputVariable.name;
+
+ // Fragment outputs can't be arrays of arrays. ESSL 3.10 section 4.3.6.
+ const std::string &elementString =
+ (outputVariable.isArray() ? Str(outputLocation.arrayIndex) : "");
+
+ ASSERT(outputVariable.active);
+
+ PixelShaderOutputVariable outputKeyVariable;
+ outputKeyVariable.type = outputVariable.type;
+ outputKeyVariable.name = variableName + elementString;
+ outputKeyVariable.source =
+ variableName +
+ (outputVariable.isArray() ? ArrayString(outputLocation.arrayIndex) : "");
+ outputKeyVariable.outputLocation = outputLocationIndex;
+ outputKeyVariable.outputIndex = 1;
+
+ outPixelShaderKey->push_back(outputKeyVariable);
+ }
+ }
+}
+
+// BuiltinVarying Implementation.
+BuiltinVarying::BuiltinVarying() : enabled(false), index(0), systemValue(false) {}
+
+std::string BuiltinVarying::str() const
+{
+ return (systemValue ? semantic : (semantic + Str(index)));
+}
+
+void BuiltinVarying::enableSystem(const std::string &systemValueSemantic)
+{
+ enabled = true;
+ semantic = systemValueSemantic;
+ systemValue = true;
+}
+
+void BuiltinVarying::enable(const std::string &semanticVal, unsigned int indexVal)
+{
+ enabled = true;
+ semantic = semanticVal;
+ index = indexVal;
+}
+
+// BuiltinVaryingsD3D Implementation.
+BuiltinVaryingsD3D::BuiltinVaryingsD3D(const ProgramD3DMetadata &metadata,
+ const VaryingPacking &packing)
+{
+ updateBuiltins(gl::ShaderType::Vertex, metadata, packing);
+ updateBuiltins(gl::ShaderType::Fragment, metadata, packing);
+ int shaderModel = metadata.getRendererMajorShaderModel();
+ if (shaderModel >= 4)
+ {
+ updateBuiltins(gl::ShaderType::Geometry, metadata, packing);
+ }
+ // In shader model >= 4, some builtins need to be the same in vertex and pixel shaders - input
+ // struct needs to be a prefix of output struct.
+ ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glPosition.enabled ==
+ mBuiltinInfo[gl::ShaderType::Fragment].glPosition.enabled);
+ ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glFragCoord.enabled ==
+ mBuiltinInfo[gl::ShaderType::Fragment].glFragCoord.enabled);
+ ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glPointCoord.enabled ==
+ mBuiltinInfo[gl::ShaderType::Fragment].glPointCoord.enabled);
+ ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glPointSize.enabled ==
+ mBuiltinInfo[gl::ShaderType::Fragment].glPointSize.enabled);
+ ASSERT(shaderModel < 4 || mBuiltinInfo[gl::ShaderType::Vertex].glViewIDOVR.enabled ==
+ mBuiltinInfo[gl::ShaderType::Fragment].glViewIDOVR.enabled);
+}
+
+BuiltinVaryingsD3D::~BuiltinVaryingsD3D() = default;
+
+void BuiltinVaryingsD3D::updateBuiltins(gl::ShaderType shaderType,
+ const ProgramD3DMetadata &metadata,
+ const VaryingPacking &packing)
+{
+ const std::string &userSemantic = GetVaryingSemantic(metadata.getRendererMajorShaderModel(),
+ metadata.usesSystemValuePointSize());
+
+ // Note that when enabling builtins only for specific shader stages in shader model >= 4, the
+ // code needs to ensure that the input struct of the shader stage is a prefix of the output
+ // struct of the previous stage.
+
+ unsigned int reservedSemanticIndex = packing.getMaxSemanticIndex();
+
+ BuiltinInfo *builtins = &mBuiltinInfo[shaderType];
+
+ if (metadata.getRendererMajorShaderModel() >= 4)
+ {
+ builtins->dxPosition.enableSystem("SV_Position");
+ }
+ else if (shaderType == gl::ShaderType::Fragment)
+ {
+ builtins->dxPosition.enableSystem("VPOS");
+ }
+ else
+ {
+ builtins->dxPosition.enableSystem("POSITION");
+ }
+
+ if (metadata.usesTransformFeedbackGLPosition())
+ {
+ builtins->glPosition.enable(userSemantic, reservedSemanticIndex++);
+ }
+
+ if (metadata.usesFragCoord())
+ {
+ builtins->glFragCoord.enable(userSemantic, reservedSemanticIndex++);
+ }
+
+ if (shaderType == gl::ShaderType::Vertex ? metadata.addsPointCoordToVertexShader()
+ : metadata.usesPointCoord())
+ {
+ // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
+ // In D3D11 we manually compute gl_PointCoord in the GS.
+ if (metadata.getRendererMajorShaderModel() >= 4)
+ {
+ builtins->glPointCoord.enable(userSemantic, reservedSemanticIndex++);
+ }
+ else
+ {
+ builtins->glPointCoord.enable("TEXCOORD", 0);
+ }
+ }
+
+ if (metadata.hasANGLEMultiviewEnabled())
+ {
+ // Although it is possible to compute gl_ViewID_OVR from the value of
+ // SV_ViewportArrayIndex or SV_RenderTargetArrayIndex and the multi-view state in the
+ // driver constant buffer, it is easier and cleaner to always pass it as a varying.
+ builtins->glViewIDOVR.enable(userSemantic, reservedSemanticIndex++);
+
+ if (shaderType == gl::ShaderType::Vertex)
+ {
+ if (metadata.canSelectViewInVertexShader())
+ {
+ builtins->glViewportIndex.enableSystem("SV_ViewportArrayIndex");
+ builtins->glLayer.enableSystem("SV_RenderTargetArrayIndex");
+ }
+ }
+
+ if (shaderType == gl::ShaderType::Geometry)
+ {
+ // gl_Layer and gl_ViewportIndex are necessary so that we can write to either based on
+ // the multiview state in the driver constant buffer.
+ builtins->glViewportIndex.enableSystem("SV_ViewportArrayIndex");
+ builtins->glLayer.enableSystem("SV_RenderTargetArrayIndex");
+ }
+ }
+
+ // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders
+ if (metadata.usesSystemValuePointSize() &&
+ (shaderType != gl::ShaderType::Fragment || metadata.getRendererMajorShaderModel() >= 4))
+ {
+ builtins->glPointSize.enableSystem("PSIZE");
+ }
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicHLSL.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicHLSL.h
new file mode 100644
index 0000000000..3398bae8d7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicHLSL.h
@@ -0,0 +1,212 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DynamicHLSL.h: Interface for link and run-time HLSL generation
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
+#define LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
+
+#include <map>
+#include <vector>
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/DynamicImage2DHLSL.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace sh
+{
+struct ShaderVariable;
+} // namespace sh
+
+namespace gl
+{
+class InfoLog;
+struct VariableLocation;
+class VaryingPacking;
+struct VertexAttribute;
+} // namespace gl
+
+namespace rx
+{
+class ProgramD3DMetadata;
+class ShaderD3D;
+struct ShaderStorageBlock;
+
+// This class needs to match OutputHLSL::decorate
+class DecorateVariable final : angle::NonCopyable
+{
+ public:
+ explicit DecorateVariable(const std::string &str) : mName(str) {}
+ const std::string &getName() const { return mName; }
+
+ private:
+ const std::string &mName;
+};
+
+inline std::ostream &operator<<(std::ostream &o, const DecorateVariable &dv)
+{
+ if (dv.getName().compare(0, 3, "gl_") != 0)
+ {
+ o << "_";
+ }
+ o << dv.getName();
+ return o;
+}
+
+struct PixelShaderOutputVariable
+{
+ PixelShaderOutputVariable() {}
+ PixelShaderOutputVariable(GLenum typeIn,
+ const std::string &nameIn,
+ const std::string &sourceIn,
+ size_t outputLocationIn,
+ size_t outputIndexIn)
+ : type(typeIn),
+ name(nameIn),
+ source(sourceIn),
+ outputLocation(outputLocationIn),
+ outputIndex(outputIndexIn)
+ {}
+
+ GLenum type = GL_NONE;
+ std::string name;
+ std::string source;
+ size_t outputLocation = 0;
+ size_t outputIndex = 0;
+};
+
+struct BuiltinVarying final : private angle::NonCopyable
+{
+ BuiltinVarying();
+
+ std::string str() const;
+ void enableSystem(const std::string &systemValueSemantic);
+ void enable(const std::string &semanticVal, unsigned int indexVal);
+
+ bool enabled;
+ std::string semantic;
+ unsigned int index;
+ bool systemValue;
+};
+
+struct BuiltinInfo
+{
+ BuiltinInfo();
+ ~BuiltinInfo();
+
+ BuiltinVarying dxPosition;
+ BuiltinVarying glPosition;
+ BuiltinVarying glFragCoord;
+ BuiltinVarying glPointCoord;
+ BuiltinVarying glPointSize;
+ BuiltinVarying glViewIDOVR;
+ BuiltinVarying glViewportIndex;
+ BuiltinVarying glLayer;
+};
+
+inline std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize)
+{
+ // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord)
+ // In D3D11 we manually compute gl_PointCoord in the GS.
+ return ((programUsesPointSize && majorShaderModel < 4) ? "COLOR" : "TEXCOORD");
+}
+
+class BuiltinVaryingsD3D
+{
+ public:
+ BuiltinVaryingsD3D(const ProgramD3DMetadata &metadata, const gl::VaryingPacking &packing);
+ ~BuiltinVaryingsD3D();
+
+ bool usesPointSize() const { return mBuiltinInfo[gl::ShaderType::Vertex].glPointSize.enabled; }
+
+ const BuiltinInfo &operator[](gl::ShaderType shaderType) const
+ {
+ return mBuiltinInfo[shaderType];
+ }
+ BuiltinInfo &operator[](gl::ShaderType shaderType) { return mBuiltinInfo[shaderType]; }
+
+ private:
+ void updateBuiltins(gl::ShaderType shaderType,
+ const ProgramD3DMetadata &metadata,
+ const gl::VaryingPacking &packing);
+
+ gl::ShaderMap<BuiltinInfo> mBuiltinInfo;
+};
+
+class DynamicHLSL : angle::NonCopyable
+{
+ public:
+ explicit DynamicHLSL(RendererD3D *const renderer);
+
+ std::string generateVertexShaderForInputLayout(
+ const std::string &sourceShader,
+ const gl::InputLayout &inputLayout,
+ const std::vector<sh::ShaderVariable> &shaderAttributes,
+ const std::vector<rx::ShaderStorageBlock> &shaderStorageBlocks,
+ size_t baseUAVRegister) const;
+ std::string generatePixelShaderForOutputSignature(
+ const std::string &sourceShader,
+ const std::vector<PixelShaderOutputVariable> &outputVariables,
+ bool usesFragDepth,
+ const std::vector<GLenum> &outputLayout,
+ const std::vector<rx::ShaderStorageBlock> &shaderStorageBlocks,
+ size_t baseUAVRegister) const;
+ std::string generateShaderForImage2DBindSignature(
+ ProgramD3D &programD3D,
+ const gl::ProgramState &programData,
+ gl::ShaderType shaderType,
+ const std::string &shaderHLSL,
+ std::vector<sh::ShaderVariable> &image2DUniforms,
+ const gl::ImageUnitTextureTypeMap &image2DBindLayout,
+ unsigned int baseUAVRegister) const;
+ void generateShaderLinkHLSL(const gl::Context *context,
+ const gl::Caps &caps,
+ const gl::ProgramState &programData,
+ const ProgramD3DMetadata &programMetadata,
+ const gl::VaryingPacking &varyingPacking,
+ const BuiltinVaryingsD3D &builtinsD3D,
+ gl::ShaderMap<std::string> *shaderHLSL) const;
+
+ std::string generateGeometryShaderPreamble(const gl::VaryingPacking &varyingPacking,
+ const BuiltinVaryingsD3D &builtinsD3D,
+ const bool hasANGLEMultiviewEnabled,
+ const bool selectViewInVS) const;
+
+ std::string generateGeometryShaderHLSL(const gl::Caps &caps,
+ gl::PrimitiveMode primitiveType,
+ const gl::ProgramState &programData,
+ const bool useViewScale,
+ const bool hasANGLEMultiviewEnabled,
+ const bool selectViewInVS,
+ const bool pointSpriteEmulation,
+ const std::string &preambleString) const;
+
+ void getPixelShaderOutputKey(const gl::State &data,
+ const gl::ProgramState &programData,
+ const ProgramD3DMetadata &metadata,
+ std::vector<PixelShaderOutputVariable> *outPixelShaderKey);
+
+ private:
+ RendererD3D *const mRenderer;
+
+ void generateVaryingLinkHLSL(const gl::VaryingPacking &varyingPacking,
+ const BuiltinInfo &builtins,
+ bool programUsesPointSize,
+ std::ostringstream &hlslStream) const;
+
+ static void GenerateAttributeConversionHLSL(angle::FormatID vertexFormatID,
+ const sh::ShaderVariable &shaderAttrib,
+ std::ostringstream &outStream);
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp
new file mode 100644
index 0000000000..cf775d0b46
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp
@@ -0,0 +1,919 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DynamicImage2DHLSL.cpp: Implementation for link and run-time HLSL generation
+//
+
+#include "libANGLE/renderer/d3d/DynamicImage2DHLSL.h"
+
+#include "common/string_utils.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+
+using namespace gl;
+
+namespace rx
+{
+
+namespace
+{
+
+enum Image2DHLSLGroup
+{
+ IMAGE2D_R_FLOAT4,
+ IMAGE2D_MIN = IMAGE2D_R_FLOAT4,
+ IMAGE2D_R_UNORM,
+ IMAGE2D_R_SNORM,
+ IMAGE2D_R_UINT4,
+ IMAGE2D_R_INT4,
+ IMAGE2D_W_FLOAT4,
+ IMAGE2D_W_UNORM,
+ IMAGE2D_W_SNORM,
+ IMAGE2D_W_UINT4,
+ IMAGE2D_W_INT4,
+ IMAGE2D_UNKNOWN,
+ IMAGE2D_MAX = IMAGE2D_UNKNOWN
+};
+
+enum Image2DMethod
+{
+ IMAGE2DSIZE,
+ IMAGE2DLOAD,
+ IMAGE2DSTORE
+};
+
+Image2DHLSLGroup image2DHLSLGroup(const sh::ShaderVariable &uniform)
+{
+ GLenum format = uniform.imageUnitFormat;
+ bool readonly = uniform.readonly;
+ switch (uniform.type)
+ {
+ case GL_IMAGE_2D:
+ {
+ switch (format)
+ {
+ case GL_RGBA32F:
+ case GL_RGBA16F:
+ case GL_R32F:
+ return readonly ? IMAGE2D_R_FLOAT4 : IMAGE2D_W_FLOAT4;
+ case GL_RGBA8:
+ return readonly ? IMAGE2D_R_UNORM : IMAGE2D_W_UNORM;
+ case GL_RGBA8_SNORM:
+ return readonly ? IMAGE2D_R_SNORM : IMAGE2D_W_SNORM;
+ default:
+ UNREACHABLE();
+ return IMAGE2D_UNKNOWN;
+ }
+ }
+ case GL_INT_IMAGE_2D:
+ {
+ switch (format)
+ {
+ case GL_RGBA32I:
+ case GL_RGBA16I:
+ case GL_RGBA8I:
+ case GL_R32I:
+ return readonly ? IMAGE2D_R_INT4 : IMAGE2D_W_INT4;
+ default:
+ UNREACHABLE();
+ return IMAGE2D_UNKNOWN;
+ }
+ }
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ {
+ switch (format)
+ {
+ case GL_RGBA32UI:
+ case GL_RGBA16UI:
+ case GL_RGBA8UI:
+ case GL_R32UI:
+ return readonly ? IMAGE2D_R_UINT4 : IMAGE2D_W_UINT4;
+ default:
+ UNREACHABLE();
+ return IMAGE2D_UNKNOWN;
+ }
+ }
+ default:
+ UNREACHABLE();
+ return IMAGE2D_UNKNOWN;
+ }
+}
+
+std::string Image2DHLSLGroupSuffix(Image2DHLSLGroup group)
+{
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ return "2D";
+ case IMAGE2D_R_UNORM:
+ return "2D_unorm_float4_";
+ case IMAGE2D_R_SNORM:
+ return "2D_snorm_float4_";
+ case IMAGE2D_R_UINT4:
+ return "2D_uint4_";
+ case IMAGE2D_R_INT4:
+ return "2D_int4_";
+ case IMAGE2D_W_FLOAT4:
+ return "RW2D_float4_";
+ case IMAGE2D_W_UNORM:
+ return "RW2D_unorm_float4_";
+ case IMAGE2D_W_SNORM:
+ return "RW2D_snorm_float4_";
+ case IMAGE2D_W_UINT4:
+ return "RW2D_uint4_";
+ case IMAGE2D_W_INT4:
+ return "RW2D_int4_";
+ default:
+ UNREACHABLE();
+ }
+
+ return "<unknown group type>";
+}
+
+std::string Image2DHLSLTextureString(Image2DHLSLGroup group,
+ gl::TextureType type,
+ bool rasterOrdered)
+{
+ std::string textureString;
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_R_INT4:
+ break;
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ case IMAGE2D_W_UINT4:
+ case IMAGE2D_W_INT4:
+ textureString += rasterOrdered ? "RasterizerOrdered" : "RW";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ textureString += "Texture";
+
+ switch (type)
+ {
+ case gl::TextureType::_2D:
+ textureString += "2D";
+ break;
+ case gl::TextureType::_3D:
+ textureString += "3D";
+ break;
+ case gl::TextureType::_2DArray:
+ textureString += "2DArray";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_W_FLOAT4:
+ textureString += "<float4>";
+ break;
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_W_UNORM:
+ textureString += "<unorm float4>";
+ break;
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_W_SNORM:
+ textureString += "<snorm float4>";
+ break;
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_W_UINT4:
+ textureString += "<uint4>";
+ break;
+ case IMAGE2D_R_INT4:
+ case IMAGE2D_W_INT4:
+ textureString += "<int4>";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return textureString;
+}
+
+std::string Image2DHLSLGroupOffsetPrefix(Image2DHLSLGroup group)
+{
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_R_INT4:
+ return "readonlyImageIndexOffset";
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ case IMAGE2D_W_UINT4:
+ case IMAGE2D_W_INT4:
+ return "imageIndexOffset";
+ default:
+ UNREACHABLE();
+ }
+
+ return "<unknown group type>";
+}
+
+std::string Image2DHLSLGroupDeclarationPrefix(Image2DHLSLGroup group)
+{
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_R_INT4:
+ return "readonlyImages";
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ case IMAGE2D_W_UINT4:
+ case IMAGE2D_W_INT4:
+ return "images";
+ default:
+ UNREACHABLE();
+ }
+
+ return "<unknown group type>";
+}
+
+std::string Image2DHLSLGroupRegisterSuffix(Image2DHLSLGroup group)
+{
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_R_INT4:
+ return "t";
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ case IMAGE2D_W_UINT4:
+ case IMAGE2D_W_INT4:
+ return "u";
+ default:
+ UNREACHABLE();
+ }
+
+ return "<unknown group type>";
+}
+
+std::string Image2DHLSLGroupFunctionName(Image2DHLSLGroup group, Image2DMethod method)
+{
+ std::string name = "gl_image";
+ name += Image2DHLSLGroupSuffix(group);
+ switch (method)
+ {
+ case IMAGE2DSIZE:
+ name += "Size";
+ break;
+ case IMAGE2DLOAD:
+ name += "Load";
+ break;
+ case IMAGE2DSTORE:
+ name += "Store";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return name;
+}
+
+std::string getImage2DGroupReturnType(Image2DHLSLGroup group, Image2DMethod method)
+{
+ switch (method)
+ {
+ case IMAGE2DSIZE:
+ return "int2";
+ case IMAGE2DLOAD:
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ return "float4";
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_W_UINT4:
+ return "uint4";
+ case IMAGE2D_R_INT4:
+ case IMAGE2D_W_INT4:
+ return "int4";
+ default:
+ UNREACHABLE();
+ return "unknown group type";
+ }
+ case IMAGE2DSTORE:
+ return "void";
+ default:
+ UNREACHABLE();
+ return "unknown image method";
+ }
+}
+
+std::string getImageMetadata(Image2DHLSLGroup group)
+{
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_R_INT4:
+ return "readonlyImageMetadata[imageIndex - readonlyImageIndexStart]";
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ case IMAGE2D_W_UINT4:
+ case IMAGE2D_W_INT4:
+ return "imageMetadata[imageIndex - imageIndexStart]";
+ default:
+ UNREACHABLE();
+ return "unknown image method";
+ }
+}
+
+void OutputImage2DFunctionArgumentList(std::ostringstream &out,
+ Image2DHLSLGroup group,
+ Image2DMethod method)
+{
+ out << "uint imageIndex";
+
+ if (method == IMAGE2DLOAD || method == IMAGE2DSTORE)
+ {
+ out << ", int2 p";
+ if (method == IMAGE2DSTORE)
+ {
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ out << ", float4 data";
+ break;
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_W_UINT4:
+ out << ", uint4 data";
+ break;
+ case IMAGE2D_R_INT4:
+ case IMAGE2D_W_INT4:
+ out << ", int4 data";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ }
+}
+
+void OutputImage2DSizeFunction(std::ostringstream &out,
+ Image2DHLSLGroup textureGroup,
+ unsigned int totalCount,
+ unsigned int texture2DCount,
+ unsigned int texture3DCount,
+ unsigned int texture2DArrayCount,
+ const std::string &offsetStr,
+ const std::string &declarationStr)
+{
+ out << getImage2DGroupReturnType(textureGroup, IMAGE2DSIZE) << " "
+ << Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSIZE) << "(";
+ OutputImage2DFunctionArgumentList(out, textureGroup, IMAGE2DSIZE);
+ out << ")\n"
+ "{\n";
+ out << " uint width, height;\n";
+
+ if (texture2DCount > 0)
+ {
+ if (texture2DCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
+ out << " " << declarationStr << "2D[index].GetDimensions(width, height);\n";
+ }
+ else
+ {
+ out << " if (imageIndex >= " << offsetStr << "2D && imageIndex < " << offsetStr
+ << "2D + " << texture2DCount << ")\n";
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
+ out << " " << declarationStr << "2D[index].GetDimensions(width, height);\n";
+ out << " }\n";
+ }
+ }
+
+ if (texture3DCount > 0)
+ {
+ if (texture3DCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
+ out << " uint depth;\n";
+ out << " " << declarationStr << "3D[index].GetDimensions(width, height, depth);\n";
+ }
+ else
+ {
+ if (texture2DArrayCount == 0)
+ {
+ out << " else\n";
+ }
+ else
+ {
+ if (texture2DCount == 0)
+ {
+ out << " if ";
+ }
+ else
+ {
+ out << " else if";
+ }
+ out << "(imageIndex >= " << offsetStr << "3D && imageIndex < " << offsetStr
+ << "3D + " << texture3DCount << ")\n";
+ }
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
+ out << " uint depth;\n";
+ out << " " << declarationStr
+ << "3D[index].GetDimensions(width, height, depth);\n";
+ out << " }\n";
+ }
+ }
+
+ if (texture2DArrayCount > 0)
+ {
+ if (texture2DArrayCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
+ out << " uint depth;\n";
+ out << " " << declarationStr
+ << "2DArray[index].GetDimensions(width, height, depth);\n";
+ }
+ else
+ {
+ out << " else\n";
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
+ out << " uint depth;\n";
+ out << " " << declarationStr
+ << "2DArray[index].GetDimensions(width, height, depth);\n";
+ out << " }\n";
+ }
+ }
+ out << " return int2(width, height);\n";
+
+ out << "}\n";
+}
+
+void OutputImage2DLoadFunction(std::ostringstream &out,
+ Image2DHLSLGroup textureGroup,
+ unsigned int totalCount,
+ unsigned int texture2DCount,
+ unsigned int texture3DCount,
+ unsigned int texture2DArrayCount,
+ const std::string &offsetStr,
+ const std::string &declarationStr)
+{
+ out << getImage2DGroupReturnType(textureGroup, IMAGE2DLOAD) << " "
+ << Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DLOAD) << "(";
+ OutputImage2DFunctionArgumentList(out, textureGroup, IMAGE2DLOAD);
+ out << ")\n"
+ "{\n";
+
+ out << " " << getImage2DGroupReturnType(textureGroup, IMAGE2DLOAD) << " result;\n";
+
+ if (texture2DCount > 0)
+ {
+ if (texture2DCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
+ out << " result = " << declarationStr << "2D[index][uint2(p.x, p.y)];\n";
+ }
+ else
+ {
+ out << " if (imageIndex >= " << offsetStr << "2D && imageIndex < " << offsetStr
+ << "2D + " << texture2DCount << ")\n";
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
+ out << " result = " << declarationStr << "2D[index][uint2(p.x, p.y)];\n";
+ out << " }\n";
+ }
+ }
+
+ if (texture3DCount > 0)
+ {
+ if (texture3DCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
+ out << " result = " << declarationStr << "3D[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)];\n";
+ }
+ else
+ {
+ if (texture2DArrayCount == 0)
+ {
+ out << " else\n";
+ }
+ else
+ {
+ if (texture2DCount == 0)
+ {
+ out << " if ";
+ }
+ else
+ {
+ out << " else if";
+ }
+ out << "(imageIndex >= " << offsetStr << "3D && imageIndex < " << offsetStr
+ << "3D + " << texture3DCount << ")\n";
+ }
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
+ out << " result = " << declarationStr << "3D[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)];\n";
+ out << " }\n";
+ }
+ }
+
+ if (texture2DArrayCount > 0)
+ {
+ if (texture2DArrayCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
+ out << " result = " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)];\n";
+ }
+ else
+ {
+ out << " else\n";
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
+ out << " result = " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)];\n";
+ out << " }\n";
+ }
+ }
+
+ out << " return result;\n";
+ out << "}\n";
+}
+
+void OutputImage2DStoreFunction(std::ostringstream &out,
+ Image2DHLSLGroup textureGroup,
+ unsigned int totalCount,
+ unsigned int texture2DCount,
+ unsigned int texture3DCount,
+ unsigned int texture2DArrayCount,
+ const std::string &offsetStr,
+ const std::string &declarationStr)
+{
+ out << getImage2DGroupReturnType(textureGroup, IMAGE2DSTORE) << " "
+ << Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSTORE) << "(";
+ OutputImage2DFunctionArgumentList(out, textureGroup, IMAGE2DSTORE);
+ out << ")\n"
+ "{\n";
+
+ if (texture2DCount > 0)
+ {
+ if (texture2DCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
+ out << " " << declarationStr << "2D[index][uint2(p.x, p.y)] = data;\n";
+ }
+ else
+ {
+ out << " if (imageIndex >= " << offsetStr << "2D && imageIndex < " << offsetStr
+ << "2D + " << texture2DCount << ")\n";
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
+ out << " " << declarationStr << "2D[index][uint2(p.x, p.y)] = data;\n";
+ out << " }\n";
+ }
+ }
+
+ if (texture3DCount > 0)
+ {
+ if (texture3DCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
+ out << " " << declarationStr << "3D[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)] = data;\n";
+ }
+ else
+ {
+ if (texture2DArrayCount == 0)
+ {
+ out << " else\n";
+ }
+ else
+ {
+ if (texture2DCount == 0)
+ {
+ out << " if ";
+ }
+ else
+ {
+ out << " else if";
+ }
+ out << "(imageIndex >= " << offsetStr << "3D && imageIndex < " << offsetStr
+ << "3D + " << texture3DCount << ")\n";
+ }
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
+ out << " " << declarationStr << "3D[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)] = data;\n";
+ out << " }\n";
+ }
+ }
+
+ if (texture2DArrayCount > 0)
+ {
+ if (texture2DArrayCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
+ out << " " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)] = data;\n";
+ }
+ else
+ {
+ out << " else\n";
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
+ out << " " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)] = data;\n";
+ out << " }\n";
+ }
+ }
+
+ out << "}\n";
+}
+
+unsigned int *GetImage2DRegisterIndex(Image2DHLSLGroup textureGroup,
+ unsigned int *groupTextureRegisterIndex,
+ unsigned int *groupRWTextureRegisterIndex)
+{
+ switch (textureGroup)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_R_INT4:
+ return groupTextureRegisterIndex;
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ case IMAGE2D_W_UINT4:
+ case IMAGE2D_W_INT4:
+ return groupRWTextureRegisterIndex;
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+
+void OutputHLSLImage2DUniformGroup(ProgramD3D &programD3D,
+ const gl::ProgramState &programData,
+ gl::ShaderType shaderType,
+ std::ostringstream &out,
+ const Image2DHLSLGroup textureGroup,
+ const std::vector<sh::ShaderVariable> &group,
+ const gl::ImageUnitTextureTypeMap &image2DBindLayout,
+ unsigned int baseUAVRegister,
+ unsigned int *groupTextureRegisterIndex,
+ unsigned int *groupRWTextureRegisterIndex,
+ unsigned int *image2DTexture3D,
+ unsigned int *image2DTexture2DArray,
+ unsigned int *image2DTexture2D)
+{
+ if (group.empty())
+ {
+ return;
+ }
+
+ unsigned int texture2DCount = 0, texture3DCount = 0, texture2DArrayCount = 0;
+ bool texture2DRasterOrdered = false, texture3DRasterOrdered = false,
+ texture2DArrayRasterOrdered = false;
+ for (const sh::ShaderVariable &uniform : group)
+ {
+ if (!programD3D.hasNamedUniform(uniform.name))
+ {
+ continue;
+ }
+ for (unsigned int index = 0; index < uniform.getArraySizeProduct(); index++)
+ {
+ switch (image2DBindLayout.at(uniform.binding + index))
+ {
+ case gl::TextureType::_2D:
+ texture2DCount++;
+ texture2DRasterOrdered |= uniform.rasterOrdered;
+ break;
+ case gl::TextureType::_3D:
+ texture3DCount++;
+ texture3DRasterOrdered |= uniform.rasterOrdered;
+ break;
+ case gl::TextureType::_2DArray:
+ case gl::TextureType::CubeMap:
+ texture2DArrayCount++;
+ texture2DArrayRasterOrdered |= uniform.rasterOrdered;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ }
+
+ unsigned int totalCount = texture2DCount + texture3DCount + texture2DArrayCount;
+ unsigned int *image2DRegisterIndex = GetImage2DRegisterIndex(
+ textureGroup, groupTextureRegisterIndex, groupRWTextureRegisterIndex);
+ unsigned int texture2DRegisterIndex = *image2DRegisterIndex;
+ unsigned int texture3DRegisterIndex = texture2DRegisterIndex + texture2DCount;
+ unsigned int texture2DArrayRegisterIndex = texture3DRegisterIndex + texture3DCount;
+ *image2DRegisterIndex += totalCount;
+
+ std::string offsetStr =
+ Image2DHLSLGroupOffsetPrefix(textureGroup) + Image2DHLSLGroupSuffix(textureGroup);
+ std::string declarationStr =
+ Image2DHLSLGroupDeclarationPrefix(textureGroup) + Image2DHLSLGroupSuffix(textureGroup);
+ std::string registerStr = Image2DHLSLGroupRegisterSuffix(textureGroup);
+ if (texture2DCount > 0)
+ {
+ out << "static const uint " << offsetStr << "2D = " << texture2DRegisterIndex << ";\n";
+ out << "uniform "
+ << Image2DHLSLTextureString(textureGroup, gl::TextureType::_2D, texture2DRasterOrdered)
+ << " " << declarationStr << "2D[" << texture2DCount << "]"
+ << " : register(" << registerStr << baseUAVRegister + texture2DRegisterIndex << ");\n";
+ }
+ if (texture3DCount > 0)
+ {
+ out << "static const uint " << offsetStr << "3D = " << texture3DRegisterIndex << ";\n";
+ out << "uniform "
+ << Image2DHLSLTextureString(textureGroup, gl::TextureType::_3D, texture3DRasterOrdered)
+ << " " << declarationStr << "3D[" << texture3DCount << "]"
+ << " : register(" << registerStr << baseUAVRegister + texture3DRegisterIndex << ");\n";
+ }
+ if (texture2DArrayCount > 0)
+ {
+ out << "static const uint " << offsetStr << "2DArray = " << texture2DArrayRegisterIndex
+ << ";\n";
+ out << "uniform "
+ << Image2DHLSLTextureString(textureGroup, gl::TextureType::_2DArray,
+ texture2DArrayRasterOrdered)
+ << " " << declarationStr << "2DArray[" << texture2DArrayCount << "]"
+ << " : register(" << registerStr << baseUAVRegister + texture2DArrayRegisterIndex
+ << ");\n";
+ }
+ for (const sh::ShaderVariable &uniform : group)
+ {
+ if (!programD3D.hasNamedUniform(uniform.name))
+ {
+ continue;
+ }
+
+ out << "static const uint " << DecorateVariable(uniform.name)
+ << ArrayIndexString(uniform.arraySizes) << " = {";
+ for (unsigned int index = 0; index < uniform.getArraySizeProduct(); index++)
+ {
+ if (index > 0)
+ {
+ out << ", ";
+ }
+ switch (image2DBindLayout.at(uniform.binding + index))
+ {
+ case gl::TextureType::_2D:
+ {
+ out << texture2DRegisterIndex;
+ programD3D.assignImage2DRegisters(shaderType, texture2DRegisterIndex,
+ uniform.binding + index, uniform.readonly);
+ texture2DRegisterIndex++;
+ break;
+ }
+ case gl::TextureType::_3D:
+ {
+ out << texture3DRegisterIndex;
+ programD3D.assignImage2DRegisters(shaderType, texture3DRegisterIndex,
+ uniform.binding + index, uniform.readonly);
+ texture3DRegisterIndex++;
+ break;
+ }
+ case gl::TextureType::_2DArray:
+ case gl::TextureType::CubeMap:
+ {
+ out << texture2DArrayRegisterIndex;
+ programD3D.assignImage2DRegisters(shaderType, texture2DArrayRegisterIndex,
+ uniform.binding + index, uniform.readonly);
+ texture2DArrayRegisterIndex++;
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ }
+ out << "};\n";
+ }
+
+ gl::Shader *shaderGL = programData.getAttachedShader(shaderType);
+ const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shaderGL);
+
+ if (shaderD3D->useImage2DFunction(Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSIZE)))
+ {
+ OutputImage2DSizeFunction(out, textureGroup, totalCount, texture2DCount, texture3DCount,
+ texture2DArrayCount, offsetStr, declarationStr);
+ }
+ if (shaderD3D->useImage2DFunction(Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DLOAD)))
+ {
+ OutputImage2DLoadFunction(out, textureGroup, totalCount, texture2DCount, texture3DCount,
+ texture2DArrayCount, offsetStr, declarationStr);
+ }
+ if (shaderD3D->useImage2DFunction(Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSTORE)))
+ {
+ OutputImage2DStoreFunction(out, textureGroup, totalCount, texture2DCount, texture3DCount,
+ texture2DArrayCount, offsetStr, declarationStr);
+ }
+}
+
+// kImage2DFunctionString must be the same as outputHLSL.
+constexpr const char kImage2DFunctionString[] = "// @@ IMAGE2D DECLARATION FUNCTION STRING @@";
+} // anonymous namespace
+
+std::string GenerateShaderForImage2DBindSignature(
+ ProgramD3D &programD3D,
+ const gl::ProgramState &programData,
+ gl::ShaderType shaderType,
+ const std::string &shaderHLSL,
+ std::vector<sh::ShaderVariable> &image2DUniforms,
+ const gl::ImageUnitTextureTypeMap &image2DBindLayout,
+ unsigned int baseUAVRegister)
+{
+ std::vector<std::vector<sh::ShaderVariable>> groupedImage2DUniforms(IMAGE2D_MAX + 1);
+ unsigned int image2DTexture3DCount = 0, image2DTexture2DArrayCount = 0;
+ for (sh::ShaderVariable &image2D : image2DUniforms)
+ {
+ for (unsigned int index = 0; index < image2D.getArraySizeProduct(); index++)
+ {
+ // Any image variable declared without a binding qualifier is initially bound to unit
+ // zero.
+ if (image2D.binding == -1)
+ {
+ image2D.binding = 0;
+ }
+ switch (image2DBindLayout.at(image2D.binding + index))
+ {
+ case gl::TextureType::_2D:
+ break;
+ case gl::TextureType::_3D:
+ image2DTexture3DCount++;
+ break;
+ case gl::TextureType::_2DArray:
+ case gl::TextureType::CubeMap:
+ image2DTexture2DArrayCount++;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ Image2DHLSLGroup group = image2DHLSLGroup(image2D);
+ groupedImage2DUniforms[group].push_back(image2D);
+ }
+
+ gl::Shader *shaderGL = programData.getAttachedShader(shaderType);
+ const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shaderGL);
+ unsigned int groupTextureRegisterIndex = shaderD3D->getReadonlyImage2DRegisterIndex();
+ unsigned int groupRWTextureRegisterIndex = shaderD3D->getImage2DRegisterIndex();
+ unsigned int image2DTexture3DIndex = 0;
+ unsigned int image2DTexture2DArrayIndex = image2DTexture3DCount;
+ unsigned int image2DTexture2DIndex = image2DTexture3DCount + image2DTexture2DArrayCount;
+ std::ostringstream out;
+
+ for (int groupId = IMAGE2D_MIN; groupId < IMAGE2D_MAX; ++groupId)
+ {
+ OutputHLSLImage2DUniformGroup(
+ programD3D, programData, shaderType, out, Image2DHLSLGroup(groupId),
+ groupedImage2DUniforms[groupId], image2DBindLayout, baseUAVRegister,
+ &groupTextureRegisterIndex, &groupRWTextureRegisterIndex, &image2DTexture3DIndex,
+ &image2DTexture2DArrayIndex, &image2DTexture2DIndex);
+ }
+
+ std::string result = shaderHLSL;
+ bool success = angle::ReplaceSubstring(&result, kImage2DFunctionString, out.str());
+ ASSERT(success);
+
+ return result;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.h
new file mode 100644
index 0000000000..6533c972f8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.h
@@ -0,0 +1,28 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DynamicImage2DHLSL.h: Interface for link and run-time HLSL generation
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_DYNAMICIMAGE2DHLSL_H_
+#define LIBANGLE_RENDERER_D3D_DYNAMICIMAGE2DHLSL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+std::string GenerateShaderForImage2DBindSignature(
+ ProgramD3D &programD3D,
+ const gl::ProgramState &programData,
+ gl::ShaderType shaderType,
+ const std::string &shaderHLSL,
+ std::vector<sh::ShaderVariable> &image2DUniforms,
+ const gl::ImageUnitTextureTypeMap &image2DBindLayout,
+ unsigned int baseUAVRegister);
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/EGLImageD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/EGLImageD3D.cpp
new file mode 100644
index 0000000000..c2ff39ba24
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/EGLImageD3D.cpp
@@ -0,0 +1,93 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// EGLImageD3D.cpp: Implements the rx::EGLImageD3D class, the D3D implementation of EGL images
+
+#include "libANGLE/renderer/d3d/EGLImageD3D.h"
+
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
+
+#include <EGL/eglext.h>
+
+namespace rx
+{
+
+EGLImageD3D::EGLImageD3D(const egl::ImageState &state,
+ EGLenum target,
+ const egl::AttributeMap &attribs,
+ RendererD3D *renderer)
+ : ImageImpl(state), mRenderer(renderer), mRenderTarget(nullptr)
+{
+ ASSERT(renderer != nullptr);
+}
+
+EGLImageD3D::~EGLImageD3D()
+{
+ SafeDelete(mRenderTarget);
+}
+
+egl::Error EGLImageD3D::initialize(const egl::Display *display)
+{
+ return egl::NoError();
+}
+
+angle::Result EGLImageD3D::orphan(const gl::Context *context, egl::ImageSibling *sibling)
+{
+ if (sibling == mState.source)
+ {
+ ANGLE_TRY(copyToLocalRendertarget(context));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result EGLImageD3D::getRenderTarget(const gl::Context *context,
+ RenderTargetD3D **outRT) const
+{
+ if (mState.source != nullptr)
+ {
+ ASSERT(!mRenderTarget);
+ FramebufferAttachmentRenderTarget *rt = nullptr;
+ ANGLE_TRY(
+ mState.source->getAttachmentRenderTarget(context, GL_NONE, mState.imageIndex, 0, &rt));
+ *outRT = static_cast<RenderTargetD3D *>(rt);
+ return angle::Result::Continue;
+ }
+
+ ASSERT(mRenderTarget);
+ *outRT = mRenderTarget;
+ return angle::Result::Continue;
+}
+
+angle::Result EGLImageD3D::copyToLocalRendertarget(const gl::Context *context)
+{
+ ASSERT(mState.source != nullptr);
+ ASSERT(mRenderTarget == nullptr);
+
+ RenderTargetD3D *curRenderTarget = nullptr;
+ ANGLE_TRY(getRenderTarget(context, &curRenderTarget));
+
+ {
+ std::unique_lock lock(mState.targetsLock);
+ // Invalidate FBOs with this Image attached. Only currently applies to D3D11.
+ for (egl::ImageSibling *target : mState.targets)
+ {
+ target->onStateChange(angle::SubjectMessage::SubjectChanged);
+ }
+ }
+
+ return mRenderer->createRenderTargetCopy(context, curRenderTarget, &mRenderTarget);
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/EGLImageD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/EGLImageD3D.h
new file mode 100644
index 0000000000..53c18739af
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/EGLImageD3D.h
@@ -0,0 +1,55 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// EGLImageD3D.h: Defines the rx::EGLImageD3D class, the D3D implementation of EGL images
+
+#ifndef LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_
+#define LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_
+
+#include "libANGLE/renderer/ImageImpl.h"
+
+namespace gl
+{
+class Context;
+}
+
+namespace egl
+{
+class AttributeMap;
+}
+
+namespace rx
+{
+class FramebufferAttachmentObjectImpl;
+class TextureD3D;
+class RenderbufferD3D;
+class RendererD3D;
+class RenderTargetD3D;
+
+class EGLImageD3D final : public ImageImpl
+{
+ public:
+ EGLImageD3D(const egl::ImageState &state,
+ EGLenum target,
+ const egl::AttributeMap &attribs,
+ RendererD3D *renderer);
+ ~EGLImageD3D() override;
+
+ egl::Error initialize(const egl::Display *display) override;
+
+ angle::Result orphan(const gl::Context *context, egl::ImageSibling *sibling) override;
+
+ angle::Result getRenderTarget(const gl::Context *context, RenderTargetD3D **outRT) const;
+
+ private:
+ angle::Result copyToLocalRendertarget(const gl::Context *context);
+
+ RendererD3D *mRenderer;
+ RenderTargetD3D *mRenderTarget;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
new file mode 100644
index 0000000000..5a8279a586
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -0,0 +1,402 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FramebufferD3D.cpp: Implements the DefaultAttachmentD3D and FramebufferD3D classes.
+
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+
+#include "common/bitset_utils.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/d3d/ContextD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+
+namespace rx
+{
+
+namespace
+{
+
+ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
+{
+ ClearParameters clearParams;
+ memset(&clearParams, 0, sizeof(ClearParameters));
+
+ clearParams.colorF = state.getColorClearValue();
+ clearParams.colorType = GL_FLOAT;
+ clearParams.clearDepth = false;
+ clearParams.depthValue = state.getDepthClearValue();
+ clearParams.clearStencil = false;
+ clearParams.stencilValue = state.getStencilClearValue();
+ clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask;
+
+ const auto *framebufferObject = state.getDrawFramebuffer();
+ const gl::Extents &framebufferSize = framebufferObject->getFirstNonNullAttachment()->getSize();
+ const gl::Offset &surfaceTextureOffset = framebufferObject->getSurfaceTextureOffset();
+ if (state.isScissorTestEnabled())
+ {
+ clearParams.scissorEnabled = true;
+ clearParams.scissor = state.getScissor();
+ clearParams.scissor.x = clearParams.scissor.x + surfaceTextureOffset.x;
+ clearParams.scissor.y = clearParams.scissor.y + surfaceTextureOffset.y;
+ }
+ else if (surfaceTextureOffset != gl::kOffsetZero)
+ {
+ clearParams.scissorEnabled = true;
+ clearParams.scissor = gl::Rectangle(surfaceTextureOffset.x, surfaceTextureOffset.y,
+ framebufferSize.width, framebufferSize.height);
+ }
+
+ const bool clearColor =
+ (mask & GL_COLOR_BUFFER_BIT) && framebufferObject->hasEnabledDrawBuffer();
+ if (clearColor)
+ {
+ clearParams.clearColor.set();
+ }
+ else
+ {
+ clearParams.clearColor.reset();
+ }
+ clearParams.colorMask = state.getBlendStateExt().getColorMaskBits();
+
+ if (mask & GL_DEPTH_BUFFER_BIT)
+ {
+ if (state.getDepthStencilState().depthMask &&
+ framebufferObject->getDepthAttachment() != nullptr)
+ {
+ clearParams.clearDepth = true;
+ }
+ }
+
+ if (mask & GL_STENCIL_BUFFER_BIT)
+ {
+ if (framebufferObject->getStencilAttachment() != nullptr &&
+ framebufferObject->getStencilAttachment()->getStencilSize() > 0)
+ {
+ clearParams.clearStencil = true;
+ }
+ }
+
+ return clearParams;
+}
+} // namespace
+
+ClearParameters::ClearParameters() = default;
+
+ClearParameters::ClearParameters(const ClearParameters &other) = default;
+
+FramebufferD3D::FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer)
+ : FramebufferImpl(data), mRenderer(renderer), mMockAttachment()
+{}
+
+FramebufferD3D::~FramebufferD3D() {}
+
+angle::Result FramebufferD3D::clear(const gl::Context *context, GLbitfield mask)
+{
+ ClearParameters clearParams = GetClearParameters(context->getState(), mask);
+ return clearImpl(context, clearParams);
+}
+
+angle::Result FramebufferD3D::clearBufferfv(const gl::Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values)
+{
+ // glClearBufferfv can be called to clear the color buffer or depth buffer
+ ClearParameters clearParams = GetClearParameters(context->getState(), 0);
+
+ if (buffer == GL_COLOR)
+ {
+ for (unsigned int i = 0; i < clearParams.clearColor.size(); i++)
+ {
+ clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+ }
+ clearParams.colorF = gl::ColorF(values[0], values[1], values[2], values[3]);
+ clearParams.colorType = GL_FLOAT;
+ }
+
+ if (buffer == GL_DEPTH)
+ {
+ clearParams.clearDepth = true;
+ clearParams.depthValue = values[0];
+ }
+
+ return clearImpl(context, clearParams);
+}
+
+angle::Result FramebufferD3D::clearBufferuiv(const gl::Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values)
+{
+ // glClearBufferuiv can only be called to clear a color buffer
+ ClearParameters clearParams = GetClearParameters(context->getState(), 0);
+ for (unsigned int i = 0; i < clearParams.clearColor.size(); i++)
+ {
+ clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+ }
+ clearParams.colorUI = gl::ColorUI(values[0], values[1], values[2], values[3]);
+ clearParams.colorType = GL_UNSIGNED_INT;
+
+ return clearImpl(context, clearParams);
+}
+
+angle::Result FramebufferD3D::clearBufferiv(const gl::Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values)
+{
+ // glClearBufferiv can be called to clear the color buffer or stencil buffer
+ ClearParameters clearParams = GetClearParameters(context->getState(), 0);
+
+ if (buffer == GL_COLOR)
+ {
+ for (unsigned int i = 0; i < clearParams.clearColor.size(); i++)
+ {
+ clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+ }
+ clearParams.colorI = gl::ColorI(values[0], values[1], values[2], values[3]);
+ clearParams.colorType = GL_INT;
+ }
+
+ if (buffer == GL_STENCIL)
+ {
+ clearParams.clearStencil = true;
+ clearParams.stencilValue = values[0];
+ }
+
+ return clearImpl(context, clearParams);
+}
+
+angle::Result FramebufferD3D::clearBufferfi(const gl::Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil)
+{
+ // glClearBufferfi can only be called to clear a depth stencil buffer
+ ClearParameters clearParams = GetClearParameters(context->getState(), 0);
+ clearParams.clearDepth = true;
+ clearParams.depthValue = depth;
+ clearParams.clearStencil = true;
+ clearParams.stencilValue = stencil;
+
+ return clearImpl(context, clearParams);
+}
+
+angle::Result FramebufferD3D::readPixels(const gl::Context *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelPackState &pack,
+ gl::Buffer *packBuffer,
+ void *pixels)
+{
+ // Clip read area to framebuffer.
+ const gl::Extents fbSize = getState().getReadPixelsAttachment(format)->getSize();
+ const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
+ gl::Rectangle clippedArea;
+ if (!ClipRectangle(area, fbRect, &clippedArea))
+ {
+ // nothing to read
+ return angle::Result::Continue;
+ }
+
+ const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(format, type);
+
+ ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
+
+ GLuint outputPitch = 0;
+ ANGLE_CHECK_GL_MATH(contextD3D,
+ sizedFormatInfo.computeRowPitch(type, area.width, pack.alignment,
+ pack.rowLength, &outputPitch));
+
+ GLuint outputSkipBytes = 0;
+ ANGLE_CHECK_GL_MATH(contextD3D, sizedFormatInfo.computeSkipBytes(type, outputPitch, 0, pack,
+ false, &outputSkipBytes));
+ outputSkipBytes += (clippedArea.x - area.x) * sizedFormatInfo.pixelBytes +
+ (clippedArea.y - area.y) * outputPitch;
+
+ return readPixelsImpl(context, clippedArea, format, type, outputPitch, pack, packBuffer,
+ static_cast<uint8_t *>(pixels) + outputSkipBytes);
+}
+
+angle::Result FramebufferD3D::blit(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter)
+{
+ const auto &glState = context->getState();
+ const gl::Framebuffer *sourceFramebuffer = glState.getReadFramebuffer();
+ const gl::Rectangle *scissor = glState.isScissorTestEnabled() ? &glState.getScissor() : nullptr;
+ ANGLE_TRY(blitImpl(context, sourceArea, destArea, scissor, (mask & GL_COLOR_BUFFER_BIT) != 0,
+ (mask & GL_DEPTH_BUFFER_BIT) != 0, (mask & GL_STENCIL_BUFFER_BIT) != 0,
+ filter, sourceFramebuffer));
+
+ return angle::Result::Continue;
+}
+
+gl::FramebufferStatus FramebufferD3D::checkStatus(const gl::Context *context) const
+{
+ // if we have both a depth and stencil buffer, they must refer to the same object
+ // since we only support packed_depth_stencil and not separate depth and stencil
+ if (mState.hasSeparateDepthAndStencilAttachments())
+ {
+ return gl::FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_UNSUPPORTED,
+ gl::err::kFramebufferIncompleteUnsupportedSeparateDepthStencilBuffers);
+ }
+
+ // D3D11 does not allow for overlapping RenderTargetViews.
+ // If WebGL compatibility is enabled, this has already been checked at a higher level.
+ ASSERT(!context->isWebGL() || mState.colorAttachmentsAreUniqueImages());
+ if (!context->isWebGL())
+ {
+ if (!mState.colorAttachmentsAreUniqueImages())
+ {
+ return gl::FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_UNSUPPORTED,
+ gl::err::kFramebufferIncompleteUnsupportedNonUniqueAttachments);
+ }
+ }
+
+ // D3D requires all render targets to have the same dimensions.
+ if (!mState.attachmentsHaveSameDimensions())
+ {
+ return gl::FramebufferStatus::Incomplete(
+ GL_FRAMEBUFFER_UNSUPPORTED,
+ gl::err::kFramebufferIncompleteUnsupportedMissmatchedDimensions);
+ }
+
+ return gl::FramebufferStatus::Complete();
+}
+
+angle::Result FramebufferD3D::syncState(const gl::Context *context,
+ GLenum binding,
+ const gl::Framebuffer::DirtyBits &dirtyBits,
+ gl::Command command)
+{
+ if (!mColorAttachmentsForRender.valid())
+ {
+ return angle::Result::Continue;
+ }
+
+ for (auto dirtyBit : dirtyBits)
+ {
+ if ((dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 &&
+ dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) ||
+ dirtyBit == gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS)
+ {
+ mColorAttachmentsForRender.reset();
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const gl::Context *context)
+{
+ gl::DrawBufferMask activeProgramOutputs =
+ context->getState().getProgram()->getExecutable().getActiveOutputVariablesMask();
+
+ if (mColorAttachmentsForRender.valid() && mCurrentActiveProgramOutputs == activeProgramOutputs)
+ {
+ return mColorAttachmentsForRender.value();
+ }
+
+ // Does not actually free memory
+ gl::AttachmentList colorAttachmentsForRender;
+ mColorAttachmentsForRenderMask.reset();
+
+ const auto &colorAttachments = mState.getColorAttachments();
+ const auto &drawBufferStates = mState.getDrawBufferStates();
+ const auto &features = mRenderer->getFeatures();
+
+ for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
+ {
+ GLenum drawBufferState = drawBufferStates[attachmentIndex];
+ const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex];
+
+ if (colorAttachment.isAttached() && drawBufferState != GL_NONE &&
+ activeProgramOutputs[attachmentIndex])
+ {
+ ASSERT(drawBufferState == GL_BACK ||
+ drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
+ colorAttachmentsForRender.push_back(&colorAttachment);
+ mColorAttachmentsForRenderMask.set(attachmentIndex);
+ }
+ else if (!features.mrtPerfWorkaround.enabled)
+ {
+ colorAttachmentsForRender.push_back(nullptr);
+ mColorAttachmentsForRenderMask.set(attachmentIndex);
+ }
+ }
+
+ // When rendering with no render target on D3D, two bugs lead to incorrect behavior on Intel
+ // drivers < 4815. The rendering samples always pass neglecting discard statements in pixel
+ // shader. We add a mock texture as render target in such case.
+ if (mRenderer->getFeatures().addMockTextureNoRenderTarget.enabled &&
+ colorAttachmentsForRender.empty() && activeProgramOutputs.any())
+ {
+ static_assert(static_cast<size_t>(activeProgramOutputs.size()) <= 32,
+ "Size of active program outputs should less or equal than 32.");
+ const GLuint activeProgramLocation = static_cast<GLuint>(
+ gl::ScanForward(static_cast<uint32_t>(activeProgramOutputs.bits())));
+
+ if (mMockAttachment.isAttached() &&
+ (mMockAttachment.getBinding() - GL_COLOR_ATTACHMENT0) == activeProgramLocation)
+ {
+ colorAttachmentsForRender.push_back(&mMockAttachment);
+ }
+ else
+ {
+ // Remove mock attachment to prevents us from leaking it, and the program may require
+ // it to be attached to a new binding point.
+ if (mMockAttachment.isAttached())
+ {
+ mMockAttachment.detach(context, Serial());
+ }
+
+ gl::Texture *mockTex = nullptr;
+ // TODO(jmadill): Handle error if mock texture can't be created.
+ (void)mRenderer->getIncompleteTexture(context, gl::TextureType::_2D, &mockTex);
+ if (mockTex)
+ {
+ gl::ImageIndex index = gl::ImageIndex::Make2D(0);
+ mMockAttachment = gl::FramebufferAttachment(
+ context, GL_TEXTURE, GL_COLOR_ATTACHMENT0_EXT + activeProgramLocation, index,
+ mockTex, Serial());
+ colorAttachmentsForRender.push_back(&mMockAttachment);
+ }
+ }
+ }
+
+ mColorAttachmentsForRender = std::move(colorAttachmentsForRender);
+ mCurrentActiveProgramOutputs = activeProgramOutputs;
+
+ return mColorAttachmentsForRender.value();
+}
+
+void FramebufferD3D::destroy(const gl::Context *context)
+{
+ if (mMockAttachment.isAttached())
+ {
+ mMockAttachment.detach(context, Serial());
+ }
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/FramebufferD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/FramebufferD3D.h
new file mode 100644
index 0000000000..67e19bd4bc
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/FramebufferD3D.h
@@ -0,0 +1,143 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FramebufferD3D.h: Defines the DefaultAttachmentD3D and FramebufferD3D classes.
+
+#ifndef LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_
+#define LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_
+
+#include <cstdint>
+#include <vector>
+
+#include "common/Color.h"
+#include "common/Optional.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/FramebufferImpl.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+struct PixelPackState;
+
+typedef std::vector<const FramebufferAttachment *> AttachmentList;
+} // namespace gl
+
+namespace rx
+{
+class RendererD3D;
+class RenderTargetD3D;
+
+struct ClearParameters
+{
+ ClearParameters();
+ ClearParameters(const ClearParameters &other);
+
+ gl::DrawBufferMask clearColor;
+ gl::ColorF colorF;
+ gl::ColorI colorI;
+ gl::ColorUI colorUI;
+ GLenum colorType;
+ gl::BlendStateExt::ColorMaskStorage::Type colorMask;
+
+ bool clearDepth;
+ float depthValue;
+
+ bool clearStencil;
+ GLint stencilValue;
+ GLuint stencilWriteMask;
+
+ bool scissorEnabled;
+ gl::Rectangle scissor;
+};
+
+class FramebufferD3D : public FramebufferImpl
+{
+ public:
+ FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer);
+ ~FramebufferD3D() override;
+
+ angle::Result clear(const gl::Context *context, GLbitfield mask) override;
+ angle::Result clearBufferfv(const gl::Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *values) override;
+ angle::Result clearBufferuiv(const gl::Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *values) override;
+ angle::Result clearBufferiv(const gl::Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *values) override;
+ angle::Result clearBufferfi(const gl::Context *context,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil) override;
+
+ angle::Result readPixels(const gl::Context *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelPackState &pack,
+ gl::Buffer *packBuffer,
+ void *pixels) override;
+
+ angle::Result blit(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ GLbitfield mask,
+ GLenum filter) override;
+
+ gl::FramebufferStatus checkStatus(const gl::Context *context) const override;
+
+ angle::Result syncState(const gl::Context *context,
+ GLenum binding,
+ const gl::Framebuffer::DirtyBits &dirtyBits,
+ gl::Command command) override;
+
+ const gl::AttachmentList &getColorAttachmentsForRender(const gl::Context *context);
+
+ const gl::DrawBufferMask getLastColorAttachmentsForRenderMask() const
+ {
+ return mColorAttachmentsForRenderMask;
+ }
+
+ void destroy(const gl::Context *context) override;
+
+ private:
+ virtual angle::Result clearImpl(const gl::Context *context,
+ const ClearParameters &clearParams) = 0;
+
+ virtual angle::Result readPixelsImpl(const gl::Context *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ gl::Buffer *packBuffer,
+ uint8_t *pixels) = 0;
+
+ virtual angle::Result blitImpl(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ const gl::Rectangle *scissor,
+ bool blitRenderTarget,
+ bool blitDepth,
+ bool blitStencil,
+ GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer) = 0;
+
+ RendererD3D *mRenderer;
+ Optional<gl::AttachmentList> mColorAttachmentsForRender;
+ gl::DrawBufferMask mCurrentActiveProgramOutputs;
+ gl::DrawBufferMask mColorAttachmentsForRenderMask;
+
+ gl::FramebufferAttachment mMockAttachment;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
new file mode 100644
index 0000000000..e7260e403a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
@@ -0,0 +1,387 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "libANGLE/renderer/d3d/HLSLCompiler.h"
+
+#include <sstream>
+
+#include "common/system_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/features.h"
+#include "libANGLE/histogram_macros.h"
+#include "libANGLE/renderer/d3d/ContextD3D.h"
+#include "libANGLE/trace.h"
+
+namespace
+{
+#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
+# ifdef CREATE_COMPILER_FLAG_INFO
+# undef CREATE_COMPILER_FLAG_INFO
+# endif
+
+# define CREATE_COMPILER_FLAG_INFO(flag) \
+ { \
+ flag, #flag \
+ }
+
+struct CompilerFlagInfo
+{
+ UINT mFlag;
+ const char *mName;
+};
+
+CompilerFlagInfo CompilerFlagInfos[] = {
+ // NOTE: The data below is copied from d3dcompiler.h
+ // If something changes there it should be changed here as well
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_DEBUG), // (1 << 0)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_SKIP_VALIDATION), // (1 << 1)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_SKIP_OPTIMIZATION), // (1 << 2)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PACK_MATRIX_ROW_MAJOR), // (1 << 3)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR), // (1 << 4)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PARTIAL_PRECISION), // (1 << 5)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_FORCE_VS_SOFTWARE_NO_OPT), // (1 << 6)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_FORCE_PS_SOFTWARE_NO_OPT), // (1 << 7)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_NO_PRESHADER), // (1 << 8)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_AVOID_FLOW_CONTROL), // (1 << 9)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_PREFER_FLOW_CONTROL), // (1 << 10)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_ENABLE_STRICTNESS), // (1 << 11)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_ENABLE_BACKWARDS_COMPATIBILITY), // (1 << 12)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_IEEE_STRICTNESS), // (1 << 13)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL0), // (1 << 14)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL1), // 0
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL2), // ((1 << 14) | (1 << 15))
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_OPTIMIZATION_LEVEL3), // (1 << 15)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_RESERVED16), // (1 << 16)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_RESERVED17), // (1 << 17)
+ CREATE_COMPILER_FLAG_INFO(D3DCOMPILE_WARNINGS_ARE_ERRORS) // (1 << 18)
+};
+
+# undef CREATE_COMPILER_FLAG_INFO
+
+bool IsCompilerFlagSet(UINT mask, UINT flag)
+{
+ bool isFlagSet = IsMaskFlagSet(mask, flag);
+
+ switch (flag)
+ {
+ case D3DCOMPILE_OPTIMIZATION_LEVEL0:
+ return isFlagSet && !IsMaskFlagSet(mask, UINT(D3DCOMPILE_OPTIMIZATION_LEVEL3));
+
+ case D3DCOMPILE_OPTIMIZATION_LEVEL1:
+ return (mask & D3DCOMPILE_OPTIMIZATION_LEVEL2) == UINT(0);
+
+ case D3DCOMPILE_OPTIMIZATION_LEVEL3:
+ return isFlagSet && !IsMaskFlagSet(mask, UINT(D3DCOMPILE_OPTIMIZATION_LEVEL0));
+
+ default:
+ return isFlagSet;
+ }
+}
+#endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
+
+constexpr char kOldCompilerLibrary[] = "d3dcompiler_old.dll";
+
+enum D3DCompilerLoadLibraryResult
+{
+ D3DCompilerDefaultLibrarySuccess,
+ D3DCompilerOldLibrarySuccess,
+ D3DCompilerFailure,
+ D3DCompilerEnumBoundary,
+};
+} // anonymous namespace
+
+namespace rx
+{
+
+CompileConfig::CompileConfig() : flags(0), name() {}
+
+CompileConfig::CompileConfig(UINT flags, const std::string &name) : flags(flags), name(name) {}
+
+HLSLCompiler::HLSLCompiler()
+ : mInitialized(false),
+ mD3DCompilerModule(nullptr),
+ mD3DCompileFunc(nullptr),
+ mD3DDisassembleFunc(nullptr)
+{}
+
+HLSLCompiler::~HLSLCompiler()
+{
+ release();
+}
+
+angle::Result HLSLCompiler::ensureInitialized(d3d::Context *context)
+{
+ if (mInitialized)
+ {
+ return angle::Result::Continue;
+ }
+
+ ANGLE_TRACE_EVENT0("gpu.angle", "HLSLCompiler::initialize");
+#if !defined(ANGLE_ENABLE_WINDOWS_UWP)
+# if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
+ // Find a D3DCompiler module that had already been loaded based on a predefined list of
+ // versions.
+ static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES;
+
+ for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i)
+ {
+ if (GetModuleHandleExA(0, d3dCompilerNames[i], &mD3DCompilerModule))
+ {
+ break;
+ }
+ }
+# endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
+
+ if (!mD3DCompilerModule)
+ {
+ // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was
+ // built with.
+ mD3DCompilerModule = LoadLibraryA(D3DCOMPILER_DLL_A);
+
+ if (mD3DCompilerModule)
+ {
+ ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3DCompilerLoadLibraryResult",
+ D3DCompilerDefaultLibrarySuccess, D3DCompilerEnumBoundary);
+ }
+ else
+ {
+ WARN() << "Failed to load HLSL compiler library. Using 'old' DLL.";
+ mD3DCompilerModule = LoadLibraryA(kOldCompilerLibrary);
+ if (mD3DCompilerModule)
+ {
+ ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3DCompilerLoadLibraryResult",
+ D3DCompilerOldLibrarySuccess, D3DCompilerEnumBoundary);
+ }
+ }
+ }
+
+ if (!mD3DCompilerModule)
+ {
+ DWORD lastError = GetLastError();
+ ERR() << "D3D Compiler LoadLibrary failed. GetLastError=" << lastError;
+ ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3DCompilerLoadLibraryResult", D3DCompilerFailure,
+ D3DCompilerEnumBoundary);
+ ANGLE_TRY_HR(context, E_OUTOFMEMORY, "LoadLibrary failed to load D3D Compiler DLL.");
+ }
+
+ mD3DCompileFunc =
+ reinterpret_cast<pD3DCompile>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
+ ASSERT(mD3DCompileFunc);
+
+ mD3DDisassembleFunc =
+ reinterpret_cast<pD3DDisassemble>(GetProcAddress(mD3DCompilerModule, "D3DDisassemble"));
+ ASSERT(mD3DDisassembleFunc);
+
+#else
+ // D3D Shader compiler is linked already into this module, so the export
+ // can be directly assigned.
+ mD3DCompilerModule = nullptr;
+ mD3DCompileFunc = reinterpret_cast<pD3DCompile>(D3DCompile);
+ mD3DDisassembleFunc = reinterpret_cast<pD3DDisassemble>(D3DDisassemble);
+#endif
+
+ ANGLE_CHECK_HR(context, mD3DCompileFunc, "Error finding D3DCompile entry point.",
+ E_OUTOFMEMORY);
+
+ mInitialized = true;
+ return angle::Result::Continue;
+}
+
+void HLSLCompiler::release()
+{
+ if (mInitialized)
+ {
+ FreeLibrary(mD3DCompilerModule);
+ mD3DCompilerModule = nullptr;
+ mD3DCompileFunc = nullptr;
+ mD3DDisassembleFunc = nullptr;
+ mInitialized = false;
+ }
+}
+
+angle::Result HLSLCompiler::compileToBinary(d3d::Context *context,
+ gl::InfoLog &infoLog,
+ const std::string &hlsl,
+ const std::string &profile,
+ const std::vector<CompileConfig> &configs,
+ const D3D_SHADER_MACRO *overrideMacros,
+ ID3DBlob **outCompiledBlob,
+ std::string *outDebugInfo)
+{
+ ASSERT(mInitialized);
+
+#if !defined(ANGLE_ENABLE_WINDOWS_UWP)
+ ASSERT(mD3DCompilerModule);
+#endif
+ ASSERT(mD3DCompileFunc);
+
+#if !defined(ANGLE_ENABLE_WINDOWS_UWP) && defined(ANGLE_ENABLE_DEBUG_TRACE)
+ std::string sourcePath = angle::CreateTemporaryFile().value();
+ std::ostringstream stream;
+ stream << "#line 2 \"" << sourcePath << "\"\n\n" << hlsl;
+ std::string sourceText = stream.str();
+ writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
+#endif
+
+ const D3D_SHADER_MACRO *macros = overrideMacros ? overrideMacros : nullptr;
+
+ for (size_t i = 0; i < configs.size(); ++i)
+ {
+ ID3DBlob *errorMessage = nullptr;
+ ID3DBlob *binary = nullptr;
+ HRESULT result = S_OK;
+
+ {
+ ANGLE_TRACE_EVENT1("gpu.angle", "D3DCompile", "source", hlsl);
+ result = mD3DCompileFunc(hlsl.c_str(), hlsl.length(), gl::g_fakepath, macros, nullptr,
+ "main", profile.c_str(), configs[i].flags, 0, &binary,
+ &errorMessage);
+ }
+
+ if (errorMessage)
+ {
+ std::string message = static_cast<const char *>(errorMessage->GetBufferPointer());
+ SafeRelease(errorMessage);
+ ANGLE_TRACE_EVENT1("gpu.angle", "D3DCompile::Error", "error", errorMessage);
+
+ infoLog.appendSanitized(message.c_str());
+
+ // This produces unbelievable amounts of spam in about:gpu.
+ // WARN() << std::endl << hlsl;
+
+ WARN() << std::endl << message;
+
+ if (macros != nullptr)
+ {
+ constexpr const char *kLoopRelatedErrors[] = {
+ // "can't unroll loops marked with loop attribute"
+ "error X3531:",
+
+ // "cannot have gradient operations inside loops with divergent flow control",
+ // even though it is counter-intuitive to disable unrolling for this error, some
+ // very long shaders have trouble deciding which loops to unroll and turning off
+ // forced unrolls allows them to compile properly.
+ "error X4014:",
+
+ // "array index out of bounds", loop unrolling can result in invalid array
+ // access if the indices become constant, causing loops that may never be
+ // executed to generate compilation errors
+ "error X3504:",
+ };
+
+ bool hasLoopRelatedError = false;
+ for (const char *errorType : kLoopRelatedErrors)
+ {
+ if (message.find(errorType) != std::string::npos)
+ {
+ hasLoopRelatedError = true;
+ break;
+ }
+ }
+
+ if (hasLoopRelatedError)
+ {
+ // Disable [loop] and [flatten]
+ macros = nullptr;
+
+ // Retry without changing compiler flags
+ i--;
+ continue;
+ }
+ }
+ }
+
+ if (SUCCEEDED(result))
+ {
+ *outCompiledBlob = binary;
+
+ (*outDebugInfo) +=
+ "// COMPILER INPUT HLSL BEGIN\n\n" + hlsl + "\n// COMPILER INPUT HLSL END\n";
+
+#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
+ (*outDebugInfo) += "\n\n// ASSEMBLY BEGIN\n\n";
+ (*outDebugInfo) += "// Compiler configuration: " + configs[i].name + "\n// Flags:\n";
+ for (size_t fIx = 0; fIx < ArraySize(CompilerFlagInfos); ++fIx)
+ {
+ if (IsCompilerFlagSet(configs[i].flags, CompilerFlagInfos[fIx].mFlag))
+ {
+ (*outDebugInfo) += std::string("// ") + CompilerFlagInfos[fIx].mName + "\n";
+ }
+ }
+
+ (*outDebugInfo) += "// Macros:\n";
+ if (macros == nullptr)
+ {
+ (*outDebugInfo) += "// - : -\n";
+ }
+ else
+ {
+ for (const D3D_SHADER_MACRO *mIt = macros; mIt->Name != nullptr; ++mIt)
+ {
+ (*outDebugInfo) +=
+ std::string("// ") + mIt->Name + " : " + mIt->Definition + "\n";
+ }
+ }
+
+ std::string disassembly;
+ ANGLE_TRY(disassembleBinary(context, binary, &disassembly));
+ (*outDebugInfo) += "\n" + disassembly + "\n// ASSEMBLY END\n";
+#endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
+ return angle::Result::Continue;
+ }
+
+ if (result == E_OUTOFMEMORY)
+ {
+ *outCompiledBlob = nullptr;
+ ANGLE_TRY_HR(context, result, "HLSL compiler had an unexpected failure");
+ }
+
+ infoLog << "Warning: D3D shader compilation failed with " << configs[i].name << " flags. ("
+ << profile << ")";
+
+ if (i + 1 < configs.size())
+ {
+ infoLog << " Retrying with " << configs[i + 1].name;
+ }
+ }
+
+ // None of the configurations succeeded in compiling this shader but the compiler is still
+ // intact
+ *outCompiledBlob = nullptr;
+ return angle::Result::Continue;
+}
+
+angle::Result HLSLCompiler::disassembleBinary(d3d::Context *context,
+ ID3DBlob *shaderBinary,
+ std::string *disassemblyOut)
+{
+ ANGLE_TRY(ensureInitialized(context));
+
+ // Retrieve disassembly
+ UINT flags = D3D_DISASM_ENABLE_DEFAULT_VALUE_PRINTS | D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING;
+ ID3DBlob *disassembly = nullptr;
+ pD3DDisassemble disassembleFunc = reinterpret_cast<pD3DDisassemble>(mD3DDisassembleFunc);
+ LPCVOID buffer = shaderBinary->GetBufferPointer();
+ SIZE_T bufSize = shaderBinary->GetBufferSize();
+ HRESULT result = disassembleFunc(buffer, bufSize, flags, "", &disassembly);
+
+ if (SUCCEEDED(result))
+ {
+ *disassemblyOut = std::string(static_cast<const char *>(disassembly->GetBufferPointer()));
+ }
+ else
+ {
+ *disassemblyOut = "";
+ }
+
+ SafeRelease(disassembly);
+
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/HLSLCompiler.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/HLSLCompiler.h
new file mode 100644
index 0000000000..98a17799cf
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/HLSLCompiler.h
@@ -0,0 +1,74 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// HLSLCompiler: Wrapper for the D3DCompiler DLL.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_
+#define LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+#include "common/platform.h"
+
+#include <string>
+#include <vector>
+
+namespace gl
+{
+class InfoLog;
+} // namespace gl
+
+namespace rx
+{
+namespace d3d
+{
+class Context;
+} // namespace d3d
+
+struct CompileConfig
+{
+ UINT flags;
+ std::string name;
+
+ CompileConfig();
+ CompileConfig(UINT flags, const std::string &name);
+};
+
+class HLSLCompiler : angle::NonCopyable
+{
+ public:
+ HLSLCompiler();
+ ~HLSLCompiler();
+
+ void release();
+
+ // Attempt to compile a HLSL shader using the supplied configurations, may output a NULL
+ // compiled blob even if no GL errors are returned.
+ angle::Result compileToBinary(d3d::Context *context,
+ gl::InfoLog &infoLog,
+ const std::string &hlsl,
+ const std::string &profile,
+ const std::vector<CompileConfig> &configs,
+ const D3D_SHADER_MACRO *overrideMacros,
+ ID3DBlob **outCompiledBlob,
+ std::string *outDebugInfo);
+
+ angle::Result disassembleBinary(d3d::Context *context,
+ ID3DBlob *shaderBinary,
+ std::string *disassemblyOut);
+ angle::Result ensureInitialized(d3d::Context *context);
+
+ private:
+ bool mInitialized;
+ HMODULE mD3DCompilerModule;
+ pD3DCompile mD3DCompileFunc;
+ pD3DDisassemble mD3DDisassembleFunc;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/ImageD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ImageD3D.cpp
new file mode 100644
index 0000000000..67ad3aee70
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ImageD3D.cpp
@@ -0,0 +1,56 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image.h: Implements the rx::Image class, an abstract base class for the
+// renderer-specific classes which will define the interface to the underlying
+// surfaces or resources.
+
+#include "libANGLE/renderer/d3d/ImageD3D.h"
+
+namespace rx
+{
+
+ImageD3D::ImageD3D()
+ : mWidth(0),
+ mHeight(0),
+ mDepth(0),
+ mInternalFormat(GL_NONE),
+ mRenderable(false),
+ mType(gl::TextureType::InvalidEnum),
+ mDirty(false)
+{}
+
+angle::Result ImageD3D::setManagedSurface2D(const gl::Context *context,
+ TextureStorage *storage,
+ int level)
+{
+ return angle::Result::Continue;
+}
+
+angle::Result ImageD3D::setManagedSurfaceCube(const gl::Context *context,
+ TextureStorage *storage,
+ int face,
+ int level)
+{
+ return angle::Result::Continue;
+}
+
+angle::Result ImageD3D::setManagedSurface3D(const gl::Context *context,
+ TextureStorage *storage,
+ int level)
+{
+ return angle::Result::Continue;
+}
+
+angle::Result ImageD3D::setManagedSurface2DArray(const gl::Context *context,
+ TextureStorage *storage,
+ int layer,
+ int level)
+{
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/ImageD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ImageD3D.h
new file mode 100644
index 0000000000..ac58ca5cf6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ImageD3D.h
@@ -0,0 +1,105 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ImageD3D.h: Defines the rx::ImageD3D class, an abstract base class for the
+// renderer-specific classes which will define the interface to the underlying
+// surfaces or resources.
+
+#ifndef LIBANGLE_RENDERER_D3D_IMAGED3D_H_
+#define LIBANGLE_RENDERER_D3D_IMAGED3D_H_
+
+#include "common/debug.h"
+
+#include "common/PackedEnums.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/angletypes.h"
+
+namespace gl
+{
+class Context;
+class Framebuffer;
+class ImageIndex;
+struct PixelUnpackState;
+} // namespace gl
+
+namespace rx
+{
+class TextureStorage;
+class RendererD3D;
+class RenderTargetD3D;
+
+class ImageD3D : angle::NonCopyable
+{
+ public:
+ ImageD3D();
+ virtual ~ImageD3D() {}
+
+ GLsizei getWidth() const { return mWidth; }
+ GLsizei getHeight() const { return mHeight; }
+ GLsizei getDepth() const { return mDepth; }
+ GLenum getInternalFormat() const { return mInternalFormat; }
+ gl::TextureType getType() const { return mType; }
+ bool isRenderableFormat() const { return mRenderable; }
+
+ void markDirty() { mDirty = true; }
+ void markClean() { mDirty = false; }
+ virtual bool isDirty() const = 0;
+
+ virtual bool redefine(gl::TextureType type,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease) = 0;
+
+ virtual angle::Result loadData(const gl::Context *context,
+ const gl::Box &area,
+ const gl::PixelUnpackState &unpack,
+ GLenum type,
+ const void *input,
+ bool applySkipImages) = 0;
+ virtual angle::Result loadCompressedData(const gl::Context *context,
+ const gl::Box &area,
+ const void *input) = 0;
+
+ virtual angle::Result setManagedSurface2D(const gl::Context *context,
+ TextureStorage *storage,
+ int level);
+ virtual angle::Result setManagedSurfaceCube(const gl::Context *context,
+ TextureStorage *storage,
+ int face,
+ int level);
+ virtual angle::Result setManagedSurface3D(const gl::Context *context,
+ TextureStorage *storage,
+ int level);
+ virtual angle::Result setManagedSurface2DArray(const gl::Context *context,
+ TextureStorage *storage,
+ int layer,
+ int level);
+ virtual angle::Result copyToStorage(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::ImageIndex &index,
+ const gl::Box &region) = 0;
+
+ virtual angle::Result copyFromTexStorage(const gl::Context *context,
+ const gl::ImageIndex &imageIndex,
+ TextureStorage *source) = 0;
+ virtual angle::Result copyFromFramebuffer(const gl::Context *context,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) = 0;
+
+ protected:
+ GLsizei mWidth;
+ GLsizei mHeight;
+ GLsizei mDepth;
+ GLenum mInternalFormat;
+ bool mRenderable;
+ gl::TextureType mType;
+
+ bool mDirty;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_IMAGED3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexBuffer.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexBuffer.cpp
new file mode 100644
index 0000000000..423067e67e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexBuffer.cpp
@@ -0,0 +1,183 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface
+// class with derivations, classes that perform graphics API agnostic index buffer operations.
+
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/ContextD3D.h"
+
+namespace rx
+{
+
+unsigned int IndexBuffer::mNextSerial = 1;
+
+IndexBuffer::IndexBuffer()
+{
+ updateSerial();
+}
+
+IndexBuffer::~IndexBuffer() {}
+
+unsigned int IndexBuffer::getSerial() const
+{
+ return mSerial;
+}
+
+void IndexBuffer::updateSerial()
+{
+ mSerial = mNextSerial++;
+}
+
+IndexBufferInterface::IndexBufferInterface(BufferFactoryD3D *factory, bool dynamic)
+{
+ mIndexBuffer = factory->createIndexBuffer();
+
+ mDynamic = dynamic;
+ mWritePosition = 0;
+}
+
+IndexBufferInterface::~IndexBufferInterface()
+{
+ if (mIndexBuffer)
+ {
+ delete mIndexBuffer;
+ }
+}
+
+gl::DrawElementsType IndexBufferInterface::getIndexType() const
+{
+ return mIndexBuffer->getIndexType();
+}
+
+unsigned int IndexBufferInterface::getBufferSize() const
+{
+ return mIndexBuffer->getBufferSize();
+}
+
+unsigned int IndexBufferInterface::getSerial() const
+{
+ return mIndexBuffer->getSerial();
+}
+
+angle::Result IndexBufferInterface::mapBuffer(const gl::Context *context,
+ unsigned int size,
+ void **outMappedMemory,
+ unsigned int *streamOffset)
+{
+ // Protect against integer overflow
+ bool check = (mWritePosition + size < mWritePosition);
+ ANGLE_CHECK(GetImplAs<ContextD3D>(context), !check,
+ "Mapping of internal index buffer would cause an integer overflow.",
+ GL_OUT_OF_MEMORY);
+
+ angle::Result error = mIndexBuffer->mapBuffer(context, mWritePosition, size, outMappedMemory);
+ if (error == angle::Result::Stop)
+ {
+ if (outMappedMemory)
+ {
+ *outMappedMemory = nullptr;
+ }
+ return error;
+ }
+
+ if (streamOffset)
+ {
+ *streamOffset = mWritePosition;
+ }
+
+ mWritePosition += size;
+ return angle::Result::Continue;
+}
+
+angle::Result IndexBufferInterface::unmapBuffer(const gl::Context *context)
+{
+ return mIndexBuffer->unmapBuffer(context);
+}
+
+IndexBuffer *IndexBufferInterface::getIndexBuffer() const
+{
+ return mIndexBuffer;
+}
+
+unsigned int IndexBufferInterface::getWritePosition() const
+{
+ return mWritePosition;
+}
+
+void IndexBufferInterface::setWritePosition(unsigned int writePosition)
+{
+ mWritePosition = writePosition;
+}
+
+angle::Result IndexBufferInterface::discard(const gl::Context *context)
+{
+ return mIndexBuffer->discard(context);
+}
+
+angle::Result IndexBufferInterface::setBufferSize(const gl::Context *context,
+ unsigned int bufferSize,
+ gl::DrawElementsType indexType)
+{
+ if (mIndexBuffer->getBufferSize() == 0)
+ {
+ return mIndexBuffer->initialize(context, bufferSize, indexType, mDynamic);
+ }
+ else
+ {
+ return mIndexBuffer->setSize(context, bufferSize, indexType);
+ }
+}
+
+StreamingIndexBufferInterface::StreamingIndexBufferInterface(BufferFactoryD3D *factory)
+ : IndexBufferInterface(factory, true)
+{}
+
+StreamingIndexBufferInterface::~StreamingIndexBufferInterface() {}
+
+angle::Result StreamingIndexBufferInterface::reserveBufferSpace(const gl::Context *context,
+ unsigned int size,
+ gl::DrawElementsType indexType)
+{
+ unsigned int curBufferSize = getBufferSize();
+ unsigned int writePos = getWritePosition();
+ if (size > curBufferSize)
+ {
+ ANGLE_TRY(setBufferSize(context, std::max(size, 2 * curBufferSize), indexType));
+ setWritePosition(0);
+ }
+ else if (writePos + size > curBufferSize || writePos + size < writePos)
+ {
+ ANGLE_TRY(discard(context));
+ setWritePosition(0);
+ }
+
+ return angle::Result::Continue;
+}
+
+StaticIndexBufferInterface::StaticIndexBufferInterface(BufferFactoryD3D *factory)
+ : IndexBufferInterface(factory, false)
+{}
+
+StaticIndexBufferInterface::~StaticIndexBufferInterface() {}
+
+angle::Result StaticIndexBufferInterface::reserveBufferSpace(const gl::Context *context,
+ unsigned int size,
+ gl::DrawElementsType indexType)
+{
+ unsigned int curSize = getBufferSize();
+ if (curSize == 0)
+ {
+ return setBufferSize(context, size, indexType);
+ }
+
+ ASSERT(curSize >= size && indexType == getIndexType());
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexBuffer.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexBuffer.h
new file mode 100644
index 0000000000..7bab52a9f0
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexBuffer.h
@@ -0,0 +1,125 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexBuffer.h: Defines the abstract IndexBuffer class and IndexBufferInterface
+// class with derivations, classes that perform graphics API agnostic index buffer operations.
+
+#ifndef LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_
+#define LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_
+
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace rx
+{
+class BufferFactoryD3D;
+
+class IndexBuffer : angle::NonCopyable
+{
+ public:
+ IndexBuffer();
+ virtual ~IndexBuffer();
+
+ virtual angle::Result initialize(const gl::Context *context,
+ unsigned int bufferSize,
+ gl::DrawElementsType indexType,
+ bool dynamic) = 0;
+
+ virtual angle::Result mapBuffer(const gl::Context *context,
+ unsigned int offset,
+ unsigned int size,
+ void **outMappedMemory) = 0;
+ virtual angle::Result unmapBuffer(const gl::Context *context) = 0;
+
+ virtual angle::Result discard(const gl::Context *context) = 0;
+
+ virtual gl::DrawElementsType getIndexType() const = 0;
+ virtual unsigned int getBufferSize() const = 0;
+ virtual angle::Result setSize(const gl::Context *context,
+ unsigned int bufferSize,
+ gl::DrawElementsType indexType) = 0;
+
+ unsigned int getSerial() const;
+
+ protected:
+ void updateSerial();
+
+ private:
+ unsigned int mSerial;
+ static unsigned int mNextSerial;
+};
+
+class IndexBufferInterface : angle::NonCopyable
+{
+ public:
+ IndexBufferInterface(BufferFactoryD3D *factory, bool dynamic);
+ virtual ~IndexBufferInterface();
+
+ virtual angle::Result reserveBufferSpace(const gl::Context *context,
+ unsigned int size,
+ gl::DrawElementsType indexType) = 0;
+
+ gl::DrawElementsType getIndexType() const;
+ unsigned int getBufferSize() const;
+
+ unsigned int getSerial() const;
+
+ angle::Result mapBuffer(const gl::Context *context,
+ unsigned int size,
+ void **outMappedMemory,
+ unsigned int *streamOffset);
+ angle::Result unmapBuffer(const gl::Context *context);
+
+ IndexBuffer *getIndexBuffer() const;
+
+ protected:
+ unsigned int getWritePosition() const;
+ void setWritePosition(unsigned int writePosition);
+
+ angle::Result discard(const gl::Context *context);
+
+ angle::Result setBufferSize(const gl::Context *context,
+ unsigned int bufferSize,
+ gl::DrawElementsType indexType);
+
+ private:
+ IndexBuffer *mIndexBuffer;
+
+ unsigned int mWritePosition;
+ bool mDynamic;
+};
+
+class StreamingIndexBufferInterface : public IndexBufferInterface
+{
+ public:
+ explicit StreamingIndexBufferInterface(BufferFactoryD3D *factory);
+ ~StreamingIndexBufferInterface() override;
+
+ angle::Result reserveBufferSpace(const gl::Context *context,
+ unsigned int size,
+ gl::DrawElementsType indexType) override;
+};
+
+class StaticIndexBufferInterface : public IndexBufferInterface
+{
+ public:
+ explicit StaticIndexBufferInterface(BufferFactoryD3D *factory);
+ ~StaticIndexBufferInterface() override;
+
+ angle::Result reserveBufferSpace(const gl::Context *context,
+ unsigned int size,
+ gl::DrawElementsType indexType) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexDataManager.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexDataManager.cpp
new file mode 100644
index 0000000000..dd8f45342f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexDataManager.cpp
@@ -0,0 +1,318 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexDataManager.cpp: Defines the IndexDataManager, a class that
+// runs the Buffer translation process for index buffers.
+
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/ContextD3D.h"
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+
+namespace rx
+{
+
+namespace
+{
+
+template <typename InputT, typename DestT>
+void ConvertIndexArray(const void *input,
+ gl::DrawElementsType sourceType,
+ void *output,
+ gl::DrawElementsType destinationType,
+ GLsizei count,
+ bool usePrimitiveRestartFixedIndex)
+{
+ const InputT *in = static_cast<const InputT *>(input);
+ DestT *out = static_cast<DestT *>(output);
+
+ if (usePrimitiveRestartFixedIndex)
+ {
+ InputT srcRestartIndex = static_cast<InputT>(gl::GetPrimitiveRestartIndex(sourceType));
+ DestT destRestartIndex = static_cast<DestT>(gl::GetPrimitiveRestartIndex(destinationType));
+ for (GLsizei i = 0; i < count; i++)
+ {
+ out[i] = (in[i] == srcRestartIndex ? destRestartIndex : static_cast<DestT>(in[i]));
+ }
+ }
+ else
+ {
+ for (GLsizei i = 0; i < count; i++)
+ {
+ out[i] = static_cast<DestT>(in[i]);
+ }
+ }
+}
+
+void ConvertIndices(gl::DrawElementsType sourceType,
+ gl::DrawElementsType destinationType,
+ const void *input,
+ GLsizei count,
+ void *output,
+ bool usePrimitiveRestartFixedIndex)
+{
+ if (sourceType == destinationType)
+ {
+ const GLuint dstTypeSize = gl::GetDrawElementsTypeSize(destinationType);
+ memcpy(output, input, count * dstTypeSize);
+ return;
+ }
+
+ if (sourceType == gl::DrawElementsType::UnsignedByte)
+ {
+ ASSERT(destinationType == gl::DrawElementsType::UnsignedShort);
+ ConvertIndexArray<GLubyte, GLushort>(input, sourceType, output, destinationType, count,
+ usePrimitiveRestartFixedIndex);
+ }
+ else if (sourceType == gl::DrawElementsType::UnsignedShort)
+ {
+ ASSERT(destinationType == gl::DrawElementsType::UnsignedInt);
+ ConvertIndexArray<GLushort, GLuint>(input, sourceType, output, destinationType, count,
+ usePrimitiveRestartFixedIndex);
+ }
+ else
+ UNREACHABLE();
+}
+
+angle::Result StreamInIndexBuffer(const gl::Context *context,
+ IndexBufferInterface *buffer,
+ const void *data,
+ unsigned int count,
+ gl::DrawElementsType srcType,
+ gl::DrawElementsType dstType,
+ bool usePrimitiveRestartFixedIndex,
+ unsigned int *offset)
+{
+ const GLuint dstTypeBytesShift = gl::GetDrawElementsTypeShift(dstType);
+
+ bool check = (count > (std::numeric_limits<unsigned int>::max() >> dstTypeBytesShift));
+ ANGLE_CHECK(GetImplAs<ContextD3D>(context), !check,
+ "Reserving indices exceeds the maximum buffer size.", GL_OUT_OF_MEMORY);
+
+ unsigned int bufferSizeRequired = count << dstTypeBytesShift;
+ ANGLE_TRY(buffer->reserveBufferSpace(context, bufferSizeRequired, dstType));
+
+ void *output = nullptr;
+ ANGLE_TRY(buffer->mapBuffer(context, bufferSizeRequired, &output, offset));
+
+ ConvertIndices(srcType, dstType, data, count, output, usePrimitiveRestartFixedIndex);
+
+ ANGLE_TRY(buffer->unmapBuffer(context));
+ return angle::Result::Continue;
+}
+} // anonymous namespace
+
+// IndexDataManager implementation.
+IndexDataManager::IndexDataManager(BufferFactoryD3D *factory)
+ : mFactory(factory), mStreamingBufferShort(), mStreamingBufferInt()
+{}
+
+IndexDataManager::~IndexDataManager() {}
+
+void IndexDataManager::deinitialize()
+{
+ mStreamingBufferShort.reset();
+ mStreamingBufferInt.reset();
+}
+
+// This function translates a GL-style indices into DX-style indices, with their description
+// returned in translated.
+// GL can specify vertex data in immediate mode (pointer to CPU array of indices), which is not
+// possible in DX and requires streaming (Case 1). If the GL indices are specified with a buffer
+// (Case 2), in a format supported by DX (subcase a) then all is good.
+// When we have a buffer with an unsupported format (subcase b) then we need to do some translation:
+// we will start by falling back to streaming, and after a while will start using a static
+// translated copy of the index buffer.
+angle::Result IndexDataManager::prepareIndexData(const gl::Context *context,
+ gl::DrawElementsType srcType,
+ gl::DrawElementsType dstType,
+ GLsizei count,
+ gl::Buffer *glBuffer,
+ const void *indices,
+ TranslatedIndexData *translated)
+{
+ GLuint srcTypeBytes = gl::GetDrawElementsTypeSize(srcType);
+ GLuint srcTypeShift = gl::GetDrawElementsTypeShift(srcType);
+ GLuint dstTypeShift = gl::GetDrawElementsTypeShift(dstType);
+
+ BufferD3D *buffer = glBuffer ? GetImplAs<BufferD3D>(glBuffer) : nullptr;
+
+ translated->indexType = dstType;
+ translated->srcIndexData.srcBuffer = buffer;
+ translated->srcIndexData.srcIndices = indices;
+ translated->srcIndexData.srcIndexType = srcType;
+ translated->srcIndexData.srcCount = count;
+
+ // Context can be nullptr in perf tests.
+ bool primitiveRestartFixedIndexEnabled =
+ context ? context->getState().isPrimitiveRestartEnabled() : false;
+
+ // Case 1: the indices are passed by pointer, which forces the streaming of index data
+ if (glBuffer == nullptr)
+ {
+ translated->storage = nullptr;
+ return streamIndexData(context, indices, count, srcType, dstType,
+ primitiveRestartFixedIndexEnabled, translated);
+ }
+
+ // Case 2: the indices are already in a buffer
+ unsigned int offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices));
+ ASSERT(srcTypeBytes * static_cast<unsigned int>(count) + offset <= buffer->getSize());
+
+ bool offsetAligned = IsOffsetAligned(srcType, offset);
+
+ // Case 2a: the buffer can be used directly
+ if (offsetAligned && buffer->supportsDirectBinding() && dstType == srcType)
+ {
+ translated->storage = buffer;
+ translated->indexBuffer = nullptr;
+ translated->serial = buffer->getSerial();
+ translated->startIndex = (offset >> srcTypeShift);
+ translated->startOffset = offset;
+ return angle::Result::Continue;
+ }
+
+ translated->storage = nullptr;
+
+ // Case 2b: use a static translated copy or fall back to streaming
+ StaticIndexBufferInterface *staticBuffer = buffer->getStaticIndexBuffer();
+
+ bool staticBufferInitialized = staticBuffer && staticBuffer->getBufferSize() != 0;
+ bool staticBufferUsable =
+ staticBuffer && offsetAligned && staticBuffer->getIndexType() == dstType;
+
+ if (staticBufferInitialized && !staticBufferUsable)
+ {
+ buffer->invalidateStaticData(context);
+ staticBuffer = nullptr;
+ }
+
+ if (staticBuffer == nullptr || !offsetAligned)
+ {
+ const uint8_t *bufferData = nullptr;
+ ANGLE_TRY(buffer->getData(context, &bufferData));
+ ASSERT(bufferData != nullptr);
+
+ ANGLE_TRY(streamIndexData(context, bufferData + offset, count, srcType, dstType,
+ primitiveRestartFixedIndexEnabled, translated));
+ buffer->promoteStaticUsage(context, count << srcTypeShift);
+ }
+ else
+ {
+ if (!staticBufferInitialized)
+ {
+ const uint8_t *bufferData = nullptr;
+ ANGLE_TRY(buffer->getData(context, &bufferData));
+ ASSERT(bufferData != nullptr);
+
+ unsigned int convertCount =
+ static_cast<unsigned int>(buffer->getSize()) >> srcTypeShift;
+ ANGLE_TRY(StreamInIndexBuffer(context, staticBuffer, bufferData, convertCount, srcType,
+ dstType, primitiveRestartFixedIndexEnabled, nullptr));
+ }
+ ASSERT(offsetAligned && staticBuffer->getIndexType() == dstType);
+
+ translated->indexBuffer = staticBuffer->getIndexBuffer();
+ translated->serial = staticBuffer->getSerial();
+ translated->startIndex = (offset >> srcTypeShift);
+ translated->startOffset = (offset >> srcTypeShift) << dstTypeShift;
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result IndexDataManager::streamIndexData(const gl::Context *context,
+ const void *data,
+ unsigned int count,
+ gl::DrawElementsType srcType,
+ gl::DrawElementsType dstType,
+ bool usePrimitiveRestartFixedIndex,
+ TranslatedIndexData *translated)
+{
+ const GLuint dstTypeShift = gl::GetDrawElementsTypeShift(dstType);
+
+ IndexBufferInterface *indexBuffer = nullptr;
+ ANGLE_TRY(getStreamingIndexBuffer(context, dstType, &indexBuffer));
+ ASSERT(indexBuffer != nullptr);
+
+ unsigned int offset;
+ ANGLE_TRY(StreamInIndexBuffer(context, indexBuffer, data, count, srcType, dstType,
+ usePrimitiveRestartFixedIndex, &offset));
+
+ translated->indexBuffer = indexBuffer->getIndexBuffer();
+ translated->serial = indexBuffer->getSerial();
+ translated->startIndex = (offset >> dstTypeShift);
+ translated->startOffset = offset;
+
+ return angle::Result::Continue;
+}
+
+angle::Result IndexDataManager::getStreamingIndexBuffer(const gl::Context *context,
+ gl::DrawElementsType destinationIndexType,
+ IndexBufferInterface **outBuffer)
+{
+ ASSERT(outBuffer);
+ ASSERT(destinationIndexType == gl::DrawElementsType::UnsignedShort ||
+ destinationIndexType == gl::DrawElementsType::UnsignedInt);
+
+ auto &streamingBuffer = (destinationIndexType == gl::DrawElementsType::UnsignedInt)
+ ? mStreamingBufferInt
+ : mStreamingBufferShort;
+
+ if (!streamingBuffer)
+ {
+ StreamingBuffer newBuffer(new StreamingIndexBufferInterface(mFactory));
+ ANGLE_TRY(newBuffer->reserveBufferSpace(context, INITIAL_INDEX_BUFFER_SIZE,
+ destinationIndexType));
+ streamingBuffer = std::move(newBuffer);
+ }
+
+ *outBuffer = streamingBuffer.get();
+ return angle::Result::Continue;
+}
+
+angle::Result GetIndexTranslationDestType(const gl::Context *context,
+ GLsizei indexCount,
+ gl::DrawElementsType indexType,
+ const void *indices,
+ bool usePrimitiveRestartWorkaround,
+ gl::DrawElementsType *destTypeOut)
+{
+ // Avoid D3D11's primitive restart index value
+ // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx
+ if (usePrimitiveRestartWorkaround)
+ {
+ // Conservatively assume we need to translate the indices for draw indirect.
+ // This is a bit of a trick. We assume the count for an indirect draw is zero.
+ if (indexCount == 0)
+ {
+ *destTypeOut = gl::DrawElementsType::UnsignedInt;
+ return angle::Result::Continue;
+ }
+
+ gl::IndexRange indexRange;
+ ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(
+ context, indexType, indexCount, indices, &indexRange));
+ if (indexRange.end == gl::GetPrimitiveRestartIndex(indexType))
+ {
+ *destTypeOut = gl::DrawElementsType::UnsignedInt;
+ return angle::Result::Continue;
+ }
+ }
+
+ *destTypeOut = (indexType == gl::DrawElementsType::UnsignedInt)
+ ? gl::DrawElementsType::UnsignedInt
+ : gl::DrawElementsType::UnsignedShort;
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexDataManager.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexDataManager.h
new file mode 100644
index 0000000000..53bfc721da
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/IndexDataManager.h
@@ -0,0 +1,112 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexDataManager.h: Defines the IndexDataManager, a class that
+// runs the Buffer translation process for index buffers.
+
+#ifndef LIBANGLE_INDEXDATAMANAGER_H_
+#define LIBANGLE_INDEXDATAMANAGER_H_
+
+#include <GLES2/gl2.h>
+
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace
+{
+enum
+{
+ INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint)
+};
+}
+
+namespace gl
+{
+class Buffer;
+}
+
+namespace rx
+{
+class IndexBufferInterface;
+class StaticIndexBufferInterface;
+class StreamingIndexBufferInterface;
+class IndexBuffer;
+class BufferD3D;
+class RendererD3D;
+
+struct SourceIndexData
+{
+ BufferD3D *srcBuffer;
+ const void *srcIndices;
+ unsigned int srcCount;
+ gl::DrawElementsType srcIndexType;
+ bool srcIndicesChanged;
+};
+
+struct TranslatedIndexData
+{
+ unsigned int startIndex;
+ unsigned int startOffset; // In bytes
+
+ IndexBuffer *indexBuffer;
+ BufferD3D *storage;
+ gl::DrawElementsType indexType;
+ unsigned int serial;
+
+ SourceIndexData srcIndexData;
+};
+
+class IndexDataManager : angle::NonCopyable
+{
+ public:
+ explicit IndexDataManager(BufferFactoryD3D *factory);
+ virtual ~IndexDataManager();
+
+ void deinitialize();
+
+ angle::Result prepareIndexData(const gl::Context *context,
+ gl::DrawElementsType srcType,
+ gl::DrawElementsType dstType,
+ GLsizei count,
+ gl::Buffer *glBuffer,
+ const void *indices,
+ TranslatedIndexData *translated);
+
+ private:
+ angle::Result streamIndexData(const gl::Context *context,
+ const void *data,
+ unsigned int count,
+ gl::DrawElementsType srcType,
+ gl::DrawElementsType dstType,
+ bool usePrimitiveRestartFixedIndex,
+ TranslatedIndexData *translated);
+ angle::Result getStreamingIndexBuffer(const gl::Context *context,
+ gl::DrawElementsType destinationIndexType,
+ IndexBufferInterface **outBuffer);
+
+ using StreamingBuffer = std::unique_ptr<StreamingIndexBufferInterface>;
+
+ BufferFactoryD3D *const mFactory;
+ std::unique_ptr<StreamingIndexBufferInterface> mStreamingBufferShort;
+ std::unique_ptr<StreamingIndexBufferInterface> mStreamingBufferInt;
+};
+
+angle::Result GetIndexTranslationDestType(const gl::Context *context,
+ GLsizei indexCount,
+ gl::DrawElementsType indexType,
+ const void *indices,
+ bool usePrimitiveRestartWorkaround,
+ gl::DrawElementsType *destTypeOut);
+
+ANGLE_INLINE bool IsOffsetAligned(gl::DrawElementsType elementType, unsigned int offset)
+{
+ return (offset % gl::GetDrawElementsTypeSize(elementType) == 0);
+}
+} // namespace rx
+
+#endif // LIBANGLE_INDEXDATAMANAGER_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp
new file mode 100644
index 0000000000..a8543a06d7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/NativeWindowD3D.cpp
@@ -0,0 +1,19 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindowD3D.cpp: Defines NativeWindowD3D, a class for managing and performing operations on
+// an EGLNativeWindowType for the D3D renderers.
+
+#include "libANGLE/renderer/d3d/NativeWindowD3D.h"
+
+namespace rx
+{
+
+NativeWindowD3D::NativeWindowD3D(EGLNativeWindowType window) : mWindow(window) {}
+
+NativeWindowD3D::~NativeWindowD3D() {}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/NativeWindowD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/NativeWindowD3D.h
new file mode 100644
index 0000000000..8560f16bde
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/NativeWindowD3D.h
@@ -0,0 +1,38 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindowD3D.h: Defines NativeWindowD3D, a class for managing and performing operations on an
+// EGLNativeWindowType for the D3D renderers.
+
+#ifndef LIBANGLE_RENDERER_D3D_NATIVEWINDOWD3D_H_
+#define LIBANGLE_RENDERER_D3D_NATIVEWINDOWD3D_H_
+
+#include "common/debug.h"
+#include "common/platform.h"
+
+#include <EGL/eglplatform.h>
+#include "libANGLE/Config.h"
+
+namespace rx
+{
+class NativeWindowD3D : angle::NonCopyable
+{
+ public:
+ NativeWindowD3D(EGLNativeWindowType window);
+ virtual ~NativeWindowD3D();
+
+ virtual bool initialize() = 0;
+ virtual bool getClientRect(LPRECT rect) const = 0;
+ virtual bool isIconic() const = 0;
+
+ inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
+
+ private:
+ EGLNativeWindowType mWindow;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_NATIVEWINDOWD3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ProgramD3D.cpp
new file mode 100644
index 0000000000..b38ede4133
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -0,0 +1,3412 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
+
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+
+#include "common/MemoryBuffer.h"
+#include "common/bitset_utils.h"
+#include "common/string_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/ProgramLinkedResources.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/features.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/d3d/ContextD3D.h"
+#include "libANGLE/renderer/d3d/DynamicHLSL.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+#include "libANGLE/renderer/renderer_utils.h"
+#include "libANGLE/trace.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace
+{
+
+void GetDefaultInputLayoutFromShader(const gl::Context *context,
+ gl::Shader *vertexShader,
+ gl::InputLayout *inputLayoutOut)
+{
+ inputLayoutOut->clear();
+
+ if (!vertexShader)
+ {
+ return;
+ }
+
+ for (const sh::ShaderVariable &shaderAttr : vertexShader->getActiveAttributes(context))
+ {
+ if (shaderAttr.type != GL_NONE)
+ {
+ GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type);
+
+ for (size_t rowIndex = 0;
+ static_cast<int>(rowIndex) < gl::VariableRowCount(transposedType); ++rowIndex)
+ {
+ GLenum componentType = gl::VariableComponentType(transposedType);
+ GLuint components = static_cast<GLuint>(gl::VariableColumnCount(transposedType));
+ bool pureInt = (componentType != GL_FLOAT);
+
+ gl::VertexAttribType attribType =
+ gl::FromGLenum<gl::VertexAttribType>(componentType);
+
+ angle::FormatID defaultID =
+ gl::GetVertexFormatID(attribType, GL_FALSE, components, pureInt);
+
+ inputLayoutOut->push_back(defaultID);
+ }
+ }
+ }
+}
+
+size_t GetMaxOutputIndex(const std::vector<PixelShaderOutputVariable> &shaderOutputVars,
+ size_t location)
+{
+ size_t maxIndex = 0;
+ for (auto &outputVar : shaderOutputVars)
+ {
+ if (outputVar.outputLocation == location)
+ {
+ maxIndex = std::max(maxIndex, outputVar.outputIndex);
+ }
+ }
+ return maxIndex;
+}
+
+void GetDefaultOutputLayoutFromShader(
+ const std::vector<PixelShaderOutputVariable> &shaderOutputVars,
+ std::vector<GLenum> *outputLayoutOut)
+{
+ outputLayoutOut->clear();
+
+ if (!shaderOutputVars.empty())
+ {
+ size_t location = shaderOutputVars[0].outputLocation;
+ size_t maxIndex = GetMaxOutputIndex(shaderOutputVars, location);
+ outputLayoutOut->assign(maxIndex + 1,
+ GL_COLOR_ATTACHMENT0 + static_cast<unsigned int>(location));
+ }
+}
+
+void GetDefaultImage2DBindLayoutFromShader(const std::vector<sh::ShaderVariable> &image2DUniforms,
+ gl::ImageUnitTextureTypeMap *image2DBindLayout)
+{
+ image2DBindLayout->clear();
+
+ for (const sh::ShaderVariable &image2D : image2DUniforms)
+ {
+ if (gl::IsImage2DType(image2D.type))
+ {
+ if (image2D.binding == -1)
+ {
+ image2DBindLayout->insert(std::make_pair(0, gl::TextureType::_2D));
+ }
+ else
+ {
+ for (unsigned int index = 0; index < image2D.getArraySizeProduct(); index++)
+ {
+ image2DBindLayout->insert(
+ std::make_pair(image2D.binding + index, gl::TextureType::_2D));
+ }
+ }
+ }
+ }
+}
+
+gl::PrimitiveMode GetGeometryShaderTypeFromDrawMode(gl::PrimitiveMode drawMode)
+{
+ switch (drawMode)
+ {
+ // Uses the point sprite geometry shader.
+ case gl::PrimitiveMode::Points:
+ return gl::PrimitiveMode::Points;
+
+ // All line drawing uses the same geometry shader.
+ case gl::PrimitiveMode::Lines:
+ case gl::PrimitiveMode::LineStrip:
+ case gl::PrimitiveMode::LineLoop:
+ return gl::PrimitiveMode::Lines;
+
+ // The triangle fan primitive is emulated with strips in D3D11.
+ case gl::PrimitiveMode::Triangles:
+ case gl::PrimitiveMode::TriangleFan:
+ return gl::PrimitiveMode::Triangles;
+
+ // Special case for triangle strips.
+ case gl::PrimitiveMode::TriangleStrip:
+ return gl::PrimitiveMode::TriangleStrip;
+
+ default:
+ UNREACHABLE();
+ return gl::PrimitiveMode::InvalidEnum;
+ }
+}
+
+bool HasFlatInterpolationVarying(const std::vector<sh::ShaderVariable> &varyings)
+{
+ // Note: this assumes nested structs can only be packed with one interpolation.
+ for (const auto &varying : varyings)
+ {
+ if (varying.interpolation == sh::INTERPOLATION_FLAT)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool FindFlatInterpolationVaryingPerShader(const gl::Context *context, gl::Shader *shader)
+{
+ ASSERT(shader);
+ switch (shader->getType())
+ {
+ case gl::ShaderType::Vertex:
+ return HasFlatInterpolationVarying(shader->getOutputVaryings(context));
+ case gl::ShaderType::Fragment:
+ return HasFlatInterpolationVarying(shader->getInputVaryings(context));
+ case gl::ShaderType::Geometry:
+ return HasFlatInterpolationVarying(shader->getInputVaryings(context)) ||
+ HasFlatInterpolationVarying(shader->getOutputVaryings(context));
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool FindFlatInterpolationVarying(const gl::Context *context,
+ const gl::ShaderMap<gl::Shader *> &shaders)
+{
+ for (gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
+ {
+ gl::Shader *shader = shaders[shaderType];
+ if (!shader)
+ {
+ continue;
+ }
+
+ if (FindFlatInterpolationVaryingPerShader(context, shader))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Helper class that gathers uniform info from the default uniform block.
+class UniformEncodingVisitorD3D : public sh::BlockEncoderVisitor
+{
+ public:
+ UniformEncodingVisitorD3D(gl::ShaderType shaderType,
+ HLSLRegisterType registerType,
+ sh::BlockLayoutEncoder *encoder,
+ D3DUniformMap *uniformMapOut)
+ : sh::BlockEncoderVisitor("", "", encoder),
+ mShaderType(shaderType),
+ mRegisterType(registerType),
+ mUniformMapOut(uniformMapOut)
+ {}
+
+ void visitNamedOpaqueObject(const sh::ShaderVariable &sampler,
+ const std::string &name,
+ const std::string &mappedName,
+ const std::vector<unsigned int> &arraySizes) override
+ {
+ auto uniformMapEntry = mUniformMapOut->find(name);
+ if (uniformMapEntry == mUniformMapOut->end())
+ {
+ (*mUniformMapOut)[name] =
+ new D3DUniform(sampler.type, mRegisterType, name, sampler.arraySizes, true);
+ }
+ }
+
+ void encodeVariable(const sh::ShaderVariable &variable,
+ const sh::BlockMemberInfo &variableInfo,
+ const std::string &name,
+ const std::string &mappedName) override
+ {
+ auto uniformMapEntry = mUniformMapOut->find(name);
+ D3DUniform *d3dUniform = nullptr;
+
+ if (uniformMapEntry != mUniformMapOut->end())
+ {
+ d3dUniform = uniformMapEntry->second;
+ }
+ else
+ {
+ d3dUniform =
+ new D3DUniform(variable.type, mRegisterType, name, variable.arraySizes, true);
+ (*mUniformMapOut)[name] = d3dUniform;
+ }
+
+ d3dUniform->registerElement = static_cast<unsigned int>(
+ sh::BlockLayoutEncoder::GetBlockRegisterElement(variableInfo));
+ unsigned int reg =
+ static_cast<unsigned int>(sh::BlockLayoutEncoder::GetBlockRegister(variableInfo));
+
+ ASSERT(mShaderType != gl::ShaderType::InvalidEnum);
+ d3dUniform->mShaderRegisterIndexes[mShaderType] = reg;
+ }
+
+ private:
+ gl::ShaderType mShaderType;
+ HLSLRegisterType mRegisterType;
+ D3DUniformMap *mUniformMapOut;
+};
+
+class HLSLBlockLayoutEncoderFactory : public gl::CustomBlockLayoutEncoderFactory
+{
+ public:
+ sh::BlockLayoutEncoder *makeEncoder() override
+ {
+ return new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED, false);
+ }
+};
+} // anonymous namespace
+
+// D3DUniform Implementation
+
+D3DUniform::D3DUniform(GLenum type,
+ HLSLRegisterType reg,
+ const std::string &nameIn,
+ const std::vector<unsigned int> &arraySizesIn,
+ bool defaultBlock)
+ : typeInfo(gl::GetUniformTypeInfo(type)),
+ name(nameIn),
+ arraySizes(arraySizesIn),
+ mShaderData({}),
+ regType(reg),
+ registerCount(0),
+ registerElement(0)
+{
+ mShaderRegisterIndexes.fill(GL_INVALID_INDEX);
+
+ // We use data storage for default block uniforms to cache values that are sent to D3D during
+ // rendering
+ // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only)
+ if (defaultBlock)
+ {
+ // Use the row count as register count, will work for non-square matrices.
+ registerCount = typeInfo.rowCount * getArraySizeProduct();
+ }
+}
+
+D3DUniform::~D3DUniform() {}
+
+unsigned int D3DUniform::getArraySizeProduct() const
+{
+ return gl::ArraySizeProduct(arraySizes);
+}
+
+const uint8_t *D3DUniform::getDataPtrToElement(size_t elementIndex) const
+{
+ ASSERT((!isArray() && elementIndex == 0) ||
+ (isArray() && elementIndex < getArraySizeProduct()));
+
+ if (isSampler())
+ {
+ return reinterpret_cast<const uint8_t *>(&mSamplerData[elementIndex]);
+ }
+
+ return firstNonNullData() + (elementIndex > 0 ? (typeInfo.internalSize * elementIndex) : 0u);
+}
+
+bool D3DUniform::isSampler() const
+{
+ return typeInfo.isSampler;
+}
+
+bool D3DUniform::isImage() const
+{
+ return typeInfo.isImageType;
+}
+
+bool D3DUniform::isImage2D() const
+{
+ return gl::IsImage2DType(typeInfo.type);
+}
+
+bool D3DUniform::isReferencedByShader(gl::ShaderType shaderType) const
+{
+ return mShaderRegisterIndexes[shaderType] != GL_INVALID_INDEX;
+}
+
+const uint8_t *D3DUniform::firstNonNullData() const
+{
+ if (!mSamplerData.empty())
+ {
+ return reinterpret_cast<const uint8_t *>(mSamplerData.data());
+ }
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ if (mShaderData[shaderType])
+ {
+ return mShaderData[shaderType];
+ }
+ }
+
+ UNREACHABLE();
+ return nullptr;
+}
+
+// D3DInterfaceBlock Implementation
+D3DInterfaceBlock::D3DInterfaceBlock()
+{
+ mShaderRegisterIndexes.fill(GL_INVALID_INDEX);
+}
+
+D3DInterfaceBlock::D3DInterfaceBlock(const D3DInterfaceBlock &other) = default;
+
+D3DUniformBlock::D3DUniformBlock()
+{
+ mUseStructuredBuffers.fill(false);
+ mByteWidths.fill(0u);
+ mStructureByteStrides.fill(0u);
+}
+
+D3DUniformBlock::D3DUniformBlock(const D3DUniformBlock &other) = default;
+
+// D3DVarying Implementation
+
+D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0) {}
+
+D3DVarying::D3DVarying(const std::string &semanticNameIn,
+ unsigned int semanticIndexIn,
+ unsigned int componentCountIn,
+ unsigned int outputSlotIn)
+ : semanticName(semanticNameIn),
+ semanticIndex(semanticIndexIn),
+ componentCount(componentCountIn),
+ outputSlot(outputSlotIn)
+{}
+
+// ProgramD3DMetadata Implementation
+
+ProgramD3DMetadata::ProgramD3DMetadata(RendererD3D *renderer,
+ const gl::ShaderMap<const ShaderD3D *> &attachedShaders,
+ EGLenum clientType)
+ : mRendererMajorShaderModel(renderer->getMajorShaderModel()),
+ mShaderModelSuffix(renderer->getShaderModelSuffix()),
+ mUsesInstancedPointSpriteEmulation(
+ renderer->getFeatures().useInstancedPointSpriteEmulation.enabled),
+ mUsesViewScale(renderer->presentPathFastEnabled()),
+ mCanSelectViewInVertexShader(renderer->canSelectViewInVertexShader()),
+ mAttachedShaders(attachedShaders),
+ mClientType(clientType)
+{}
+
+ProgramD3DMetadata::~ProgramD3DMetadata() = default;
+
+int ProgramD3DMetadata::getRendererMajorShaderModel() const
+{
+ return mRendererMajorShaderModel;
+}
+
+bool ProgramD3DMetadata::usesBroadcast(const gl::State &data) const
+{
+ const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Fragment];
+ return (shader && shader->usesFragColor() && shader->usesMultipleRenderTargets() &&
+ data.getClientMajorVersion() < 3);
+}
+
+bool ProgramD3DMetadata::usesSecondaryColor() const
+{
+ const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Fragment];
+ return (shader && shader->usesSecondaryColor());
+}
+
+bool ProgramD3DMetadata::usesFragDepth() const
+{
+ const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Fragment];
+ return (shader && shader->usesFragDepth());
+}
+
+bool ProgramD3DMetadata::usesPointCoord() const
+{
+ const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Fragment];
+ return (shader && shader->usesPointCoord());
+}
+
+bool ProgramD3DMetadata::usesFragCoord() const
+{
+ const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Fragment];
+ return (shader && shader->usesFragCoord());
+}
+
+bool ProgramD3DMetadata::usesPointSize() const
+{
+ const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Vertex];
+ return (shader && shader->usesPointSize());
+}
+
+bool ProgramD3DMetadata::usesInsertedPointCoordValue() const
+{
+ return (!usesPointSize() || !mUsesInstancedPointSpriteEmulation) && usesPointCoord() &&
+ mRendererMajorShaderModel >= 4;
+}
+
+bool ProgramD3DMetadata::usesViewScale() const
+{
+ return mUsesViewScale;
+}
+
+bool ProgramD3DMetadata::hasANGLEMultiviewEnabled() const
+{
+ const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Vertex];
+ return (shader && shader->hasANGLEMultiviewEnabled());
+}
+
+bool ProgramD3DMetadata::usesVertexID() const
+{
+ const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Vertex];
+ return (shader && shader->usesVertexID());
+}
+
+bool ProgramD3DMetadata::usesViewID() const
+{
+ const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Fragment];
+ return (shader && shader->usesViewID());
+}
+
+bool ProgramD3DMetadata::canSelectViewInVertexShader() const
+{
+ return mCanSelectViewInVertexShader;
+}
+
+bool ProgramD3DMetadata::addsPointCoordToVertexShader() const
+{
+ // PointSprite emulation requiress that gl_PointCoord is present in the vertex shader
+ // VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
+ // Even with a geometry shader, the app can render triangles or lines and reference
+ // gl_PointCoord in the fragment shader, requiring us to provide a placeholder value. For
+ // simplicity, we always add this to the vertex shader when the fragment shader
+ // references gl_PointCoord, even if we could skip it in the geometry shader.
+ return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) ||
+ usesInsertedPointCoordValue();
+}
+
+bool ProgramD3DMetadata::usesTransformFeedbackGLPosition() const
+{
+ // gl_Position only needs to be outputted from the vertex shader if transform feedback is
+ // active. This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from
+ // the vertex shader in this case. This saves us 1 output vector.
+ return !(mRendererMajorShaderModel >= 4 && mShaderModelSuffix != "");
+}
+
+bool ProgramD3DMetadata::usesSystemValuePointSize() const
+{
+ return !mUsesInstancedPointSpriteEmulation && usesPointSize();
+}
+
+bool ProgramD3DMetadata::usesMultipleFragmentOuts() const
+{
+ const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Fragment];
+ return (shader && shader->usesMultipleRenderTargets());
+}
+
+bool ProgramD3DMetadata::usesCustomOutVars() const
+{
+
+ const rx::ShaderD3D *shader = mAttachedShaders[gl::ShaderType::Vertex];
+ int version = shader ? shader->getState().getShaderVersion() : -1;
+
+ switch (mClientType)
+ {
+ case EGL_OPENGL_API:
+ return version >= 130;
+ default:
+ return version >= 300;
+ }
+}
+
+const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const
+{
+ return mAttachedShaders[gl::ShaderType::Fragment];
+}
+
+// ProgramD3D::GetExecutableTask class
+class ProgramD3D::GetExecutableTask : public Closure, public d3d::Context
+{
+ public:
+ GetExecutableTask(const gl::Context *context, ProgramD3D *program)
+ : mProgram(program), mContext(context)
+ {}
+
+ virtual angle::Result run() = 0;
+
+ void operator()() override { mResult = run(); }
+
+ angle::Result getResult() const { return mResult; }
+ const gl::InfoLog &getInfoLog() const { return mInfoLog; }
+ ShaderExecutableD3D *getExecutable() { return mExecutable; }
+
+ void handleResult(HRESULT hr,
+ const char *message,
+ const char *file,
+ const char *function,
+ unsigned int line) override
+ {
+ mStoredHR = hr;
+ mStoredMessage = message;
+ mStoredFile = file;
+ mStoredFunction = function;
+ mStoredLine = line;
+ }
+
+ void popError(d3d::Context *context)
+ {
+ ASSERT(mStoredFile);
+ ASSERT(mStoredFunction);
+ context->handleResult(mStoredHR, mStoredMessage.c_str(), mStoredFile, mStoredFunction,
+ mStoredLine);
+ }
+
+ protected:
+ ProgramD3D *mProgram = nullptr;
+ angle::Result mResult = angle::Result::Continue;
+ gl::InfoLog mInfoLog;
+ ShaderExecutableD3D *mExecutable = nullptr;
+ HRESULT mStoredHR = S_OK;
+ std::string mStoredMessage;
+ const char *mStoredFile = nullptr;
+ const char *mStoredFunction = nullptr;
+ unsigned int mStoredLine = 0;
+ const gl::Context *mContext = nullptr;
+};
+
+// ProgramD3D Implementation
+
+ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
+ const Signature &signature,
+ ShaderExecutableD3D *shaderExecutable)
+ : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable)
+{}
+
+ProgramD3D::VertexExecutable::~VertexExecutable()
+{
+ SafeDelete(mShaderExecutable);
+}
+
+// static
+ProgramD3D::VertexExecutable::HLSLAttribType ProgramD3D::VertexExecutable::GetAttribType(
+ GLenum type)
+{
+ switch (type)
+ {
+ case GL_INT:
+ return HLSLAttribType::SIGNED_INT;
+ case GL_UNSIGNED_INT:
+ return HLSLAttribType::UNSIGNED_INT;
+ case GL_SIGNED_NORMALIZED:
+ case GL_UNSIGNED_NORMALIZED:
+ case GL_FLOAT:
+ return HLSLAttribType::FLOAT;
+ default:
+ UNREACHABLE();
+ return HLSLAttribType::FLOAT;
+ }
+}
+
+// static
+void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer,
+ const gl::InputLayout &inputLayout,
+ Signature *signatureOut)
+{
+ signatureOut->assign(inputLayout.size(), HLSLAttribType::FLOAT);
+
+ for (size_t index = 0; index < inputLayout.size(); ++index)
+ {
+ angle::FormatID vertexFormatID = inputLayout[index];
+ if (vertexFormatID == angle::FormatID::NONE)
+ continue;
+
+ VertexConversionType conversionType = renderer->getVertexConversionType(vertexFormatID);
+ if ((conversionType & VERTEX_CONVERT_GPU) == 0)
+ continue;
+
+ GLenum componentType = renderer->getVertexComponentType(vertexFormatID);
+ (*signatureOut)[index] = GetAttribType(componentType);
+ }
+}
+
+bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const
+{
+ size_t limit = std::max(mSignature.size(), signature.size());
+ for (size_t index = 0; index < limit; ++index)
+ {
+ // treat undefined indexes as FLOAT
+ auto a = index < signature.size() ? signature[index] : HLSLAttribType::FLOAT;
+ auto b = index < mSignature.size() ? mSignature[index] : HLSLAttribType::FLOAT;
+ if (a != b)
+ return false;
+ }
+
+ return true;
+}
+
+ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature,
+ ShaderExecutableD3D *shaderExecutable)
+ : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable)
+{}
+
+ProgramD3D::PixelExecutable::~PixelExecutable()
+{
+ SafeDelete(mShaderExecutable);
+}
+
+ProgramD3D::ComputeExecutable::ComputeExecutable(
+ const gl::ImageUnitTextureTypeMap &signature,
+ std::unique_ptr<ShaderExecutableD3D> shaderExecutable)
+ : mSignature(signature), mShaderExecutable(std::move(shaderExecutable))
+{}
+
+ProgramD3D::ComputeExecutable::~ComputeExecutable() {}
+
+ProgramD3D::Sampler::Sampler()
+ : active(false), logicalTextureUnit(0), textureType(gl::TextureType::_2D)
+{}
+
+ProgramD3D::Image::Image() : active(false), logicalImageUnit(0) {}
+
+unsigned int ProgramD3D::mCurrentSerial = 1;
+
+ProgramD3D::ProgramD3D(const gl::ProgramState &state, RendererD3D *renderer)
+ : ProgramImpl(state),
+ mRenderer(renderer),
+ mDynamicHLSL(nullptr),
+ mUsesPointSize(false),
+ mUsesFlatInterpolation(false),
+ mUsedShaderSamplerRanges({}),
+ mDirtySamplerMapping(true),
+ mUsedImageRange({}),
+ mUsedReadonlyImageRange({}),
+ mUsedAtomicCounterRange({}),
+ mSerial(issueSerial())
+{
+ mDynamicHLSL = new DynamicHLSL(renderer);
+}
+
+ProgramD3D::~ProgramD3D()
+{
+ reset();
+ SafeDelete(mDynamicHLSL);
+}
+
+bool ProgramD3D::usesPointSpriteEmulation() const
+{
+ return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
+}
+
+bool ProgramD3D::usesGeometryShaderForPointSpriteEmulation() const
+{
+ return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
+}
+
+bool ProgramD3D::usesGetDimensionsIgnoresBaseLevel() const
+{
+ return mRenderer->getFeatures().getDimensionsIgnoresBaseLevel.enabled;
+}
+
+bool ProgramD3D::usesGeometryShader(const gl::State &state, const gl::PrimitiveMode drawMode) const
+{
+ if (mHasANGLEMultiviewEnabled && !mRenderer->canSelectViewInVertexShader())
+ {
+ return true;
+ }
+ if (drawMode != gl::PrimitiveMode::Points)
+ {
+ if (!mUsesFlatInterpolation)
+ {
+ return false;
+ }
+ return state.getProvokingVertex() == gl::ProvokingVertexConvention::LastVertexConvention;
+ }
+ return usesGeometryShaderForPointSpriteEmulation();
+}
+
+bool ProgramD3D::usesInstancedPointSpriteEmulation() const
+{
+ return mRenderer->getFeatures().useInstancedPointSpriteEmulation.enabled;
+}
+
+GLint ProgramD3D::getSamplerMapping(gl::ShaderType type,
+ unsigned int samplerIndex,
+ const gl::Caps &caps) const
+{
+ GLint logicalTextureUnit = -1;
+
+ ASSERT(type != gl::ShaderType::InvalidEnum);
+
+ ASSERT(samplerIndex < static_cast<unsigned int>(caps.maxShaderTextureImageUnits[type]));
+
+ const auto &samplers = mShaderSamplers[type];
+ if (samplerIndex < samplers.size() && samplers[samplerIndex].active)
+ {
+ logicalTextureUnit = samplers[samplerIndex].logicalTextureUnit;
+ }
+
+ if (logicalTextureUnit >= 0 && logicalTextureUnit < caps.maxCombinedTextureImageUnits)
+ {
+ return logicalTextureUnit;
+ }
+
+ return -1;
+}
+
+// Returns the texture type for a given Direct3D 9 sampler type and
+// index (0-15 for the pixel shader and 0-3 for the vertex shader).
+gl::TextureType ProgramD3D::getSamplerTextureType(gl::ShaderType type,
+ unsigned int samplerIndex) const
+{
+ ASSERT(type != gl::ShaderType::InvalidEnum);
+
+ const auto &samplers = mShaderSamplers[type];
+ ASSERT(samplerIndex < samplers.size());
+ ASSERT(samplers[samplerIndex].active);
+
+ return samplers[samplerIndex].textureType;
+}
+
+gl::RangeUI ProgramD3D::getUsedSamplerRange(gl::ShaderType type) const
+{
+ ASSERT(type != gl::ShaderType::InvalidEnum);
+ return mUsedShaderSamplerRanges[type];
+}
+
+ProgramD3D::SamplerMapping ProgramD3D::updateSamplerMapping()
+{
+ if (!mDirtySamplerMapping)
+ {
+ return SamplerMapping::WasClean;
+ }
+
+ mDirtySamplerMapping = false;
+
+ // Retrieve sampler uniform values
+ for (const D3DUniform *d3dUniform : mD3DUniforms)
+ {
+ if (!d3dUniform->isSampler())
+ continue;
+
+ int count = d3dUniform->getArraySizeProduct();
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ if (!d3dUniform->isReferencedByShader(shaderType))
+ {
+ continue;
+ }
+
+ unsigned int firstIndex = d3dUniform->mShaderRegisterIndexes[shaderType];
+
+ std::vector<Sampler> &samplers = mShaderSamplers[shaderType];
+ for (int i = 0; i < count; i++)
+ {
+ unsigned int samplerIndex = firstIndex + i;
+
+ if (samplerIndex < samplers.size())
+ {
+ ASSERT(samplers[samplerIndex].active);
+ samplers[samplerIndex].logicalTextureUnit = d3dUniform->mSamplerData[i];
+ }
+ }
+ }
+ }
+
+ return SamplerMapping::WasDirty;
+}
+
+GLint ProgramD3D::getImageMapping(gl::ShaderType type,
+ unsigned int imageIndex,
+ bool readonly,
+ const gl::Caps &caps) const
+{
+ GLint logicalImageUnit = -1;
+ ASSERT(imageIndex < static_cast<unsigned int>(caps.maxImageUnits));
+ if (readonly && imageIndex < mReadonlyImages[type].size() &&
+ mReadonlyImages[type][imageIndex].active)
+ {
+ logicalImageUnit = mReadonlyImages[type][imageIndex].logicalImageUnit;
+ }
+ else if (imageIndex < mImages[type].size() && mImages[type][imageIndex].active)
+ {
+ logicalImageUnit = mImages[type][imageIndex].logicalImageUnit;
+ }
+
+ if (logicalImageUnit >= 0 && logicalImageUnit < caps.maxImageUnits)
+ {
+ return logicalImageUnit;
+ }
+
+ return -1;
+}
+
+gl::RangeUI ProgramD3D::getUsedImageRange(gl::ShaderType type, bool readonly) const
+{
+ return readonly ? mUsedReadonlyImageRange[type] : mUsedImageRange[type];
+}
+
+class ProgramD3D::LoadBinaryTask : public ProgramD3D::GetExecutableTask
+{
+ public:
+ LoadBinaryTask(const gl::Context *context,
+ ProgramD3D *program,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog)
+ : ProgramD3D::GetExecutableTask(context, program)
+ {
+ ASSERT(mProgram);
+ ASSERT(stream);
+
+ // Copy the remaining data from the stream locally so that the client can't modify it when
+ // loading off thread.
+ size_t dataSize = stream->remainingSize();
+ mDataCopySucceeded = mStreamData.resize(dataSize);
+ if (mDataCopySucceeded)
+ {
+ memcpy(mStreamData.data(), stream->data() + stream->offset(), dataSize);
+ }
+ }
+
+ angle::Result run() override
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "ProgramD3D::LoadBinaryTask::run");
+ if (!mDataCopySucceeded)
+ {
+ mInfoLog << "Failed to copy program binary data to local buffer.";
+ return angle::Result::Incomplete;
+ }
+
+ gl::BinaryInputStream stream(mStreamData.data(), mStreamData.size());
+ return mProgram->loadBinaryShaderExecutables(this, &stream, mInfoLog);
+ }
+
+ private:
+ bool mDataCopySucceeded;
+ angle::MemoryBuffer mStreamData;
+};
+
+class ProgramD3D::LoadBinaryLinkEvent final : public LinkEvent
+{
+ public:
+ LoadBinaryLinkEvent(const gl::Context *context,
+ std::shared_ptr<WorkerThreadPool> workerPool,
+ ProgramD3D *program,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog)
+ : mTask(std::make_shared<ProgramD3D::LoadBinaryTask>(context, program, stream, infoLog)),
+ mWaitableEvent(angle::WorkerThreadPool::PostWorkerTask(workerPool, mTask))
+ {}
+
+ angle::Result wait(const gl::Context *context) override
+ {
+ mWaitableEvent->wait();
+
+ // Continue and Incomplete are not errors. For Stop, pass the error to the ContextD3D.
+ if (mTask->getResult() != angle::Result::Stop)
+ {
+ return angle::Result::Continue;
+ }
+
+ ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
+ mTask->popError(contextD3D);
+ return angle::Result::Stop;
+ }
+
+ bool isLinking() override { return !mWaitableEvent->isReady(); }
+
+ private:
+ std::shared_ptr<ProgramD3D::LoadBinaryTask> mTask;
+ std::shared_ptr<WaitableEvent> mWaitableEvent;
+};
+
+std::unique_ptr<rx::LinkEvent> ProgramD3D::load(const gl::Context *context,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog)
+{
+
+ // TODO(jmadill): Use Renderer from contextImpl.
+
+ reset();
+
+ DeviceIdentifier binaryDeviceIdentifier = {};
+ stream->readBytes(reinterpret_cast<unsigned char *>(&binaryDeviceIdentifier),
+ sizeof(DeviceIdentifier));
+
+ DeviceIdentifier identifier = mRenderer->getAdapterIdentifier();
+ if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
+ {
+ infoLog << "Invalid program binary, device configuration has changed.";
+ return nullptr;
+ }
+
+ int compileFlags = stream->readInt<int>();
+ if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
+ {
+ infoLog << "Mismatched compilation flags.";
+ return nullptr;
+ }
+
+ for (int &index : mAttribLocationToD3DSemantic)
+ {
+ stream->readInt(&index);
+ }
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ size_t samplerCount = stream->readInt<size_t>();
+ for (size_t sampleIndex = 0; sampleIndex < samplerCount; ++sampleIndex)
+ {
+ Sampler sampler;
+ stream->readBool(&sampler.active);
+ stream->readInt(&sampler.logicalTextureUnit);
+ stream->readEnum(&sampler.textureType);
+ mShaderSamplers[shaderType].push_back(sampler);
+ }
+
+ unsigned int samplerRangeLow, samplerRangeHigh;
+ stream->readInt(&samplerRangeLow);
+ stream->readInt(&samplerRangeHigh);
+ mUsedShaderSamplerRanges[shaderType] = gl::RangeUI(samplerRangeLow, samplerRangeHigh);
+ }
+
+ for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment})
+ {
+ size_t imageCount = stream->readInt<size_t>();
+ for (size_t imageIndex = 0; imageIndex < imageCount; ++imageIndex)
+ {
+ Image image;
+ stream->readBool(&image.active);
+ stream->readInt(&image.logicalImageUnit);
+ mImages[shaderType].push_back(image);
+ }
+
+ size_t readonlyImageCount = stream->readInt<size_t>();
+ for (size_t imageIndex = 0; imageIndex < readonlyImageCount; ++imageIndex)
+ {
+ Image image;
+ stream->readBool(&image.active);
+ stream->readInt(&image.logicalImageUnit);
+ mReadonlyImages[shaderType].push_back(image);
+ }
+
+ unsigned int imageRangeLow, imageRangeHigh, readonlyImageRangeLow, readonlyImageRangeHigh;
+ stream->readInt(&imageRangeLow);
+ stream->readInt(&imageRangeHigh);
+ stream->readInt(&readonlyImageRangeLow);
+ stream->readInt(&readonlyImageRangeHigh);
+ mUsedImageRange[shaderType] = gl::RangeUI(imageRangeLow, imageRangeHigh);
+ mUsedReadonlyImageRange[shaderType] =
+ gl::RangeUI(readonlyImageRangeLow, readonlyImageRangeHigh);
+
+ unsigned int atomicCounterRangeLow, atomicCounterRangeHigh;
+ stream->readInt(&atomicCounterRangeLow);
+ stream->readInt(&atomicCounterRangeHigh);
+ mUsedAtomicCounterRange[shaderType] =
+ gl::RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
+ }
+
+ size_t shaderStorageBlockCount = stream->readInt<size_t>();
+ if (stream->error())
+ {
+ infoLog << "Invalid program binary.";
+ return nullptr;
+ }
+
+ ASSERT(mD3DShaderStorageBlocks.empty());
+ for (size_t blockIndex = 0; blockIndex < shaderStorageBlockCount; ++blockIndex)
+ {
+ D3DInterfaceBlock shaderStorageBlock;
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ stream->readInt(&shaderStorageBlock.mShaderRegisterIndexes[shaderType]);
+ }
+ mD3DShaderStorageBlocks.push_back(shaderStorageBlock);
+ }
+
+ for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment})
+ {
+ size_t image2DUniformCount = stream->readInt<size_t>();
+ if (stream->error())
+ {
+ infoLog << "Invalid program binary.";
+ return nullptr;
+ }
+
+ ASSERT(mImage2DUniforms[shaderType].empty());
+ for (size_t image2DUniformIndex = 0; image2DUniformIndex < image2DUniformCount;
+ ++image2DUniformIndex)
+ {
+ sh::ShaderVariable image2Duniform;
+ gl::LoadShaderVar(stream, &image2Duniform);
+ mImage2DUniforms[shaderType].push_back(image2Duniform);
+ }
+ }
+
+ for (unsigned int ii = 0; ii < gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS; ++ii)
+ {
+ unsigned int index = stream->readInt<unsigned int>();
+ mComputeAtomicCounterBufferRegisterIndices[ii] = index;
+ }
+
+ size_t uniformCount = stream->readInt<size_t>();
+ if (stream->error())
+ {
+ infoLog << "Invalid program binary.";
+ return nullptr;
+ }
+
+ const auto &linkedUniforms = mState.getUniforms();
+ ASSERT(mD3DUniforms.empty());
+ for (size_t uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++)
+ {
+ const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex];
+
+ D3DUniform *d3dUniform =
+ new D3DUniform(linkedUniform.type, HLSLRegisterType::None, linkedUniform.name,
+ linkedUniform.arraySizes, linkedUniform.isInDefaultBlock());
+ stream->readEnum(&d3dUniform->regType);
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ stream->readInt(&d3dUniform->mShaderRegisterIndexes[shaderType]);
+ }
+ stream->readInt(&d3dUniform->registerCount);
+ stream->readInt(&d3dUniform->registerElement);
+
+ mD3DUniforms.push_back(d3dUniform);
+ }
+
+ size_t blockCount = stream->readInt<size_t>();
+ if (stream->error())
+ {
+ infoLog << "Invalid program binary.";
+ return nullptr;
+ }
+
+ ASSERT(mD3DUniformBlocks.empty());
+ for (size_t blockIndex = 0; blockIndex < blockCount; ++blockIndex)
+ {
+ D3DUniformBlock uniformBlock;
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ stream->readInt(&uniformBlock.mShaderRegisterIndexes[shaderType]);
+ stream->readBool(&uniformBlock.mUseStructuredBuffers[shaderType]);
+ stream->readInt(&uniformBlock.mByteWidths[shaderType]);
+ stream->readInt(&uniformBlock.mStructureByteStrides[shaderType]);
+ }
+ mD3DUniformBlocks.push_back(uniformBlock);
+ }
+
+ size_t streamOutVaryingCount = stream->readInt<size_t>();
+ mStreamOutVaryings.resize(streamOutVaryingCount);
+ for (size_t varyingIndex = 0; varyingIndex < streamOutVaryingCount; ++varyingIndex)
+ {
+ D3DVarying *varying = &mStreamOutVaryings[varyingIndex];
+
+ stream->readString(&varying->semanticName);
+ stream->readInt(&varying->semanticIndex);
+ stream->readInt(&varying->componentCount);
+ stream->readInt(&varying->outputSlot);
+ }
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ stream->readString(&mShaderHLSL[shaderType]);
+ stream->readBytes(reinterpret_cast<unsigned char *>(&mShaderWorkarounds[shaderType]),
+ sizeof(CompilerWorkaroundsD3D));
+ }
+
+ stream->readBool(&mUsesFragDepth);
+ stream->readBool(&mHasANGLEMultiviewEnabled);
+ stream->readBool(&mUsesVertexID);
+ stream->readBool(&mUsesViewID);
+ stream->readBool(&mUsesPointSize);
+ stream->readBool(&mUsesFlatInterpolation);
+
+ const size_t pixelShaderKeySize = stream->readInt<size_t>();
+ mPixelShaderKey.resize(pixelShaderKeySize);
+ for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize;
+ pixelShaderKeyIndex++)
+ {
+ stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type);
+ stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name);
+ stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].source);
+ stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputLocation);
+ stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex);
+ }
+
+ stream->readString(&mGeometryShaderPreamble);
+
+ return std::make_unique<LoadBinaryLinkEvent>(context, context->getWorkerThreadPool(), this,
+ stream, infoLog);
+}
+
+angle::Result ProgramD3D::loadBinaryShaderExecutables(d3d::Context *contextD3D,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog)
+{
+ const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
+
+ bool separateAttribs = (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
+
+ size_t vertexShaderCount = stream->readInt<size_t>();
+ for (size_t vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++)
+ {
+ size_t inputLayoutSize = stream->readInt<size_t>();
+ gl::InputLayout inputLayout(inputLayoutSize, angle::FormatID::NONE);
+
+ for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++)
+ {
+ inputLayout[inputIndex] = stream->readEnum<angle::FormatID>();
+ }
+
+ size_t vertexShaderSize = stream->readInt<size_t>();
+ const unsigned char *vertexShaderFunction = binary + stream->offset();
+
+ ShaderExecutableD3D *shaderExecutable = nullptr;
+
+ ANGLE_TRY(mRenderer->loadExecutable(contextD3D, vertexShaderFunction, vertexShaderSize,
+ gl::ShaderType::Vertex, mStreamOutVaryings,
+ separateAttribs, &shaderExecutable));
+
+ if (!shaderExecutable)
+ {
+ infoLog << "Could not create vertex shader.";
+ return angle::Result::Incomplete;
+ }
+
+ // generated converted input layout
+ VertexExecutable::Signature signature;
+ VertexExecutable::getSignature(mRenderer, inputLayout, &signature);
+
+ // add new binary
+ mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
+ new VertexExecutable(inputLayout, signature, shaderExecutable)));
+
+ stream->skip(vertexShaderSize);
+ }
+
+ size_t pixelShaderCount = stream->readInt<size_t>();
+ for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++)
+ {
+ size_t outputCount = stream->readInt<size_t>();
+ std::vector<GLenum> outputs(outputCount);
+ for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++)
+ {
+ stream->readInt(&outputs[outputIndex]);
+ }
+
+ size_t pixelShaderSize = stream->readInt<size_t>();
+ const unsigned char *pixelShaderFunction = binary + stream->offset();
+ ShaderExecutableD3D *shaderExecutable = nullptr;
+
+ ANGLE_TRY(mRenderer->loadExecutable(contextD3D, pixelShaderFunction, pixelShaderSize,
+ gl::ShaderType::Fragment, mStreamOutVaryings,
+ separateAttribs, &shaderExecutable));
+
+ if (!shaderExecutable)
+ {
+ infoLog << "Could not create pixel shader.";
+ return angle::Result::Incomplete;
+ }
+
+ // add new binary
+ mPixelExecutables.push_back(
+ std::unique_ptr<PixelExecutable>(new PixelExecutable(outputs, shaderExecutable)));
+
+ stream->skip(pixelShaderSize);
+ }
+
+ for (std::unique_ptr<ShaderExecutableD3D> &geometryExe : mGeometryExecutables)
+ {
+ size_t geometryShaderSize = stream->readInt<size_t>();
+ if (geometryShaderSize == 0)
+ {
+ continue;
+ }
+
+ const unsigned char *geometryShaderFunction = binary + stream->offset();
+
+ ShaderExecutableD3D *geometryExecutable = nullptr;
+ ANGLE_TRY(mRenderer->loadExecutable(contextD3D, geometryShaderFunction, geometryShaderSize,
+ gl::ShaderType::Geometry, mStreamOutVaryings,
+ separateAttribs, &geometryExecutable));
+
+ if (!geometryExecutable)
+ {
+ infoLog << "Could not create geometry shader.";
+ return angle::Result::Incomplete;
+ }
+
+ geometryExe.reset(geometryExecutable);
+
+ stream->skip(geometryShaderSize);
+ }
+
+ size_t computeShaderCount = stream->readInt<size_t>();
+ for (size_t computeShaderIndex = 0; computeShaderIndex < computeShaderCount;
+ computeShaderIndex++)
+ {
+ size_t signatureCount = stream->readInt<size_t>();
+ gl::ImageUnitTextureTypeMap signatures;
+ for (size_t signatureIndex = 0; signatureIndex < signatureCount; signatureIndex++)
+ {
+ unsigned int imageUint;
+ gl::TextureType textureType;
+ stream->readInt(&imageUint);
+ stream->readEnum(&textureType);
+ signatures.insert(std::pair<unsigned int, gl::TextureType>(imageUint, textureType));
+ }
+
+ size_t computeShaderSize = stream->readInt<size_t>();
+ const unsigned char *computeShaderFunction = binary + stream->offset();
+
+ ShaderExecutableD3D *computeExecutable = nullptr;
+ ANGLE_TRY(mRenderer->loadExecutable(contextD3D, computeShaderFunction, computeShaderSize,
+ gl::ShaderType::Compute, std::vector<D3DVarying>(),
+ false, &computeExecutable));
+
+ if (!computeExecutable)
+ {
+ infoLog << "Could not create compute shader.";
+ return angle::Result::Incomplete;
+ }
+
+ // add new binary
+ mComputeExecutables.push_back(std::unique_ptr<ComputeExecutable>(new ComputeExecutable(
+ signatures, std::unique_ptr<ShaderExecutableD3D>(computeExecutable))));
+
+ stream->skip(computeShaderSize);
+ }
+
+ size_t bindLayoutCount = stream->readInt<size_t>();
+ for (size_t bindLayoutIndex = 0; bindLayoutIndex < bindLayoutCount; bindLayoutIndex++)
+ {
+ mImage2DBindLayoutCache[gl::ShaderType::Compute].insert(
+ std::pair<unsigned int, gl::TextureType>(stream->readInt<unsigned int>(),
+ gl::TextureType::_2D));
+ }
+
+ initializeUniformStorage(mState.getExecutable().getLinkedShaderStages());
+
+ dirtyAllUniforms();
+
+ return angle::Result::Continue;
+}
+
+void ProgramD3D::save(const gl::Context *context, gl::BinaryOutputStream *stream)
+{
+ // Output the DeviceIdentifier before we output any shader code
+ // When we load the binary again later, we can validate the device identifier before trying to
+ // compile any HLSL
+ DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier();
+ stream->writeBytes(reinterpret_cast<unsigned char *>(&binaryIdentifier),
+ sizeof(DeviceIdentifier));
+
+ stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
+
+ for (int d3dSemantic : mAttribLocationToD3DSemantic)
+ {
+ stream->writeInt(d3dSemantic);
+ }
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ stream->writeInt(mShaderSamplers[shaderType].size());
+ for (unsigned int i = 0; i < mShaderSamplers[shaderType].size(); ++i)
+ {
+ stream->writeBool(mShaderSamplers[shaderType][i].active);
+ stream->writeInt(mShaderSamplers[shaderType][i].logicalTextureUnit);
+ stream->writeEnum(mShaderSamplers[shaderType][i].textureType);
+ }
+
+ stream->writeInt(mUsedShaderSamplerRanges[shaderType].low());
+ stream->writeInt(mUsedShaderSamplerRanges[shaderType].high());
+ }
+
+ for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment})
+ {
+ stream->writeInt(mImages[shaderType].size());
+ for (size_t imageIndex = 0; imageIndex < mImages[shaderType].size(); ++imageIndex)
+ {
+ stream->writeBool(mImages[shaderType][imageIndex].active);
+ stream->writeInt(mImages[shaderType][imageIndex].logicalImageUnit);
+ }
+
+ stream->writeInt(mReadonlyImages[shaderType].size());
+ for (size_t imageIndex = 0; imageIndex < mReadonlyImages[shaderType].size(); ++imageIndex)
+ {
+ stream->writeBool(mReadonlyImages[shaderType][imageIndex].active);
+ stream->writeInt(mReadonlyImages[shaderType][imageIndex].logicalImageUnit);
+ }
+
+ stream->writeInt(mUsedImageRange[shaderType].low());
+ stream->writeInt(mUsedImageRange[shaderType].high());
+ stream->writeInt(mUsedReadonlyImageRange[shaderType].low());
+ stream->writeInt(mUsedReadonlyImageRange[shaderType].high());
+ stream->writeInt(mUsedAtomicCounterRange[shaderType].low());
+ stream->writeInt(mUsedAtomicCounterRange[shaderType].high());
+ }
+
+ stream->writeInt(mD3DShaderStorageBlocks.size());
+ for (const D3DInterfaceBlock &shaderStorageBlock : mD3DShaderStorageBlocks)
+ {
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ stream->writeIntOrNegOne(shaderStorageBlock.mShaderRegisterIndexes[shaderType]);
+ }
+ }
+
+ for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment})
+ {
+ stream->writeInt(mImage2DUniforms[shaderType].size());
+ for (const sh::ShaderVariable &image2DUniform : mImage2DUniforms[shaderType])
+ {
+ gl::WriteShaderVar(stream, image2DUniform);
+ }
+ }
+
+ for (unsigned int ii = 0; ii < gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS; ++ii)
+ {
+ stream->writeInt(mComputeAtomicCounterBufferRegisterIndices[ii]);
+ }
+
+ stream->writeInt(mD3DUniforms.size());
+ for (const D3DUniform *uniform : mD3DUniforms)
+ {
+ // Type, name and arraySize are redundant, so aren't stored in the binary.
+ stream->writeEnum(uniform->regType);
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ stream->writeIntOrNegOne(uniform->mShaderRegisterIndexes[shaderType]);
+ }
+ stream->writeInt(uniform->registerCount);
+ stream->writeInt(uniform->registerElement);
+ }
+
+ stream->writeInt(mD3DUniformBlocks.size());
+ for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks)
+ {
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ stream->writeIntOrNegOne(uniformBlock.mShaderRegisterIndexes[shaderType]);
+ stream->writeBool(uniformBlock.mUseStructuredBuffers[shaderType]);
+ stream->writeInt(uniformBlock.mByteWidths[shaderType]);
+ stream->writeInt(uniformBlock.mStructureByteStrides[shaderType]);
+ }
+ }
+
+ stream->writeInt(mStreamOutVaryings.size());
+ for (const D3DVarying &varying : mStreamOutVaryings)
+ {
+ stream->writeString(varying.semanticName);
+ stream->writeInt(varying.semanticIndex);
+ stream->writeInt(varying.componentCount);
+ stream->writeInt(varying.outputSlot);
+ }
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ stream->writeString(mShaderHLSL[shaderType]);
+ stream->writeBytes(reinterpret_cast<unsigned char *>(&mShaderWorkarounds[shaderType]),
+ sizeof(CompilerWorkaroundsD3D));
+ }
+
+ stream->writeBool(mUsesFragDepth);
+ stream->writeBool(mHasANGLEMultiviewEnabled);
+ stream->writeBool(mUsesVertexID);
+ stream->writeBool(mUsesViewID);
+ stream->writeBool(mUsesPointSize);
+ stream->writeBool(mUsesFlatInterpolation);
+
+ const std::vector<PixelShaderOutputVariable> &pixelShaderKey = mPixelShaderKey;
+ stream->writeInt(pixelShaderKey.size());
+ for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size();
+ pixelShaderKeyIndex++)
+ {
+ const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex];
+ stream->writeInt(variable.type);
+ stream->writeString(variable.name);
+ stream->writeString(variable.source);
+ stream->writeInt(variable.outputLocation);
+ stream->writeInt(variable.outputIndex);
+ }
+
+ stream->writeString(mGeometryShaderPreamble);
+
+ stream->writeInt(mVertexExecutables.size());
+ for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size();
+ vertexExecutableIndex++)
+ {
+ VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex].get();
+
+ const gl::InputLayout &inputLayout = vertexExecutable->inputs();
+ stream->writeInt(inputLayout.size());
+
+ for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++)
+ {
+ stream->writeEnum(inputLayout[inputIndex]);
+ }
+
+ size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength();
+ stream->writeInt(vertexShaderSize);
+
+ const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction();
+ stream->writeBytes(vertexBlob, vertexShaderSize);
+ }
+
+ stream->writeInt(mPixelExecutables.size());
+ for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size();
+ pixelExecutableIndex++)
+ {
+ PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex].get();
+
+ const std::vector<GLenum> &outputs = pixelExecutable->outputSignature();
+ stream->writeInt(outputs.size());
+ for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++)
+ {
+ stream->writeInt(outputs[outputIndex]);
+ }
+
+ size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength();
+ stream->writeInt(pixelShaderSize);
+
+ const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction();
+ stream->writeBytes(pixelBlob, pixelShaderSize);
+ }
+
+ for (auto const &geometryExecutable : mGeometryExecutables)
+ {
+ if (!geometryExecutable)
+ {
+ stream->writeInt<size_t>(0);
+ continue;
+ }
+
+ size_t geometryShaderSize = geometryExecutable->getLength();
+ stream->writeInt(geometryShaderSize);
+ stream->writeBytes(geometryExecutable->getFunction(), geometryShaderSize);
+ }
+
+ stream->writeInt(mComputeExecutables.size());
+ for (size_t computeExecutableIndex = 0; computeExecutableIndex < mComputeExecutables.size();
+ computeExecutableIndex++)
+ {
+ ComputeExecutable *computeExecutable = mComputeExecutables[computeExecutableIndex].get();
+
+ const gl::ImageUnitTextureTypeMap signatures = computeExecutable->signature();
+ stream->writeInt(signatures.size());
+ for (const auto &signature : signatures)
+ {
+ stream->writeInt(signature.first);
+ stream->writeEnum(signature.second);
+ }
+
+ size_t computeShaderSize = computeExecutable->shaderExecutable()->getLength();
+ stream->writeInt(computeShaderSize);
+
+ const uint8_t *computeBlob = computeExecutable->shaderExecutable()->getFunction();
+ stream->writeBytes(computeBlob, computeShaderSize);
+ }
+
+ for (gl::ShaderType shaderType : {gl::ShaderType::Compute})
+ {
+ stream->writeInt(mImage2DBindLayoutCache[shaderType].size());
+ for (auto &image2DBindLayout : mImage2DBindLayoutCache[shaderType])
+ {
+ stream->writeInt(image2DBindLayout.first);
+ }
+ }
+}
+
+void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */) {}
+
+void ProgramD3D::setSeparable(bool /* separable */) {}
+
+angle::Result ProgramD3D::getPixelExecutableForCachedOutputLayout(
+ d3d::Context *context,
+ ShaderExecutableD3D **outExecutable,
+ gl::InfoLog *infoLog)
+{
+ if (mCachedPixelExecutableIndex.valid())
+ {
+ *outExecutable = mPixelExecutables[mCachedPixelExecutableIndex.value()]->shaderExecutable();
+ return angle::Result::Continue;
+ }
+
+ std::string pixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(
+ mShaderHLSL[gl::ShaderType::Fragment], mPixelShaderKey, mUsesFragDepth,
+ mPixelShaderOutputLayoutCache, mShaderStorageBlocks[gl::ShaderType::Fragment],
+ mPixelShaderKey.size());
+
+ std::string finalPixelHLSL = mDynamicHLSL->generateShaderForImage2DBindSignature(
+ *this, mState, gl::ShaderType::Fragment, pixelHLSL,
+ mImage2DUniforms[gl::ShaderType::Fragment],
+ mImage2DBindLayoutCache[gl::ShaderType::Fragment],
+ static_cast<unsigned int>(mPixelShaderKey.size()));
+
+ // Generate new pixel executable
+ ShaderExecutableD3D *pixelExecutable = nullptr;
+
+ gl::InfoLog tempInfoLog;
+ gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
+
+ ANGLE_TRY(mRenderer->compileToExecutable(
+ context, *currentInfoLog, finalPixelHLSL, gl::ShaderType::Fragment, mStreamOutVaryings,
+ (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
+ mShaderWorkarounds[gl::ShaderType::Fragment], &pixelExecutable));
+
+ if (pixelExecutable)
+ {
+ mPixelExecutables.push_back(std::unique_ptr<PixelExecutable>(
+ new PixelExecutable(mPixelShaderOutputLayoutCache, pixelExecutable)));
+ mCachedPixelExecutableIndex = mPixelExecutables.size() - 1;
+ }
+ else if (!infoLog)
+ {
+ ERR() << "Error compiling dynamic pixel executable:" << std::endl
+ << tempInfoLog.str() << std::endl;
+ }
+
+ *outExecutable = pixelExecutable;
+ return angle::Result::Continue;
+}
+
+angle::Result ProgramD3D::getVertexExecutableForCachedInputLayout(
+ d3d::Context *context,
+ ShaderExecutableD3D **outExectuable,
+ gl::InfoLog *infoLog)
+{
+ if (mCachedVertexExecutableIndex.valid())
+ {
+ *outExectuable =
+ mVertexExecutables[mCachedVertexExecutableIndex.value()]->shaderExecutable();
+ return angle::Result::Continue;
+ }
+
+ // Generate new dynamic layout with attribute conversions
+ std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(
+ mShaderHLSL[gl::ShaderType::Vertex], mCachedInputLayout, mState.getProgramInputs(),
+ mShaderStorageBlocks[gl::ShaderType::Vertex], mPixelShaderKey.size());
+
+ // Generate new vertex executable
+ ShaderExecutableD3D *vertexExecutable = nullptr;
+
+ gl::InfoLog tempInfoLog;
+ gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
+
+ ANGLE_TRY(mRenderer->compileToExecutable(
+ context, *currentInfoLog, finalVertexHLSL, gl::ShaderType::Vertex, mStreamOutVaryings,
+ (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS),
+ mShaderWorkarounds[gl::ShaderType::Vertex], &vertexExecutable));
+
+ if (vertexExecutable)
+ {
+ mVertexExecutables.push_back(std::unique_ptr<VertexExecutable>(
+ new VertexExecutable(mCachedInputLayout, mCachedVertexSignature, vertexExecutable)));
+ mCachedVertexExecutableIndex = mVertexExecutables.size() - 1;
+ }
+ else if (!infoLog)
+ {
+ ERR() << "Error compiling dynamic vertex executable:" << std::endl
+ << tempInfoLog.str() << std::endl;
+ }
+
+ *outExectuable = vertexExecutable;
+ return angle::Result::Continue;
+}
+
+angle::Result ProgramD3D::getGeometryExecutableForPrimitiveType(d3d::Context *context,
+ const gl::State &state,
+ gl::PrimitiveMode drawMode,
+ ShaderExecutableD3D **outExecutable,
+ gl::InfoLog *infoLog)
+{
+ if (outExecutable)
+ {
+ *outExecutable = nullptr;
+ }
+
+ // Return a null shader if the current rendering doesn't use a geometry shader
+ if (!usesGeometryShader(state, drawMode))
+ {
+ return angle::Result::Continue;
+ }
+
+ gl::PrimitiveMode geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
+
+ if (mGeometryExecutables[geometryShaderType])
+ {
+ if (outExecutable)
+ {
+ *outExecutable = mGeometryExecutables[geometryShaderType].get();
+ }
+ return angle::Result::Continue;
+ }
+ const gl::Caps &caps = state.getCaps();
+ std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(
+ caps, geometryShaderType, mState, mRenderer->presentPathFastEnabled(),
+ mHasANGLEMultiviewEnabled, mRenderer->canSelectViewInVertexShader(),
+ usesGeometryShaderForPointSpriteEmulation(), mGeometryShaderPreamble);
+
+ gl::InfoLog tempInfoLog;
+ gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
+
+ ShaderExecutableD3D *geometryExecutable = nullptr;
+ angle::Result result = mRenderer->compileToExecutable(
+ context, *currentInfoLog, geometryHLSL, gl::ShaderType::Geometry, mStreamOutVaryings,
+ (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), CompilerWorkaroundsD3D(),
+ &geometryExecutable);
+
+ if (!infoLog && result == angle::Result::Stop)
+ {
+ ERR() << "Error compiling dynamic geometry executable:" << std::endl
+ << tempInfoLog.str() << std::endl;
+ }
+
+ if (geometryExecutable != nullptr)
+ {
+ mGeometryExecutables[geometryShaderType].reset(geometryExecutable);
+ }
+
+ if (outExecutable)
+ {
+ *outExecutable = mGeometryExecutables[geometryShaderType].get();
+ }
+ return result;
+}
+
+class ProgramD3D::GetVertexExecutableTask : public ProgramD3D::GetExecutableTask
+{
+ public:
+ GetVertexExecutableTask(const gl::Context *context, ProgramD3D *program)
+ : GetExecutableTask(context, program)
+ {}
+ angle::Result run() override
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "ProgramD3D::GetVertexExecutableTask::run");
+
+ ANGLE_TRY(mProgram->getVertexExecutableForCachedInputLayout(this, &mExecutable, &mInfoLog));
+
+ return angle::Result::Continue;
+ }
+};
+
+void ProgramD3D::updateCachedInputLayoutFromShader(const gl::Context *context)
+{
+ GetDefaultInputLayoutFromShader(context, mState.getAttachedShader(gl::ShaderType::Vertex),
+ &mCachedInputLayout);
+ VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
+ updateCachedVertexExecutableIndex();
+}
+
+class ProgramD3D::GetPixelExecutableTask : public ProgramD3D::GetExecutableTask
+{
+ public:
+ GetPixelExecutableTask(const gl::Context *context, ProgramD3D *program)
+ : GetExecutableTask(context, program)
+ {}
+ angle::Result run() override
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "ProgramD3D::GetPixelExecutableTask::run");
+ if (!mProgram->mState.getAttachedShader(gl::ShaderType::Fragment))
+ {
+ return angle::Result::Continue;
+ }
+
+ mProgram->updateCachedOutputLayoutFromShader();
+ mProgram->updateCachedImage2DBindLayoutFromShader(gl::ShaderType::Fragment);
+ ANGLE_TRY(mProgram->getPixelExecutableForCachedOutputLayout(this, &mExecutable, &mInfoLog));
+
+ return angle::Result::Continue;
+ }
+};
+
+void ProgramD3D::updateCachedOutputLayoutFromShader()
+{
+ GetDefaultOutputLayoutFromShader(mPixelShaderKey, &mPixelShaderOutputLayoutCache);
+ updateCachedPixelExecutableIndex();
+}
+
+void ProgramD3D::updateCachedImage2DBindLayoutFromShader(gl::ShaderType shaderType)
+{
+ GetDefaultImage2DBindLayoutFromShader(mImage2DUniforms[shaderType],
+ &mImage2DBindLayoutCache[shaderType]);
+ switch (shaderType)
+ {
+ case gl::ShaderType::Compute:
+ updateCachedComputeExecutableIndex();
+ break;
+ case gl::ShaderType::Fragment:
+ updateCachedPixelExecutableIndex();
+ break;
+ case gl::ShaderType::Vertex:
+ updateCachedVertexExecutableIndex();
+ break;
+ default:
+ ASSERT(false);
+ break;
+ }
+}
+
+class ProgramD3D::GetGeometryExecutableTask : public ProgramD3D::GetExecutableTask
+{
+ public:
+ GetGeometryExecutableTask(const gl::Context *context,
+ ProgramD3D *program,
+ const gl::State &state)
+ : GetExecutableTask(context, program), mState(state)
+ {}
+
+ angle::Result run() override
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "ProgramD3D::GetGeometryExecutableTask::run");
+ // Auto-generate the geometry shader here, if we expect to be using point rendering in
+ // D3D11.
+ if (mProgram->usesGeometryShader(mState, gl::PrimitiveMode::Points))
+ {
+ ANGLE_TRY(mProgram->getGeometryExecutableForPrimitiveType(
+ this, mState, gl::PrimitiveMode::Points, &mExecutable, &mInfoLog));
+ }
+
+ return angle::Result::Continue;
+ }
+
+ private:
+ const gl::State &mState;
+};
+
+class ProgramD3D::GetComputeExecutableTask : public ProgramD3D::GetExecutableTask
+{
+ public:
+ GetComputeExecutableTask(const gl::Context *context, ProgramD3D *program)
+ : GetExecutableTask(context, program)
+ {}
+ angle::Result run() override
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "ProgramD3D::GetComputeExecutableTask::run");
+ mProgram->updateCachedImage2DBindLayoutFromShader(gl::ShaderType::Compute);
+ ShaderExecutableD3D *computeExecutable = nullptr;
+ ANGLE_TRY(mProgram->getComputeExecutableForImage2DBindLayout(
+ mContext, this, &computeExecutable, &mInfoLog));
+
+ return computeExecutable ? angle::Result::Continue : angle::Result::Incomplete;
+ }
+};
+
+// The LinkEvent implementation for linking a rendering(VS, FS, GS) program.
+class ProgramD3D::GraphicsProgramLinkEvent final : public LinkEvent
+{
+ public:
+ GraphicsProgramLinkEvent(gl::InfoLog &infoLog,
+ std::shared_ptr<WorkerThreadPool> workerPool,
+ std::shared_ptr<ProgramD3D::GetVertexExecutableTask> vertexTask,
+ std::shared_ptr<ProgramD3D::GetPixelExecutableTask> pixelTask,
+ std::shared_ptr<ProgramD3D::GetGeometryExecutableTask> geometryTask,
+ bool useGS,
+ const ShaderD3D *vertexShader,
+ const ShaderD3D *fragmentShader)
+ : mInfoLog(infoLog),
+ mVertexTask(vertexTask),
+ mPixelTask(pixelTask),
+ mGeometryTask(geometryTask),
+ mWaitEvents({{std::shared_ptr<WaitableEvent>(
+ angle::WorkerThreadPool::PostWorkerTask(workerPool, mVertexTask)),
+ std::shared_ptr<WaitableEvent>(
+ angle::WorkerThreadPool::PostWorkerTask(workerPool, mPixelTask)),
+ std::shared_ptr<WaitableEvent>(
+ angle::WorkerThreadPool::PostWorkerTask(workerPool, mGeometryTask))}}),
+ mUseGS(useGS),
+ mVertexShader(vertexShader),
+ mFragmentShader(fragmentShader)
+ {}
+
+ angle::Result wait(const gl::Context *context) override
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "ProgramD3D::GraphicsProgramLinkEvent::wait");
+ WaitableEvent::WaitMany(&mWaitEvents);
+
+ ANGLE_TRY(checkTask(context, mVertexTask.get()));
+ ANGLE_TRY(checkTask(context, mPixelTask.get()));
+ ANGLE_TRY(checkTask(context, mGeometryTask.get()));
+
+ if (mVertexTask->getResult() == angle::Result::Incomplete ||
+ mPixelTask->getResult() == angle::Result::Incomplete ||
+ mGeometryTask->getResult() == angle::Result::Incomplete)
+ {
+ return angle::Result::Incomplete;
+ }
+
+ ShaderExecutableD3D *defaultVertexExecutable = mVertexTask->getExecutable();
+ ShaderExecutableD3D *defaultPixelExecutable = mPixelTask->getExecutable();
+ ShaderExecutableD3D *pointGS = mGeometryTask->getExecutable();
+
+ if (mUseGS && pointGS)
+ {
+ // Geometry shaders are currently only used internally, so there is no corresponding
+ // shader object at the interface level. For now the geometry shader debug info is
+ // prepended to the vertex shader.
+ mVertexShader->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n");
+ mVertexShader->appendDebugInfo(pointGS->getDebugInfo());
+ mVertexShader->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n");
+ }
+
+ if (defaultVertexExecutable)
+ {
+ mVertexShader->appendDebugInfo(defaultVertexExecutable->getDebugInfo());
+ }
+
+ if (defaultPixelExecutable)
+ {
+ mFragmentShader->appendDebugInfo(defaultPixelExecutable->getDebugInfo());
+ }
+
+ bool isLinked = (defaultVertexExecutable && defaultPixelExecutable && (!mUseGS || pointGS));
+ if (!isLinked)
+ {
+ mInfoLog << "Failed to create D3D Shaders";
+ }
+ return isLinked ? angle::Result::Continue : angle::Result::Incomplete;
+ }
+
+ bool isLinking() override
+ {
+ for (auto &event : mWaitEvents)
+ {
+ if (!event->isReady())
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private:
+ angle::Result checkTask(const gl::Context *context, ProgramD3D::GetExecutableTask *task)
+ {
+ if (!task->getInfoLog().empty())
+ {
+ mInfoLog << task->getInfoLog().str();
+ }
+
+ // Continue and Incomplete are not errors. For Stop, pass the error to the ContextD3D.
+ if (task->getResult() != angle::Result::Stop)
+ {
+ return angle::Result::Continue;
+ }
+
+ ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
+ task->popError(contextD3D);
+ return angle::Result::Stop;
+ }
+
+ gl::InfoLog &mInfoLog;
+ std::shared_ptr<ProgramD3D::GetVertexExecutableTask> mVertexTask;
+ std::shared_ptr<ProgramD3D::GetPixelExecutableTask> mPixelTask;
+ std::shared_ptr<ProgramD3D::GetGeometryExecutableTask> mGeometryTask;
+ std::array<std::shared_ptr<WaitableEvent>, 3> mWaitEvents;
+ bool mUseGS;
+ const ShaderD3D *mVertexShader;
+ const ShaderD3D *mFragmentShader;
+};
+
+// The LinkEvent implementation for linking a computing program.
+class ProgramD3D::ComputeProgramLinkEvent final : public LinkEvent
+{
+ public:
+ ComputeProgramLinkEvent(gl::InfoLog &infoLog,
+ std::shared_ptr<ProgramD3D::GetComputeExecutableTask> computeTask,
+ std::shared_ptr<WaitableEvent> event)
+ : mInfoLog(infoLog), mComputeTask(computeTask), mWaitEvent(event)
+ {}
+
+ bool isLinking() override { return !mWaitEvent->isReady(); }
+
+ angle::Result wait(const gl::Context *context) override
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "ProgramD3D::ComputeProgramLinkEvent::wait");
+ mWaitEvent->wait();
+
+ angle::Result result = mComputeTask->getResult();
+ if (result != angle::Result::Continue)
+ {
+ mInfoLog << "Failed to create D3D compute shader.";
+ }
+ return result;
+ }
+
+ private:
+ gl::InfoLog &mInfoLog;
+ std::shared_ptr<ProgramD3D::GetComputeExecutableTask> mComputeTask;
+ std::shared_ptr<WaitableEvent> mWaitEvent;
+};
+
+std::unique_ptr<LinkEvent> ProgramD3D::compileProgramExecutables(const gl::Context *context,
+ gl::InfoLog &infoLog)
+{
+ ANGLE_TRACE_EVENT0("gpu.angle", "ProgramD3D::compileProgramExecutables");
+ // Ensure the compiler is initialized to avoid race conditions.
+ angle::Result result = mRenderer->ensureHLSLCompilerInitialized(GetImplAs<ContextD3D>(context));
+ if (result != angle::Result::Continue)
+ {
+ return std::make_unique<LinkEventDone>(result);
+ }
+
+ auto vertexTask = std::make_shared<GetVertexExecutableTask>(context, this);
+ auto pixelTask = std::make_shared<GetPixelExecutableTask>(context, this);
+ auto geometryTask =
+ std::make_shared<GetGeometryExecutableTask>(context, this, context->getState());
+ bool useGS = usesGeometryShader(context->getState(), gl::PrimitiveMode::Points);
+ gl::Shader *vertexShader = mState.getAttachedShader(gl::ShaderType::Vertex);
+ gl::Shader *fragmentShader = mState.getAttachedShader(gl::ShaderType::Fragment);
+ const ShaderD3D *vertexShaderD3D = vertexShader ? GetImplAs<ShaderD3D>(vertexShader) : nullptr;
+ const ShaderD3D *fragmentShaderD3D =
+ fragmentShader ? GetImplAs<ShaderD3D>(fragmentShader) : nullptr;
+
+ return std::make_unique<GraphicsProgramLinkEvent>(infoLog, context->getWorkerThreadPool(),
+ vertexTask, pixelTask, geometryTask, useGS,
+ vertexShaderD3D, fragmentShaderD3D);
+}
+
+std::unique_ptr<LinkEvent> ProgramD3D::compileComputeExecutable(const gl::Context *context,
+ gl::InfoLog &infoLog)
+{
+ ANGLE_TRACE_EVENT0("gpu.angle", "ProgramD3D::compileComputeExecutable");
+ // Ensure the compiler is initialized to avoid race conditions.
+ angle::Result result = mRenderer->ensureHLSLCompilerInitialized(GetImplAs<ContextD3D>(context));
+ if (result != angle::Result::Continue)
+ {
+ return std::make_unique<LinkEventDone>(result);
+ }
+ auto computeTask = std::make_shared<GetComputeExecutableTask>(context, this);
+
+ std::shared_ptr<WaitableEvent> waitableEvent;
+
+ // TODO(jie.a.chen@intel.com): Fix the flaky bug.
+ // http://anglebug.com/3349
+ bool compileInParallel = false;
+ if (!compileInParallel)
+ {
+ (*computeTask)();
+ waitableEvent = std::make_shared<WaitableEventDone>();
+ }
+ else
+ {
+ waitableEvent =
+ WorkerThreadPool::PostWorkerTask(context->getWorkerThreadPool(), computeTask);
+ }
+
+ return std::make_unique<ComputeProgramLinkEvent>(infoLog, computeTask, waitableEvent);
+}
+
+angle::Result ProgramD3D::getComputeExecutableForImage2DBindLayout(
+ const gl::Context *glContext,
+ d3d::Context *context,
+ ShaderExecutableD3D **outExecutable,
+ gl::InfoLog *infoLog)
+{
+ ANGLE_TRACE_EVENT0("gpu.angle", "ProgramD3D::getComputeExecutableForImage2DBindLayout");
+ if (mCachedComputeExecutableIndex.valid())
+ {
+ *outExecutable =
+ mComputeExecutables[mCachedComputeExecutableIndex.value()]->shaderExecutable();
+ return angle::Result::Continue;
+ }
+
+ std::string computeHLSL =
+ mState.getAttachedShader(gl::ShaderType::Compute)->getTranslatedSource(glContext);
+
+ std::string finalComputeHLSL = mDynamicHLSL->generateShaderForImage2DBindSignature(
+ *this, mState, gl::ShaderType::Compute, computeHLSL,
+ mImage2DUniforms[gl::ShaderType::Compute], mImage2DBindLayoutCache[gl::ShaderType::Compute],
+ 0u);
+
+ // Generate new compute executable
+ ShaderExecutableD3D *computeExecutable = nullptr;
+
+ gl::InfoLog tempInfoLog;
+ gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
+
+ ANGLE_TRY(mRenderer->compileToExecutable(context, *currentInfoLog, finalComputeHLSL,
+ gl::ShaderType::Compute, std::vector<D3DVarying>(),
+ false, CompilerWorkaroundsD3D(), &computeExecutable));
+
+ if (computeExecutable)
+ {
+ mComputeExecutables.push_back(std::unique_ptr<ComputeExecutable>(
+ new ComputeExecutable(mImage2DBindLayoutCache[gl::ShaderType::Compute],
+ std::unique_ptr<ShaderExecutableD3D>(computeExecutable))));
+ mCachedComputeExecutableIndex = mComputeExecutables.size() - 1;
+ }
+ else if (!infoLog)
+ {
+ ERR() << "Error compiling dynamic compute executable:" << std::endl
+ << tempInfoLog.str() << std::endl;
+ }
+ *outExecutable = computeExecutable;
+
+ return angle::Result::Continue;
+}
+
+std::unique_ptr<LinkEvent> ProgramD3D::link(const gl::Context *context,
+ const gl::ProgramLinkedResources &resources,
+ gl::InfoLog &infoLog,
+ const gl::ProgramMergedVaryings & /*mergedVaryings*/)
+{
+ ANGLE_TRACE_EVENT0("gpu.angle", "ProgramD3D::link");
+ const auto &data = context->getState();
+
+ reset();
+
+ gl::Shader *computeShader = mState.getAttachedShader(gl::ShaderType::Compute);
+ if (computeShader)
+ {
+ mShaderSamplers[gl::ShaderType::Compute].resize(
+ data.getCaps().maxShaderTextureImageUnits[gl::ShaderType::Compute]);
+ mImages[gl::ShaderType::Compute].resize(data.getCaps().maxImageUnits);
+ mReadonlyImages[gl::ShaderType::Compute].resize(data.getCaps().maxImageUnits);
+
+ mShaderUniformsDirty.set(gl::ShaderType::Compute);
+
+ linkResources(context, resources);
+
+ for (const sh::ShaderVariable &uniform : computeShader->getUniforms(context))
+ {
+ if (gl::IsImageType(uniform.type) && gl::IsImage2DType(uniform.type))
+ {
+ mImage2DUniforms[gl::ShaderType::Compute].push_back(uniform);
+ }
+ }
+
+ defineUniformsAndAssignRegisters(context);
+
+ return compileComputeExecutable(context, infoLog);
+ }
+ else
+ {
+ gl::ShaderMap<const ShaderD3D *> shadersD3D = {};
+ for (gl::ShaderType shaderType : gl::kAllGraphicsShaderTypes)
+ {
+ if (gl::Shader *shader = mState.getAttachedShader(shaderType))
+ {
+ shadersD3D[shaderType] = GetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
+
+ mShaderSamplers[shaderType].resize(
+ data.getCaps().maxShaderTextureImageUnits[shaderType]);
+ mImages[shaderType].resize(data.getCaps().maxImageUnits);
+ mReadonlyImages[shaderType].resize(data.getCaps().maxImageUnits);
+
+ shadersD3D[shaderType]->generateWorkarounds(&mShaderWorkarounds[shaderType]);
+
+ mShaderUniformsDirty.set(shaderType);
+
+ const std::set<std::string> &slowCompilingUniformBlockSet =
+ shadersD3D[shaderType]->getSlowCompilingUniformBlockSet();
+ if (slowCompilingUniformBlockSet.size() > 0)
+ {
+ std::ostringstream stream;
+ stream << "You could get a better shader compiling performance if you re-write"
+ << " the uniform block(s)\n[ ";
+ for (const std::string &str : slowCompilingUniformBlockSet)
+ {
+ stream << str << " ";
+ }
+ stream << "]\nin the " << gl::GetShaderTypeString(shaderType) << " shader.\n";
+
+ stream << "You could get more details from "
+ "https://chromium.googlesource.com/angle/angle/+/refs/heads/main/"
+ "src/libANGLE/renderer/d3d/d3d11/"
+ "UniformBlockToStructuredBufferTranslation.md\n";
+ ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_MEDIUM,
+ stream.str().c_str());
+ }
+
+ for (const sh::ShaderVariable &uniform : shader->getUniforms(context))
+ {
+ if (gl::IsImageType(uniform.type) && gl::IsImage2DType(uniform.type))
+ {
+ mImage2DUniforms[shaderType].push_back(uniform);
+ }
+ }
+ }
+ }
+
+ if (mRenderer->getNativeLimitations().noFrontFacingSupport)
+ {
+ const ShaderD3D *fragmentShader = shadersD3D[gl::ShaderType::Fragment];
+ if (fragmentShader && fragmentShader->usesFrontFacing())
+ {
+ infoLog << "The current renderer doesn't support gl_FrontFacing";
+ return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
+ }
+ }
+
+ const gl::VaryingPacking &varyingPacking =
+ resources.varyingPacking.getOutputPacking(gl::ShaderType::Vertex);
+
+ ProgramD3DMetadata metadata(mRenderer, shadersD3D, context->getClientType());
+ BuiltinVaryingsD3D builtins(metadata, varyingPacking);
+
+ mDynamicHLSL->generateShaderLinkHLSL(context, context->getCaps(), mState, metadata,
+ varyingPacking, builtins, &mShaderHLSL);
+
+ const ShaderD3D *vertexShader = shadersD3D[gl::ShaderType::Vertex];
+ mUsesPointSize = vertexShader && vertexShader->usesPointSize();
+ mDynamicHLSL->getPixelShaderOutputKey(data, mState, metadata, &mPixelShaderKey);
+ mUsesFragDepth = metadata.usesFragDepth();
+ mUsesVertexID = metadata.usesVertexID();
+ mUsesViewID = metadata.usesViewID();
+ mHasANGLEMultiviewEnabled = metadata.hasANGLEMultiviewEnabled();
+
+ // Cache if we use flat shading
+ mUsesFlatInterpolation = FindFlatInterpolationVarying(context, mState.getAttachedShaders());
+
+ if (mRenderer->getMajorShaderModel() >= 4)
+ {
+ mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(
+ varyingPacking, builtins, mHasANGLEMultiviewEnabled,
+ metadata.canSelectViewInVertexShader());
+ }
+
+ initAttribLocationsToD3DSemantic(context);
+
+ defineUniformsAndAssignRegisters(context);
+
+ gatherTransformFeedbackVaryings(varyingPacking, builtins[gl::ShaderType::Vertex]);
+
+ linkResources(context, resources);
+
+ if (mState.getAttachedShader(gl::ShaderType::Vertex))
+ {
+ updateCachedInputLayoutFromShader(context);
+ }
+
+ return compileProgramExecutables(context, infoLog);
+ }
+}
+
+GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
+{
+ // TODO(jmadill): Do something useful here?
+ return GL_TRUE;
+}
+
+void ProgramD3D::initializeShaderStorageBlocks(const gl::Context *context)
+{
+ if (mState.getShaderStorageBlocks().empty())
+ {
+ return;
+ }
+
+ ASSERT(mD3DShaderStorageBlocks.empty());
+
+ // Assign registers and update sizes.
+ gl::ShaderMap<const ShaderD3D *> shadersD3D = {};
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ shadersD3D[shaderType] = SafeGetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
+ }
+ for (const gl::InterfaceBlock &shaderStorageBlock : mState.getShaderStorageBlocks())
+ {
+ unsigned int shaderStorageBlockElement =
+ shaderStorageBlock.isArray ? shaderStorageBlock.arrayElement : 0;
+ D3DInterfaceBlock d3dShaderStorageBlock;
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ if (shaderStorageBlock.isActive(shaderType))
+ {
+ ASSERT(shadersD3D[shaderType]);
+ unsigned int baseRegister =
+ shadersD3D[shaderType]->getShaderStorageBlockRegister(shaderStorageBlock.name);
+
+ d3dShaderStorageBlock.mShaderRegisterIndexes[shaderType] =
+ baseRegister + shaderStorageBlockElement;
+ }
+ }
+ mD3DShaderStorageBlocks.push_back(d3dShaderStorageBlock);
+ }
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ gl::Shader *shader = mState.getAttachedShader(shaderType);
+ if (!shader)
+ {
+ continue;
+ }
+ ShaderD3D *shaderD3D = SafeGetImplAs<ShaderD3D>(shader);
+ for (const sh::InterfaceBlock &ssbo : shader->getShaderStorageBlocks(context))
+ {
+ if (!ssbo.active)
+ {
+ continue;
+ }
+ ShaderStorageBlock block;
+ block.name = !ssbo.instanceName.empty() ? ssbo.instanceName : ssbo.name;
+ block.arraySize = ssbo.isArray() ? ssbo.arraySize : 0;
+ block.registerIndex = shaderD3D->getShaderStorageBlockRegister(ssbo.name);
+ mShaderStorageBlocks[shaderType].push_back(block);
+ }
+ }
+}
+
+void ProgramD3D::initializeUniformBlocks()
+{
+ if (mState.getUniformBlocks().empty())
+ {
+ return;
+ }
+
+ ASSERT(mD3DUniformBlocks.empty());
+
+ // Assign registers and update sizes.
+ gl::ShaderMap<const ShaderD3D *> shadersD3D = {};
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ shadersD3D[shaderType] = SafeGetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
+ }
+
+ for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
+ {
+ unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0;
+
+ D3DUniformBlock d3dUniformBlock;
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ if (uniformBlock.isActive(shaderType))
+ {
+ ASSERT(shadersD3D[shaderType]);
+ unsigned int baseRegister =
+ shadersD3D[shaderType]->getUniformBlockRegister(uniformBlock.name);
+ d3dUniformBlock.mShaderRegisterIndexes[shaderType] =
+ baseRegister + uniformBlockElement;
+ bool useStructuredBuffer =
+ shadersD3D[shaderType]->shouldUniformBlockUseStructuredBuffer(
+ uniformBlock.name);
+ if (useStructuredBuffer)
+ {
+ d3dUniformBlock.mUseStructuredBuffers[shaderType] = true;
+ d3dUniformBlock.mByteWidths[shaderType] = uniformBlock.dataSize;
+ d3dUniformBlock.mStructureByteStrides[shaderType] =
+ uniformBlock.firstFieldArraySize == 0u
+ ? uniformBlock.dataSize
+ : uniformBlock.dataSize / uniformBlock.firstFieldArraySize;
+ }
+ }
+ }
+
+ mD3DUniformBlocks.push_back(d3dUniformBlock);
+ }
+}
+
+void ProgramD3D::initializeUniformStorage(const gl::ShaderBitSet &availableShaderStages)
+{
+ // Compute total default block size
+ gl::ShaderMap<unsigned int> shaderRegisters = {};
+ for (const D3DUniform *d3dUniform : mD3DUniforms)
+ {
+ if (d3dUniform->isSampler())
+ {
+ continue;
+ }
+
+ for (gl::ShaderType shaderType : availableShaderStages)
+ {
+ if (d3dUniform->isReferencedByShader(shaderType))
+ {
+ shaderRegisters[shaderType] = std::max(
+ shaderRegisters[shaderType],
+ d3dUniform->mShaderRegisterIndexes[shaderType] + d3dUniform->registerCount);
+ }
+ }
+ }
+
+ // We only reset uniform storages for the shader stages available in the program (attached
+ // shaders in ProgramD3D::link() and linkedShaderStages in ProgramD3D::load()).
+ for (gl::ShaderType shaderType : availableShaderStages)
+ {
+ mShaderUniformStorages[shaderType].reset(
+ mRenderer->createUniformStorage(shaderRegisters[shaderType] * 16u));
+ }
+
+ // Iterate the uniforms again to assign data pointers to default block uniforms.
+ for (D3DUniform *d3dUniform : mD3DUniforms)
+ {
+ if (d3dUniform->isSampler())
+ {
+ d3dUniform->mSamplerData.resize(d3dUniform->getArraySizeProduct(), 0);
+ continue;
+ }
+
+ for (gl::ShaderType shaderType : availableShaderStages)
+ {
+ if (d3dUniform->isReferencedByShader(shaderType))
+ {
+ d3dUniform->mShaderData[shaderType] =
+ mShaderUniformStorages[shaderType]->getDataPointer(
+ d3dUniform->mShaderRegisterIndexes[shaderType],
+ d3dUniform->registerElement);
+ }
+ }
+ }
+}
+
+void ProgramD3D::updateUniformBufferCache(const gl::Caps &caps)
+{
+ if (mState.getUniformBlocks().empty())
+ {
+ return;
+ }
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ mShaderUBOCaches[shaderType].clear();
+ mShaderUBOCachesUseSB[shaderType].clear();
+ }
+
+ for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size();
+ uniformBlockIndex++)
+ {
+ const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex];
+ GLuint blockBinding = mState.getUniformBlockBinding(uniformBlockIndex);
+
+ // Unnecessary to apply an unreferenced standard or shared UBO
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ if (!uniformBlock.activeInShader(shaderType))
+ {
+ continue;
+ }
+
+ bool useStructuredBuffer = uniformBlock.mUseStructuredBuffers[shaderType];
+ unsigned int registerIndex = uniformBlock.mShaderRegisterIndexes[shaderType];
+ if (useStructuredBuffer)
+ {
+ D3DUBOCacheUseSB cacheUseSB;
+ cacheUseSB.registerIndex = registerIndex;
+ cacheUseSB.binding = blockBinding;
+ cacheUseSB.byteWidth = uniformBlock.mByteWidths[shaderType];
+ cacheUseSB.structureByteStride = uniformBlock.mStructureByteStrides[shaderType];
+ mShaderUBOCachesUseSB[shaderType].push_back(cacheUseSB);
+ }
+ else
+ {
+ ASSERT(registerIndex <
+ static_cast<unsigned int>(caps.maxShaderUniformBlocks[shaderType]));
+ D3DUBOCache cache;
+ cache.registerIndex = registerIndex;
+ cache.binding = blockBinding;
+ mShaderUBOCaches[shaderType].push_back(cache);
+ }
+ }
+ }
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ GLuint uniformBlockCount = static_cast<GLuint>(mShaderUBOCaches[shaderType].size() +
+ mShaderUBOCachesUseSB[shaderType].size());
+ ASSERT(uniformBlockCount <=
+ static_cast<unsigned int>(caps.maxShaderUniformBlocks[shaderType]));
+ }
+}
+
+unsigned int ProgramD3D::getAtomicCounterBufferRegisterIndex(GLuint binding,
+ gl::ShaderType shaderType) const
+{
+ if (shaderType != gl::ShaderType::Compute)
+ {
+ // Implement atomic counters for non-compute shaders
+ // http://anglebug.com/1729
+ UNIMPLEMENTED();
+ }
+ return mComputeAtomicCounterBufferRegisterIndices[binding];
+}
+
+unsigned int ProgramD3D::getShaderStorageBufferRegisterIndex(GLuint blockIndex,
+ gl::ShaderType shaderType) const
+{
+ return mD3DShaderStorageBlocks[blockIndex].mShaderRegisterIndexes[shaderType];
+}
+
+const std::vector<D3DUBOCache> &ProgramD3D::getShaderUniformBufferCache(
+ gl::ShaderType shaderType) const
+{
+ return mShaderUBOCaches[shaderType];
+}
+
+const std::vector<D3DUBOCacheUseSB> &ProgramD3D::getShaderUniformBufferCacheUseSB(
+ gl::ShaderType shaderType) const
+{
+ return mShaderUBOCachesUseSB[shaderType];
+}
+
+void ProgramD3D::dirtyAllUniforms()
+{
+ mShaderUniformsDirty = mState.getExecutable().getLinkedShaderStages();
+}
+
+void ProgramD3D::markUniformsClean()
+{
+ mShaderUniformsDirty.reset();
+}
+
+void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ setUniformInternal(location, count, v, GL_FLOAT);
+}
+
+void ProgramD3D::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ setUniformInternal(location, count, v, GL_FLOAT_VEC2);
+}
+
+void ProgramD3D::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ setUniformInternal(location, count, v, GL_FLOAT_VEC3);
+}
+
+void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ setUniformInternal(location, count, v, GL_FLOAT_VEC4);
+}
+
+void ProgramD3D::setUniformMatrix2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfvInternal<2, 2>(location, count, transpose, value);
+}
+
+void ProgramD3D::setUniformMatrix3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfvInternal<3, 3>(location, count, transpose, value);
+}
+
+void ProgramD3D::setUniformMatrix4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfvInternal<4, 4>(location, count, transpose, value);
+}
+
+void ProgramD3D::setUniformMatrix2x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfvInternal<2, 3>(location, count, transpose, value);
+}
+
+void ProgramD3D::setUniformMatrix3x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfvInternal<3, 2>(location, count, transpose, value);
+}
+
+void ProgramD3D::setUniformMatrix2x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfvInternal<2, 4>(location, count, transpose, value);
+}
+
+void ProgramD3D::setUniformMatrix4x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfvInternal<4, 2>(location, count, transpose, value);
+}
+
+void ProgramD3D::setUniformMatrix3x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfvInternal<3, 4>(location, count, transpose, value);
+}
+
+void ProgramD3D::setUniformMatrix4x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ setUniformMatrixfvInternal<4, 3>(location, count, transpose, value);
+}
+
+void ProgramD3D::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+ setUniformInternal(location, count, v, GL_INT);
+}
+
+void ProgramD3D::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+ setUniformInternal(location, count, v, GL_INT_VEC2);
+}
+
+void ProgramD3D::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+ setUniformInternal(location, count, v, GL_INT_VEC3);
+}
+
+void ProgramD3D::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+ setUniformInternal(location, count, v, GL_INT_VEC4);
+}
+
+void ProgramD3D::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ setUniformInternal(location, count, v, GL_UNSIGNED_INT);
+}
+
+void ProgramD3D::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC2);
+}
+
+void ProgramD3D::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC3);
+}
+
+void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ setUniformInternal(location, count, v, GL_UNSIGNED_INT_VEC4);
+}
+
+void ProgramD3D::defineUniformsAndAssignRegisters(const gl::Context *context)
+{
+ D3DUniformMap uniformMap;
+
+ gl::ShaderBitSet attachedShaders;
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ gl::Shader *shader = mState.getAttachedShader(shaderType);
+ if (shader)
+ {
+ for (const sh::ShaderVariable &uniform : shader->getUniforms(context))
+ {
+ if (uniform.active)
+ {
+ defineUniformBase(shader, uniform, &uniformMap);
+ }
+ }
+
+ attachedShaders.set(shader->getType());
+ }
+ }
+
+ // Initialize the D3DUniform list to mirror the indexing of the GL layer.
+ for (const gl::LinkedUniform &glUniform : mState.getUniforms())
+ {
+ if (!glUniform.isInDefaultBlock())
+ continue;
+
+ std::string name = glUniform.name;
+ if (glUniform.isArray())
+ {
+ // In the program state, array uniform names include [0] as in the program resource
+ // spec. Here we don't include it.
+ // TODO(oetuaho@nvidia.com): consider using the same uniform naming here as in the GL
+ // layer.
+ ASSERT(angle::EndsWith(name, "[0]"));
+ name.resize(name.length() - 3);
+ }
+ auto mapEntry = uniformMap.find(name);
+ ASSERT(mapEntry != uniformMap.end());
+ mD3DUniforms.push_back(mapEntry->second);
+ }
+
+ assignAllSamplerRegisters();
+ assignAllAtomicCounterRegisters();
+ // Samplers and readonly images share shader input resource slot, adjust low value of
+ // readonly image range.
+ for (gl::ShaderType shaderType : {gl::ShaderType::Compute, gl::ShaderType::Fragment})
+ {
+ mUsedReadonlyImageRange[shaderType] =
+ gl::RangeUI(mUsedShaderSamplerRanges[shaderType].high(),
+ mUsedShaderSamplerRanges[shaderType].high());
+ // Atomic counter buffers and non-readonly images share input resource slots
+ mUsedImageRange[shaderType] = gl::RangeUI(mUsedAtomicCounterRange[shaderType].high(),
+ mUsedAtomicCounterRange[shaderType].high());
+ }
+ assignAllImageRegisters();
+ initializeUniformStorage(attachedShaders);
+}
+
+void ProgramD3D::defineUniformBase(const gl::Shader *shader,
+ const sh::ShaderVariable &uniform,
+ D3DUniformMap *uniformMap)
+{
+ sh::StubBlockEncoder stubEncoder;
+
+ // Samplers get their registers assigned in assignAllSamplerRegisters, and images get their
+ // registers assigned in assignAllImageRegisters.
+ if (gl::IsSamplerType(uniform.type))
+ {
+ UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::Texture,
+ &stubEncoder, uniformMap);
+ sh::TraverseShaderVariable(uniform, false, &visitor);
+ return;
+ }
+
+ if (gl::IsImageType(uniform.type))
+ {
+ if (uniform.readonly)
+ {
+ UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::Texture,
+ &stubEncoder, uniformMap);
+ sh::TraverseShaderVariable(uniform, false, &visitor);
+ }
+ else
+ {
+ UniformEncodingVisitorD3D visitor(
+ shader->getType(), HLSLRegisterType::UnorderedAccessView, &stubEncoder, uniformMap);
+ sh::TraverseShaderVariable(uniform, false, &visitor);
+ }
+ mImageBindingMap[uniform.name] = uniform.binding;
+ return;
+ }
+
+ if (uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn())
+ {
+ UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::None, &stubEncoder,
+ uniformMap);
+ sh::TraverseShaderVariable(uniform, false, &visitor);
+ return;
+ }
+ else if (gl::IsAtomicCounterType(uniform.type))
+ {
+ UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::UnorderedAccessView,
+ &stubEncoder, uniformMap);
+ sh::TraverseShaderVariable(uniform, false, &visitor);
+ mAtomicBindingMap[uniform.name] = uniform.binding;
+ return;
+ }
+
+ const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader);
+ unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
+ ShShaderOutput outputType = shaderD3D->getCompilerOutputType();
+ sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType), true);
+ encoder.skipRegisters(startRegister);
+
+ UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::None, &encoder,
+ uniformMap);
+ sh::TraverseShaderVariable(uniform, false, &visitor);
+}
+
+bool ProgramD3D::hasNamedUniform(const std::string &name)
+{
+ for (D3DUniform *d3dUniform : mD3DUniforms)
+ {
+ if (d3dUniform->name == name)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Assume count is already clamped.
+template <typename T>
+void ProgramD3D::setUniformImpl(D3DUniform *targetUniform,
+ const gl::VariableLocation &locationInfo,
+ GLsizei count,
+ const T *v,
+ uint8_t *targetState,
+ GLenum uniformType)
+{
+ const int components = targetUniform->typeInfo.componentCount;
+ const unsigned int arrayElementOffset = locationInfo.arrayIndex;
+ const int blockSize = 4;
+
+ if (targetUniform->typeInfo.type == uniformType)
+ {
+ T *dest = reinterpret_cast<T *>(targetState) + arrayElementOffset * blockSize;
+ const T *source = v;
+
+ // If the component is equal to the block size, we can optimize to a single memcpy.
+ // Otherwise, we have to do partial block writes.
+ if (components == blockSize)
+ {
+ memcpy(dest, source, components * count * sizeof(T));
+ }
+ else
+ {
+ for (GLint i = 0; i < count; i++, dest += blockSize, source += components)
+ {
+ memcpy(dest, source, components * sizeof(T));
+ }
+ }
+ }
+ else
+ {
+ ASSERT(targetUniform->typeInfo.type == gl::VariableBoolVectorType(uniformType));
+ GLint *boolParams = reinterpret_cast<GLint *>(targetState) + arrayElementOffset * 4;
+
+ for (GLint i = 0; i < count; i++)
+ {
+ GLint *dest = boolParams + (i * 4);
+ const T *source = v + (i * components);
+
+ for (int c = 0; c < components; c++)
+ {
+ dest[c] = (source[c] == static_cast<T>(0)) ? GL_FALSE : GL_TRUE;
+ }
+ }
+ }
+}
+
+template <typename T>
+void ProgramD3D::setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType)
+{
+ const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
+ D3DUniform *targetUniform = mD3DUniforms[locationInfo.index];
+
+ if (targetUniform->typeInfo.isSampler)
+ {
+ ASSERT(uniformType == GL_INT);
+ size_t size = count * sizeof(T);
+ GLint *dest = &targetUniform->mSamplerData[locationInfo.arrayIndex];
+ if (memcmp(dest, v, size) != 0)
+ {
+ memcpy(dest, v, size);
+ mDirtySamplerMapping = true;
+ }
+ return;
+ }
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ uint8_t *targetState = targetUniform->mShaderData[shaderType];
+ if (targetState)
+ {
+ setUniformImpl(targetUniform, locationInfo, count, v, targetState, uniformType);
+ mShaderUniformsDirty.set(shaderType);
+ }
+ }
+}
+
+template <int cols, int rows>
+void ProgramD3D::setUniformMatrixfvInternal(GLint location,
+ GLsizei countIn,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ D3DUniform *targetUniform = getD3DUniformFromLocation(location);
+ const gl::VariableLocation &uniformLocation = mState.getUniformLocations()[location];
+ unsigned int arrayElementOffset = uniformLocation.arrayIndex;
+ unsigned int elementCount = targetUniform->getArraySizeProduct();
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ if (targetUniform->mShaderData[shaderType])
+ {
+ SetFloatUniformMatrixHLSL<cols, rows>::Run(arrayElementOffset, elementCount, countIn,
+ transpose, value,
+ targetUniform->mShaderData[shaderType]);
+ mShaderUniformsDirty.set(shaderType);
+ }
+ }
+}
+
+void ProgramD3D::assignAllSamplerRegisters()
+{
+ for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
+ {
+ if (mD3DUniforms[uniformIndex]->isSampler())
+ {
+ assignSamplerRegisters(uniformIndex);
+ }
+ }
+}
+
+void ProgramD3D::assignSamplerRegisters(size_t uniformIndex)
+{
+ D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
+ ASSERT(d3dUniform->isSampler());
+ // If the uniform is an array of arrays, then we have separate entries for each inner array in
+ // mD3DUniforms. However, the sampler register info is stored in the shader only for the
+ // outermost array.
+ std::vector<unsigned int> subscripts;
+ const std::string baseName = gl::ParseResourceName(d3dUniform->name, &subscripts);
+ unsigned int registerOffset =
+ mState.getUniforms()[uniformIndex].parentArrayIndex() * d3dUniform->getArraySizeProduct();
+
+ bool hasUniform = false;
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ if (!mState.getAttachedShader(shaderType))
+ {
+ continue;
+ }
+
+ const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(mState.getAttachedShader(shaderType));
+ if (shaderD3D->hasUniform(baseName))
+ {
+ d3dUniform->mShaderRegisterIndexes[shaderType] =
+ shaderD3D->getUniformRegister(baseName) + registerOffset;
+ ASSERT(d3dUniform->mShaderRegisterIndexes[shaderType] != GL_INVALID_VALUE);
+
+ AssignSamplers(d3dUniform->mShaderRegisterIndexes[shaderType], d3dUniform->typeInfo,
+ d3dUniform->getArraySizeProduct(), mShaderSamplers[shaderType],
+ &mUsedShaderSamplerRanges[shaderType]);
+ hasUniform = true;
+ }
+ }
+
+ ASSERT(hasUniform);
+}
+
+// static
+void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex,
+ const gl::UniformTypeInfo &typeInfo,
+ unsigned int samplerCount,
+ std::vector<Sampler> &outSamplers,
+ gl::RangeUI *outUsedRange)
+{
+ unsigned int samplerIndex = startSamplerIndex;
+
+ do
+ {
+ ASSERT(samplerIndex < outSamplers.size());
+ Sampler *sampler = &outSamplers[samplerIndex];
+ sampler->active = true;
+ sampler->textureType = gl::FromGLenum<gl::TextureType>(typeInfo.textureType);
+ sampler->logicalTextureUnit = 0;
+ outUsedRange->extend(samplerIndex);
+ samplerIndex++;
+ } while (samplerIndex < startSamplerIndex + samplerCount);
+}
+
+void ProgramD3D::assignAllImageRegisters()
+{
+ for (size_t uniformIndex = 0; uniformIndex < mD3DUniforms.size(); ++uniformIndex)
+ {
+ if (mD3DUniforms[uniformIndex]->isImage() && !mD3DUniforms[uniformIndex]->isImage2D())
+ {
+ assignImageRegisters(uniformIndex);
+ }
+ }
+}
+
+void ProgramD3D::assignAllAtomicCounterRegisters()
+{
+ if (mAtomicBindingMap.empty())
+ {
+ return;
+ }
+ gl::ShaderType shaderType = gl::ShaderType::Compute;
+ const gl::Shader *computeShader = mState.getAttachedShader(shaderType);
+ if (computeShader)
+ {
+ const ShaderD3D *computeShaderD3D = GetImplAs<ShaderD3D>(computeShader);
+ auto &registerIndices = mComputeAtomicCounterBufferRegisterIndices;
+ for (auto &atomicBinding : mAtomicBindingMap)
+ {
+ ASSERT(computeShaderD3D->hasUniform(atomicBinding.first));
+ unsigned int currentRegister =
+ computeShaderD3D->getUniformRegister(atomicBinding.first);
+ ASSERT(currentRegister != GL_INVALID_INDEX);
+ const int kBinding = atomicBinding.second;
+
+ registerIndices[kBinding] = currentRegister;
+
+ mUsedAtomicCounterRange[gl::ShaderType::Compute].extend(currentRegister);
+ }
+ }
+ else
+ {
+ // Implement atomic counters for non-compute shaders
+ // http://anglebug.com/1729
+ UNIMPLEMENTED();
+ }
+}
+
+void ProgramD3D::assignImageRegisters(size_t uniformIndex)
+{
+ D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
+ ASSERT(d3dUniform->isImage());
+ // If the uniform is an array of arrays, then we have separate entries for each inner array in
+ // mD3DUniforms. However, the image register info is stored in the shader only for the
+ // outermost array.
+ std::vector<unsigned int> subscripts;
+ const std::string baseName = gl::ParseResourceName(d3dUniform->name, &subscripts);
+ unsigned int registerOffset =
+ mState.getUniforms()[uniformIndex].parentArrayIndex() * d3dUniform->getArraySizeProduct();
+
+ const gl::Shader *computeShader = mState.getAttachedShader(gl::ShaderType::Compute);
+ if (computeShader)
+ {
+ const ShaderD3D *computeShaderD3D =
+ GetImplAs<ShaderD3D>(mState.getAttachedShader(gl::ShaderType::Compute));
+ ASSERT(computeShaderD3D->hasUniform(baseName));
+ d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] =
+ computeShaderD3D->getUniformRegister(baseName) + registerOffset;
+ ASSERT(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute] != GL_INVALID_INDEX);
+ auto bindingIter = mImageBindingMap.find(baseName);
+ ASSERT(bindingIter != mImageBindingMap.end());
+ if (d3dUniform->regType == HLSLRegisterType::Texture)
+ {
+ AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute],
+ bindingIter->second, d3dUniform->getArraySizeProduct(),
+ mReadonlyImages[gl::ShaderType::Compute],
+ &mUsedReadonlyImageRange[gl::ShaderType::Compute]);
+ }
+ else if (d3dUniform->regType == HLSLRegisterType::UnorderedAccessView)
+ {
+ AssignImages(d3dUniform->mShaderRegisterIndexes[gl::ShaderType::Compute],
+ bindingIter->second, d3dUniform->getArraySizeProduct(),
+ mImages[gl::ShaderType::Compute],
+ &mUsedImageRange[gl::ShaderType::Compute]);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ // TODO(xinghua.cao@intel.com): Implement image variables in vertex shader and pixel shader.
+ UNIMPLEMENTED();
+ }
+}
+
+// static
+void ProgramD3D::AssignImages(unsigned int startImageIndex,
+ int startLogicalImageUnit,
+ unsigned int imageCount,
+ std::vector<Image> &outImages,
+ gl::RangeUI *outUsedRange)
+{
+ unsigned int imageIndex = startImageIndex;
+
+ // If declare without a binding qualifier, any uniform image variable (include all elements of
+ // unbound image array) shoud be bound to unit zero.
+ if (startLogicalImageUnit == -1)
+ {
+ ASSERT(imageIndex < outImages.size());
+ Image *image = &outImages[imageIndex];
+ image->active = true;
+ image->logicalImageUnit = 0;
+ outUsedRange->extend(imageIndex);
+ return;
+ }
+
+ unsigned int logcalImageUnit = startLogicalImageUnit;
+ do
+ {
+ ASSERT(imageIndex < outImages.size());
+ Image *image = &outImages[imageIndex];
+ image->active = true;
+ image->logicalImageUnit = logcalImageUnit;
+ outUsedRange->extend(imageIndex);
+ imageIndex++;
+ logcalImageUnit++;
+ } while (imageIndex < startImageIndex + imageCount);
+}
+
+void ProgramD3D::assignImage2DRegisters(gl::ShaderType shaderType,
+ unsigned int startImageIndex,
+ int startLogicalImageUnit,
+ bool readonly)
+{
+ if (readonly)
+ {
+ AssignImages(startImageIndex, startLogicalImageUnit, 1, mReadonlyImages[shaderType],
+ &mUsedReadonlyImageRange[shaderType]);
+ }
+ else
+ {
+ AssignImages(startImageIndex, startLogicalImageUnit, 1, mImages[shaderType],
+ &mUsedImageRange[shaderType]);
+ }
+}
+
+void ProgramD3D::reset()
+{
+ mVertexExecutables.clear();
+ mPixelExecutables.clear();
+ mComputeExecutables.clear();
+
+ for (auto &geometryExecutable : mGeometryExecutables)
+ {
+ geometryExecutable.reset(nullptr);
+ }
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ mShaderHLSL[shaderType].clear();
+ }
+
+ mUsesFragDepth = false;
+ mHasANGLEMultiviewEnabled = false;
+ mUsesVertexID = false;
+ mUsesViewID = false;
+ mPixelShaderKey.clear();
+ mUsesPointSize = false;
+ mUsesFlatInterpolation = false;
+
+ SafeDeleteContainer(mD3DUniforms);
+ mD3DUniformBlocks.clear();
+ mD3DShaderStorageBlocks.clear();
+ mComputeAtomicCounterBufferRegisterIndices.fill({});
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ mShaderUniformStorages[shaderType].reset();
+ mShaderSamplers[shaderType].clear();
+ mImages[shaderType].clear();
+ mReadonlyImages[shaderType].clear();
+ }
+
+ mUsedShaderSamplerRanges.fill({0, 0});
+ mUsedAtomicCounterRange.fill({0, 0});
+ mDirtySamplerMapping = true;
+ mUsedImageRange.fill({0, 0});
+ mUsedReadonlyImageRange.fill({0, 0});
+
+ mAttribLocationToD3DSemantic.fill(-1);
+
+ mStreamOutVaryings.clear();
+
+ mGeometryShaderPreamble.clear();
+
+ markUniformsClean();
+
+ mCachedPixelExecutableIndex.reset();
+ mCachedVertexExecutableIndex.reset();
+}
+
+unsigned int ProgramD3D::getSerial() const
+{
+ return mSerial;
+}
+
+unsigned int ProgramD3D::issueSerial()
+{
+ return mCurrentSerial++;
+}
+
+void ProgramD3D::initAttribLocationsToD3DSemantic(const gl::Context *context)
+{
+ gl::Shader *vertexShader = mState.getAttachedShader(gl::ShaderType::Vertex);
+ if (!vertexShader)
+ {
+ return;
+ }
+
+ // Init semantic index
+ int semanticIndex = 0;
+ for (const sh::ShaderVariable &attribute : vertexShader->getActiveAttributes(context))
+ {
+ int regCount = gl::VariableRegisterCount(attribute.type);
+ GLuint location = mState.getAttributeLocation(attribute.name);
+ ASSERT(location != std::numeric_limits<GLuint>::max());
+
+ for (int reg = 0; reg < regCount; ++reg)
+ {
+ mAttribLocationToD3DSemantic[location + reg] = semanticIndex++;
+ }
+ }
+}
+
+void ProgramD3D::updateCachedInputLayout(Serial associatedSerial, const gl::State &state)
+{
+ if (mCurrentVertexArrayStateSerial == associatedSerial)
+ {
+ return;
+ }
+
+ mCurrentVertexArrayStateSerial = associatedSerial;
+ mCachedInputLayout.clear();
+
+ const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes();
+ const gl::AttributesMask &attributesMask =
+ mState.getExecutable().getActiveAttribLocationsMask();
+
+ for (size_t locationIndex : attributesMask)
+ {
+ int d3dSemantic = mAttribLocationToD3DSemantic[locationIndex];
+
+ if (d3dSemantic != -1)
+ {
+ if (mCachedInputLayout.size() < static_cast<size_t>(d3dSemantic + 1))
+ {
+ mCachedInputLayout.resize(d3dSemantic + 1, angle::FormatID::NONE);
+ }
+ mCachedInputLayout[d3dSemantic] =
+ GetVertexFormatID(vertexAttributes[locationIndex],
+ state.getVertexAttribCurrentValue(locationIndex).Type);
+ }
+ }
+
+ VertexExecutable::getSignature(mRenderer, mCachedInputLayout, &mCachedVertexSignature);
+
+ updateCachedVertexExecutableIndex();
+}
+
+void ProgramD3D::updateCachedOutputLayout(const gl::Context *context,
+ const gl::Framebuffer *framebuffer)
+{
+ mPixelShaderOutputLayoutCache.clear();
+
+ FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(framebuffer);
+ const auto &colorbuffers = fboD3D->getColorAttachmentsForRender(context);
+
+ for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
+ {
+ const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment];
+
+ if (colorbuffer)
+ {
+ auto binding = colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0
+ : colorbuffer->getBinding();
+ size_t maxIndex = binding != GL_NONE ? GetMaxOutputIndex(mPixelShaderKey,
+ binding - GL_COLOR_ATTACHMENT0)
+ : 0;
+ mPixelShaderOutputLayoutCache.insert(mPixelShaderOutputLayoutCache.end(), maxIndex + 1,
+ binding);
+ }
+ else
+ {
+ mPixelShaderOutputLayoutCache.push_back(GL_NONE);
+ }
+ }
+
+ updateCachedPixelExecutableIndex();
+}
+
+void ProgramD3D::updateCachedComputeImage2DBindLayout(const gl::Context *context)
+{
+ const auto &glState = context->getState();
+ for (auto &image2DBindLayout : mImage2DBindLayoutCache[gl::ShaderType::Compute])
+ {
+ const gl::ImageUnit &imageUnit = glState.getImageUnit(image2DBindLayout.first);
+ if (imageUnit.texture.get())
+ {
+ image2DBindLayout.second = imageUnit.texture->getType();
+ }
+ else
+ {
+ image2DBindLayout.second = gl::TextureType::_2D;
+ }
+ }
+
+ updateCachedComputeExecutableIndex();
+}
+
+void ProgramD3D::gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyingPacking,
+ const BuiltinInfo &builtins)
+{
+ const std::string &varyingSemantic =
+ GetVaryingSemantic(mRenderer->getMajorShaderModel(), usesPointSize());
+
+ // Gather the linked varyings that are used for transform feedback, they should all exist.
+ mStreamOutVaryings.clear();
+
+ const auto &tfVaryingNames = mState.getTransformFeedbackVaryingNames();
+ for (unsigned int outputSlot = 0; outputSlot < static_cast<unsigned int>(tfVaryingNames.size());
+ ++outputSlot)
+ {
+ const auto &tfVaryingName = tfVaryingNames[outputSlot];
+ if (tfVaryingName == "gl_Position")
+ {
+ if (builtins.glPosition.enabled)
+ {
+ mStreamOutVaryings.emplace_back(builtins.glPosition.semantic,
+ builtins.glPosition.index, 4, outputSlot);
+ }
+ }
+ else if (tfVaryingName == "gl_FragCoord")
+ {
+ if (builtins.glFragCoord.enabled)
+ {
+ mStreamOutVaryings.emplace_back(builtins.glFragCoord.semantic,
+ builtins.glFragCoord.index, 4, outputSlot);
+ }
+ }
+ else if (tfVaryingName == "gl_PointSize")
+ {
+ if (builtins.glPointSize.enabled)
+ {
+ mStreamOutVaryings.emplace_back("PSIZE", 0, 1, outputSlot);
+ }
+ }
+ else
+ {
+ const auto &registerInfos = varyingPacking.getRegisterList();
+ for (GLuint registerIndex = 0u; registerIndex < registerInfos.size(); ++registerIndex)
+ {
+ const auto &registerInfo = registerInfos[registerIndex];
+ const auto &varying = registerInfo.packedVarying->varying();
+ GLenum transposedType = gl::TransposeMatrixType(varying.type);
+ int componentCount = gl::VariableColumnCount(transposedType);
+ ASSERT(!varying.isBuiltIn() && !varying.isStruct());
+
+ // There can be more than one register assigned to a particular varying, and each
+ // register needs its own stream out entry.
+ if (registerInfo.tfVaryingName() == tfVaryingName)
+ {
+ mStreamOutVaryings.emplace_back(varyingSemantic, registerIndex, componentCount,
+ outputSlot);
+ }
+ }
+ }
+ }
+}
+
+D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location)
+{
+ return mD3DUniforms[mState.getUniformLocations()[location].index];
+}
+
+const D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location) const
+{
+ return mD3DUniforms[mState.getUniformLocations()[location].index];
+}
+
+bool ProgramD3D::hasVertexExecutableForCachedInputLayout()
+{
+ return mCachedVertexExecutableIndex.valid();
+}
+
+bool ProgramD3D::hasGeometryExecutableForPrimitiveType(const gl::State &state,
+ gl::PrimitiveMode drawMode)
+{
+ if (!usesGeometryShader(state, drawMode))
+ {
+ // No shader necessary mean we have the required (null) executable.
+ return true;
+ }
+
+ gl::PrimitiveMode geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode);
+ return mGeometryExecutables[geometryShaderType].get() != nullptr;
+}
+
+bool ProgramD3D::hasPixelExecutableForCachedOutputLayout()
+{
+ return mCachedPixelExecutableIndex.valid();
+}
+
+bool ProgramD3D::hasComputeExecutableForCachedImage2DBindLayout()
+{
+ return mCachedComputeExecutableIndex.valid();
+}
+
+template <typename DestT>
+void ProgramD3D::getUniformInternal(GLint location, DestT *dataOut) const
+{
+ const gl::VariableLocation &locationInfo = mState.getUniformLocations()[location];
+ const gl::LinkedUniform &uniform = mState.getUniforms()[locationInfo.index];
+
+ const D3DUniform *targetUniform = getD3DUniformFromLocation(location);
+ const uint8_t *srcPointer = targetUniform->getDataPtrToElement(locationInfo.arrayIndex);
+
+ if (gl::IsMatrixType(uniform.type))
+ {
+ GetMatrixUniform(uniform.type, dataOut, reinterpret_cast<const DestT *>(srcPointer), true);
+ }
+ else
+ {
+ memcpy(dataOut, srcPointer, uniform.getElementSize());
+ }
+}
+
+void ProgramD3D::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
+{
+ getUniformInternal(location, params);
+}
+
+void ProgramD3D::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
+{
+ getUniformInternal(location, params);
+}
+
+void ProgramD3D::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
+{
+ getUniformInternal(location, params);
+}
+
+void ProgramD3D::updateCachedVertexExecutableIndex()
+{
+ mCachedVertexExecutableIndex.reset();
+ for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++)
+ {
+ if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature))
+ {
+ mCachedVertexExecutableIndex = executableIndex;
+ break;
+ }
+ }
+}
+
+void ProgramD3D::updateCachedPixelExecutableIndex()
+{
+ mCachedPixelExecutableIndex.reset();
+ for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
+ {
+ if (mPixelExecutables[executableIndex]->matchesSignature(mPixelShaderOutputLayoutCache))
+ {
+ mCachedPixelExecutableIndex = executableIndex;
+ break;
+ }
+ }
+}
+
+void ProgramD3D::updateCachedComputeExecutableIndex()
+{
+ mCachedComputeExecutableIndex.reset();
+ for (size_t executableIndex = 0; executableIndex < mComputeExecutables.size();
+ executableIndex++)
+ {
+ if (mComputeExecutables[executableIndex]->matchesSignature(
+ mImage2DBindLayoutCache[gl::ShaderType::Compute]))
+ {
+ mCachedComputeExecutableIndex = executableIndex;
+ break;
+ }
+ }
+}
+
+void ProgramD3D::linkResources(const gl::Context *context,
+ const gl::ProgramLinkedResources &resources)
+{
+ HLSLBlockLayoutEncoderFactory hlslEncoderFactory;
+ gl::ProgramLinkedResourcesLinker linker(&hlslEncoderFactory);
+
+ linker.linkResources(context, mState, resources);
+
+ initializeUniformBlocks();
+ initializeShaderStorageBlocks(context);
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/ProgramD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ProgramD3D.h
new file mode 100644
index 0000000000..baa77fcb79
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ProgramD3D.h
@@ -0,0 +1,613 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ProgramD3D.h: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_
+#define LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_
+
+#include <string>
+#include <vector>
+
+#include "compiler/translator/blocklayoutHLSL.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ProgramImpl.h"
+#include "libANGLE/renderer/d3d/DynamicHLSL.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "platform/FeaturesD3D_autogen.h"
+
+namespace rx
+{
+class RendererD3D;
+class UniformStorageD3D;
+class ShaderExecutableD3D;
+
+#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
+// WARNING: D3DCOMPILE_OPTIMIZATION_LEVEL3 may lead to a DX9 shader compiler hang.
+// It should only be used selectively to work around specific bugs.
+# define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1
+#endif
+
+enum class HLSLRegisterType : uint8_t
+{
+ None = 0,
+ Texture = 1,
+ UnorderedAccessView = 2
+};
+
+// Helper struct representing a single shader uniform
+// TODO(jmadill): Make uniform blocks shared between all programs, so we don't need separate
+// register indices.
+struct D3DUniform : private angle::NonCopyable
+{
+ D3DUniform(GLenum type,
+ HLSLRegisterType reg,
+ const std::string &nameIn,
+ const std::vector<unsigned int> &arraySizesIn,
+ bool defaultBlock);
+ ~D3DUniform();
+
+ bool isSampler() const;
+ bool isImage() const;
+ bool isImage2D() const;
+ bool isArray() const { return !arraySizes.empty(); }
+ unsigned int getArraySizeProduct() const;
+ bool isReferencedByShader(gl::ShaderType shaderType) const;
+
+ const uint8_t *firstNonNullData() const;
+ const uint8_t *getDataPtrToElement(size_t elementIndex) const;
+
+ // Duplicated from the GL layer
+ const gl::UniformTypeInfo &typeInfo;
+ std::string name; // Names of arrays don't include [0], unlike at the GL layer.
+ std::vector<unsigned int> arraySizes;
+
+ // Pointer to a system copies of the data. Separate pointers for each uniform storage type.
+ gl::ShaderMap<uint8_t *> mShaderData;
+
+ // Register information.
+ HLSLRegisterType regType;
+ gl::ShaderMap<unsigned int> mShaderRegisterIndexes;
+ unsigned int registerCount;
+
+ // Register "elements" are used for uniform structs in ES3, to appropriately identify single
+ // uniforms
+ // inside aggregate types, which are packed according C-like structure rules.
+ unsigned int registerElement;
+
+ // Special buffer for sampler values.
+ std::vector<GLint> mSamplerData;
+};
+
+struct D3DInterfaceBlock
+{
+ D3DInterfaceBlock();
+ D3DInterfaceBlock(const D3DInterfaceBlock &other);
+
+ bool activeInShader(gl::ShaderType shaderType) const
+ {
+ return mShaderRegisterIndexes[shaderType] != GL_INVALID_INDEX;
+ }
+
+ gl::ShaderMap<unsigned int> mShaderRegisterIndexes;
+};
+
+struct D3DUniformBlock : D3DInterfaceBlock
+{
+ D3DUniformBlock();
+ D3DUniformBlock(const D3DUniformBlock &other);
+
+ gl::ShaderMap<bool> mUseStructuredBuffers;
+ gl::ShaderMap<unsigned int> mByteWidths;
+ gl::ShaderMap<unsigned int> mStructureByteStrides;
+};
+
+struct ShaderStorageBlock
+{
+ std::string name;
+ unsigned int arraySize = 0;
+ unsigned int registerIndex = 0;
+};
+
+struct D3DUBOCache
+{
+ unsigned int registerIndex;
+ int binding;
+};
+
+struct D3DUBOCacheUseSB : D3DUBOCache
+{
+ unsigned int byteWidth;
+ unsigned int structureByteStride;
+};
+
+struct D3DVarying final
+{
+ D3DVarying();
+ D3DVarying(const std::string &semanticNameIn,
+ unsigned int semanticIndexIn,
+ unsigned int componentCountIn,
+ unsigned int outputSlotIn);
+
+ D3DVarying(const D3DVarying &) = default;
+ D3DVarying &operator=(const D3DVarying &) = default;
+
+ std::string semanticName;
+ unsigned int semanticIndex;
+ unsigned int componentCount;
+ unsigned int outputSlot;
+};
+
+class ProgramD3DMetadata final : angle::NonCopyable
+{
+ public:
+ ProgramD3DMetadata(RendererD3D *renderer,
+ const gl::ShaderMap<const ShaderD3D *> &attachedShaders,
+ EGLenum clientType);
+ ~ProgramD3DMetadata();
+
+ int getRendererMajorShaderModel() const;
+ bool usesBroadcast(const gl::State &data) const;
+ bool usesSecondaryColor() const;
+ bool usesFragDepth() const;
+ bool usesPointCoord() const;
+ bool usesFragCoord() const;
+ bool usesPointSize() const;
+ bool usesInsertedPointCoordValue() const;
+ bool usesViewScale() const;
+ bool hasANGLEMultiviewEnabled() const;
+ bool usesVertexID() const;
+ bool usesViewID() const;
+ bool canSelectViewInVertexShader() const;
+ bool addsPointCoordToVertexShader() const;
+ bool usesTransformFeedbackGLPosition() const;
+ bool usesSystemValuePointSize() const;
+ bool usesMultipleFragmentOuts() const;
+ bool usesCustomOutVars() const;
+ const ShaderD3D *getFragmentShader() const;
+
+ private:
+ const int mRendererMajorShaderModel;
+ const std::string mShaderModelSuffix;
+ const bool mUsesInstancedPointSpriteEmulation;
+ const bool mUsesViewScale;
+ const bool mCanSelectViewInVertexShader;
+ const gl::ShaderMap<const ShaderD3D *> mAttachedShaders;
+ const EGLenum mClientType;
+};
+
+using D3DUniformMap = std::map<std::string, D3DUniform *>;
+
+class ProgramD3D : public ProgramImpl
+{
+ public:
+ ProgramD3D(const gl::ProgramState &data, RendererD3D *renderer);
+ ~ProgramD3D() override;
+
+ const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; }
+
+ GLint getSamplerMapping(gl::ShaderType type,
+ unsigned int samplerIndex,
+ const gl::Caps &caps) const;
+ gl::TextureType getSamplerTextureType(gl::ShaderType type, unsigned int samplerIndex) const;
+ gl::RangeUI getUsedSamplerRange(gl::ShaderType type) const;
+
+ enum SamplerMapping
+ {
+ WasDirty,
+ WasClean,
+ };
+
+ SamplerMapping updateSamplerMapping();
+
+ GLint getImageMapping(gl::ShaderType type,
+ unsigned int imageIndex,
+ bool readonly,
+ const gl::Caps &caps) const;
+ gl::RangeUI getUsedImageRange(gl::ShaderType type, bool readonly) const;
+
+ bool usesPointSize() const { return mUsesPointSize; }
+ bool usesPointSpriteEmulation() const;
+ bool usesGeometryShader(const gl::State &state, gl::PrimitiveMode drawMode) const;
+ bool usesGeometryShaderForPointSpriteEmulation() const;
+ bool usesGetDimensionsIgnoresBaseLevel() const;
+ bool usesInstancedPointSpriteEmulation() const;
+
+ std::unique_ptr<LinkEvent> load(const gl::Context *context,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog) override;
+ void save(const gl::Context *context, gl::BinaryOutputStream *stream) override;
+ void setBinaryRetrievableHint(bool retrievable) override;
+ void setSeparable(bool separable) override;
+
+ angle::Result getVertexExecutableForCachedInputLayout(d3d::Context *context,
+ ShaderExecutableD3D **outExectuable,
+ gl::InfoLog *infoLog);
+ angle::Result getGeometryExecutableForPrimitiveType(d3d::Context *errContext,
+ const gl::State &state,
+ gl::PrimitiveMode drawMode,
+ ShaderExecutableD3D **outExecutable,
+ gl::InfoLog *infoLog);
+ angle::Result getPixelExecutableForCachedOutputLayout(d3d::Context *context,
+ ShaderExecutableD3D **outExectuable,
+ gl::InfoLog *infoLog);
+ angle::Result getComputeExecutableForImage2DBindLayout(const gl::Context *glContext,
+ d3d::Context *context,
+ ShaderExecutableD3D **outExecutable,
+ gl::InfoLog *infoLog);
+ std::unique_ptr<LinkEvent> link(const gl::Context *context,
+ const gl::ProgramLinkedResources &resources,
+ gl::InfoLog &infoLog,
+ const gl::ProgramMergedVaryings &mergedVaryings) override;
+ GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override;
+
+ void updateUniformBufferCache(const gl::Caps &caps);
+
+ unsigned int getAtomicCounterBufferRegisterIndex(GLuint binding,
+ gl::ShaderType shaderType) const;
+
+ unsigned int getShaderStorageBufferRegisterIndex(GLuint blockIndex,
+ gl::ShaderType shaderType) const;
+ const std::vector<D3DUBOCache> &getShaderUniformBufferCache(gl::ShaderType shaderType) const;
+ const std::vector<D3DUBOCacheUseSB> &getShaderUniformBufferCacheUseSB(
+ gl::ShaderType shaderType) const;
+
+ void dirtyAllUniforms();
+
+ void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) override;
+ void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) override;
+ void setUniform3fv(GLint location, GLsizei count, const GLfloat *v) override;
+ void setUniform4fv(GLint location, GLsizei count, const GLfloat *v) override;
+ void setUniform1iv(GLint location, GLsizei count, const GLint *v) override;
+ void setUniform2iv(GLint location, GLsizei count, const GLint *v) override;
+ void setUniform3iv(GLint location, GLsizei count, const GLint *v) override;
+ void setUniform4iv(GLint location, GLsizei count, const GLint *v) override;
+ void setUniform1uiv(GLint location, GLsizei count, const GLuint *v) override;
+ void setUniform2uiv(GLint location, GLsizei count, const GLuint *v) override;
+ void setUniform3uiv(GLint location, GLsizei count, const GLuint *v) override;
+ void setUniform4uiv(GLint location, GLsizei count, const GLuint *v) override;
+ void setUniformMatrix2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) override;
+ void setUniformMatrix3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) override;
+ void setUniformMatrix4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) override;
+ void setUniformMatrix2x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) override;
+ void setUniformMatrix3x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) override;
+ void setUniformMatrix2x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) override;
+ void setUniformMatrix4x2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) override;
+ void setUniformMatrix3x4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) override;
+ void setUniformMatrix4x3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value) override;
+
+ void getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const override;
+ void getUniformiv(const gl::Context *context, GLint location, GLint *params) const override;
+ void getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const override;
+
+ UniformStorageD3D *getShaderUniformStorage(gl::ShaderType shaderType) const
+ {
+ return mShaderUniformStorages[shaderType].get();
+ }
+
+ unsigned int getSerial() const;
+
+ const AttribIndexArray &getAttribLocationToD3DSemantics() const
+ {
+ return mAttribLocationToD3DSemantic;
+ }
+
+ void updateCachedInputLayout(Serial associatedSerial, const gl::State &state);
+ void updateCachedOutputLayout(const gl::Context *context, const gl::Framebuffer *framebuffer);
+ void updateCachedComputeImage2DBindLayout(const gl::Context *context);
+
+ bool isSamplerMappingDirty() { return mDirtySamplerMapping; }
+
+ // Checks if we need to recompile certain shaders.
+ bool hasVertexExecutableForCachedInputLayout();
+ bool hasGeometryExecutableForPrimitiveType(const gl::State &state, gl::PrimitiveMode drawMode);
+ bool hasPixelExecutableForCachedOutputLayout();
+ bool hasComputeExecutableForCachedImage2DBindLayout();
+
+ bool anyShaderUniformsDirty() const { return mShaderUniformsDirty.any(); }
+
+ bool areShaderUniformsDirty(gl::ShaderType shaderType) const
+ {
+ return mShaderUniformsDirty[shaderType];
+ }
+ const std::vector<D3DUniform *> &getD3DUniforms() const { return mD3DUniforms; }
+ void markUniformsClean();
+
+ const gl::ProgramState &getState() const { return mState; }
+
+ bool hasShaderStage(gl::ShaderType shaderType) const
+ {
+ return mState.getExecutable().getLinkedShaderStages()[shaderType];
+ }
+
+ void assignImage2DRegisters(gl::ShaderType shaderType,
+ unsigned int startImageIndex,
+ int startLogicalImageUnit,
+ bool readonly);
+ bool hasNamedUniform(const std::string &name);
+
+ bool usesVertexID() const { return mUsesVertexID; }
+
+ private:
+ // These forward-declared tasks are used for multi-thread shader compiles.
+ class GetExecutableTask;
+ class GetVertexExecutableTask;
+ class GetPixelExecutableTask;
+ class GetGeometryExecutableTask;
+ class GetComputeExecutableTask;
+ class GraphicsProgramLinkEvent;
+ class ComputeProgramLinkEvent;
+
+ class LoadBinaryTask;
+ class LoadBinaryLinkEvent;
+
+ class VertexExecutable
+ {
+ public:
+ enum HLSLAttribType
+ {
+ FLOAT,
+ UNSIGNED_INT,
+ SIGNED_INT,
+ };
+
+ typedef std::vector<HLSLAttribType> Signature;
+
+ VertexExecutable(const gl::InputLayout &inputLayout,
+ const Signature &signature,
+ ShaderExecutableD3D *shaderExecutable);
+ ~VertexExecutable();
+
+ bool matchesSignature(const Signature &signature) const;
+ static void getSignature(RendererD3D *renderer,
+ const gl::InputLayout &inputLayout,
+ Signature *signatureOut);
+
+ const gl::InputLayout &inputs() const { return mInputs; }
+ const Signature &signature() const { return mSignature; }
+ ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; }
+
+ private:
+ static HLSLAttribType GetAttribType(GLenum type);
+
+ gl::InputLayout mInputs;
+ Signature mSignature;
+ ShaderExecutableD3D *mShaderExecutable;
+ };
+
+ class PixelExecutable
+ {
+ public:
+ PixelExecutable(const std::vector<GLenum> &outputSignature,
+ ShaderExecutableD3D *shaderExecutable);
+ ~PixelExecutable();
+
+ bool matchesSignature(const std::vector<GLenum> &signature) const
+ {
+ return mOutputSignature == signature;
+ }
+
+ const std::vector<GLenum> &outputSignature() const { return mOutputSignature; }
+ ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; }
+
+ private:
+ std::vector<GLenum> mOutputSignature;
+ ShaderExecutableD3D *mShaderExecutable;
+ };
+
+ class ComputeExecutable
+ {
+ public:
+ ComputeExecutable(const gl::ImageUnitTextureTypeMap &signature,
+ std::unique_ptr<ShaderExecutableD3D> shaderExecutable);
+ ~ComputeExecutable();
+
+ bool matchesSignature(const gl::ImageUnitTextureTypeMap &signature) const
+ {
+ return mSignature == signature;
+ }
+
+ const gl::ImageUnitTextureTypeMap &signature() const { return mSignature; }
+ ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable.get(); }
+
+ private:
+ gl::ImageUnitTextureTypeMap mSignature;
+ std::unique_ptr<ShaderExecutableD3D> mShaderExecutable;
+ };
+
+ struct Sampler
+ {
+ Sampler();
+
+ bool active;
+ GLint logicalTextureUnit;
+ gl::TextureType textureType;
+ };
+
+ struct Image
+ {
+ Image();
+ bool active;
+ GLint logicalImageUnit;
+ };
+
+ void initializeUniformStorage(const gl::ShaderBitSet &availableShaderStages);
+
+ void defineUniformsAndAssignRegisters(const gl::Context *context);
+ void defineUniformBase(const gl::Shader *shader,
+ const sh::ShaderVariable &uniform,
+ D3DUniformMap *uniformMap);
+ void assignAllSamplerRegisters();
+ void assignSamplerRegisters(size_t uniformIndex);
+
+ static void AssignSamplers(unsigned int startSamplerIndex,
+ const gl::UniformTypeInfo &typeInfo,
+ unsigned int samplerCount,
+ std::vector<Sampler> &outSamplers,
+ gl::RangeUI *outUsedRange);
+
+ void assignAllImageRegisters();
+ void assignAllAtomicCounterRegisters();
+ void assignImageRegisters(size_t uniformIndex);
+ static void AssignImages(unsigned int startImageIndex,
+ int startLogicalImageUnit,
+ unsigned int imageCount,
+ std::vector<Image> &outImages,
+ gl::RangeUI *outUsedRange);
+
+ template <typename DestT>
+ void getUniformInternal(GLint location, DestT *dataOut) const;
+
+ template <typename T>
+ void setUniformImpl(D3DUniform *targetUniform,
+ const gl::VariableLocation &locationInfo,
+ GLsizei count,
+ const T *v,
+ uint8_t *targetData,
+ GLenum uniformType);
+
+ template <typename T>
+ void setUniformInternal(GLint location, GLsizei count, const T *v, GLenum uniformType);
+
+ template <int cols, int rows>
+ void setUniformMatrixfvInternal(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+
+ std::unique_ptr<LinkEvent> compileProgramExecutables(const gl::Context *context,
+ gl::InfoLog &infoLog);
+ std::unique_ptr<LinkEvent> compileComputeExecutable(const gl::Context *context,
+ gl::InfoLog &infoLog);
+
+ angle::Result loadBinaryShaderExecutables(d3d::Context *contextD3D,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog);
+
+ void gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyings,
+ const BuiltinInfo &builtins);
+ D3DUniform *getD3DUniformFromLocation(GLint location);
+ const D3DUniform *getD3DUniformFromLocation(GLint location) const;
+
+ void initAttribLocationsToD3DSemantic(const gl::Context *context);
+
+ void reset();
+ void initializeUniformBlocks();
+ void initializeShaderStorageBlocks(const gl::Context *context);
+
+ void updateCachedInputLayoutFromShader(const gl::Context *context);
+ void updateCachedOutputLayoutFromShader();
+ void updateCachedImage2DBindLayoutFromShader(gl::ShaderType shaderType);
+ void updateCachedVertexExecutableIndex();
+ void updateCachedPixelExecutableIndex();
+ void updateCachedComputeExecutableIndex();
+
+ void linkResources(const gl::Context *context, const gl::ProgramLinkedResources &resources);
+
+ RendererD3D *mRenderer;
+ DynamicHLSL *mDynamicHLSL;
+
+ std::vector<std::unique_ptr<VertexExecutable>> mVertexExecutables;
+ std::vector<std::unique_ptr<PixelExecutable>> mPixelExecutables;
+ angle::PackedEnumMap<gl::PrimitiveMode, std::unique_ptr<ShaderExecutableD3D>>
+ mGeometryExecutables;
+ std::vector<std::unique_ptr<ComputeExecutable>> mComputeExecutables;
+
+ gl::ShaderMap<std::string> mShaderHLSL;
+ gl::ShaderMap<CompilerWorkaroundsD3D> mShaderWorkarounds;
+
+ bool mUsesFragDepth;
+ bool mHasANGLEMultiviewEnabled;
+ bool mUsesVertexID;
+ bool mUsesViewID;
+ std::vector<PixelShaderOutputVariable> mPixelShaderKey;
+
+ // Common code for all dynamic geometry shaders. Consists mainly of the GS input and output
+ // structures, built from the linked varying info. We store the string itself instead of the
+ // packed varyings for simplicity.
+ std::string mGeometryShaderPreamble;
+
+ bool mUsesPointSize;
+ bool mUsesFlatInterpolation;
+
+ gl::ShaderMap<std::unique_ptr<UniformStorageD3D>> mShaderUniformStorages;
+
+ gl::ShaderMap<std::vector<Sampler>> mShaderSamplers;
+ gl::ShaderMap<gl::RangeUI> mUsedShaderSamplerRanges;
+ bool mDirtySamplerMapping;
+
+ gl::ShaderMap<std::vector<Image>> mImages;
+ gl::ShaderMap<std::vector<Image>> mReadonlyImages;
+ gl::ShaderMap<gl::RangeUI> mUsedImageRange;
+ gl::ShaderMap<gl::RangeUI> mUsedReadonlyImageRange;
+ gl::ShaderMap<gl::RangeUI> mUsedAtomicCounterRange;
+
+ // Cache for pixel shader output layout to save reallocations.
+ std::vector<GLenum> mPixelShaderOutputLayoutCache;
+ Optional<size_t> mCachedPixelExecutableIndex;
+
+ AttribIndexArray mAttribLocationToD3DSemantic;
+
+ unsigned int mSerial;
+
+ gl::ShaderMap<std::vector<D3DUBOCache>> mShaderUBOCaches;
+ gl::ShaderMap<std::vector<D3DUBOCacheUseSB>> mShaderUBOCachesUseSB;
+ VertexExecutable::Signature mCachedVertexSignature;
+ gl::InputLayout mCachedInputLayout;
+ Optional<size_t> mCachedVertexExecutableIndex;
+
+ std::vector<D3DVarying> mStreamOutVaryings;
+ std::vector<D3DUniform *> mD3DUniforms;
+ std::map<std::string, int> mImageBindingMap;
+ std::map<std::string, int> mAtomicBindingMap;
+ std::vector<D3DUniformBlock> mD3DUniformBlocks;
+ std::vector<D3DInterfaceBlock> mD3DShaderStorageBlocks;
+ gl::ShaderMap<std::vector<ShaderStorageBlock>> mShaderStorageBlocks;
+ std::array<unsigned int, gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS>
+ mComputeAtomicCounterBufferRegisterIndices;
+
+ gl::ShaderMap<std::vector<sh::ShaderVariable>> mImage2DUniforms;
+ gl::ShaderMap<gl::ImageUnitTextureTypeMap> mImage2DBindLayoutCache;
+ Optional<size_t> mCachedComputeExecutableIndex;
+
+ gl::ShaderBitSet mShaderUniformsDirty;
+
+ static unsigned int issueSerial();
+ static unsigned int mCurrentSerial;
+
+ Serial mCurrentVertexArrayStateSerial;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp
new file mode 100644
index 0000000000..4529a9d84e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp
@@ -0,0 +1,31 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTargetD3D.cpp: Implements serial handling for rx::RenderTargetD3D
+
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+
+namespace rx
+{
+unsigned int RenderTargetD3D::mCurrentSerial = 1;
+
+RenderTargetD3D::RenderTargetD3D() : mSerial(issueSerials(1)) {}
+
+RenderTargetD3D::~RenderTargetD3D() {}
+
+unsigned int RenderTargetD3D::getSerial() const
+{
+ return mSerial;
+}
+
+unsigned int RenderTargetD3D::issueSerials(unsigned int count)
+{
+ unsigned int firstSerial = mCurrentSerial;
+ mCurrentSerial += count;
+ return firstSerial;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderTargetD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderTargetD3D.h
new file mode 100644
index 0000000000..b5bed63bcd
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderTargetD3D.h
@@ -0,0 +1,44 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTargetD3D.h: Defines an abstract wrapper class to manage IDirect3DSurface9
+// and ID3D11View objects belonging to renderbuffers and renderable textures.
+
+#ifndef LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_
+#define LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+
+class RenderTargetD3D : public FramebufferAttachmentRenderTarget
+{
+ public:
+ RenderTargetD3D();
+ ~RenderTargetD3D() override;
+
+ virtual GLsizei getWidth() const = 0;
+ virtual GLsizei getHeight() const = 0;
+ virtual GLsizei getDepth() const = 0;
+ virtual GLenum getInternalFormat() const = 0;
+ virtual GLsizei getSamples() const = 0;
+ gl::Extents getExtents() const { return gl::Extents(getWidth(), getHeight(), getDepth()); }
+ bool isMultisampled() const { return getSamples() > 0; }
+
+ virtual unsigned int getSerial() const;
+ static unsigned int issueSerials(unsigned int count);
+
+ private:
+ const unsigned int mSerial;
+ static unsigned int mCurrentSerial;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp
new file mode 100644
index 0000000000..9114b88f3f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp
@@ -0,0 +1,126 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferD3d.cpp: Implements the RenderbufferD3D class, a specialization of RenderbufferImpl
+
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/renderer/d3d/ContextD3D.h"
+#include "libANGLE/renderer/d3d/EGLImageD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+RenderbufferD3D::RenderbufferD3D(const gl::RenderbufferState &state, RendererD3D *renderer)
+ : RenderbufferImpl(state), mRenderer(renderer), mRenderTarget(nullptr), mImage(nullptr)
+{}
+
+RenderbufferD3D::~RenderbufferD3D()
+{
+ SafeDelete(mRenderTarget);
+ mImage = nullptr;
+}
+
+void RenderbufferD3D::onDestroy(const gl::Context *context)
+{
+ SafeDelete(mRenderTarget);
+}
+
+angle::Result RenderbufferD3D::setStorage(const gl::Context *context,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ return setStorageMultisample(context, 0, internalformat, width, height,
+ gl::MultisamplingMode::Regular);
+}
+
+angle::Result RenderbufferD3D::setStorageMultisample(const gl::Context *context,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ gl::MultisamplingMode mode)
+{
+ // TODO: Correctly differentiate between normal multisampling and render to texture. In the
+ // latter case, the renderbuffer must be automatically resolved when rendering is broken and
+ // operations performed on it (such as blit, copy etc) should use the resolved image.
+ // http://anglebug.com/3107.
+
+ // If the renderbuffer parameters are queried, the calling function
+ // will expect one of the valid renderbuffer formats for use in
+ // glRenderbufferStorage, but we should create depth and stencil buffers
+ // as DEPTH24_STENCIL8
+ GLenum creationFormat = internalformat;
+ if (internalformat == GL_DEPTH_COMPONENT16 || internalformat == GL_STENCIL_INDEX8)
+ {
+ creationFormat = GL_DEPTH24_STENCIL8_OES;
+ }
+
+ // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
+ // the specified storage.
+ // Because ES 3.0 already knows the exact number of supported samples, it would already have
+ // been validated and generated GL_INVALID_VALUE.
+ const gl::TextureCaps &formatCaps = mRenderer->getNativeTextureCaps().get(creationFormat);
+ ANGLE_CHECK_GL_ALLOC(GetImplAs<ContextD3D>(context),
+ static_cast<uint32_t>(samples) <= formatCaps.getMaxSamples());
+
+ RenderTargetD3D *newRT = nullptr;
+ ANGLE_TRY(
+ mRenderer->createRenderTarget(context, width, height, creationFormat, samples, &newRT));
+
+ SafeDelete(mRenderTarget);
+ mImage = nullptr;
+ mRenderTarget = newRT;
+
+ return angle::Result::Continue;
+}
+
+angle::Result RenderbufferD3D::setStorageEGLImageTarget(const gl::Context *context,
+ egl::Image *image)
+{
+ mImage = GetImplAs<EGLImageD3D>(image);
+ SafeDelete(mRenderTarget);
+
+ return angle::Result::Continue;
+}
+
+angle::Result RenderbufferD3D::getRenderTarget(const gl::Context *context,
+ RenderTargetD3D **outRenderTarget)
+{
+ if (mImage)
+ {
+ return mImage->getRenderTarget(context, outRenderTarget);
+ }
+ else
+ {
+ *outRenderTarget = mRenderTarget;
+ return angle::Result::Continue;
+ }
+}
+
+angle::Result RenderbufferD3D::getAttachmentRenderTarget(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
+ GLsizei samples,
+ FramebufferAttachmentRenderTarget **rtOut)
+{
+ return getRenderTarget(context, reinterpret_cast<RenderTargetD3D **>(rtOut));
+}
+
+angle::Result RenderbufferD3D::initializeContents(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex)
+{
+ RenderTargetD3D *renderTarget = nullptr;
+ ANGLE_TRY(getRenderTarget(context, &renderTarget));
+ return mRenderer->initRenderTarget(context, renderTarget);
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderbufferD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderbufferD3D.h
new file mode 100644
index 0000000000..7b48c48073
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/RenderbufferD3D.h
@@ -0,0 +1,63 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferD3d.h: Defines the RenderbufferD3D class which implements RenderbufferImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_
+#define LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_
+
+#include "angle_gl.h"
+
+#include "common/angleutils.h"
+#include "libANGLE/renderer/RenderbufferImpl.h"
+
+namespace rx
+{
+class EGLImageD3D;
+class RendererD3D;
+class RenderTargetD3D;
+class SwapChainD3D;
+
+class RenderbufferD3D : public RenderbufferImpl
+{
+ public:
+ RenderbufferD3D(const gl::RenderbufferState &state, RendererD3D *renderer);
+ ~RenderbufferD3D() override;
+
+ void onDestroy(const gl::Context *context) override;
+
+ angle::Result setStorage(const gl::Context *context,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height) override;
+ angle::Result setStorageMultisample(const gl::Context *context,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ gl::MultisamplingMode mode) override;
+ angle::Result setStorageEGLImageTarget(const gl::Context *context, egl::Image *image) override;
+
+ angle::Result getRenderTarget(const gl::Context *context, RenderTargetD3D **outRenderTarget);
+ angle::Result getAttachmentRenderTarget(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
+ GLsizei samples,
+ FramebufferAttachmentRenderTarget **rtOut) override;
+
+ angle::Result initializeContents(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex) override;
+
+ private:
+ RendererD3D *mRenderer;
+ RenderTargetD3D *mRenderTarget;
+ EGLImageD3D *mImage;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/RendererD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/RendererD3D.cpp
new file mode 100644
index 0000000000..39e6e536dd
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/RendererD3D.cpp
@@ -0,0 +1,247 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RendererD3D.cpp: Implementation of the base D3D Renderer.
+
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+#include "common/MemoryBuffer.h"
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/TextureImpl.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
+#include "libANGLE/renderer/d3d/DisplayD3D.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/SamplerD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+
+namespace rx
+{
+
+RendererD3D::RendererD3D(egl::Display *display)
+ : mDisplay(display),
+ mPresentPathFastEnabled(false),
+ mCapsInitialized(false),
+ mFeaturesInitialized(false),
+ mDisjoint(false),
+ mDeviceLost(false)
+{}
+
+RendererD3D::~RendererD3D() {}
+
+bool RendererD3D::skipDraw(const gl::State &glState, gl::PrimitiveMode drawMode)
+{
+ if (drawMode == gl::PrimitiveMode::Points)
+ {
+ bool usesPointSize = GetImplAs<ProgramD3D>(glState.getProgram())->usesPointSize();
+
+ // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
+ // which affects varying interpolation. Since the value of gl_PointSize is
+ // undefined when not written, just skip drawing to avoid unexpected results.
+ if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
+ {
+ // Notify developers of risking undefined behavior.
+ WARN() << "Point rendering without writing to gl_PointSize.";
+ return true;
+ }
+ }
+ else if (gl::IsTriangleMode(drawMode))
+ {
+ if (glState.getRasterizerState().cullFace &&
+ glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+gl::GraphicsResetStatus RendererD3D::getResetStatus()
+{
+ if (!mDeviceLost)
+ {
+ if (testDeviceLost())
+ {
+ mDeviceLost = true;
+ notifyDeviceLost();
+ return gl::GraphicsResetStatus::UnknownContextReset;
+ }
+ return gl::GraphicsResetStatus::NoError;
+ }
+
+ if (testDeviceResettable())
+ {
+ return gl::GraphicsResetStatus::NoError;
+ }
+
+ return gl::GraphicsResetStatus::UnknownContextReset;
+}
+
+void RendererD3D::notifyDeviceLost()
+{
+ mDisplay->notifyDeviceLost();
+}
+
+void RendererD3D::setGPUDisjoint()
+{
+ mDisjoint = true;
+}
+
+GLint RendererD3D::getGPUDisjoint()
+{
+ bool disjoint = mDisjoint;
+
+ // Disjoint flag is cleared when read
+ mDisjoint = false;
+
+ return disjoint;
+}
+
+GLint64 RendererD3D::getTimestamp()
+{
+ // D3D has no way to get an actual timestamp reliably so 0 is returned
+ return 0;
+}
+
+void RendererD3D::ensureCapsInitialized() const
+{
+ if (!mCapsInitialized)
+ {
+ generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
+ mCapsInitialized = true;
+ }
+}
+
+const gl::Caps &RendererD3D::getNativeCaps() const
+{
+ ensureCapsInitialized();
+ return mNativeCaps;
+}
+
+const gl::TextureCapsMap &RendererD3D::getNativeTextureCaps() const
+{
+ ensureCapsInitialized();
+ return mNativeTextureCaps;
+}
+
+const gl::Extensions &RendererD3D::getNativeExtensions() const
+{
+ ensureCapsInitialized();
+ return mNativeExtensions;
+}
+
+const gl::Limitations &RendererD3D::getNativeLimitations() const
+{
+ ensureCapsInitialized();
+ return mNativeLimitations;
+}
+
+ShPixelLocalStorageType RendererD3D::getNativePixelLocalStorageType() const
+{
+ if (!getNativeExtensions().shaderPixelLocalStorageANGLE)
+ {
+ return ShPixelLocalStorageType::NotSupported;
+ }
+ // Read/write UAVs only support "r32*" images.
+ return ShPixelLocalStorageType::ImageStoreR32PackedFormats;
+}
+
+Serial RendererD3D::generateSerial()
+{
+ return mSerialFactory.generate();
+}
+
+bool InstancedPointSpritesActive(ProgramD3D *programD3D, gl::PrimitiveMode mode)
+{
+ return programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation() &&
+ mode == gl::PrimitiveMode::Points;
+}
+
+angle::Result RendererD3D::initRenderTarget(const gl::Context *context,
+ RenderTargetD3D *renderTarget)
+{
+ return clearRenderTarget(context, renderTarget, gl::ColorF(0, 0, 0, 0), 1, 0);
+}
+
+const angle::FeaturesD3D &RendererD3D::getFeatures() const
+{
+ if (!mFeaturesInitialized)
+ {
+ initializeFeatures(&mFeatures);
+ mFeaturesInitialized = true;
+ }
+
+ return mFeatures;
+}
+
+unsigned int GetBlendSampleMask(const gl::State &glState, int samples)
+{
+ unsigned int mask = 0;
+ if (glState.isSampleCoverageEnabled())
+ {
+ GLfloat coverageValue = glState.getSampleCoverageValue();
+ if (coverageValue != 0)
+ {
+ float threshold = 0.5f;
+
+ for (int i = 0; i < samples; ++i)
+ {
+ mask <<= 1;
+
+ if ((i + 1) * coverageValue >= threshold)
+ {
+ threshold += 1.0f;
+ mask |= 1;
+ }
+ }
+ }
+
+ bool coverageInvert = glState.getSampleCoverageInvert();
+ if (coverageInvert)
+ {
+ mask = ~mask;
+ }
+ }
+ else
+ {
+ mask = 0xFFFFFFFF;
+ }
+
+ if (glState.isSampleMaskEnabled())
+ {
+ mask &= glState.getSampleMaskWord(0);
+ }
+
+ return mask;
+}
+
+GLenum DefaultGLErrorCode(HRESULT hr)
+{
+ switch (hr)
+ {
+#ifdef ANGLE_ENABLE_D3D9
+ case D3DERR_OUTOFVIDEOMEMORY:
+#endif
+ case E_OUTOFMEMORY:
+ return GL_OUT_OF_MEMORY;
+ default:
+ return GL_INVALID_OPERATION;
+ }
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/RendererD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/RendererD3D.h
new file mode 100644
index 0000000000..3846e1eb2a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/RendererD3D.h
@@ -0,0 +1,489 @@
+
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RendererD3D.h: Defines a back-end specific class for the DirectX renderer.
+
+#ifndef LIBANGLE_RENDERER_D3D_RENDERERD3D_H_
+#define LIBANGLE_RENDERER_D3D_RENDERERD3D_H_
+
+#include <array>
+
+#include "common/Color.h"
+#include "common/MemoryBuffer.h"
+#include "common/debug.h"
+#include "libANGLE/Device.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Version.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.h"
+#include "libANGLE/renderer/renderer_utils.h"
+#include "libANGLE/renderer/serial_utils.h"
+#include "platform/FeaturesD3D_autogen.h"
+
+namespace egl
+{
+class ConfigSet;
+}
+
+namespace gl
+{
+class ErrorSet;
+class FramebufferState;
+class InfoLog;
+class Texture;
+struct LinkedVarying;
+} // namespace gl
+
+namespace rx
+{
+class ContextImpl;
+struct D3DUniform;
+struct D3DVarying;
+class DeviceD3D;
+class EGLImageD3D;
+class FramebufferImpl;
+class ImageD3D;
+class IndexBuffer;
+class NativeWindowD3D;
+class ProgramD3D;
+class RenderTargetD3D;
+class ShaderExecutableD3D;
+class SwapChainD3D;
+class TextureStorage;
+struct TranslatedIndexData;
+class UniformStorageD3D;
+class VertexBuffer;
+
+struct DeviceIdentifier
+{
+ UINT VendorId;
+ UINT DeviceId;
+ UINT SubSysId;
+ UINT Revision;
+ UINT FeatureLevel;
+};
+
+enum RendererClass
+{
+ RENDERER_D3D11,
+ RENDERER_D3D9
+};
+
+struct BindFlags
+{
+ bool renderTarget = false;
+ bool unorderedAccess = false;
+ static BindFlags RenderTarget()
+ {
+ BindFlags flags;
+ flags.renderTarget = true;
+ return flags;
+ }
+ static BindFlags UnorderedAccess()
+ {
+ BindFlags flags;
+ flags.unorderedAccess = true;
+ return flags;
+ }
+};
+
+// A d3d::Context wraps error handling.
+namespace d3d
+{
+class Context : angle::NonCopyable
+{
+ public:
+ Context() {}
+ virtual ~Context() {}
+
+ virtual void handleResult(HRESULT hr,
+ const char *message,
+ const char *file,
+ const char *function,
+ unsigned int line) = 0;
+};
+} // namespace d3d
+
+// ANGLE_TRY for HRESULT errors.
+#define ANGLE_TRY_HR(CONTEXT, EXPR, MESSAGE) \
+ do \
+ { \
+ auto ANGLE_LOCAL_VAR = (EXPR); \
+ if (ANGLE_UNLIKELY(FAILED(ANGLE_LOCAL_VAR))) \
+ { \
+ CONTEXT->handleResult(ANGLE_LOCAL_VAR, MESSAGE, __FILE__, ANGLE_FUNCTION, __LINE__); \
+ return angle::Result::Stop; \
+ } \
+ } while (0)
+
+#define ANGLE_CHECK_HR(CONTEXT, EXPR, MESSAGE, ERROR) \
+ do \
+ { \
+ if (ANGLE_UNLIKELY(!(EXPR))) \
+ { \
+ CONTEXT->handleResult(ERROR, MESSAGE, __FILE__, ANGLE_FUNCTION, __LINE__); \
+ return angle::Result::Stop; \
+ } \
+ } while (0)
+
+#define ANGLE_HR_UNREACHABLE(context) \
+ UNREACHABLE(); \
+ ANGLE_CHECK_HR(context, false, "Unreachble code reached.", E_FAIL)
+
+// Check if the device is lost every 10 failures to get the query data
+constexpr unsigned int kPollingD3DDeviceLostCheckFrequency = 10;
+
+// Useful for unit testing
+class BufferFactoryD3D : angle::NonCopyable
+{
+ public:
+ BufferFactoryD3D() {}
+ virtual ~BufferFactoryD3D() {}
+
+ virtual VertexBuffer *createVertexBuffer() = 0;
+ virtual IndexBuffer *createIndexBuffer() = 0;
+
+ // TODO(jmadill): add VertexFormatCaps
+ virtual VertexConversionType getVertexConversionType(angle::FormatID vertexFormatID) const = 0;
+ virtual GLenum getVertexComponentType(angle::FormatID vertexFormatID) const = 0;
+
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+ // function.
+ virtual angle::Result getVertexSpaceRequired(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance,
+ unsigned int *bytesRequiredOut) const = 0;
+};
+
+using AttribIndexArray = gl::AttribArray<int>;
+
+class RendererD3D : public BufferFactoryD3D
+{
+ public:
+ explicit RendererD3D(egl::Display *display);
+ ~RendererD3D() override;
+
+ virtual egl::Error initialize() = 0;
+
+ virtual egl::ConfigSet generateConfigs() = 0;
+ virtual void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const = 0;
+
+ virtual ContextImpl *createContext(const gl::State &state, gl::ErrorSet *errorSet) = 0;
+
+ virtual std::string getRendererDescription() const = 0;
+ virtual std::string getVendorString() const = 0;
+ virtual std::string getVersionString(bool includeFullVersion) const = 0;
+
+ virtual int getMinorShaderModel() const = 0;
+ virtual std::string getShaderModelSuffix() const = 0;
+
+ // Direct3D Specific methods
+ virtual DeviceIdentifier getAdapterIdentifier() const = 0;
+
+ virtual bool isValidNativeWindow(EGLNativeWindowType window) const = 0;
+ virtual NativeWindowD3D *createNativeWindow(EGLNativeWindowType window,
+ const egl::Config *config,
+ const egl::AttributeMap &attribs) const = 0;
+
+ virtual SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow,
+ HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation,
+ EGLint samples) = 0;
+ virtual egl::Error getD3DTextureInfo(const egl::Config *configuration,
+ IUnknown *d3dTexture,
+ const egl::AttributeMap &attribs,
+ EGLint *width,
+ EGLint *height,
+ GLsizei *samples,
+ gl::Format *glFormat,
+ const angle::Format **angleFormat,
+ UINT *arraySlice) const = 0;
+ virtual egl::Error validateShareHandle(const egl::Config *config,
+ HANDLE shareHandle,
+ const egl::AttributeMap &attribs) const = 0;
+
+ virtual int getMajorShaderModel() const = 0;
+
+ virtual void setGlobalDebugAnnotator() = 0;
+
+ const angle::FeaturesD3D &getFeatures() const;
+
+ // Pixel operations
+ virtual angle::Result copyImage2D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) = 0;
+ virtual angle::Result copyImageCube(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ gl::TextureTarget target,
+ GLint level) = 0;
+ virtual angle::Result copyImage3D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) = 0;
+ virtual angle::Result copyImage2DArray(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) = 0;
+
+ virtual angle::Result copyTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ gl::TextureTarget srcTarget,
+ const gl::Box &sourceBox,
+ GLenum destFormat,
+ GLenum destType,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ gl::TextureTarget destTarget,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha) = 0;
+ virtual angle::Result copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ TextureStorage *storage,
+ GLint destLevel) = 0;
+
+ // RenderTarget creation
+ virtual angle::Result createRenderTarget(const gl::Context *context,
+ int width,
+ int height,
+ GLenum format,
+ GLsizei samples,
+ RenderTargetD3D **outRT) = 0;
+ virtual angle::Result createRenderTargetCopy(const gl::Context *context,
+ RenderTargetD3D *source,
+ RenderTargetD3D **outRT) = 0;
+
+ // Shader operations
+ virtual angle::Result loadExecutable(d3d::Context *context,
+ const uint8_t *function,
+ size_t length,
+ gl::ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ ShaderExecutableD3D **outExecutable) = 0;
+ virtual angle::Result compileToExecutable(d3d::Context *context,
+ gl::InfoLog &infoLog,
+ const std::string &shaderHLSL,
+ gl::ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ const CompilerWorkaroundsD3D &workarounds,
+ ShaderExecutableD3D **outExectuable) = 0;
+ virtual angle::Result ensureHLSLCompilerInitialized(d3d::Context *context) = 0;
+
+ virtual UniformStorageD3D *createUniformStorage(size_t storageSize) = 0;
+
+ // Image operations
+ virtual ImageD3D *createImage() = 0;
+ virtual ExternalImageSiblingImpl *createExternalImageSibling(
+ const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs) = 0;
+ virtual angle::Result generateMipmap(const gl::Context *context,
+ ImageD3D *dest,
+ ImageD3D *source) = 0;
+ virtual angle::Result generateMipmapUsingD3D(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::TextureState &textureState) = 0;
+ virtual angle::Result copyImage(const gl::Context *context,
+ ImageD3D *dest,
+ ImageD3D *source,
+ const gl::Box &sourceBox,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha) = 0;
+ virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain,
+ const std::string &label) = 0;
+ virtual TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage,
+ RenderTargetD3D *renderTargetD3D,
+ const std::string &label) = 0;
+ virtual TextureStorage *createTextureStorageBuffer(
+ const gl::OffsetBindingPointer<gl::Buffer> &buffer,
+ GLenum internalFormat,
+ const std::string &label) = 0;
+ virtual TextureStorage *createTextureStorageExternal(
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc,
+ const std::string &label) = 0;
+ virtual TextureStorage *createTextureStorage2D(GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ const std::string &label,
+ bool hintLevelZeroOnly) = 0;
+ virtual TextureStorage *createTextureStorageCube(GLenum internalformat,
+ BindFlags bindFlags,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly,
+ const std::string &label) = 0;
+ virtual TextureStorage *createTextureStorage3D(GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ const std::string &label) = 0;
+ virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ const std::string &label) = 0;
+ virtual TextureStorage *createTextureStorage2DMultisample(GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ int samples,
+ bool fixedSampleLocations,
+ const std::string &label) = 0;
+ virtual TextureStorage *createTextureStorage2DMultisampleArray(GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ int samples,
+ bool fixedSampleLocations,
+ const std::string &label) = 0;
+
+ // Buffer-to-texture and Texture-to-buffer copies
+ virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0;
+ virtual angle::Result fastCopyBufferToTexture(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea) = 0;
+
+ // Device lost
+ gl::GraphicsResetStatus getResetStatus();
+ void notifyDeviceLost();
+ virtual bool resetDevice() = 0;
+ virtual bool testDeviceLost() = 0;
+ virtual bool testDeviceResettable() = 0;
+
+ virtual RendererClass getRendererClass() const = 0;
+ virtual void *getD3DDevice() = 0;
+
+ void setGPUDisjoint();
+
+ GLint getGPUDisjoint();
+ GLint64 getTimestamp();
+
+ virtual angle::Result clearRenderTarget(const gl::Context *context,
+ RenderTargetD3D *renderTarget,
+ const gl::ColorF &clearColorValue,
+ const float clearDepthValue,
+ const unsigned int clearStencilValue) = 0;
+
+ virtual DeviceImpl *createEGLDevice() = 0;
+
+ bool presentPathFastEnabled() const { return mPresentPathFastEnabled; }
+
+ // Stream creation
+ virtual StreamProducerImpl *createStreamProducerD3DTexture(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) = 0;
+
+ const gl::Caps &getNativeCaps() const;
+ const gl::TextureCapsMap &getNativeTextureCaps() const;
+ const gl::Extensions &getNativeExtensions() const;
+ const gl::Limitations &getNativeLimitations() const;
+ ShPixelLocalStorageType getNativePixelLocalStorageType() const;
+ virtual void initializeFrontendFeatures(angle::FrontendFeatures *features) const = 0;
+
+ // Necessary hack for default framebuffers in D3D.
+ virtual FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) = 0;
+
+ virtual gl::Version getMaxSupportedESVersion() const = 0;
+ virtual gl::Version getMaxConformantESVersion() const = 0;
+
+ angle::Result initRenderTarget(const gl::Context *context, RenderTargetD3D *renderTarget);
+
+ virtual angle::Result getIncompleteTexture(const gl::Context *context,
+ gl::TextureType type,
+ gl::Texture **textureOut) = 0;
+
+ Serial generateSerial();
+
+ virtual bool canSelectViewInVertexShader() const = 0;
+
+ protected:
+ virtual bool getLUID(LUID *adapterLuid) const = 0;
+ virtual void generateCaps(gl::Caps *outCaps,
+ gl::TextureCapsMap *outTextureCaps,
+ gl::Extensions *outExtensions,
+ gl::Limitations *outLimitations) const = 0;
+
+ bool skipDraw(const gl::State &glState, gl::PrimitiveMode drawMode);
+
+ egl::Display *mDisplay;
+
+ bool mPresentPathFastEnabled;
+
+ private:
+ void ensureCapsInitialized() const;
+
+ virtual void initializeFeatures(angle::FeaturesD3D *features) const = 0;
+
+ mutable bool mCapsInitialized;
+ mutable gl::Caps mNativeCaps;
+ mutable gl::TextureCapsMap mNativeTextureCaps;
+ mutable gl::Extensions mNativeExtensions;
+ mutable gl::Limitations mNativeLimitations;
+
+ mutable bool mFeaturesInitialized;
+ mutable angle::FeaturesD3D mFeatures;
+
+ bool mDisjoint;
+ bool mDeviceLost;
+
+ SerialFactory mSerialFactory;
+};
+
+unsigned int GetBlendSampleMask(const gl::State &glState, int samples);
+bool InstancedPointSpritesActive(ProgramD3D *programD3D, gl::PrimitiveMode mode);
+GLenum DefaultGLErrorCode(HRESULT hr);
+
+// Define stubs so we don't need to include D3D9/D3D11 headers directly.
+RendererD3D *CreateRenderer11(egl::Display *display);
+RendererD3D *CreateRenderer9(egl::Display *display);
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_RENDERERD3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/SamplerD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/SamplerD3D.h
new file mode 100644
index 0000000000..ad4b15a4ab
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/SamplerD3D.h
@@ -0,0 +1,33 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SamplerD3D.h: Defines the rx::SamplerD3D class, an implementation of SamplerImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_
+#define LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_
+
+#include "libANGLE/renderer/SamplerImpl.h"
+
+namespace rx
+{
+
+class SamplerD3D : public SamplerImpl
+{
+ public:
+ SamplerD3D(const gl::SamplerState &state) : SamplerImpl(state) {}
+ ~SamplerD3D() override {}
+
+ angle::Result syncState(const gl::Context *context, const bool dirtyBits) override;
+};
+
+inline angle::Result SamplerD3D::syncState(const gl::Context *context, const bool dirtyBits)
+{
+ return angle::Result::Continue;
+}
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderD3D.cpp
new file mode 100644
index 0000000000..ae8a9ebcfb
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderD3D.cpp
@@ -0,0 +1,391 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderD3D.cpp: Defines the rx::ShaderD3D class which implements rx::ShaderImpl.
+
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+
+#include "common/system_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/features.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/trace.h"
+
+namespace rx
+{
+
+class TranslateTaskD3D : public angle::Closure
+{
+ public:
+ TranslateTaskD3D(ShHandle handle,
+ const ShCompileOptions &options,
+ const std::string &source,
+ const std::string &sourcePath)
+ : mHandle(handle),
+ mOptions(options),
+ mSource(source),
+ mSourcePath(sourcePath),
+ mResult(false)
+ {}
+
+ void operator()() override
+ {
+ ANGLE_TRACE_EVENT1("gpu.angle", "TranslateTask::run", "source", mSource);
+ std::vector<const char *> srcStrings;
+ if (!mSourcePath.empty())
+ {
+ srcStrings.push_back(mSourcePath.c_str());
+ }
+ srcStrings.push_back(mSource.c_str());
+
+ mResult = sh::Compile(mHandle, &srcStrings[0], srcStrings.size(), mOptions);
+ }
+
+ bool getResult() { return mResult; }
+
+ private:
+ ShHandle mHandle;
+ ShCompileOptions mOptions;
+ std::string mSource;
+ std::string mSourcePath;
+ bool mResult;
+};
+
+using PostTranslateFunctor =
+ std::function<bool(gl::ShCompilerInstance *compiler, std::string *infoLog)>;
+
+class WaitableCompileEventD3D final : public WaitableCompileEvent
+{
+ public:
+ WaitableCompileEventD3D(std::shared_ptr<angle::WaitableEvent> waitableEvent,
+ gl::ShCompilerInstance *compilerInstance,
+ PostTranslateFunctor &&postTranslateFunctor,
+ std::shared_ptr<TranslateTaskD3D> translateTask)
+ : WaitableCompileEvent(waitableEvent),
+ mCompilerInstance(compilerInstance),
+ mPostTranslateFunctor(std::move(postTranslateFunctor)),
+ mTranslateTask(translateTask)
+ {}
+
+ bool getResult() override { return mTranslateTask->getResult(); }
+
+ bool postTranslate(std::string *infoLog) override
+ {
+ return mPostTranslateFunctor(mCompilerInstance, infoLog);
+ }
+
+ private:
+ gl::ShCompilerInstance *mCompilerInstance;
+ PostTranslateFunctor mPostTranslateFunctor;
+ std::shared_ptr<TranslateTaskD3D> mTranslateTask;
+};
+
+ShaderD3D::ShaderD3D(const gl::ShaderState &state, RendererD3D *renderer)
+ : ShaderImpl(state), mRenderer(renderer)
+{
+ uncompile();
+}
+
+ShaderD3D::~ShaderD3D() {}
+
+std::string ShaderD3D::getDebugInfo() const
+{
+ if (mDebugInfo.empty())
+ {
+ return "";
+ }
+
+ return mDebugInfo + std::string("\n// ") + gl::GetShaderTypeString(mState.getShaderType()) +
+ " SHADER END\n";
+}
+
+// initialize/clean up previous state
+void ShaderD3D::uncompile()
+{
+ // set by compileToHLSL
+ mCompilerOutputType = SH_ESSL_OUTPUT;
+
+ mUsesMultipleRenderTargets = false;
+ mUsesFragColor = false;
+ mUsesFragData = false;
+ mUsesSecondaryColor = false;
+ mUsesFragCoord = false;
+ mUsesFrontFacing = false;
+ mUsesHelperInvocation = false;
+ mUsesPointSize = false;
+ mUsesPointCoord = false;
+ mUsesDepthRange = false;
+ mUsesFragDepth = false;
+ mHasANGLEMultiviewEnabled = false;
+ mUsesVertexID = false;
+ mUsesViewID = false;
+ mUsesDiscardRewriting = false;
+ mUsesNestedBreak = false;
+ mRequiresIEEEStrictCompiling = false;
+
+ mDebugInfo.clear();
+}
+
+void ShaderD3D::generateWorkarounds(CompilerWorkaroundsD3D *workarounds) const
+{
+ if (mUsesDiscardRewriting)
+ {
+ // ANGLE issue 486:
+ // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by
+ // disabling optimization
+ workarounds->skipOptimization = true;
+ }
+ else if (mUsesNestedBreak)
+ {
+ // ANGLE issue 603:
+ // Work-around a D3D9 compiler bug that presents itself when using break in a nested loop,
+ // by maximizing optimization We want to keep the use of
+ // ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes
+ // precedence
+ workarounds->useMaxOptimization = true;
+ }
+
+ if (mRequiresIEEEStrictCompiling)
+ {
+ // IEEE Strictness for D3D compiler needs to be enabled for NaNs to work.
+ workarounds->enableIEEEStrictness = true;
+ }
+}
+
+unsigned int ShaderD3D::getUniformRegister(const std::string &uniformName) const
+{
+ ASSERT(mUniformRegisterMap.count(uniformName) > 0);
+ return mUniformRegisterMap.find(uniformName)->second;
+}
+
+unsigned int ShaderD3D::getUniformBlockRegister(const std::string &blockName) const
+{
+ ASSERT(mUniformBlockRegisterMap.count(blockName) > 0);
+ return mUniformBlockRegisterMap.find(blockName)->second;
+}
+
+bool ShaderD3D::shouldUniformBlockUseStructuredBuffer(const std::string &blockName) const
+{
+ ASSERT(mUniformBlockUseStructuredBufferMap.count(blockName) > 0);
+ return mUniformBlockUseStructuredBufferMap.find(blockName)->second;
+}
+
+unsigned int ShaderD3D::getShaderStorageBlockRegister(const std::string &blockName) const
+{
+ ASSERT(mShaderStorageBlockRegisterMap.count(blockName) > 0);
+ return mShaderStorageBlockRegisterMap.find(blockName)->second;
+}
+
+ShShaderOutput ShaderD3D::getCompilerOutputType() const
+{
+ return mCompilerOutputType;
+}
+
+bool ShaderD3D::useImage2DFunction(const std::string &functionName) const
+{
+ if (mUsedImage2DFunctionNames.empty())
+ {
+ return false;
+ }
+
+ return mUsedImage2DFunctionNames.find(functionName) != mUsedImage2DFunctionNames.end();
+}
+
+const std::set<std::string> &ShaderD3D::getSlowCompilingUniformBlockSet() const
+{
+ return mSlowCompilingUniformBlockSet;
+}
+
+const std::map<std::string, unsigned int> &GetUniformRegisterMap(
+ const std::map<std::string, unsigned int> *uniformRegisterMap)
+{
+ ASSERT(uniformRegisterMap);
+ return *uniformRegisterMap;
+}
+
+const std::set<std::string> &GetSlowCompilingUniformBlockSet(
+ const std::set<std::string> *slowCompilingUniformBlockSet)
+{
+ ASSERT(slowCompilingUniformBlockSet);
+ return *slowCompilingUniformBlockSet;
+}
+
+const std::set<std::string> &GetUsedImage2DFunctionNames(
+ const std::set<std::string> *usedImage2DFunctionNames)
+{
+ ASSERT(usedImage2DFunctionNames);
+ return *usedImage2DFunctionNames;
+}
+
+std::shared_ptr<WaitableCompileEvent> ShaderD3D::compile(const gl::Context *context,
+ gl::ShCompilerInstance *compilerInstance,
+ ShCompileOptions *options)
+{
+ std::string sourcePath;
+ uncompile();
+
+ const angle::FeaturesD3D &features = mRenderer->getFeatures();
+ const gl::Extensions &extensions = mRenderer->getNativeExtensions();
+
+ const std::string &source = mState.getSource();
+
+#if !defined(ANGLE_ENABLE_WINDOWS_UWP)
+ if (gl::DebugAnnotationsActive(context))
+ {
+ sourcePath = angle::CreateTemporaryFile().value();
+ writeFile(sourcePath.c_str(), source.c_str(), source.length());
+ options->lineDirectives = true;
+ options->sourcePath = true;
+ }
+#endif
+
+ if (features.expandIntegerPowExpressions.enabled)
+ {
+ options->expandSelectHLSLIntegerPowExpressions = true;
+ }
+
+ if (features.getDimensionsIgnoresBaseLevel.enabled)
+ {
+ options->HLSLGetDimensionsIgnoresBaseLevel = true;
+ }
+
+ if (features.preAddTexelFetchOffsets.enabled)
+ {
+ options->rewriteTexelFetchOffsetToTexelFetch = true;
+ }
+ if (features.rewriteUnaryMinusOperator.enabled)
+ {
+ options->rewriteIntegerUnaryMinusOperator = true;
+ }
+ if (features.emulateIsnanFloat.enabled)
+ {
+ options->emulateIsnanFloatFunction = true;
+ }
+ if (features.skipVSConstantRegisterZero.enabled &&
+ mState.getShaderType() == gl::ShaderType::Vertex)
+ {
+ options->skipD3DConstantRegisterZero = true;
+ }
+ if (features.forceAtomicValueResolution.enabled)
+ {
+ options->forceAtomicValueResolution = true;
+ }
+ if (features.allowTranslateUniformBlockToStructuredBuffer.enabled)
+ {
+ options->allowTranslateUniformBlockToStructuredBuffer = true;
+ }
+ if (extensions.multiviewOVR || extensions.multiview2OVR)
+ {
+ options->initializeBuiltinsForInstancedMultiview = true;
+ }
+ if (extensions.shaderPixelLocalStorageANGLE)
+ {
+ options->pls.type = mRenderer->getNativePixelLocalStorageType();
+ if (extensions.shaderPixelLocalStorageCoherentANGLE)
+ {
+ options->pls.fragmentSynchronizationType =
+ ShFragmentSynchronizationType::RasterizerOrderViews_D3D;
+ }
+ }
+
+ auto postTranslateFunctor = [this](gl::ShCompilerInstance *compiler, std::string *infoLog) {
+ // TODO(jmadill): We shouldn't need to cache this.
+ mCompilerOutputType = compiler->getShaderOutputType();
+
+ const std::string &translatedSource = mState.getTranslatedSource();
+
+ mUsesMultipleRenderTargets = translatedSource.find("GL_USES_MRT") != std::string::npos;
+ mUsesFragColor = translatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos;
+ mUsesFragData = translatedSource.find("GL_USES_FRAG_DATA") != std::string::npos;
+ mUsesSecondaryColor = translatedSource.find("GL_USES_SECONDARY_COLOR") != std::string::npos;
+ mUsesFragCoord = translatedSource.find("GL_USES_FRAG_COORD") != std::string::npos;
+ mUsesFrontFacing = translatedSource.find("GL_USES_FRONT_FACING") != std::string::npos;
+ mUsesHelperInvocation =
+ translatedSource.find("GL_USES_HELPER_INVOCATION") != std::string::npos;
+ mUsesPointSize = translatedSource.find("GL_USES_POINT_SIZE") != std::string::npos;
+ mUsesPointCoord = translatedSource.find("GL_USES_POINT_COORD") != std::string::npos;
+ mUsesDepthRange = translatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos;
+ mUsesFragDepth = translatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos;
+ mHasANGLEMultiviewEnabled =
+ translatedSource.find("GL_ANGLE_MULTIVIEW_ENABLED") != std::string::npos;
+ mUsesVertexID = translatedSource.find("GL_USES_VERTEX_ID") != std::string::npos;
+ mUsesViewID = translatedSource.find("GL_USES_VIEW_ID") != std::string::npos;
+ mUsesDiscardRewriting =
+ translatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
+ mUsesNestedBreak = translatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
+ mRequiresIEEEStrictCompiling =
+ translatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos;
+
+ ShHandle compilerHandle = compiler->getHandle();
+
+ mUniformRegisterMap = GetUniformRegisterMap(sh::GetUniformRegisterMap(compilerHandle));
+ mReadonlyImage2DRegisterIndex = sh::GetReadonlyImage2DRegisterIndex(compilerHandle);
+ mImage2DRegisterIndex = sh::GetImage2DRegisterIndex(compilerHandle);
+ mUsedImage2DFunctionNames =
+ GetUsedImage2DFunctionNames(sh::GetUsedImage2DFunctionNames(compilerHandle));
+
+ for (const sh::InterfaceBlock &interfaceBlock : mState.getUniformBlocks())
+ {
+ if (interfaceBlock.active)
+ {
+ unsigned int index = static_cast<unsigned int>(-1);
+ bool blockRegisterResult =
+ sh::GetUniformBlockRegister(compilerHandle, interfaceBlock.name, &index);
+ ASSERT(blockRegisterResult);
+ bool useStructuredBuffer =
+ sh::ShouldUniformBlockUseStructuredBuffer(compilerHandle, interfaceBlock.name);
+
+ mUniformBlockRegisterMap[interfaceBlock.name] = index;
+ mUniformBlockUseStructuredBufferMap[interfaceBlock.name] = useStructuredBuffer;
+ }
+ }
+
+ mSlowCompilingUniformBlockSet =
+ GetSlowCompilingUniformBlockSet(sh::GetSlowCompilingUniformBlockSet(compilerHandle));
+
+ for (const sh::InterfaceBlock &interfaceBlock : mState.getShaderStorageBlocks())
+ {
+ if (interfaceBlock.active)
+ {
+ unsigned int index = static_cast<unsigned int>(-1);
+ bool blockRegisterResult =
+ sh::GetShaderStorageBlockRegister(compilerHandle, interfaceBlock.name, &index);
+ ASSERT(blockRegisterResult);
+
+ mShaderStorageBlockRegisterMap[interfaceBlock.name] = index;
+ }
+ }
+
+ mDebugInfo += std::string("// ") + gl::GetShaderTypeString(mState.getShaderType()) +
+ " SHADER BEGIN\n";
+ mDebugInfo += "\n// GLSL BEGIN\n\n" + mState.getSource() + "\n\n// GLSL END\n\n\n";
+ mDebugInfo +=
+ "// INITIAL HLSL BEGIN\n\n" + translatedSource + "\n// INITIAL HLSL END\n\n\n";
+ // Successive steps will append more info
+ return true;
+ };
+
+ auto workerThreadPool = context->getWorkerThreadPool();
+ auto translateTask = std::make_shared<TranslateTaskD3D>(compilerInstance->getHandle(), *options,
+ source, sourcePath);
+
+ return std::make_shared<WaitableCompileEventD3D>(
+ angle::WorkerThreadPool::PostWorkerTask(workerThreadPool, translateTask), compilerInstance,
+ std::move(postTranslateFunctor), translateTask);
+}
+
+bool ShaderD3D::hasUniform(const std::string &name) const
+{
+ return mUniformRegisterMap.find(name) != mUniformRegisterMap.end();
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderD3D.h
new file mode 100644
index 0000000000..d1c5622a27
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderD3D.h
@@ -0,0 +1,126 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderD3D.h: Defines the rx::ShaderD3D class which implements rx::ShaderImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_SHADERD3D_H_
+#define LIBANGLE_RENDERER_D3D_SHADERD3D_H_
+
+#include "libANGLE/renderer/ShaderImpl.h"
+
+#include <map>
+
+namespace angle
+{
+struct FeaturesD3D;
+} // namespace angle
+
+namespace gl
+{
+struct Extensions;
+}
+
+namespace rx
+{
+class DynamicHLSL;
+class RendererD3D;
+struct D3DUniform;
+
+// Workarounds attached to each shader. Do not need to expose information about these workarounds so
+// a simple bool struct suffices.
+struct CompilerWorkaroundsD3D
+{
+ bool skipOptimization = false;
+
+ bool useMaxOptimization = false;
+
+ // IEEE strictness needs to be enabled for NANs to work.
+ bool enableIEEEStrictness = false;
+};
+
+class ShaderD3D : public ShaderImpl
+{
+ public:
+ ShaderD3D(const gl::ShaderState &state, RendererD3D *renderer);
+ ~ShaderD3D() override;
+
+ std::shared_ptr<WaitableCompileEvent> compile(const gl::Context *context,
+ gl::ShCompilerInstance *compilerInstance,
+ ShCompileOptions *options) override;
+
+ std::string getDebugInfo() const override;
+
+ // D3D-specific methods
+ void uncompile();
+
+ bool hasUniform(const std::string &name) const;
+
+ // Query regular uniforms with their name. Query sampler fields of structs with field selection
+ // using dot (.) operator.
+ unsigned int getUniformRegister(const std::string &uniformName) const;
+
+ unsigned int getUniformBlockRegister(const std::string &blockName) const;
+ bool shouldUniformBlockUseStructuredBuffer(const std::string &blockName) const;
+ unsigned int getShaderStorageBlockRegister(const std::string &blockName) const;
+ unsigned int getReadonlyImage2DRegisterIndex() const { return mReadonlyImage2DRegisterIndex; }
+ unsigned int getImage2DRegisterIndex() const { return mImage2DRegisterIndex; }
+ bool useImage2DFunction(const std::string &functionName) const;
+ const std::set<std::string> &getSlowCompilingUniformBlockSet() const;
+ void appendDebugInfo(const std::string &info) const { mDebugInfo += info; }
+
+ void generateWorkarounds(CompilerWorkaroundsD3D *workarounds) const;
+
+ bool usesMultipleRenderTargets() const { return mUsesMultipleRenderTargets; }
+ bool usesFragColor() const { return mUsesFragColor; }
+ bool usesFragData() const { return mUsesFragData; }
+ bool usesSecondaryColor() const { return mUsesSecondaryColor; }
+ bool usesFragCoord() const { return mUsesFragCoord; }
+ bool usesFrontFacing() const { return mUsesFrontFacing; }
+ bool usesHelperInvocation() const { return mUsesHelperInvocation; }
+ bool usesPointSize() const { return mUsesPointSize; }
+ bool usesPointCoord() const { return mUsesPointCoord; }
+ bool usesDepthRange() const { return mUsesDepthRange; }
+ bool usesFragDepth() const { return mUsesFragDepth; }
+ bool usesVertexID() const { return mUsesVertexID; }
+ bool usesViewID() const { return mUsesViewID; }
+ bool hasANGLEMultiviewEnabled() const { return mHasANGLEMultiviewEnabled; }
+
+ ShShaderOutput getCompilerOutputType() const;
+
+ private:
+ bool mUsesMultipleRenderTargets;
+ bool mUsesFragColor;
+ bool mUsesFragData;
+ bool mUsesSecondaryColor;
+ bool mUsesFragCoord;
+ bool mUsesFrontFacing;
+ bool mUsesHelperInvocation;
+ bool mUsesPointSize;
+ bool mUsesPointCoord;
+ bool mUsesDepthRange;
+ bool mUsesFragDepth;
+ bool mHasANGLEMultiviewEnabled;
+ bool mUsesVertexID;
+ bool mUsesViewID;
+ bool mUsesDiscardRewriting;
+ bool mUsesNestedBreak;
+ bool mRequiresIEEEStrictCompiling;
+
+ RendererD3D *mRenderer;
+ ShShaderOutput mCompilerOutputType;
+ mutable std::string mDebugInfo;
+ std::map<std::string, unsigned int> mUniformRegisterMap;
+ std::map<std::string, unsigned int> mUniformBlockRegisterMap;
+ std::map<std::string, bool> mUniformBlockUseStructuredBufferMap;
+ std::set<std::string> mSlowCompilingUniformBlockSet;
+ std::map<std::string, unsigned int> mShaderStorageBlockRegisterMap;
+ unsigned int mReadonlyImage2DRegisterIndex;
+ unsigned int mImage2DRegisterIndex;
+ std::set<std::string> mUsedImage2DFunctionNames;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_SHADERD3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp
new file mode 100644
index 0000000000..eab3becc91
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp
@@ -0,0 +1,67 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderExecutable.cpp: Implements a class to contain D3D shader executable
+// implementation details.
+
+#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
+
+#include "common/angleutils.h"
+
+namespace rx
+{
+
+ShaderExecutableD3D::ShaderExecutableD3D(const void *function, size_t length)
+ : mFunctionBuffer(length)
+{
+ memcpy(mFunctionBuffer.data(), function, length);
+}
+
+ShaderExecutableD3D::~ShaderExecutableD3D() {}
+
+const uint8_t *ShaderExecutableD3D::getFunction() const
+{
+ return mFunctionBuffer.data();
+}
+
+size_t ShaderExecutableD3D::getLength() const
+{
+ return mFunctionBuffer.size();
+}
+
+const std::string &ShaderExecutableD3D::getDebugInfo() const
+{
+ return mDebugInfo;
+}
+
+void ShaderExecutableD3D::appendDebugInfo(const std::string &info)
+{
+ mDebugInfo += info;
+}
+
+UniformStorageD3D::UniformStorageD3D(size_t initialSize) : mUniformData()
+{
+ bool result = mUniformData.resize(initialSize);
+ ASSERT(result);
+
+ // Uniform data is zero-initialized by default.
+ mUniformData.fill(0);
+}
+
+UniformStorageD3D::~UniformStorageD3D() {}
+
+size_t UniformStorageD3D::size() const
+{
+ return mUniformData.size();
+}
+
+uint8_t *UniformStorageD3D::getDataPointer(unsigned int registerIndex, unsigned int registerElement)
+{
+ size_t offset = ((registerIndex * 4 + registerElement) * sizeof(float));
+ return mUniformData.data() + offset;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h
new file mode 100644
index 0000000000..673822b152
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h
@@ -0,0 +1,57 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderExecutable.h: Defines a class to contain D3D shader executable
+// implementation details.
+
+#ifndef LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_
+#define LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_
+
+#include "common/MemoryBuffer.h"
+#include "common/debug.h"
+
+#include <cstdint>
+#include <vector>
+
+namespace rx
+{
+
+class ShaderExecutableD3D : angle::NonCopyable
+{
+ public:
+ ShaderExecutableD3D(const void *function, size_t length);
+ virtual ~ShaderExecutableD3D();
+
+ const uint8_t *getFunction() const;
+
+ size_t getLength() const;
+
+ const std::string &getDebugInfo() const;
+
+ void appendDebugInfo(const std::string &info);
+
+ private:
+ std::vector<uint8_t> mFunctionBuffer;
+ std::string mDebugInfo;
+};
+
+class UniformStorageD3D : angle::NonCopyable
+{
+ public:
+ UniformStorageD3D(size_t initialSize);
+ virtual ~UniformStorageD3D();
+
+ size_t size() const;
+
+ uint8_t *getDataPointer(unsigned int registerIndex, unsigned int registerElement);
+
+ private:
+ angle::MemoryBuffer mUniformData;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
new file mode 100644
index 0000000000..256808637f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
@@ -0,0 +1,517 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SurfaceD3D.cpp: D3D implementation of an EGL surface
+
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/Format.h"
+#include "libANGLE/renderer/d3d/DisplayD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+
+#include <EGL/eglext.h>
+#include <tchar.h>
+#include <algorithm>
+
+namespace rx
+{
+
+SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ EGLNativeWindowType window,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+ : SurfaceImpl(state),
+ mRenderer(renderer),
+ mDisplay(display),
+ mFixedSize(window == nullptr || attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE),
+ mFixedWidth(0),
+ mFixedHeight(0),
+ mOrientation(static_cast<EGLint>(attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0))),
+ mRenderTargetFormat(state.config->renderTargetFormat),
+ mDepthStencilFormat(state.config->depthStencilFormat),
+ mColorFormat(nullptr),
+ mSwapChain(nullptr),
+ mSwapIntervalDirty(true),
+ mNativeWindow(renderer->createNativeWindow(window, state.config, attribs)),
+ mWidth(static_cast<EGLint>(attribs.get(EGL_WIDTH, 0))),
+ mHeight(static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0))),
+ mSwapInterval(1),
+ mShareHandle(0),
+ mD3DTexture(nullptr),
+ mBuftype(buftype)
+{
+ if (window != nullptr && !mFixedSize)
+ {
+ mWidth = -1;
+ mHeight = -1;
+ }
+
+ if (mFixedSize)
+ {
+ mFixedWidth = mWidth;
+ mFixedHeight = mHeight;
+ }
+
+ switch (buftype)
+ {
+ case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+ mShareHandle = static_cast<HANDLE>(clientBuffer);
+ break;
+
+ case EGL_D3D_TEXTURE_ANGLE:
+ mD3DTexture = static_cast<IUnknown *>(clientBuffer);
+ ASSERT(mD3DTexture != nullptr);
+ mD3DTexture->AddRef();
+ break;
+
+ default:
+ break;
+ }
+}
+
+SurfaceD3D::~SurfaceD3D()
+{
+ releaseSwapChain();
+ SafeDelete(mNativeWindow);
+ SafeRelease(mD3DTexture);
+}
+
+void SurfaceD3D::releaseSwapChain()
+{
+ SafeDelete(mSwapChain);
+}
+
+egl::Error SurfaceD3D::initialize(const egl::Display *display)
+{
+ if (mNativeWindow->getNativeWindow())
+ {
+ if (!mNativeWindow->initialize())
+ {
+ return egl::EglBadSurface();
+ }
+ }
+
+ if (mBuftype == EGL_D3D_TEXTURE_ANGLE)
+ {
+ ANGLE_TRY(mRenderer->getD3DTextureInfo(mState.config, mD3DTexture, mState.attributes,
+ &mFixedWidth, &mFixedHeight, nullptr, nullptr,
+ &mColorFormat, nullptr));
+ if (mState.attributes.contains(EGL_GL_COLORSPACE))
+ {
+ if (mColorFormat->id != angle::FormatID::R8G8B8A8_TYPELESS &&
+ mColorFormat->id != angle::FormatID::B8G8R8A8_TYPELESS)
+ {
+ return egl::EglBadMatch()
+ << "EGL_GL_COLORSPACE may only be specified for TYPELESS textures";
+ }
+ }
+ if (mColorFormat->id == angle::FormatID::R8G8B8A8_TYPELESS)
+ {
+ EGLAttrib colorspace =
+ mState.attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR);
+ if (colorspace == EGL_GL_COLORSPACE_SRGB)
+ {
+ mColorFormat = &angle::Format::Get(angle::FormatID::R8G8B8A8_TYPELESS_SRGB);
+ }
+ }
+ if (mColorFormat->id == angle::FormatID::B8G8R8A8_TYPELESS)
+ {
+ EGLAttrib colorspace =
+ mState.attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR);
+ if (colorspace == EGL_GL_COLORSPACE_SRGB)
+ {
+ mColorFormat = &angle::Format::Get(angle::FormatID::B8G8R8A8_TYPELESS_SRGB);
+ }
+ }
+ mRenderTargetFormat = mColorFormat->fboImplementationInternalFormat;
+ }
+
+ ANGLE_TRY(resetSwapChain(display));
+ return egl::NoError();
+}
+
+egl::Error SurfaceD3D::bindTexImage(const gl::Context *, gl::Texture *, EGLint)
+{
+ return egl::NoError();
+}
+
+egl::Error SurfaceD3D::releaseTexImage(const gl::Context *, EGLint)
+{
+ return egl::NoError();
+}
+
+egl::Error SurfaceD3D::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
+{
+ if (!mState.directComposition)
+ {
+ return egl::EglBadSurface()
+ << "getSyncValues: surface requires Direct Composition to be enabled";
+ }
+
+ return mSwapChain->getSyncValues(ust, msc, sbc);
+}
+
+egl::Error SurfaceD3D::getMscRate(EGLint *numerator, EGLint *denominator)
+{
+ UNIMPLEMENTED();
+ return egl::EglBadAccess();
+}
+
+egl::Error SurfaceD3D::resetSwapChain(const egl::Display *display)
+{
+ ASSERT(!mSwapChain);
+
+ int width;
+ int height;
+
+ if (!mFixedSize)
+ {
+ RECT windowRect;
+ if (!mNativeWindow->getClientRect(&windowRect))
+ {
+ ASSERT(false);
+
+ return egl::EglBadSurface() << "Could not retrieve the window dimensions";
+ }
+
+ width = windowRect.right - windowRect.left;
+ height = windowRect.bottom - windowRect.top;
+ }
+ else
+ {
+ // non-window surface - size is determined at creation
+ width = mFixedWidth;
+ height = mFixedHeight;
+ }
+
+ mSwapChain =
+ mRenderer->createSwapChain(mNativeWindow, mShareHandle, mD3DTexture, mRenderTargetFormat,
+ mDepthStencilFormat, mOrientation, mState.config->samples);
+ if (!mSwapChain)
+ {
+ return egl::EglBadAlloc();
+ }
+
+ // This is a bit risky to pass the proxy context here, but it can happen at almost any time.
+ DisplayD3D *displayD3D = GetImplAs<DisplayD3D>(display);
+ egl::Error error = resetSwapChain(displayD3D, width, height);
+ if (error.isError())
+ {
+ SafeDelete(mSwapChain);
+ return error;
+ }
+
+ return egl::NoError();
+}
+
+egl::Error SurfaceD3D::resizeSwapChain(DisplayD3D *displayD3D,
+ int backbufferWidth,
+ int backbufferHeight)
+{
+ ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
+ ASSERT(mSwapChain);
+
+ EGLint status =
+ mSwapChain->resize(displayD3D, std::max(1, backbufferWidth), std::max(1, backbufferHeight));
+
+ if (status == EGL_CONTEXT_LOST)
+ {
+ mDisplay->notifyDeviceLost();
+ return egl::Error(status);
+ }
+ else if (status != EGL_SUCCESS)
+ {
+ return egl::Error(status);
+ }
+
+ mWidth = backbufferWidth;
+ mHeight = backbufferHeight;
+
+ return egl::NoError();
+}
+
+egl::Error SurfaceD3D::resetSwapChain(DisplayD3D *displayD3D,
+ int backbufferWidth,
+ int backbufferHeight)
+{
+ ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
+ ASSERT(mSwapChain);
+
+ EGLint status = mSwapChain->reset(displayD3D, std::max(1, backbufferWidth),
+ std::max(1, backbufferHeight), mSwapInterval);
+
+ if (status == EGL_CONTEXT_LOST)
+ {
+ mRenderer->notifyDeviceLost();
+ return egl::Error(status);
+ }
+ else if (status != EGL_SUCCESS)
+ {
+ return egl::Error(status);
+ }
+
+ mWidth = backbufferWidth;
+ mHeight = backbufferHeight;
+ mSwapIntervalDirty = false;
+
+ return egl::NoError();
+}
+
+egl::Error SurfaceD3D::swapRect(DisplayD3D *displayD3D,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height)
+{
+ if (!mSwapChain)
+ {
+ return egl::NoError();
+ }
+
+ if (x + width > mWidth)
+ {
+ width = mWidth - x;
+ }
+
+ if (y + height > mHeight)
+ {
+ height = mHeight - y;
+ }
+
+ if (width != 0 && height != 0)
+ {
+ EGLint status = mSwapChain->swapRect(displayD3D, x, y, width, height);
+
+ if (status == EGL_CONTEXT_LOST)
+ {
+ mRenderer->notifyDeviceLost();
+ return egl::Error(status);
+ }
+ else if (status != EGL_SUCCESS)
+ {
+ return egl::Error(status);
+ }
+ }
+
+ ANGLE_TRY(checkForOutOfDateSwapChain(displayD3D));
+
+ return egl::NoError();
+}
+
+egl::Error SurfaceD3D::checkForOutOfDateSwapChain(DisplayD3D *displayD3D)
+{
+ RECT client;
+ int clientWidth = getWidth();
+ int clientHeight = getHeight();
+ bool sizeDirty = false;
+ if (!mFixedSize && !mNativeWindow->isIconic())
+ {
+ // The window is automatically resized to 150x22 when it's minimized, but the swapchain
+ // shouldn't be resized because that's not a useful size to render to.
+ if (!mNativeWindow->getClientRect(&client))
+ {
+ UNREACHABLE();
+ return egl::NoError();
+ }
+
+ // Grow the buffer now, if the window has grown. We need to grow now to avoid losing
+ // information.
+ clientWidth = client.right - client.left;
+ clientHeight = client.bottom - client.top;
+ sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
+ }
+ else if (mFixedSize)
+ {
+ clientWidth = mFixedWidth;
+ clientHeight = mFixedHeight;
+ sizeDirty = mFixedWidth != getWidth() || mFixedHeight != getHeight();
+ }
+
+ if (mSwapIntervalDirty)
+ {
+ ANGLE_TRY(resetSwapChain(displayD3D, clientWidth, clientHeight));
+ }
+ else if (sizeDirty)
+ {
+ ANGLE_TRY(resizeSwapChain(displayD3D, clientWidth, clientHeight));
+ }
+
+ return egl::NoError();
+}
+
+egl::Error SurfaceD3D::swap(const gl::Context *context)
+{
+ DisplayD3D *displayD3D = GetImplAs<DisplayD3D>(context->getDisplay());
+ return swapRect(displayD3D, 0, 0, mWidth, mHeight);
+}
+
+egl::Error SurfaceD3D::postSubBuffer(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height)
+{
+ DisplayD3D *displayD3D = GetImplAs<DisplayD3D>(context->getDisplay());
+ return swapRect(displayD3D, x, y, width, height);
+}
+
+rx::SwapChainD3D *SurfaceD3D::getSwapChain() const
+{
+ return mSwapChain;
+}
+
+void SurfaceD3D::setSwapInterval(EGLint interval)
+{
+ if (mSwapInterval == interval)
+ {
+ return;
+ }
+
+ mSwapInterval = interval;
+ mSwapIntervalDirty = true;
+}
+
+void SurfaceD3D::setFixedWidth(EGLint width)
+{
+ mFixedWidth = width;
+}
+
+void SurfaceD3D::setFixedHeight(EGLint height)
+{
+ mFixedHeight = height;
+}
+
+EGLint SurfaceD3D::getWidth() const
+{
+ return mWidth;
+}
+
+EGLint SurfaceD3D::getHeight() const
+{
+ return mHeight;
+}
+
+EGLint SurfaceD3D::isPostSubBufferSupported() const
+{
+ // post sub buffer is always possible on D3D surfaces
+ return EGL_TRUE;
+}
+
+EGLint SurfaceD3D::getSwapBehavior() const
+{
+ return EGL_BUFFER_PRESERVED;
+}
+
+egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ if (attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
+ {
+ *value = mSwapChain->getShareHandle();
+ }
+ else if (attribute == EGL_DXGI_KEYED_MUTEX_ANGLE)
+ {
+ *value = mSwapChain->getKeyedMutex();
+ }
+ else
+ UNREACHABLE();
+
+ return egl::NoError();
+}
+
+const angle::Format *SurfaceD3D::getD3DTextureColorFormat() const
+{
+ return mColorFormat;
+}
+
+egl::Error SurfaceD3D::attachToFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer)
+{
+ return egl::NoError();
+}
+
+egl::Error SurfaceD3D::detachFromFramebuffer(const gl::Context *context,
+ gl::Framebuffer *framebuffer)
+{
+ return egl::NoError();
+}
+
+angle::Result SurfaceD3D::getAttachmentRenderTarget(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
+ GLsizei samples,
+ FramebufferAttachmentRenderTarget **rtOut)
+{
+ if (binding == GL_BACK)
+ {
+ *rtOut = mSwapChain->getColorRenderTarget();
+ }
+ else
+ {
+ *rtOut = mSwapChain->getDepthStencilRenderTarget();
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result SurfaceD3D::initializeContents(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex)
+{
+ switch (binding)
+ {
+ case GL_BACK:
+ ASSERT(mState.config->renderTargetFormat != GL_NONE);
+ ANGLE_TRY(mRenderer->initRenderTarget(context, mSwapChain->getColorRenderTarget()));
+ break;
+
+ case GL_DEPTH:
+ case GL_STENCIL:
+ ASSERT(mState.config->depthStencilFormat != GL_NONE);
+ ANGLE_TRY(
+ mRenderer->initRenderTarget(context, mSwapChain->getDepthStencilRenderTarget()));
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return angle::Result::Continue;
+}
+
+WindowSurfaceD3D::WindowSurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs)
+ : SurfaceD3D(state, renderer, display, window, 0, static_cast<EGLClientBuffer>(0), attribs)
+{}
+
+WindowSurfaceD3D::~WindowSurfaceD3D() {}
+
+PbufferSurfaceD3D::PbufferSurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs)
+ : SurfaceD3D(state,
+ renderer,
+ display,
+ static_cast<EGLNativeWindowType>(0),
+ buftype,
+ clientBuffer,
+ attribs)
+{}
+
+PbufferSurfaceD3D::~PbufferSurfaceD3D() {}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/SurfaceD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/SurfaceD3D.h
new file mode 100644
index 0000000000..720943c8d1
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/SurfaceD3D.h
@@ -0,0 +1,145 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SurfaceD3D.h: D3D implementation of an EGL surface
+
+#ifndef LIBANGLE_RENDERER_D3D_SURFACED3D_H_
+#define LIBANGLE_RENDERER_D3D_SURFACED3D_H_
+
+#include "libANGLE/renderer/SurfaceImpl.h"
+#include "libANGLE/renderer/d3d/NativeWindowD3D.h"
+
+namespace egl
+{
+class Surface;
+}
+
+namespace rx
+{
+class DisplayD3D;
+class SwapChainD3D;
+class RendererD3D;
+
+class SurfaceD3D : public SurfaceImpl
+{
+ public:
+ ~SurfaceD3D() override;
+ void releaseSwapChain();
+
+ egl::Error initialize(const egl::Display *display) override;
+
+ egl::Error swap(const gl::Context *context) override;
+ egl::Error postSubBuffer(const gl::Context *context,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(const gl::Context *context,
+ gl::Texture *texture,
+ EGLint buffer) override;
+ egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override;
+ egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
+ egl::Error getMscRate(EGLint *numerator, EGLint *denominator) override;
+ void setSwapInterval(EGLint interval) override;
+ void setFixedWidth(EGLint width) override;
+ void setFixedHeight(EGLint height) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+ EGLint getSwapBehavior() const override;
+
+ // D3D implementations
+ SwapChainD3D *getSwapChain() const;
+
+ egl::Error resetSwapChain(const egl::Display *display);
+
+ egl::Error checkForOutOfDateSwapChain(DisplayD3D *displayD3D);
+
+ angle::Result getAttachmentRenderTarget(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
+ GLsizei samples,
+ FramebufferAttachmentRenderTarget **rtOut) override;
+ angle::Result initializeContents(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex) override;
+
+ const angle::Format *getD3DTextureColorFormat() const override;
+
+ egl::Error attachToFramebuffer(const gl::Context *context,
+ gl::Framebuffer *framebuffer) override;
+ egl::Error detachFromFramebuffer(const gl::Context *context,
+ gl::Framebuffer *framebuffer) override;
+
+ protected:
+ SurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ EGLNativeWindowType window,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs);
+
+ egl::Error swapRect(DisplayD3D *displayD3D, EGLint x, EGLint y, EGLint width, EGLint height);
+ egl::Error resetSwapChain(DisplayD3D *displayD3D, int backbufferWidth, int backbufferHeight);
+ egl::Error resizeSwapChain(DisplayD3D *displayD3D, int backbufferWidth, int backbufferHeight);
+
+ RendererD3D *mRenderer;
+ egl::Display *mDisplay;
+
+ bool mFixedSize;
+ GLint mFixedWidth;
+ GLint mFixedHeight;
+ GLint mOrientation;
+
+ GLenum mRenderTargetFormat;
+ GLenum mDepthStencilFormat;
+ const angle::Format *mColorFormat;
+
+ SwapChainD3D *mSwapChain;
+ bool mSwapIntervalDirty;
+
+ NativeWindowD3D *mNativeWindow; // Handler for the Window that the surface is created for.
+ EGLint mWidth;
+ EGLint mHeight;
+
+ EGLint mSwapInterval;
+
+ HANDLE mShareHandle;
+ IUnknown *mD3DTexture;
+
+ EGLenum mBuftype;
+};
+
+class WindowSurfaceD3D : public SurfaceD3D
+{
+ public:
+ WindowSurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ EGLNativeWindowType window,
+ const egl::AttributeMap &attribs);
+ ~WindowSurfaceD3D() override;
+};
+
+class PbufferSurfaceD3D : public SurfaceD3D
+{
+ public:
+ PbufferSurfaceD3D(const egl::SurfaceState &state,
+ RendererD3D *renderer,
+ egl::Display *display,
+ EGLenum buftype,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs);
+ ~PbufferSurfaceD3D() override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_SURFACED3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/SwapChainD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/SwapChainD3D.cpp
new file mode 100644
index 0000000000..8891888a68
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/SwapChainD3D.cpp
@@ -0,0 +1,34 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChainD3D.cpp: Defines a back-end specific class that hides the details of the
+// implementation-specific swapchain.
+
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+
+namespace rx
+{
+
+SwapChainD3D::SwapChainD3D(HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat)
+ : mOffscreenRenderTargetFormat(backBufferFormat),
+ mDepthBufferFormat(depthBufferFormat),
+ mShareHandle(shareHandle),
+ mD3DTexture(d3dTexture)
+{
+ if (mD3DTexture)
+ {
+ mD3DTexture->AddRef();
+ }
+}
+
+SwapChainD3D::~SwapChainD3D()
+{
+ SafeRelease(mD3DTexture);
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/SwapChainD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/SwapChainD3D.h
new file mode 100644
index 0000000000..fcbab95c8d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/SwapChainD3D.h
@@ -0,0 +1,83 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChainD3D.h: Defines a back-end specific class that hides the details of the
+// implementation-specific swapchain.
+
+#ifndef LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_
+#define LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+
+#include "common/angleutils.h"
+#include "common/platform.h"
+#include "libANGLE/Error.h"
+
+#if !defined(ANGLE_FORCE_VSYNC_OFF)
+# define ANGLE_FORCE_VSYNC_OFF 0
+#endif
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace egl
+{
+class Display;
+} // namespace egl
+
+namespace rx
+{
+class DisplayD3D;
+class RenderTargetD3D;
+
+class SwapChainD3D : angle::NonCopyable
+{
+ public:
+ SwapChainD3D(HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat);
+ virtual ~SwapChainD3D();
+
+ virtual EGLint resize(DisplayD3D *displayD3D,
+ EGLint backbufferWidth,
+ EGLint backbufferSize) = 0;
+ virtual EGLint reset(DisplayD3D *displayD3D,
+ EGLint backbufferWidth,
+ EGLint backbufferHeight,
+ EGLint swapInterval) = 0;
+ virtual EGLint swapRect(DisplayD3D *displayD3D,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height) = 0;
+ virtual void recreate() = 0;
+
+ virtual RenderTargetD3D *getColorRenderTarget() = 0;
+ virtual RenderTargetD3D *getDepthStencilRenderTarget() = 0;
+
+ GLenum getRenderTargetInternalFormat() const { return mOffscreenRenderTargetFormat; }
+ GLenum getDepthBufferInternalFormat() const { return mDepthBufferFormat; }
+
+ HANDLE getShareHandle() { return mShareHandle; }
+ virtual void *getKeyedMutex() = 0;
+
+ virtual egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) = 0;
+
+ protected:
+ const GLenum mOffscreenRenderTargetFormat;
+ const GLenum mDepthBufferFormat;
+
+ HANDLE mShareHandle;
+ IUnknown *mD3DTexture;
+};
+
+} // namespace rx
+#endif // LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/TextureD3D.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/TextureD3D.cpp
new file mode 100644
index 0000000000..fc22f000be
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/TextureD3D.cpp
@@ -0,0 +1,4640 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends.
+
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/BufferImpl.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/ContextD3D.h"
+#include "libANGLE/renderer/d3d/EGLImageD3D.h"
+#include "libANGLE/renderer/d3d/ImageD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
+
+namespace rx
+{
+
+namespace
+{
+
+angle::Result GetUnpackPointer(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels,
+ ptrdiff_t layerOffset,
+ const uint8_t **pointerOut)
+{
+ if (unpackBuffer)
+ {
+ // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not
+ // supported
+ ptrdiff_t offset = reinterpret_cast<ptrdiff_t>(pixels);
+
+ // TODO: this is the only place outside of renderer that asks for a buffers raw data.
+ // This functionality should be moved into renderer and the getData method of BufferImpl
+ // removed.
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(unpackBuffer);
+ ASSERT(bufferD3D);
+ const uint8_t *bufferData = nullptr;
+ ANGLE_TRY(bufferD3D->getData(context, &bufferData));
+ *pointerOut = bufferData + offset;
+ }
+ else
+ {
+ *pointerOut = pixels;
+ }
+
+ // Offset the pointer for 2D array layer (if it's valid)
+ if (*pointerOut != nullptr)
+ {
+ *pointerOut += layerOffset;
+ }
+
+ return angle::Result::Continue;
+}
+
+bool IsRenderTargetUsage(GLenum usage)
+{
+ return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+}
+} // namespace
+
+TextureD3D::TextureD3D(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureImpl(state),
+ mRenderer(renderer),
+ mDirtyImages(true),
+ mImmutable(false),
+ mTexStorage(nullptr),
+ mTexStorageObserverBinding(this, kTextureStorageObserverMessageIndex),
+ mBaseLevel(0)
+{}
+
+TextureD3D::~TextureD3D()
+{
+ ASSERT(!mTexStorage);
+}
+
+angle::Result TextureD3D::getNativeTexture(const gl::Context *context, TextureStorage **outStorage)
+{
+ // ensure the underlying texture is created
+ ANGLE_TRY(initializeStorage(context, BindFlags()));
+
+ if (mTexStorage)
+ {
+ ANGLE_TRY(updateStorage(context));
+ }
+
+ ASSERT(outStorage);
+
+ *outStorage = mTexStorage;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D::getImageAndSyncFromStorage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ ImageD3D **outImage)
+{
+ ImageD3D *image = getImage(index);
+ if (mTexStorage && mTexStorage->isRenderTarget())
+ {
+ ANGLE_TRY(image->copyFromTexStorage(context, index, mTexStorage));
+ mDirtyImages = true;
+ }
+ image->markClean();
+ *outImage = image;
+ return angle::Result::Continue;
+}
+
+GLint TextureD3D::getLevelZeroWidth() const
+{
+ ASSERT(gl::CountLeadingZeros(static_cast<uint32_t>(getBaseLevelWidth())) > getBaseLevel());
+ return getBaseLevelWidth() << mBaseLevel;
+}
+
+GLint TextureD3D::getLevelZeroHeight() const
+{
+ ASSERT(gl::CountLeadingZeros(static_cast<uint32_t>(getBaseLevelHeight())) > getBaseLevel());
+ return getBaseLevelHeight() << mBaseLevel;
+}
+
+GLint TextureD3D::getLevelZeroDepth() const
+{
+ return getBaseLevelDepth();
+}
+
+GLint TextureD3D::getBaseLevelWidth() const
+{
+ const ImageD3D *baseImage = getBaseLevelImage();
+ return (baseImage ? baseImage->getWidth() : 0);
+}
+
+GLint TextureD3D::getBaseLevelHeight() const
+{
+ const ImageD3D *baseImage = getBaseLevelImage();
+ return (baseImage ? baseImage->getHeight() : 0);
+}
+
+GLint TextureD3D::getBaseLevelDepth() const
+{
+ const ImageD3D *baseImage = getBaseLevelImage();
+ return (baseImage ? baseImage->getDepth() : 0);
+}
+
+// Note: "base level image" is loosely defined to be any image from the base level,
+// where in the base of 2D array textures and cube maps there are several. Don't use
+// the base level image for anything except querying texture format and size.
+GLenum TextureD3D::getBaseLevelInternalFormat() const
+{
+ const ImageD3D *baseImage = getBaseLevelImage();
+ return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
+}
+
+angle::Result TextureD3D::setStorage(const gl::Context *context,
+ gl::TextureType type,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D::setStorageMultisample(const gl::Context *context,
+ gl::TextureType type,
+ GLsizei samples,
+ GLint internalformat,
+ const gl::Extents &size,
+ bool fixedSampleLocations)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D::setBuffer(const gl::Context *context, GLenum internalFormat)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D::setStorageExternalMemory(const gl::Context *context,
+ gl::TextureType type,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ gl::MemoryObject *memoryObject,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+bool TextureD3D::couldUseSetData() const
+{
+ if (!mRenderer->getFeatures().setDataFasterThanImageUpload.enabled)
+ {
+ return false;
+ }
+
+ if (!mRenderer->getFeatures().setDataFasterThanImageUploadOn128bitFormats.enabled)
+ {
+ gl::InternalFormat internalFormat =
+ gl::GetSizedInternalFormatInfo(getBaseLevelInternalFormat());
+ return internalFormat.pixelBytes < 16;
+ }
+
+ return true;
+}
+
+bool TextureD3D::shouldUseSetData(const ImageD3D *image) const
+{
+ if (!couldUseSetData())
+ {
+ return false;
+ }
+
+ if (image->isDirty())
+ {
+ return false;
+ }
+
+ gl::InternalFormat internalFormat = gl::GetSizedInternalFormatInfo(image->getInternalFormat());
+
+ // We can only handle full updates for depth-stencil textures, so to avoid complications
+ // disable them entirely.
+ if (internalFormat.depthBits > 0 || internalFormat.stencilBits > 0)
+ {
+ return false;
+ }
+
+ // TODO(jmadill): Handle compressed internal formats
+ return (mTexStorage && !internalFormat.compressed);
+}
+
+angle::Result TextureD3D::setImageImpl(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels,
+ ptrdiff_t layerOffset)
+{
+ ImageD3D *image = getImage(index);
+ ASSERT(image);
+
+ // No-op
+ if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
+ {
+ return angle::Result::Continue;
+ }
+
+ // We no longer need the "GLenum format" parameter to TexImage to determine what data format
+ // "pixels" contains. From our image internal format we know how many channels to expect, and
+ // "type" gives the format of pixel's components.
+ const uint8_t *pixelData = nullptr;
+ ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData));
+
+ if (pixelData != nullptr)
+ {
+ if (shouldUseSetData(image))
+ {
+ ANGLE_TRY(
+ mTexStorage->setData(context, index, image, nullptr, type, unpack, pixelData));
+ }
+ else
+ {
+ gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(),
+ image->getDepth());
+ ANGLE_TRY(image->loadData(context, fullImageArea, unpack, type, pixelData,
+ index.usesTex3D()));
+ }
+
+ mDirtyImages = true;
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D::subImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels,
+ ptrdiff_t layerOffset)
+{
+ // CPU readback & copy where direct GPU copy is not supported
+ const uint8_t *pixelData = nullptr;
+ ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData));
+
+ if (pixelData != nullptr)
+ {
+ ImageD3D *image = getImage(index);
+ ASSERT(image);
+
+ if (shouldUseSetData(image))
+ {
+ return mTexStorage->setData(context, index, image, &area, type, unpack, pixelData);
+ }
+
+ ANGLE_TRY(image->loadData(context, area, unpack, type, pixelData, index.usesTex3D()));
+ ANGLE_TRY(commitRegion(context, index, area));
+ mDirtyImages = true;
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D::setCompressedImageImpl(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels,
+ ptrdiff_t layerOffset)
+{
+ ImageD3D *image = getImage(index);
+ ASSERT(image);
+
+ if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0)
+ {
+ return angle::Result::Continue;
+ }
+
+ // We no longer need the "GLenum format" parameter to TexImage to determine what data format
+ // "pixels" contains. From our image internal format we know how many channels to expect, and
+ // "type" gives the format of pixel's components.
+ const uint8_t *pixelData = nullptr;
+ gl::Buffer *unpackBuffer = context->getState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
+ ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData));
+
+ if (pixelData != nullptr)
+ {
+ gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
+ ANGLE_TRY(image->loadCompressedData(context, fullImageArea, pixelData));
+
+ mDirtyImages = true;
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D::subImageCompressed(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels,
+ ptrdiff_t layerOffset)
+{
+ const uint8_t *pixelData = nullptr;
+ gl::Buffer *unpackBuffer = context->getState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
+ ANGLE_TRY(GetUnpackPointer(context, unpack, unpackBuffer, pixels, layerOffset, &pixelData));
+
+ if (pixelData != nullptr)
+ {
+ ImageD3D *image = getImage(index);
+ ASSERT(image);
+
+ ANGLE_TRY(image->loadCompressedData(context, area, pixelData));
+
+ mDirtyImages = true;
+ }
+
+ return angle::Result::Continue;
+}
+
+bool TextureD3D::isFastUnpackable(const gl::Buffer *unpackBuffer,
+ const gl::PixelUnpackState &unpack,
+ GLenum sizedInternalFormat)
+{
+ return unpackBuffer != nullptr && unpack.skipRows == 0 && unpack.skipPixels == 0 &&
+ unpack.imageHeight == 0 && unpack.skipImages == 0 &&
+ mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
+}
+
+angle::Result TextureD3D::fastUnpackPixels(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels,
+ const gl::Box &destArea,
+ GLenum sizedInternalFormat,
+ GLenum type,
+ RenderTargetD3D *destRenderTarget)
+{
+ bool check = (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 ||
+ unpack.skipImages != 0);
+ ANGLE_CHECK(GetImplAs<ContextD3D>(context), !check,
+ "Unimplemented pixel store parameters in fastUnpackPixels", GL_INVALID_OPERATION);
+
+ // No-op
+ if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
+ {
+ return angle::Result::Continue;
+ }
+
+ // In order to perform the fast copy through the shader, we must have the right format, and be
+ // able to create a render target.
+ ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat));
+
+ uintptr_t offset = reinterpret_cast<uintptr_t>(pixels);
+
+ ANGLE_TRY(mRenderer->fastCopyBufferToTexture(
+ context, unpack, unpackBuffer, static_cast<unsigned int>(offset), destRenderTarget,
+ sizedInternalFormat, type, destArea));
+
+ return angle::Result::Continue;
+}
+
+GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const
+{
+ if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) ||
+ mRenderer->getNativeExtensions().textureNpotOES)
+ {
+ // Maximum number of levels
+ return gl::log2(std::max(std::max(width, height), depth)) + 1;
+ }
+ else
+ {
+ // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps.
+ return 1;
+ }
+}
+
+TextureStorage *TextureD3D::getStorage()
+{
+ ASSERT(mTexStorage);
+ return mTexStorage;
+}
+
+ImageD3D *TextureD3D::getBaseLevelImage() const
+{
+ if (mBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ return nullptr;
+ }
+ return getImage(getImageIndex(mBaseLevel, 0));
+}
+
+angle::Result TextureD3D::setImageExternal(const gl::Context *context,
+ gl::TextureType type,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc)
+{
+ // Only external images can accept external textures
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D::generateMipmap(const gl::Context *context)
+{
+ const GLuint baseLevel = mState.getEffectiveBaseLevel();
+ const GLuint maxLevel = mState.getMipmapMaxLevel();
+ ASSERT(maxLevel > baseLevel); // Should be checked before calling this.
+
+ if (mTexStorage && mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ // Switch to using the mipmapped texture.
+ TextureStorage *textureStorageEXT = nullptr;
+ ANGLE_TRY(getNativeTexture(context, &textureStorageEXT));
+ ANGLE_TRY(textureStorageEXT->useLevelZeroWorkaroundTexture(context, false));
+ }
+
+ // Set up proper mipmap chain in our Image array.
+ ANGLE_TRY(initMipmapImages(context));
+
+ if (mTexStorage && mTexStorage->supportsNativeMipmapFunction())
+ {
+ ANGLE_TRY(updateStorage(context));
+
+ // Generate the mipmap chain using the ad-hoc DirectX function.
+ ANGLE_TRY(mRenderer->generateMipmapUsingD3D(context, mTexStorage, mState));
+ }
+ else
+ {
+ // Generate the mipmap chain, one level at a time.
+ ANGLE_TRY(generateMipmapUsingImages(context, maxLevel));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D::generateMipmapUsingImages(const gl::Context *context,
+ const GLuint maxLevel)
+{
+ // We know that all layers have the same dimension, for the texture to be complete
+ GLint layerCount = static_cast<GLint>(getLayerCount(mBaseLevel));
+
+ if (mTexStorage && !mTexStorage->isRenderTarget() &&
+ canCreateRenderTargetForImage(getImageIndex(mBaseLevel, 0)) &&
+ mRenderer->getRendererClass() == RENDERER_D3D11)
+ {
+ if (!mRenderer->getFeatures().setDataFasterThanImageUpload.enabled)
+ {
+ ANGLE_TRY(updateStorage(context));
+ }
+ ANGLE_TRY(ensureRenderTarget(context));
+ }
+ else if (couldUseSetData() && mTexStorage)
+ {
+ // When making mipmaps with the setData workaround enabled, the texture storage has
+ // the image data already. For non-render-target storage, we have to pull it out into
+ // an image layer.
+ if (!mTexStorage->isRenderTarget())
+ {
+ // Copy from the storage mip 0 to Image mip 0
+ for (GLint layer = 0; layer < layerCount; ++layer)
+ {
+ gl::ImageIndex srcIndex = getImageIndex(mBaseLevel, layer);
+
+ ImageD3D *image = getImage(srcIndex);
+ ANGLE_TRY(image->copyFromTexStorage(context, srcIndex, mTexStorage));
+ }
+ }
+ else
+ {
+ ANGLE_TRY(updateStorage(context));
+ }
+ }
+
+ // TODO: Decouple this from zeroMaxLodWorkaround. This is a 9_3 restriction, unrelated to
+ // zeroMaxLodWorkaround. The restriction is because Feature Level 9_3 can't create SRVs on
+ // individual levels of the texture. As a result, even if the storage is a rendertarget, we
+ // can't use the GPU to generate the mipmaps without further work. The D3D9 renderer works
+ // around this by copying each level of the texture into its own single-layer GPU texture (in
+ // Blit9::boxFilter). Feature Level 9_3 could do something similar, or it could continue to use
+ // CPU-side mipmap generation, or something else.
+ bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget() &&
+ !(mRenderer->getFeatures().zeroMaxLodWorkaround.enabled));
+ if (renderableStorage)
+ {
+ ANGLE_TRY(updateStorage(context));
+ }
+
+ for (GLint layer = 0; layer < layerCount; ++layer)
+ {
+ for (GLuint mip = mBaseLevel + 1; mip <= maxLevel; ++mip)
+ {
+ ASSERT(getLayerCount(mip) == layerCount);
+
+ gl::ImageIndex sourceIndex = getImageIndex(mip - 1, layer);
+ gl::ImageIndex destIndex = getImageIndex(mip, layer);
+
+ if (renderableStorage)
+ {
+ // GPU-side mipmapping
+ ANGLE_TRY(mTexStorage->generateMipmap(context, sourceIndex, destIndex));
+ }
+ else
+ {
+ // CPU-side mipmapping
+ ANGLE_TRY(
+ mRenderer->generateMipmap(context, getImage(destIndex), getImage(sourceIndex)));
+ }
+ }
+ }
+
+ mDirtyImages = !renderableStorage;
+
+ if (mTexStorage && mDirtyImages)
+ {
+ ANGLE_TRY(updateStorage(context));
+ }
+
+ return angle::Result::Continue;
+}
+
+bool TextureD3D::isBaseImageZeroSize() const
+{
+ ImageD3D *baseImage = getBaseLevelImage();
+
+ if (!baseImage || baseImage->getWidth() <= 0 || baseImage->getHeight() <= 0)
+ {
+ return true;
+ }
+
+ if (baseImage->getType() == gl::TextureType::_3D && baseImage->getDepth() <= 0)
+ {
+ return true;
+ }
+
+ if (baseImage->getType() == gl::TextureType::_2DArray && getLayerCount(getBaseLevel()) <= 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+angle::Result TextureD3D::ensureBindFlags(const gl::Context *context, BindFlags bindFlags)
+{
+ ANGLE_TRY(initializeStorage(context, bindFlags));
+
+ // initializeStorage can fail with NoError if the texture is not complete. This is not
+ // an error for incomplete sampling, but it is a big problem for rendering.
+ if (!mTexStorage)
+ {
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Stop;
+ }
+
+ if (!isBaseImageZeroSize())
+ {
+ ASSERT(mTexStorage);
+ if ((bindFlags.renderTarget && !mTexStorage->isRenderTarget()) ||
+ (bindFlags.unorderedAccess && !mTexStorage->isUnorderedAccess()))
+ {
+ TexStoragePointer newRenderTargetStorage;
+ ANGLE_TRY(createCompleteStorage(context, bindFlags, &newRenderTargetStorage));
+
+ ANGLE_TRY(mTexStorage->copyToStorage(context, newRenderTargetStorage.get()));
+ ANGLE_TRY(setCompleteTexStorage(context, newRenderTargetStorage.get()));
+ newRenderTargetStorage.release();
+ // If this texture is used in compute shader, we should invalidate this texture so that
+ // the UAV/SRV is rebound again with this new texture storage in next dispatch call.
+ mTexStorage->invalidateTextures();
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D::ensureRenderTarget(const gl::Context *context)
+{
+ return ensureBindFlags(context, BindFlags::RenderTarget());
+}
+
+angle::Result TextureD3D::ensureUnorderedAccess(const gl::Context *context)
+{
+ return ensureBindFlags(context, BindFlags::UnorderedAccess());
+}
+
+bool TextureD3D::canCreateRenderTargetForImage(const gl::ImageIndex &index) const
+{
+ if (index.getType() == gl::TextureType::_2DMultisample ||
+ index.getType() == gl::TextureType::_2DMultisampleArray)
+ {
+ ASSERT(index.getType() != gl::TextureType::_2DMultisampleArray || index.hasLayer());
+ return true;
+ }
+
+ ImageD3D *image = getImage(index);
+ ASSERT(image);
+ bool levelsComplete = (isImageComplete(index) && isImageComplete(getImageIndex(0, 0)));
+ return (image->isRenderableFormat() && levelsComplete);
+}
+
+angle::Result TextureD3D::commitRegion(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &region)
+{
+ if (mTexStorage)
+ {
+ ASSERT(isValidIndex(index));
+ ImageD3D *image = getImage(index);
+ ANGLE_TRY(image->copyToStorage(context, mTexStorage, index, region));
+ image->markClean();
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D::getAttachmentRenderTarget(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
+ GLsizei samples,
+ FramebufferAttachmentRenderTarget **rtOut)
+{
+ RenderTargetD3D *rtD3D = nullptr;
+ ANGLE_TRY(getRenderTarget(context, imageIndex, samples, &rtD3D));
+ *rtOut = static_cast<FramebufferAttachmentRenderTarget *>(rtD3D);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D::setBaseLevel(const gl::Context *context, GLuint baseLevel)
+{
+ const int oldStorageWidth = std::max(1, getLevelZeroWidth());
+ const int oldStorageHeight = std::max(1, getLevelZeroHeight());
+ const int oldStorageDepth = std::max(1, getLevelZeroDepth());
+ const int oldStorageFormat = getBaseLevelInternalFormat();
+ mBaseLevel = baseLevel;
+
+ // When the base level changes, the texture storage might not be valid anymore, since it could
+ // have been created based on the dimensions of the previous specified level range.
+ const int newStorageWidth = std::max(1, getLevelZeroWidth());
+ const int newStorageHeight = std::max(1, getLevelZeroHeight());
+ const int newStorageDepth = std::max(1, getLevelZeroDepth());
+ const int newStorageFormat = getBaseLevelInternalFormat();
+ if (mTexStorage &&
+ (newStorageWidth != oldStorageWidth || newStorageHeight != oldStorageHeight ||
+ newStorageDepth != oldStorageDepth || newStorageFormat != oldStorageFormat))
+ {
+ markAllImagesDirty();
+
+ // Iterate over all images, and backup the content if it's been used as a render target. The
+ // D3D11 backend can automatically restore images on storage destroy, but it only works for
+ // images that have been associated with the texture storage before, which is insufficient
+ // here.
+ if (mTexStorage->isRenderTarget())
+ {
+ gl::ImageIndexIterator iterator = imageIterator();
+ while (iterator.hasNext())
+ {
+ const gl::ImageIndex index = iterator.next();
+ const GLsizei samples = getRenderToTextureSamples();
+ RenderTargetD3D *renderTarget = nullptr;
+ ANGLE_TRY(mTexStorage->findRenderTarget(context, index, samples, &renderTarget));
+ if (renderTarget)
+ {
+ ANGLE_TRY(getImage(index)->copyFromTexStorage(context, index, mTexStorage));
+ }
+ }
+ }
+
+ ANGLE_TRY(releaseTexStorage(context, gl::TexLevelMask()));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D::onLabelUpdate(const gl::Context *context)
+{
+ if (mTexStorage)
+ {
+ mTexStorage->setLabel(mState.getLabel());
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D::syncState(const gl::Context *context,
+ const gl::Texture::DirtyBits &dirtyBits,
+ gl::Command source)
+{
+ // This could be improved using dirty bits.
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D::releaseTexStorage(const gl::Context *context,
+ const gl::TexLevelMask &copyStorageToImagesMask)
+{
+ if (!mTexStorage)
+ {
+ return angle::Result::Continue;
+ }
+
+ if (mTexStorage->isRenderTarget())
+ {
+ const GLenum storageFormat = getBaseLevelInternalFormat();
+ const size_t storageLevels = mTexStorage->getLevelCount();
+
+ gl::ImageIndexIterator iterator = imageIterator();
+ while (iterator.hasNext())
+ {
+ const gl::ImageIndex index = iterator.next();
+ ImageD3D *image = getImage(index);
+ const int storageWidth = std::max(1, getLevelZeroWidth() >> index.getLevelIndex());
+ const int storageHeight = std::max(1, getLevelZeroHeight() >> index.getLevelIndex());
+ if (image && isImageComplete(index) && image->getWidth() == storageWidth &&
+ image->getHeight() == storageHeight &&
+ image->getInternalFormat() == storageFormat &&
+ index.getLevelIndex() < static_cast<int>(storageLevels) &&
+ copyStorageToImagesMask[index.getLevelIndex()])
+ {
+ ANGLE_TRY(image->copyFromTexStorage(context, index, mTexStorage));
+ }
+ }
+ }
+
+ onStateChange(angle::SubjectMessage::StorageReleased);
+
+ auto err = mTexStorage->onDestroy(context);
+ SafeDelete(mTexStorage);
+ return err;
+}
+
+void TextureD3D::onDestroy(const gl::Context *context)
+{
+ (void)releaseTexStorage(context, gl::TexLevelMask());
+}
+
+angle::Result TextureD3D::initializeContents(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex)
+{
+ ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
+ gl::ImageIndex index = imageIndex;
+
+ // Special case for D3D11 3D textures. We can't create render targets for individual layers of a
+ // 3D texture, so force the clear to the entire mip. There shouldn't ever be a case where we
+ // would lose existing data.
+ if (index.getType() == gl::TextureType::_3D)
+ {
+ index = gl::ImageIndex::Make3D(index.getLevelIndex(), gl::ImageIndex::kEntireLevel);
+ }
+ else if (index.getType() == gl::TextureType::_2DArray && !index.hasLayer())
+ {
+ std::array<GLint, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS> tempLayerCounts;
+
+ GLint levelIndex = index.getLevelIndex();
+ tempLayerCounts[levelIndex] = getLayerCount(levelIndex);
+ gl::ImageIndexIterator iterator =
+ gl::ImageIndexIterator::Make2DArray(levelIndex, levelIndex + 1, tempLayerCounts.data());
+ while (iterator.hasNext())
+ {
+ ANGLE_TRY(initializeContents(context, GL_NONE, iterator.next()));
+ }
+ return angle::Result::Continue;
+ }
+ else if (index.getType() == gl::TextureType::_2DMultisampleArray && !index.hasLayer())
+ {
+ std::array<GLint, gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS> tempLayerCounts;
+
+ ASSERT(index.getLevelIndex() == 0);
+ tempLayerCounts[0] = getLayerCount(0);
+ gl::ImageIndexIterator iterator =
+ gl::ImageIndexIterator::Make2DMultisampleArray(tempLayerCounts.data());
+ while (iterator.hasNext())
+ {
+ ANGLE_TRY(initializeContents(context, GL_NONE, iterator.next()));
+ }
+ return angle::Result::Continue;
+ }
+
+ // Force image clean.
+ ImageD3D *image = getImage(index);
+ if (image)
+ {
+ image->markClean();
+ }
+
+ // Fast path: can use a render target clear.
+ // We don't use the fast path with the zero max lod workaround because it would introduce a race
+ // between the rendertarget and the staging images.
+ const angle::FeaturesD3D &features = mRenderer->getFeatures();
+ bool shouldUseClear = (image == nullptr);
+ if (canCreateRenderTargetForImage(index) && !features.zeroMaxLodWorkaround.enabled &&
+ (shouldUseClear || features.allowClearForRobustResourceInit.enabled))
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+ ASSERT(mTexStorage);
+ RenderTargetD3D *renderTarget = nullptr;
+ ANGLE_TRY(mTexStorage->getRenderTarget(context, index, 0, &renderTarget));
+ ANGLE_TRY(mRenderer->initRenderTarget(context, renderTarget));
+
+ // Force image clean again, the texture storage may have been re-created and the image used.
+ if (image)
+ {
+ image->markClean();
+ }
+
+ return angle::Result::Continue;
+ }
+
+ ASSERT(image != nullptr);
+
+ // Slow path: non-renderable texture or the texture levels aren't set up.
+ const auto &formatInfo = gl::GetSizedInternalFormatInfo(image->getInternalFormat());
+
+ GLuint imageBytes = 0;
+ ANGLE_CHECK_GL_MATH(contextD3D, formatInfo.computeRowPitch(formatInfo.type, image->getWidth(),
+ 1, 0, &imageBytes));
+ imageBytes *= image->getHeight() * image->getDepth();
+
+ gl::PixelUnpackState zeroDataUnpackState;
+ zeroDataUnpackState.alignment = 1;
+
+ angle::MemoryBuffer *zeroBuffer = nullptr;
+ ANGLE_CHECK_GL_ALLOC(contextD3D, context->getZeroFilledBuffer(imageBytes, &zeroBuffer));
+
+ if (shouldUseSetData(image))
+ {
+ ANGLE_TRY(mTexStorage->setData(context, index, image, nullptr, formatInfo.type,
+ zeroDataUnpackState, zeroBuffer->data()));
+ }
+ else
+ {
+ gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
+ ANGLE_TRY(image->loadData(context, fullImageArea, zeroDataUnpackState, formatInfo.type,
+ zeroBuffer->data(), false));
+
+ // Force an update to the tex storage so we avoid problems with subImage and dirty regions.
+ if (mTexStorage)
+ {
+ ANGLE_TRY(commitRegion(context, index, fullImageArea));
+ image->markClean();
+ }
+ else
+ {
+ mDirtyImages = true;
+ }
+ }
+ return angle::Result::Continue;
+}
+
+GLsizei TextureD3D::getRenderToTextureSamples()
+{
+ if (mTexStorage)
+ {
+ return mTexStorage->getRenderToTextureSamples();
+ }
+ return 0;
+}
+
+void TextureD3D::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
+{
+ onStateChange(message);
+}
+
+TextureD3D_2D::TextureD3D_2D(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureD3D(state, renderer)
+{
+ mEGLImageTarget = false;
+ for (auto &image : mImageArray)
+ {
+ image.reset(renderer->createImage());
+ }
+}
+
+void TextureD3D_2D::onDestroy(const gl::Context *context)
+{
+ // Delete the Images before the TextureStorage. Images might be relying on the TextureStorage
+ // for some of their data. If TextureStorage is deleted before the Images, then their data will
+ // be wastefully copied back from the GPU before we delete the Images.
+ for (auto &image : mImageArray)
+ {
+ image.reset();
+ }
+ return TextureD3D::onDestroy(context);
+}
+
+TextureD3D_2D::~TextureD3D_2D() {}
+
+ImageD3D *TextureD3D_2D::getImage(int level, int layer) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(layer == 0);
+ return mImageArray[level].get();
+}
+
+ImageD3D *TextureD3D_2D::getImage(const gl::ImageIndex &index) const
+{
+ ASSERT(index.getLevelIndex() < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(!index.hasLayer());
+ ASSERT(index.getType() == gl::TextureType::_2D ||
+ index.getType() == gl::TextureType::VideoImage);
+ return mImageArray[index.getLevelIndex()].get();
+}
+
+GLsizei TextureD3D_2D::getLayerCount(int level) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ return 1;
+}
+
+GLsizei TextureD3D_2D::getWidth(GLint level) const
+{
+ if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ return mImageArray[level]->getWidth();
+ else
+ return 0;
+}
+
+GLsizei TextureD3D_2D::getHeight(GLint level) const
+{
+ if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ return mImageArray[level]->getHeight();
+ else
+ return 0;
+}
+
+GLenum TextureD3D_2D::getInternalFormat(GLint level) const
+{
+ if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ return mImageArray[level]->getInternalFormat();
+ else
+ return GL_NONE;
+}
+
+bool TextureD3D_2D::isDepth(GLint level) const
+{
+ return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
+}
+
+bool TextureD3D_2D::isSRGB(GLint level) const
+{
+ return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).colorEncoding == GL_SRGB;
+}
+
+angle::Result TextureD3D_2D::setImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels)
+{
+ ASSERT((index.getTarget() == gl::TextureTarget::_2D ||
+ index.getTarget() == gl::TextureTarget::VideoImage) &&
+ size.depth == 1);
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+
+ bool fastUnpacked = false;
+
+ ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
+ size, false));
+
+ // Attempt a fast gpu copy of the pixel data to the surface
+ if (mTexStorage)
+ {
+ ANGLE_TRY(mTexStorage->releaseMultisampledTexStorageForLevel(index.getLevelIndex()));
+ }
+ if (isFastUnpackable(unpackBuffer, unpack, internalFormatInfo.sizedInternalFormat) &&
+ isLevelComplete(index.getLevelIndex()))
+ {
+ // Will try to create RT storage if it does not exist
+ RenderTargetD3D *destRenderTarget = nullptr;
+ ANGLE_TRY(getRenderTarget(context, index, getRenderToTextureSamples(), &destRenderTarget));
+
+ gl::Box destArea(0, 0, 0, getWidth(index.getLevelIndex()), getHeight(index.getLevelIndex()),
+ 1);
+
+ ANGLE_TRY(fastUnpackPixels(context, unpack, unpackBuffer, pixels, destArea,
+ internalFormatInfo.sizedInternalFormat, type, destRenderTarget));
+
+ // Ensure we don't overwrite our newly initialized data
+ mImageArray[index.getLevelIndex()]->markClean();
+
+ fastUnpacked = true;
+ }
+
+ if (!fastUnpacked)
+ {
+ ANGLE_TRY(setImageImpl(context, index, type, unpack, unpackBuffer, pixels, 0));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::setSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_2D && area.depth == 1 && area.z == 0);
+
+ GLenum mipFormat = getInternalFormat(index.getLevelIndex());
+ if (mTexStorage)
+ {
+ ANGLE_TRY(mTexStorage->releaseMultisampledTexStorageForLevel(index.getLevelIndex()));
+ }
+ if (isFastUnpackable(unpackBuffer, unpack, mipFormat) && isLevelComplete(index.getLevelIndex()))
+ {
+ RenderTargetD3D *renderTarget = nullptr;
+ ANGLE_TRY(getRenderTarget(context, index, getRenderToTextureSamples(), &renderTarget));
+ ASSERT(!mImageArray[index.getLevelIndex()]->isDirty());
+
+ return fastUnpackPixels(context, unpack, unpackBuffer, pixels, area, mipFormat, type,
+ renderTarget);
+ }
+ else
+ {
+ return TextureD3D::subImage(context, index, area, format, type, unpack, unpackBuffer,
+ pixels, 0);
+ }
+}
+
+angle::Result TextureD3D_2D::setCompressedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_2D && size.depth == 1);
+
+ // compressed formats don't have separate sized internal formats-- we can just use the
+ // compressed format directly
+ ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormat, size, false));
+
+ return setCompressedImageImpl(context, index, unpack, pixels, 0);
+}
+
+angle::Result TextureD3D_2D::setCompressedSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_2D && area.depth == 1 && area.z == 0);
+ ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0));
+
+ return commitRegion(context, index, area);
+}
+
+angle::Result TextureD3D_2D::copyImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ gl::Framebuffer *source)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_2D);
+
+ const gl::InternalFormat &internalFormatInfo =
+ gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
+ gl::Extents sourceExtents(sourceArea.width, sourceArea.height, 1);
+ ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
+ sourceExtents, false));
+
+ gl::Extents fbSize = source->getReadColorAttachment()->getSize();
+
+ // Does the read area extend beyond the framebuffer?
+ bool outside = sourceArea.x < 0 || sourceArea.y < 0 ||
+ sourceArea.x + sourceArea.width > fbSize.width ||
+ sourceArea.y + sourceArea.height > fbSize.height;
+
+ // WebGL requires that pixels that would be outside the framebuffer are treated as zero values,
+ // so clear the mip level to 0 prior to making the copy if any pixel would be sampled outside.
+ // Same thing for robust resource init.
+ if (outside && (context->isWebGL() || context->isRobustResourceInitEnabled()))
+ {
+ ANGLE_TRY(initializeContents(context, GL_NONE, index));
+ }
+
+ gl::Rectangle clippedArea;
+ if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
+ {
+ // Empty source area, nothing to do.
+ return angle::Result::Continue;
+ }
+
+ gl::Offset destOffset(clippedArea.x - sourceArea.x, clippedArea.y - sourceArea.y, 0);
+
+ // If the zero max LOD workaround is active, then we can't sample from individual layers of the
+ // framebuffer in shaders, so we should use the non-rendering copy path.
+ if (!canCreateRenderTargetForImage(index) ||
+ mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ ANGLE_TRY(mImageArray[index.getLevelIndex()]->copyFromFramebuffer(context, destOffset,
+ clippedArea, source));
+ mDirtyImages = true;
+ }
+ else
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+
+ if (clippedArea.width != 0 && clippedArea.height != 0 &&
+ isValidLevel(index.getLevelIndex()))
+ {
+ ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
+ ANGLE_TRY(mRenderer->copyImage2D(context, source, clippedArea, internalFormat,
+ destOffset, mTexStorage, index.getLevelIndex()));
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::copySubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ gl::Framebuffer *source)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_2D && destOffset.z == 0);
+
+ gl::Extents fbSize = source->getReadColorAttachment()->getSize();
+ gl::Rectangle clippedArea;
+ if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
+ {
+ return angle::Result::Continue;
+ }
+ const gl::Offset clippedOffset(destOffset.x + clippedArea.x - sourceArea.x,
+ destOffset.y + clippedArea.y - sourceArea.y, 0);
+
+ // can only make our texture storage to a render target if level 0 is defined (with a width &
+ // height) and the current level we're copying to is defined (with appropriate format, width &
+ // height)
+
+ // If the zero max LOD workaround is active, then we can't sample from individual layers of the
+ // framebuffer in shaders, so we should use the non-rendering copy path.
+ if (!canCreateRenderTargetForImage(index) ||
+ mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ ANGLE_TRY(mImageArray[index.getLevelIndex()]->copyFromFramebuffer(context, clippedOffset,
+ clippedArea, source));
+ mDirtyImages = true;
+ onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
+ }
+ else
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+
+ if (isValidLevel(index.getLevelIndex()))
+ {
+ ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
+ ANGLE_TRY(mRenderer->copyImage2D(context, source, clippedArea,
+ gl::GetUnsizedFormat(getBaseLevelInternalFormat()),
+ clippedOffset, mTexStorage, index.getLevelIndex()));
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::copyTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ GLenum type,
+ GLint sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_2D);
+
+ gl::TextureType sourceType = source->getType();
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+ gl::Extents size(
+ static_cast<int>(source->getWidth(NonCubeTextureTypeToTarget(sourceType), sourceLevel)),
+ static_cast<int>(source->getHeight(NonCubeTextureTypeToTarget(sourceType), sourceLevel)),
+ 1);
+ ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
+ size, false));
+
+ gl::Box sourceBox(0, 0, 0, size.width, size.height, 1);
+ gl::Offset destOffset(0, 0, 0);
+
+ if (!isSRGB(index.getLevelIndex()) && canCreateRenderTargetForImage(index))
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+ ASSERT(isValidLevel(index.getLevelIndex()));
+ ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
+
+ ANGLE_TRY(mRenderer->copyTexture(context, source, sourceLevel, gl::TextureTarget::_2D,
+ sourceBox, internalFormatInfo.format,
+ internalFormatInfo.type, destOffset, mTexStorage,
+ index.getTarget(), index.getLevelIndex(), unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+ }
+ else
+ {
+ gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(sourceLevel);
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+ ImageD3D *sourceImage = nullptr;
+ ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));
+
+ ImageD3D *destImage = nullptr;
+ ANGLE_TRY(getImageAndSyncFromStorage(context, index, &destImage));
+
+ ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceBox, destOffset,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+
+ mDirtyImages = true;
+
+ gl::Box destRegion(destOffset, size);
+ ANGLE_TRY(commitRegion(context, index, destRegion));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::copySubTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ GLint sourceLevel,
+ const gl::Box &sourceBox,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_2D);
+
+ if (!isSRGB(index.getLevelIndex()) && canCreateRenderTargetForImage(index))
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+ ASSERT(isValidLevel(index.getLevelIndex()));
+ ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
+
+ const gl::InternalFormat &internalFormatInfo =
+ gl::GetSizedInternalFormatInfo(getInternalFormat(index.getLevelIndex()));
+ ANGLE_TRY(mRenderer->copyTexture(context, source, sourceLevel, gl::TextureTarget::_2D,
+ sourceBox, internalFormatInfo.format,
+ internalFormatInfo.type, destOffset, mTexStorage,
+ index.getTarget(), index.getLevelIndex(), unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+ }
+ else
+ {
+ gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(sourceLevel);
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+ ImageD3D *sourceImage = nullptr;
+ ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));
+
+ ImageD3D *destImage = nullptr;
+ ANGLE_TRY(getImageAndSyncFromStorage(context, index, &destImage));
+
+ ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceBox, destOffset,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+
+ mDirtyImages = true;
+
+ gl::Box destRegion(destOffset.x, destOffset.y, 0, sourceBox.width, sourceBox.height, 1);
+ ANGLE_TRY(commitRegion(context, index, destRegion));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source)
+{
+ gl::TextureTarget sourceTarget = NonCubeTextureTypeToTarget(source->getType());
+ GLint sourceLevel = 0;
+
+ GLint destLevel = 0;
+
+ GLenum sizedInternalFormat =
+ source->getFormat(sourceTarget, sourceLevel).info->sizedInternalFormat;
+ gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
+ static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
+ ANGLE_TRY(redefineImage(context, destLevel, sizedInternalFormat, size, false));
+
+ ANGLE_TRY(initializeStorage(context, BindFlags()));
+ ASSERT(mTexStorage);
+
+ ANGLE_TRY(
+ mRenderer->copyCompressedTexture(context, source, sourceLevel, mTexStorage, destLevel));
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::setStorage(const gl::Context *context,
+ gl::TextureType type,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size)
+{
+ ASSERT(type == gl::TextureType::_2D && size.depth == 1);
+
+ for (size_t level = 0; level < levels; level++)
+ {
+ gl::Extents levelSize(std::max(1, size.width >> level), std::max(1, size.height >> level),
+ 1);
+ ANGLE_TRY(redefineImage(context, level, internalFormat, levelSize, true));
+ }
+
+ for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ ANGLE_TRY(redefineImage(context, level, GL_NONE, gl::Extents(0, 0, 1), true));
+ }
+
+ // TODO(geofflang): Verify storage creation had no errors
+ BindFlags flags;
+ flags.renderTarget = IsRenderTargetUsage(mState.getUsage());
+ TexStoragePointer storage = {
+ mRenderer->createTextureStorage2D(internalFormat, flags, size.width, size.height,
+ static_cast<int>(levels), mState.getLabel(), false),
+ context};
+
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
+
+ ANGLE_TRY(updateStorage(context));
+
+ mImmutable = true;
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::bindTexImage(const gl::Context *context, egl::Surface *surface)
+{
+ GLenum internalformat = surface->getConfig()->renderTargetFormat;
+
+ gl::Extents size(surface->getWidth(), surface->getHeight(), 1);
+ ANGLE_TRY(redefineImage(context, 0, internalformat, size, true));
+
+ ANGLE_TRY(releaseTexStorage(context, gl::TexLevelMask()));
+
+ SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+ ASSERT(surfaceD3D);
+
+ mTexStorage = mRenderer->createTextureStorage2D(surfaceD3D->getSwapChain(), mState.getLabel());
+ mEGLImageTarget = false;
+
+ mDirtyImages = false;
+ mImageArray[0]->markClean();
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::releaseTexImage(const gl::Context *context)
+{
+ if (mTexStorage)
+ {
+ ANGLE_TRY(releaseTexStorage(context, gl::TexLevelMask()));
+ }
+
+ for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ ANGLE_TRY(redefineImage(context, i, GL_NONE, gl::Extents(0, 0, 1), true));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image)
+{
+ EGLImageD3D *eglImaged3d = GetImplAs<EGLImageD3D>(image);
+
+ // Set the properties of the base mip level from the EGL image
+ const auto &format = image->getFormat();
+ gl::Extents size(static_cast<int>(image->getWidth()), static_cast<int>(image->getHeight()), 1);
+ ANGLE_TRY(redefineImage(context, 0, format.info->sizedInternalFormat, size, true));
+
+ // Clear all other images.
+ for (size_t level = 1; level < mImageArray.size(); level++)
+ {
+ ANGLE_TRY(redefineImage(context, level, GL_NONE, gl::Extents(0, 0, 1), true));
+ }
+
+ ANGLE_TRY(releaseTexStorage(context, gl::TexLevelMask()));
+ mImageArray[0]->markClean();
+
+ // Pass in the RenderTargetD3D here: createTextureStorage can't generate an error.
+ RenderTargetD3D *renderTargetD3D = nullptr;
+ ANGLE_TRY(eglImaged3d->getRenderTarget(context, &renderTargetD3D));
+
+ mTexStorage =
+ mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D, mState.getLabel());
+ mEGLImageTarget = true;
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::initMipmapImages(const gl::Context *context)
+{
+ const GLuint baseLevel = mState.getEffectiveBaseLevel();
+ const GLuint maxLevel = mState.getMipmapMaxLevel();
+ // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
+ // levels.
+ for (GLuint level = baseLevel + 1; level <= maxLevel; level++)
+ {
+ gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1),
+ std::max(getLevelZeroHeight() >> level, 1), 1);
+
+ ANGLE_TRY(redefineImage(context, level, getBaseLevelInternalFormat(), levelSize, false));
+ }
+
+ // We should be mip-complete now so generate the storage.
+ ANGLE_TRY(initializeStorage(context, BindFlags::RenderTarget()));
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(!index.hasLayer());
+
+ // ensure the underlying texture is created
+ ANGLE_TRY(ensureRenderTarget(context));
+ ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
+
+ return mTexStorage->getRenderTarget(context, index, samples, outRT);
+}
+
+bool TextureD3D_2D::isValidLevel(int level) const
+{
+ return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : false);
+}
+
+bool TextureD3D_2D::isLevelComplete(int level) const
+{
+ if (isImmutable())
+ {
+ return true;
+ }
+
+ GLsizei width = getLevelZeroWidth();
+ GLsizei height = getLevelZeroHeight();
+
+ if (width <= 0 || height <= 0)
+ {
+ return false;
+ }
+
+ // The base image level is complete if the width and height are positive
+ if (level == static_cast<int>(getBaseLevel()))
+ {
+ return true;
+ }
+
+ ASSERT(level >= 0 && level <= static_cast<int>(mImageArray.size()) &&
+ mImageArray[level] != nullptr);
+ ImageD3D *image = mImageArray[level].get();
+
+ if (image->getInternalFormat() != getBaseLevelInternalFormat())
+ {
+ return false;
+ }
+
+ if (image->getWidth() != std::max(1, width >> level))
+ {
+ return false;
+ }
+
+ if (image->getHeight() != std::max(1, height >> level))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool TextureD3D_2D::isImageComplete(const gl::ImageIndex &index) const
+{
+ return isLevelComplete(index.getLevelIndex());
+}
+
+// Constructs a native texture resource from the texture images
+angle::Result TextureD3D_2D::initializeStorage(const gl::Context *context, BindFlags bindFlags)
+{
+ // Only initialize the first time this texture is used as a render target or shader resource
+ if (mTexStorage)
+ {
+ return angle::Result::Continue;
+ }
+
+ // do not attempt to create storage for nonexistant data
+ if (!isLevelComplete(getBaseLevel()))
+ {
+ return angle::Result::Continue;
+ }
+
+ bindFlags.renderTarget |= IsRenderTargetUsage(mState.getUsage());
+
+ TexStoragePointer storage;
+ ANGLE_TRY(createCompleteStorage(context, bindFlags, &storage));
+
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
+
+ ASSERT(mTexStorage);
+
+ // flush image data to the storage
+ ANGLE_TRY(updateStorage(context));
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outStorage) const
+{
+ GLsizei width = getLevelZeroWidth();
+ GLsizei height = getLevelZeroHeight();
+ GLenum internalFormat = getBaseLevelInternalFormat();
+
+ ASSERT(width > 0 && height > 0);
+
+ // use existing storage level count, when previously specified by TexStorage*D
+ GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
+
+ bool hintLevelZeroOnly = false;
+ if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ // If any of the CPU images (levels >= 1) are dirty, then the textureStorage2D should use
+ // the mipped texture to begin with. Otherwise, it should use the level-zero-only texture.
+ hintLevelZeroOnly = true;
+ for (int level = 1; level < levels && hintLevelZeroOnly; level++)
+ {
+ hintLevelZeroOnly = !(mImageArray[level]->isDirty() && isLevelComplete(level));
+ }
+ }
+
+ // TODO(geofflang): Determine if the texture creation succeeded
+ *outStorage = {mRenderer->createTextureStorage2D(internalFormat, bindFlags, width, height,
+ levels, mState.getLabel(), hintLevelZeroOnly),
+ context};
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage)
+{
+ if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
+ {
+ for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
+ {
+ ANGLE_TRY(
+ mImageArray[level]->setManagedSurface2D(context, newCompleteTexStorage, level));
+ }
+ }
+
+ gl::TexLevelMask copyImageMask;
+ copyImageMask.set();
+
+ ANGLE_TRY(releaseTexStorage(context, copyImageMask));
+ mTexStorage = newCompleteTexStorage;
+ mTexStorageObserverBinding.bind(mTexStorage);
+
+ mDirtyImages = true;
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::updateStorage(const gl::Context *context)
+{
+ if (!mDirtyImages)
+ {
+ return angle::Result::Continue;
+ }
+
+ ASSERT(mTexStorage != nullptr);
+ GLint storageLevels = mTexStorage->getLevelCount();
+ for (int level = 0; level < storageLevels; level++)
+ {
+ if (mImageArray[level]->isDirty() && isLevelComplete(level))
+ {
+ ANGLE_TRY(updateStorageLevel(context, level));
+ }
+ }
+
+ mDirtyImages = false;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::updateStorageLevel(const gl::Context *context, int level)
+{
+ ASSERT(level <= static_cast<int>(mImageArray.size()) && mImageArray[level] != nullptr);
+ ASSERT(isLevelComplete(level));
+
+ if (mImageArray[level]->isDirty())
+ {
+ gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+ gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1);
+ ANGLE_TRY(commitRegion(context, index, region));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2D::redefineImage(const gl::Context *context,
+ size_t level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease)
+{
+ ASSERT(size.depth == 1);
+
+ // If there currently is a corresponding storage texture image, it has these parameters
+ const int storageWidth = std::max(1, getLevelZeroWidth() >> level);
+ const int storageHeight = std::max(1, getLevelZeroHeight() >> level);
+ const GLenum storageFormat = getBaseLevelInternalFormat();
+
+ if (mTexStorage)
+ {
+ const size_t storageLevels = mTexStorage->getLevelCount();
+
+ // If the storage was from an EGL image, copy it back into local images to preserve it
+ // while orphaning
+ if (level != 0 && mEGLImageTarget)
+ {
+ ANGLE_TRY(mImageArray[0]->copyFromTexStorage(context, gl::ImageIndex::Make2D(0),
+ mTexStorage));
+ }
+
+ if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth ||
+ size.height != storageHeight || internalformat != storageFormat ||
+ mEGLImageTarget) // Discard mismatched storage
+ {
+ gl::TexLevelMask copyImageMask;
+ copyImageMask.set();
+ copyImageMask.set(level, false);
+
+ ANGLE_TRY(releaseTexStorage(context, copyImageMask));
+ markAllImagesDirty();
+ }
+ }
+
+ mImageArray[level]->redefine(gl::TextureType::_2D, internalformat, size, forceRelease);
+ mDirtyImages = mDirtyImages || mImageArray[level]->isDirty();
+
+ // Can't be an EGL image target after being redefined
+ mEGLImageTarget = false;
+
+ return angle::Result::Continue;
+}
+
+gl::ImageIndexIterator TextureD3D_2D::imageIterator() const
+{
+ return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount());
+}
+
+gl::ImageIndex TextureD3D_2D::getImageIndex(GLint mip, GLint /*layer*/) const
+{
+ // "layer" does not apply to 2D Textures.
+ return gl::ImageIndex::Make2D(mip);
+}
+
+bool TextureD3D_2D::isValidIndex(const gl::ImageIndex &index) const
+{
+ return (mTexStorage && index.getType() == gl::TextureType::_2D && index.getLevelIndex() >= 0 &&
+ index.getLevelIndex() < mTexStorage->getLevelCount());
+}
+
+void TextureD3D_2D::markAllImagesDirty()
+{
+ for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mImageArray[i]->markDirty();
+ }
+ mDirtyImages = true;
+}
+
+TextureD3D_Cube::TextureD3D_Cube(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureD3D(state, renderer)
+{
+ for (auto &face : mImageArray)
+ {
+ for (auto &image : face)
+ {
+ image.reset(renderer->createImage());
+ }
+ }
+}
+
+void TextureD3D_Cube::onDestroy(const gl::Context *context)
+{
+ // Delete the Images before the TextureStorage. Images might be relying on the TextureStorage
+ // for some of their data. If TextureStorage is deleted before the Images, then their data will
+ // be wastefully copied back from the GPU before we delete the Images.
+ for (auto &face : mImageArray)
+ {
+ for (auto &image : face)
+ {
+ image.reset();
+ }
+ }
+ return TextureD3D::onDestroy(context);
+}
+
+TextureD3D_Cube::~TextureD3D_Cube() {}
+
+ImageD3D *TextureD3D_Cube::getImage(int level, int layer) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(layer >= 0 && static_cast<size_t>(layer) < gl::kCubeFaceCount);
+ return mImageArray[layer][level].get();
+}
+
+ImageD3D *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const
+{
+ ASSERT(index.getLevelIndex() < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(gl::IsCubeMapFaceTarget(index.getTarget()));
+ return mImageArray[index.cubeMapFaceIndex()][index.getLevelIndex()].get();
+}
+
+GLsizei TextureD3D_Cube::getLayerCount(int level) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ return gl::kCubeFaceCount;
+}
+
+GLenum TextureD3D_Cube::getInternalFormat(GLint level, GLint layer) const
+{
+ if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ return mImageArray[layer][level]->getInternalFormat();
+ else
+ return GL_NONE;
+}
+
+bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const
+{
+ return gl::GetSizedInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0;
+}
+
+bool TextureD3D_Cube::isSRGB(GLint level, GLint layer) const
+{
+ return gl::GetSizedInternalFormatInfo(getInternalFormat(level, layer)).colorEncoding == GL_SRGB;
+}
+
+angle::Result TextureD3D_Cube::setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Cube::setImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels)
+{
+ ASSERT(size.depth == 1);
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+ ANGLE_TRY(redefineImage(context, index.cubeMapFaceIndex(), index.getLevelIndex(),
+ internalFormatInfo.sizedInternalFormat, size, false));
+
+ return setImageImpl(context, index, type, unpack, unpackBuffer, pixels, 0);
+}
+
+angle::Result TextureD3D_Cube::setSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels)
+{
+ ASSERT(area.depth == 1 && area.z == 0);
+ return TextureD3D::subImage(context, index, area, format, type, unpack, unpackBuffer, pixels,
+ 0);
+}
+
+angle::Result TextureD3D_Cube::setCompressedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ASSERT(size.depth == 1);
+
+ // compressed formats don't have separate sized internal formats-- we can just use the
+ // compressed format directly
+ ANGLE_TRY(redefineImage(context, index.cubeMapFaceIndex(), index.getLevelIndex(),
+ internalFormat, size, false));
+
+ return setCompressedImageImpl(context, index, unpack, pixels, 0);
+}
+
+angle::Result TextureD3D_Cube::setCompressedSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ASSERT(area.depth == 1 && area.z == 0);
+
+ ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0));
+ return commitRegion(context, index, area);
+}
+
+angle::Result TextureD3D_Cube::copyImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ gl::Framebuffer *source)
+{
+ GLint faceIndex = index.cubeMapFaceIndex();
+ const gl::InternalFormat &internalFormatInfo =
+ gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
+
+ gl::Extents size(sourceArea.width, sourceArea.height, 1);
+ ANGLE_TRY(redefineImage(context, faceIndex, index.getLevelIndex(),
+ internalFormatInfo.sizedInternalFormat, size, false));
+
+ gl::Extents fbSize = source->getReadColorAttachment()->getSize();
+
+ // Does the read area extend beyond the framebuffer?
+ bool outside = sourceArea.x < 0 || sourceArea.y < 0 ||
+ sourceArea.x + sourceArea.width > fbSize.width ||
+ sourceArea.y + sourceArea.height > fbSize.height;
+
+ // WebGL requires that pixels that would be outside the framebuffer are treated as zero values,
+ // so clear the mip level to 0 prior to making the copy if any pixel would be sampled outside.
+ // Same thing for robust resource init.
+ if (outside && (context->isWebGL() || context->isRobustResourceInitEnabled()))
+ {
+ ANGLE_TRY(initializeContents(context, GL_NONE, index));
+ }
+
+ gl::Rectangle clippedArea;
+ if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
+ {
+ // Empty source area, nothing to do.
+ return angle::Result::Continue;
+ }
+
+ gl::Offset destOffset(clippedArea.x - sourceArea.x, clippedArea.y - sourceArea.y, 0);
+
+ // If the zero max LOD workaround is active, then we can't sample from individual layers of the
+ // framebuffer in shaders, so we should use the non-rendering copy path.
+ if (!canCreateRenderTargetForImage(index) ||
+ mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ ANGLE_TRY(mImageArray[faceIndex][index.getLevelIndex()]->copyFromFramebuffer(
+ context, destOffset, clippedArea, source));
+ mDirtyImages = true;
+ onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
+ }
+ else
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+
+ ASSERT(size.width == size.height);
+
+ if (size.width > 0 && isValidFaceLevel(faceIndex, index.getLevelIndex()))
+ {
+ ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.getLevelIndex()));
+ ANGLE_TRY(mRenderer->copyImageCube(context, source, clippedArea, internalFormat,
+ destOffset, mTexStorage, index.getTarget(),
+ index.getLevelIndex()));
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Cube::copySubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ gl::Framebuffer *source)
+{
+ gl::Extents fbSize = source->getReadColorAttachment()->getSize();
+ gl::Rectangle clippedArea;
+ if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height), &clippedArea))
+ {
+ return angle::Result::Continue;
+ }
+ const gl::Offset clippedOffset(destOffset.x + clippedArea.x - sourceArea.x,
+ destOffset.y + clippedArea.y - sourceArea.y, 0);
+
+ GLint faceIndex = index.cubeMapFaceIndex();
+
+ // If the zero max LOD workaround is active, then we can't sample from individual layers of the
+ // framebuffer in shaders, so we should use the non-rendering copy path.
+ if (!canCreateRenderTargetForImage(index) ||
+ mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ ANGLE_TRY(mImageArray[faceIndex][index.getLevelIndex()]->copyFromFramebuffer(
+ context, clippedOffset, clippedArea, source));
+ mDirtyImages = true;
+ onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
+ }
+ else
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+ if (isValidFaceLevel(faceIndex, index.getLevelIndex()))
+ {
+ ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.getLevelIndex()));
+ ANGLE_TRY(mRenderer->copyImageCube(
+ context, source, clippedArea, gl::GetUnsizedFormat(getBaseLevelInternalFormat()),
+ clippedOffset, mTexStorage, index.getTarget(), index.getLevelIndex()));
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Cube::copyTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ GLenum type,
+ GLint sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ ASSERT(gl::IsCubeMapFaceTarget(index.getTarget()));
+
+ gl::TextureTarget sourceTarget = NonCubeTextureTypeToTarget(source->getType());
+
+ GLint faceIndex = index.cubeMapFaceIndex();
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+ gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
+ static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
+ ANGLE_TRY(redefineImage(context, faceIndex, index.getLevelIndex(),
+ internalFormatInfo.sizedInternalFormat, size, false));
+
+ gl::Box sourceBox(0, 0, 0, size.width, size.height, 1);
+ gl::Offset destOffset(0, 0, 0);
+
+ if (!isSRGB(index.getLevelIndex(), faceIndex) && canCreateRenderTargetForImage(index))
+ {
+
+ ANGLE_TRY(ensureRenderTarget(context));
+ ASSERT(isValidFaceLevel(faceIndex, index.getLevelIndex()));
+ ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.getLevelIndex()));
+
+ ANGLE_TRY(mRenderer->copyTexture(context, source, sourceLevel, gl::TextureTarget::_2D,
+ sourceBox, internalFormatInfo.format,
+ internalFormatInfo.type, destOffset, mTexStorage,
+ index.getTarget(), index.getLevelIndex(), unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+ }
+ else
+ {
+ gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(sourceLevel);
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+ ImageD3D *sourceImage = nullptr;
+ ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));
+
+ ImageD3D *destImage = nullptr;
+ ANGLE_TRY(getImageAndSyncFromStorage(context, index, &destImage));
+
+ ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceBox, destOffset,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+
+ mDirtyImages = true;
+
+ gl::Box destRegion(destOffset, size);
+ ANGLE_TRY(commitRegion(context, index, destRegion));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Cube::copySubTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ GLint sourceLevel,
+ const gl::Box &sourceBox,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ ASSERT(gl::IsCubeMapFaceTarget(index.getTarget()));
+
+ GLint faceIndex = index.cubeMapFaceIndex();
+
+ if (!isSRGB(index.getLevelIndex(), faceIndex) && canCreateRenderTargetForImage(index))
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+ ASSERT(isValidFaceLevel(faceIndex, index.getLevelIndex()));
+ ANGLE_TRY(updateStorageFaceLevel(context, faceIndex, index.getLevelIndex()));
+
+ const gl::InternalFormat &internalFormatInfo =
+ gl::GetSizedInternalFormatInfo(getInternalFormat(index.getLevelIndex(), faceIndex));
+ ANGLE_TRY(mRenderer->copyTexture(context, source, sourceLevel, gl::TextureTarget::_2D,
+ sourceBox, internalFormatInfo.format,
+ internalFormatInfo.type, destOffset, mTexStorage,
+ index.getTarget(), index.getLevelIndex(), unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+ }
+ else
+ {
+ gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make2D(sourceLevel);
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+ ImageD3D *sourceImage = nullptr;
+ ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));
+
+ ImageD3D *destImage = nullptr;
+ ANGLE_TRY(getImageAndSyncFromStorage(context, index, &destImage));
+
+ ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceBox, destOffset,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+
+ mDirtyImages = true;
+
+ gl::Box destRegion(destOffset.x, destOffset.y, 0, sourceBox.width, sourceBox.height, 1);
+ ANGLE_TRY(commitRegion(context, index, destRegion));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Cube::setStorage(const gl::Context *context,
+ gl::TextureType type,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size)
+{
+ ASSERT(size.width == size.height);
+ ASSERT(size.depth == 1);
+
+ for (size_t level = 0; level < levels; level++)
+ {
+ GLsizei mipSize = std::max(1, size.width >> level);
+ for (size_t faceIndex = 0; faceIndex < gl::kCubeFaceCount; faceIndex++)
+ {
+ mImageArray[faceIndex][level]->redefine(gl::TextureType::CubeMap, internalFormat,
+ gl::Extents(mipSize, mipSize, 1), true);
+ }
+ }
+
+ for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ for (size_t faceIndex = 0; faceIndex < gl::kCubeFaceCount; faceIndex++)
+ {
+ mImageArray[faceIndex][level]->redefine(gl::TextureType::CubeMap, GL_NONE,
+ gl::Extents(0, 0, 0), true);
+ }
+ }
+
+ // TODO(geofflang): Verify storage creation had no errors
+ BindFlags bindFlags;
+ bindFlags.renderTarget = IsRenderTargetUsage(mState.getUsage());
+
+ TexStoragePointer storage = {
+ mRenderer->createTextureStorageCube(internalFormat, bindFlags, size.width,
+ static_cast<int>(levels), false, mState.getLabel()),
+ context};
+
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
+
+ ANGLE_TRY(updateStorage(context));
+
+ mImmutable = true;
+
+ return angle::Result::Continue;
+}
+
+// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool TextureD3D_Cube::isCubeComplete() const
+{
+ int baseWidth = getBaseLevelWidth();
+ int baseHeight = getBaseLevelHeight();
+ GLenum baseFormat = getBaseLevelInternalFormat();
+
+ if (baseWidth <= 0 || baseWidth != baseHeight)
+ {
+ return false;
+ }
+
+ for (size_t faceIndex = 1; faceIndex < gl::kCubeFaceCount; faceIndex++)
+ {
+ const ImageD3D &faceBaseImage = *mImageArray[faceIndex][getBaseLevel()];
+
+ if (faceBaseImage.getWidth() != baseWidth || faceBaseImage.getHeight() != baseHeight ||
+ faceBaseImage.getInternalFormat() != baseFormat)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+angle::Result TextureD3D_Cube::bindTexImage(const gl::Context *context, egl::Surface *surface)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Cube::releaseTexImage(const gl::Context *context)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Cube::initMipmapImages(const gl::Context *context)
+{
+ const GLuint baseLevel = mState.getEffectiveBaseLevel();
+ const GLuint maxLevel = mState.getMipmapMaxLevel();
+ // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
+ // levels.
+ for (int faceIndex = 0; faceIndex < static_cast<int>(gl::kCubeFaceCount); faceIndex++)
+ {
+ for (GLuint level = baseLevel + 1; level <= maxLevel; level++)
+ {
+ int faceLevelSize =
+ (std::max(mImageArray[faceIndex][baseLevel]->getWidth() >> (level - baseLevel), 1));
+ ANGLE_TRY(redefineImage(context, faceIndex, level,
+ mImageArray[faceIndex][baseLevel]->getInternalFormat(),
+ gl::Extents(faceLevelSize, faceLevelSize, 1), false));
+ }
+ }
+
+ // We should be mip-complete now so generate the storage.
+ ANGLE_TRY(initializeStorage(context, BindFlags::RenderTarget()));
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Cube::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(gl::IsCubeMapFaceTarget(index.getTarget()));
+
+ // ensure the underlying texture is created
+ ANGLE_TRY(ensureRenderTarget(context));
+ ANGLE_TRY(updateStorageFaceLevel(context, index.cubeMapFaceIndex(), index.getLevelIndex()));
+
+ return mTexStorage->getRenderTarget(context, index, samples, outRT);
+}
+
+angle::Result TextureD3D_Cube::initializeStorage(const gl::Context *context, BindFlags bindFlags)
+{
+ // Only initialize the first time this texture is used as a render target or shader resource
+ if (mTexStorage)
+ {
+ return angle::Result::Continue;
+ }
+
+ // do not attempt to create storage for nonexistant data
+ if (!isFaceLevelComplete(0, getBaseLevel()))
+ {
+ return angle::Result::Continue;
+ }
+
+ bindFlags.renderTarget |= IsRenderTargetUsage(mState.getUsage());
+
+ TexStoragePointer storage;
+ ANGLE_TRY(createCompleteStorage(context, bindFlags, &storage));
+
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
+
+ ASSERT(mTexStorage);
+
+ // flush image data to the storage
+ ANGLE_TRY(updateStorage(context));
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Cube::createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outStorage) const
+{
+ GLsizei size = getLevelZeroWidth();
+
+ ASSERT(size > 0);
+
+ // use existing storage level count, when previously specified by TexStorage*D
+ GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1));
+
+ bool hintLevelZeroOnly = false;
+ if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ // If any of the CPU images (levels >= 1) are dirty, then the textureStorageEXT should use
+ // the mipped texture to begin with. Otherwise, it should use the level-zero-only texture.
+ hintLevelZeroOnly = true;
+ for (int faceIndex = 0;
+ faceIndex < static_cast<int>(gl::kCubeFaceCount) && hintLevelZeroOnly; faceIndex++)
+ {
+ for (int level = 1; level < levels && hintLevelZeroOnly; level++)
+ {
+ hintLevelZeroOnly = !(mImageArray[faceIndex][level]->isDirty() &&
+ isFaceLevelComplete(faceIndex, level));
+ }
+ }
+ }
+
+ // TODO (geofflang): detect if storage creation succeeded
+ *outStorage = {
+ mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), bindFlags, size, levels,
+ hintLevelZeroOnly, mState.getLabel()),
+ context};
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Cube::setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage)
+{
+ if (newCompleteTexStorage && newCompleteTexStorage->isManaged())
+ {
+ for (int faceIndex = 0; faceIndex < static_cast<int>(gl::kCubeFaceCount); faceIndex++)
+ {
+ for (int level = 0; level < newCompleteTexStorage->getLevelCount(); level++)
+ {
+ ANGLE_TRY(mImageArray[faceIndex][level]->setManagedSurfaceCube(
+ context, newCompleteTexStorage, faceIndex, level));
+ }
+ }
+ }
+
+ gl::TexLevelMask copyImageMask;
+ copyImageMask.set();
+
+ ANGLE_TRY(releaseTexStorage(context, copyImageMask));
+ mTexStorage = newCompleteTexStorage;
+ mTexStorageObserverBinding.bind(mTexStorage);
+
+ mDirtyImages = true;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Cube::updateStorage(const gl::Context *context)
+{
+ if (!mDirtyImages)
+ {
+ return angle::Result::Continue;
+ }
+
+ ASSERT(mTexStorage != nullptr);
+ GLint storageLevels = mTexStorage->getLevelCount();
+ for (int face = 0; face < static_cast<int>(gl::kCubeFaceCount); face++)
+ {
+ for (int level = 0; level < storageLevels; level++)
+ {
+ if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level))
+ {
+ ANGLE_TRY(updateStorageFaceLevel(context, face, level));
+ }
+ }
+ }
+
+ mDirtyImages = false;
+ return angle::Result::Continue;
+}
+
+bool TextureD3D_Cube::isValidFaceLevel(int faceIndex, int level) const
+{
+ return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
+}
+
+bool TextureD3D_Cube::isFaceLevelComplete(int faceIndex, int level) const
+{
+ if (getBaseLevel() >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ return false;
+ }
+ ASSERT(level >= 0 && static_cast<size_t>(faceIndex) < gl::kCubeFaceCount &&
+ level < static_cast<int>(mImageArray[faceIndex].size()) &&
+ mImageArray[faceIndex][level] != nullptr);
+
+ if (isImmutable())
+ {
+ return true;
+ }
+
+ int levelZeroSize = getLevelZeroWidth();
+
+ if (levelZeroSize <= 0)
+ {
+ return false;
+ }
+
+ // Check that non-zero levels are consistent with the base level.
+ const ImageD3D *faceLevelImage = mImageArray[faceIndex][level].get();
+
+ if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat())
+ {
+ return false;
+ }
+
+ if (faceLevelImage->getWidth() != std::max(1, levelZeroSize >> level))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool TextureD3D_Cube::isImageComplete(const gl::ImageIndex &index) const
+{
+ return isFaceLevelComplete(index.cubeMapFaceIndex(), index.getLevelIndex());
+}
+
+angle::Result TextureD3D_Cube::updateStorageFaceLevel(const gl::Context *context,
+ int faceIndex,
+ int level)
+{
+ ASSERT(level >= 0 && static_cast<size_t>(faceIndex) < gl::kCubeFaceCount &&
+ level < static_cast<int>(mImageArray[faceIndex].size()) &&
+ mImageArray[faceIndex][level] != nullptr);
+ ImageD3D *image = mImageArray[faceIndex][level].get();
+
+ if (image->isDirty())
+ {
+ gl::TextureTarget faceTarget = gl::CubeFaceIndexToTextureTarget(faceIndex);
+ gl::ImageIndex index = gl::ImageIndex::MakeCubeMapFace(faceTarget, level);
+ gl::Box region(0, 0, 0, image->getWidth(), image->getHeight(), 1);
+ ANGLE_TRY(commitRegion(context, index, region));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Cube::redefineImage(const gl::Context *context,
+ int faceIndex,
+ GLint level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease)
+{
+ // If there currently is a corresponding storage texture image, it has these parameters
+ const int storageWidth = std::max(1, getLevelZeroWidth() >> level);
+ const int storageHeight = std::max(1, getLevelZeroHeight() >> level);
+ const GLenum storageFormat = getBaseLevelInternalFormat();
+
+ if (mTexStorage)
+ {
+ const int storageLevels = mTexStorage->getLevelCount();
+
+ if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth ||
+ size.height != storageHeight ||
+ internalformat != storageFormat) // Discard mismatched storage
+ {
+ markAllImagesDirty();
+
+ gl::TexLevelMask copyImageMask;
+ copyImageMask.set();
+ copyImageMask.set(level, false);
+
+ ANGLE_TRY(releaseTexStorage(context, copyImageMask));
+ }
+ }
+
+ mImageArray[faceIndex][level]->redefine(gl::TextureType::CubeMap, internalformat, size,
+ forceRelease);
+ mDirtyImages = mDirtyImages || mImageArray[faceIndex][level]->isDirty();
+
+ return angle::Result::Continue;
+}
+
+gl::ImageIndexIterator TextureD3D_Cube::imageIterator() const
+{
+ return gl::ImageIndexIterator::MakeCube(0, mTexStorage->getLevelCount());
+}
+
+gl::ImageIndex TextureD3D_Cube::getImageIndex(GLint mip, GLint layer) const
+{
+ // The "layer" of the image index corresponds to the cube face
+ return gl::ImageIndex::MakeCubeMapFace(gl::CubeFaceIndexToTextureTarget(layer), mip);
+}
+
+bool TextureD3D_Cube::isValidIndex(const gl::ImageIndex &index) const
+{
+ return (mTexStorage && index.getType() == gl::TextureType::CubeMap &&
+ gl::IsCubeMapFaceTarget(index.getTarget()) && index.getLevelIndex() >= 0 &&
+ index.getLevelIndex() < mTexStorage->getLevelCount());
+}
+
+void TextureD3D_Cube::markAllImagesDirty()
+{
+ for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++)
+ {
+ for (size_t dirtyFace = 0; dirtyFace < gl::kCubeFaceCount; dirtyFace++)
+ {
+ mImageArray[dirtyFace][dirtyLevel]->markDirty();
+ }
+ }
+ mDirtyImages = true;
+}
+
+TextureD3D_3D::TextureD3D_3D(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureD3D(state, renderer)
+{
+ for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
+ {
+ mImageArray[i].reset(renderer->createImage());
+ }
+}
+
+void TextureD3D_3D::onDestroy(const gl::Context *context)
+{
+ // Delete the Images before the TextureStorage. Images might be relying on the TextureStorage
+ // for some of their data. If TextureStorage is deleted before the Images, then their data will
+ // be wastefully copied back from the GPU before we delete the Images.
+ for (auto &image : mImageArray)
+ {
+ image.reset();
+ }
+ return TextureD3D::onDestroy(context);
+}
+
+TextureD3D_3D::~TextureD3D_3D() {}
+
+ImageD3D *TextureD3D_3D::getImage(int level, int layer) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(layer == 0);
+ return mImageArray[level].get();
+}
+
+ImageD3D *TextureD3D_3D::getImage(const gl::ImageIndex &index) const
+{
+ ASSERT(index.getLevelIndex() < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(!index.hasLayer());
+ ASSERT(index.getType() == gl::TextureType::_3D);
+ return mImageArray[index.getLevelIndex()].get();
+}
+
+GLsizei TextureD3D_3D::getLayerCount(int level) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ return 1;
+}
+
+GLsizei TextureD3D_3D::getWidth(GLint level) const
+{
+ if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ return mImageArray[level]->getWidth();
+ else
+ return 0;
+}
+
+GLsizei TextureD3D_3D::getHeight(GLint level) const
+{
+ if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ return mImageArray[level]->getHeight();
+ else
+ return 0;
+}
+
+GLsizei TextureD3D_3D::getDepth(GLint level) const
+{
+ if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ return mImageArray[level]->getDepth();
+ else
+ return 0;
+}
+
+GLenum TextureD3D_3D::getInternalFormat(GLint level) const
+{
+ if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ return mImageArray[level]->getInternalFormat();
+ else
+ return GL_NONE;
+}
+
+bool TextureD3D_3D::isDepth(GLint level) const
+{
+ return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
+}
+
+bool TextureD3D_3D::isSRGB(GLint level) const
+{
+ return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).colorEncoding == GL_SRGB;
+}
+
+angle::Result TextureD3D_3D::setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_3D::setImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_3D);
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+
+ ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
+ size, false));
+
+ bool fastUnpacked = false;
+
+ // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
+ if (isFastUnpackable(unpackBuffer, unpack, internalFormatInfo.sizedInternalFormat) &&
+ !size.empty() && isLevelComplete(index.getLevelIndex()))
+ {
+ // Will try to create RT storage if it does not exist
+ RenderTargetD3D *destRenderTarget = nullptr;
+ ANGLE_TRY(getRenderTarget(context, index, getRenderToTextureSamples(), &destRenderTarget));
+
+ gl::Box destArea(0, 0, 0, getWidth(index.getLevelIndex()), getHeight(index.getLevelIndex()),
+ getDepth(index.getLevelIndex()));
+
+ ANGLE_TRY(fastUnpackPixels(context, unpack, unpackBuffer, pixels, destArea,
+ internalFormatInfo.sizedInternalFormat, type, destRenderTarget));
+
+ // Ensure we don't overwrite our newly initialized data
+ mImageArray[index.getLevelIndex()]->markClean();
+
+ fastUnpacked = true;
+ }
+
+ if (!fastUnpacked)
+ {
+ ANGLE_TRY(setImageImpl(context, index, type, unpack, unpackBuffer, pixels, 0));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_3D::setSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_3D);
+
+ // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
+ GLenum mipFormat = getInternalFormat(index.getLevelIndex());
+ if (isFastUnpackable(unpackBuffer, unpack, mipFormat) && isLevelComplete(index.getLevelIndex()))
+ {
+ RenderTargetD3D *destRenderTarget = nullptr;
+ ANGLE_TRY(getRenderTarget(context, index, getRenderToTextureSamples(), &destRenderTarget));
+ ASSERT(!mImageArray[index.getLevelIndex()]->isDirty());
+
+ return fastUnpackPixels(context, unpack, unpackBuffer, pixels, area, mipFormat, type,
+ destRenderTarget);
+ }
+ else
+ {
+ return TextureD3D::subImage(context, index, area, format, type, unpack, unpackBuffer,
+ pixels, 0);
+ }
+}
+
+angle::Result TextureD3D_3D::setCompressedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_3D);
+
+ // compressed formats don't have separate sized internal formats-- we can just use the
+ // compressed format directly
+ ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormat, size, false));
+
+ return setCompressedImageImpl(context, index, unpack, pixels, 0);
+}
+
+angle::Result TextureD3D_3D::setCompressedSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_3D);
+
+ ANGLE_TRY(TextureD3D::subImageCompressed(context, index, area, format, unpack, pixels, 0));
+ return commitRegion(context, index, area);
+}
+
+angle::Result TextureD3D_3D::copyImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ gl::Framebuffer *source)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_3D::copySubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ gl::Framebuffer *source)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_3D);
+
+ gl::Extents fbSize = source->getReadColorAttachment()->getSize();
+ gl::Rectangle clippedSourceArea;
+ if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height),
+ &clippedSourceArea))
+ {
+ return angle::Result::Continue;
+ }
+ const gl::Offset clippedDestOffset(destOffset.x + clippedSourceArea.x - sourceArea.x,
+ destOffset.y + clippedSourceArea.y - sourceArea.y,
+ destOffset.z);
+
+ // Currently, copying directly to the storage is not possible because it's not possible to
+ // create an SRV from a single layer of a 3D texture. Instead, make sure the image is up to
+ // date before the copy and then copy back to the storage afterwards if needed.
+ // TODO: Investigate 3D blits in D3D11.
+
+ bool syncTexStorage = mTexStorage && isLevelComplete(index.getLevelIndex());
+ if (syncTexStorage)
+ {
+ ANGLE_TRY(
+ mImageArray[index.getLevelIndex()]->copyFromTexStorage(context, index, mTexStorage));
+ }
+ ANGLE_TRY(mImageArray[index.getLevelIndex()]->copyFromFramebuffer(context, clippedDestOffset,
+ clippedSourceArea, source));
+ mDirtyImages = true;
+ onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
+
+ if (syncTexStorage)
+ {
+ ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_3D::copyTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ GLenum type,
+ GLint sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_3D);
+
+ gl::TextureType sourceType = source->getType();
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+ gl::Extents size(
+ static_cast<int>(source->getWidth(NonCubeTextureTypeToTarget(sourceType), sourceLevel)),
+ static_cast<int>(source->getHeight(NonCubeTextureTypeToTarget(sourceType), sourceLevel)),
+ static_cast<int>(source->getDepth(NonCubeTextureTypeToTarget(sourceType), sourceLevel)));
+
+ ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
+ size, false));
+
+ gl::Box sourceBox(0, 0, 0, size.width, size.height, size.depth);
+ gl::Offset destOffset(0, 0, 0);
+ gl::ImageIndex destIndex = gl::ImageIndex::Make3D(static_cast<GLint>(index.getLevelIndex()));
+
+ if (!isSRGB(index.getLevelIndex()) && canCreateRenderTargetForImage(destIndex))
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+ ASSERT(isValidLevel(index.getLevelIndex()));
+ ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
+
+ ANGLE_TRY(mRenderer->copyTexture(context, source, sourceLevel, gl::TextureTarget::_3D,
+ sourceBox, internalFormatInfo.format,
+ internalFormatInfo.type, destOffset, mTexStorage,
+ index.getTarget(), index.getLevelIndex(), unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+ }
+ else
+ {
+ gl::ImageIndex sourceIndex = gl::ImageIndex::Make3D(sourceLevel);
+ ImageD3D *sourceImage = nullptr;
+ ImageD3D *destImage = nullptr;
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+
+ ANGLE_TRY(getImageAndSyncFromStorage(context, destIndex, &destImage));
+ ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceIndex, &sourceImage));
+
+ ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceBox, destOffset,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+
+ mDirtyImages = true;
+
+ gl::Box destRegion(0, 0, 0, sourceBox.width, sourceBox.height, sourceBox.depth);
+ ANGLE_TRY(commitRegion(context, destIndex, destRegion));
+ }
+
+ return angle::Result::Continue;
+}
+angle::Result TextureD3D_3D::copySubTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ GLint sourceLevel,
+ const gl::Box &sourceBox,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_3D);
+
+ gl::ImageIndex destIndex = gl::ImageIndex::Make3D(static_cast<GLint>(index.getLevelIndex()));
+
+ if (!isSRGB(index.getLevelIndex()) && canCreateRenderTargetForImage(destIndex))
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+ ASSERT(isValidLevel(index.getLevelIndex()));
+ ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
+
+ const gl::InternalFormat &internalFormatInfo =
+ gl::GetSizedInternalFormatInfo(getInternalFormat(index.getLevelIndex()));
+ ANGLE_TRY(mRenderer->copyTexture(context, source, sourceLevel, gl::TextureTarget::_3D,
+ sourceBox, internalFormatInfo.format,
+ internalFormatInfo.type, destOffset, mTexStorage,
+ index.getTarget(), index.getLevelIndex(), unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+ }
+ else
+ {
+ gl::ImageIndex sourceImageIndex = gl::ImageIndex::Make3D(sourceLevel);
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+ ImageD3D *sourceImage = nullptr;
+ ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, sourceImageIndex, &sourceImage));
+
+ ImageD3D *destImage = nullptr;
+ ANGLE_TRY(getImageAndSyncFromStorage(context, destIndex, &destImage));
+
+ ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, sourceBox, destOffset,
+ unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+
+ mDirtyImages = true;
+
+ gl::Box destRegion(destOffset.x, destOffset.y, destOffset.z, sourceBox.width,
+ sourceBox.height, sourceBox.depth);
+ ANGLE_TRY(commitRegion(context, destIndex, destRegion));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_3D::setStorage(const gl::Context *context,
+ gl::TextureType type,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size)
+{
+ ASSERT(type == gl::TextureType::_3D);
+
+ for (size_t level = 0; level < levels; level++)
+ {
+ gl::Extents levelSize(std::max(1, size.width >> level), std::max(1, size.height >> level),
+ std::max(1, size.depth >> level));
+ mImageArray[level]->redefine(gl::TextureType::_3D, internalFormat, levelSize, true);
+ }
+
+ for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ mImageArray[level]->redefine(gl::TextureType::_3D, GL_NONE, gl::Extents(0, 0, 0), true);
+ }
+
+ // TODO(geofflang): Verify storage creation had no errors
+ BindFlags bindFlags;
+ bindFlags.renderTarget = IsRenderTargetUsage(mState.getUsage());
+ TexStoragePointer storage = {
+ mRenderer->createTextureStorage3D(internalFormat, bindFlags, size.width, size.height,
+ size.depth, static_cast<int>(levels), mState.getLabel()),
+ context};
+
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
+
+ ANGLE_TRY(updateStorage(context));
+
+ mImmutable = true;
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_3D::bindTexImage(const gl::Context *context, egl::Surface *surface)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_3D::releaseTexImage(const gl::Context *context)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_3D::initMipmapImages(const gl::Context *context)
+{
+ const GLuint baseLevel = mState.getEffectiveBaseLevel();
+ const GLuint maxLevel = mState.getMipmapMaxLevel();
+ // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
+ // levels.
+ for (GLuint level = baseLevel + 1; level <= maxLevel; level++)
+ {
+ gl::Extents levelSize(std::max(getLevelZeroWidth() >> level, 1),
+ std::max(getLevelZeroHeight() >> level, 1),
+ std::max(getLevelZeroDepth() >> level, 1));
+ ANGLE_TRY(redefineImage(context, level, getBaseLevelInternalFormat(), levelSize, false));
+ }
+
+ // We should be mip-complete now so generate the storage.
+ ANGLE_TRY(initializeStorage(context, BindFlags::RenderTarget()));
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_3D::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ // ensure the underlying texture is created
+ ANGLE_TRY(ensureRenderTarget(context));
+
+ if (index.hasLayer())
+ {
+ ANGLE_TRY(updateStorage(context));
+ }
+ else
+ {
+ ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
+ }
+
+ return mTexStorage->getRenderTarget(context, index, samples, outRT);
+}
+
+angle::Result TextureD3D_3D::initializeStorage(const gl::Context *context, BindFlags bindFlags)
+{
+ // Only initialize the first time this texture is used as a render target or shader resource
+ if (mTexStorage)
+ {
+ return angle::Result::Continue;
+ }
+
+ // do not attempt to create storage for nonexistant data
+ if (!isLevelComplete(getBaseLevel()))
+ {
+ return angle::Result::Continue;
+ }
+
+ TexStoragePointer storage;
+ ANGLE_TRY(createCompleteStorage(context, bindFlags, &storage));
+
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
+
+ ASSERT(mTexStorage);
+
+ // flush image data to the storage
+ ANGLE_TRY(updateStorage(context));
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_3D::createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outStorage) const
+{
+ GLsizei width = getLevelZeroWidth();
+ GLsizei height = getLevelZeroHeight();
+ GLsizei depth = getLevelZeroDepth();
+ GLenum internalFormat = getBaseLevelInternalFormat();
+
+ ASSERT(width > 0 && height > 0 && depth > 0);
+
+ // use existing storage level count, when previously specified by TexStorage*D
+ GLint levels =
+ (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, depth));
+
+ // TODO: Verify creation of the storage succeeded
+ *outStorage = {mRenderer->createTextureStorage3D(internalFormat, bindFlags, width, height,
+ depth, levels, mState.getLabel()),
+ context};
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_3D::setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage)
+{
+ gl::TexLevelMask copyImageMask;
+ copyImageMask.set();
+
+ ANGLE_TRY(releaseTexStorage(context, copyImageMask));
+ mTexStorage = newCompleteTexStorage;
+ mTexStorageObserverBinding.bind(mTexStorage);
+ mDirtyImages = true;
+
+ // We do not support managed 3D storage, as that is D3D9/ES2-only
+ ASSERT(!mTexStorage->isManaged());
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_3D::updateStorage(const gl::Context *context)
+{
+ if (!mDirtyImages)
+ {
+ return angle::Result::Continue;
+ }
+
+ ASSERT(mTexStorage != nullptr);
+ GLint storageLevels = mTexStorage->getLevelCount();
+ for (int level = 0; level < storageLevels; level++)
+ {
+ if (mImageArray[level]->isDirty() && isLevelComplete(level))
+ {
+ ANGLE_TRY(updateStorageLevel(context, level));
+ }
+ }
+
+ mDirtyImages = false;
+ return angle::Result::Continue;
+}
+
+bool TextureD3D_3D::isValidLevel(int level) const
+{
+ return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
+}
+
+bool TextureD3D_3D::isLevelComplete(int level) const
+{
+ ASSERT(level >= 0 && level < static_cast<int>(mImageArray.size()) &&
+ mImageArray[level] != nullptr);
+
+ if (isImmutable())
+ {
+ return true;
+ }
+
+ GLsizei width = getLevelZeroWidth();
+ GLsizei height = getLevelZeroHeight();
+ GLsizei depth = getLevelZeroDepth();
+
+ if (width <= 0 || height <= 0 || depth <= 0)
+ {
+ return false;
+ }
+
+ if (level == static_cast<int>(getBaseLevel()))
+ {
+ return true;
+ }
+
+ ImageD3D *levelImage = mImageArray[level].get();
+
+ if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
+ {
+ return false;
+ }
+
+ if (levelImage->getWidth() != std::max(1, width >> level))
+ {
+ return false;
+ }
+
+ if (levelImage->getHeight() != std::max(1, height >> level))
+ {
+ return false;
+ }
+
+ if (levelImage->getDepth() != std::max(1, depth >> level))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool TextureD3D_3D::isImageComplete(const gl::ImageIndex &index) const
+{
+ return isLevelComplete(index.getLevelIndex());
+}
+
+angle::Result TextureD3D_3D::updateStorageLevel(const gl::Context *context, int level)
+{
+ ASSERT(level >= 0 && level < static_cast<int>(mImageArray.size()) &&
+ mImageArray[level] != nullptr);
+ ASSERT(isLevelComplete(level));
+
+ if (mImageArray[level]->isDirty())
+ {
+ gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+ gl::Box region(0, 0, 0, getWidth(level), getHeight(level), getDepth(level));
+ ANGLE_TRY(commitRegion(context, index, region));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_3D::redefineImage(const gl::Context *context,
+ GLint level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease)
+{
+ // If there currently is a corresponding storage texture image, it has these parameters
+ const int storageWidth = std::max(1, getLevelZeroWidth() >> level);
+ const int storageHeight = std::max(1, getLevelZeroHeight() >> level);
+ const int storageDepth = std::max(1, getLevelZeroDepth() >> level);
+ const GLenum storageFormat = getBaseLevelInternalFormat();
+
+ if (mTexStorage)
+ {
+ const int storageLevels = mTexStorage->getLevelCount();
+
+ if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth ||
+ size.height != storageHeight || size.depth != storageDepth ||
+ internalformat != storageFormat) // Discard mismatched storage
+ {
+ markAllImagesDirty();
+
+ gl::TexLevelMask copyImageMask;
+ copyImageMask.set();
+ copyImageMask.set(level, false);
+
+ ANGLE_TRY(releaseTexStorage(context, copyImageMask));
+ }
+ }
+
+ mImageArray[level]->redefine(gl::TextureType::_3D, internalformat, size, forceRelease);
+ mDirtyImages = mDirtyImages || mImageArray[level]->isDirty();
+
+ return angle::Result::Continue;
+}
+
+gl::ImageIndexIterator TextureD3D_3D::imageIterator() const
+{
+ return gl::ImageIndexIterator::Make3D(0, mTexStorage->getLevelCount(),
+ gl::ImageIndex::kEntireLevel,
+ gl::ImageIndex::kEntireLevel);
+}
+
+gl::ImageIndex TextureD3D_3D::getImageIndex(GLint mip, GLint /*layer*/) const
+{
+ // The "layer" here does not apply to 3D images. We use one Image per mip.
+ return gl::ImageIndex::Make3D(mip);
+}
+
+bool TextureD3D_3D::isValidIndex(const gl::ImageIndex &index) const
+{
+ return (mTexStorage && index.getType() == gl::TextureType::_3D && index.getLevelIndex() >= 0 &&
+ index.getLevelIndex() < mTexStorage->getLevelCount());
+}
+
+void TextureD3D_3D::markAllImagesDirty()
+{
+ for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mImageArray[i]->markDirty();
+ }
+ mDirtyImages = true;
+}
+
+GLint TextureD3D_3D::getLevelZeroDepth() const
+{
+ ASSERT(gl::CountLeadingZeros(static_cast<uint32_t>(getBaseLevelDepth())) > getBaseLevel());
+ return getBaseLevelDepth() << getBaseLevel();
+}
+
+TextureD3D_2DArray::TextureD3D_2DArray(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureD3D(state, renderer)
+{
+ for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level)
+ {
+ mLayerCounts[level] = 0;
+ mImageArray[level] = nullptr;
+ }
+}
+
+void TextureD3D_2DArray::onDestroy(const gl::Context *context)
+{
+ // Delete the Images before the TextureStorage. Images might be relying on the TextureStorage
+ // for some of their data. If TextureStorage is deleted before the Images, then their data will
+ // be wastefully copied back from the GPU before we delete the Images.
+ deleteImages();
+ return TextureD3D::onDestroy(context);
+}
+
+TextureD3D_2DArray::~TextureD3D_2DArray() {}
+
+ImageD3D *TextureD3D_2DArray::getImage(int level, int layer) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT((layer == 0 && mLayerCounts[level] == 0) || layer < mLayerCounts[level]);
+ return (mImageArray[level] ? mImageArray[level][layer] : nullptr);
+}
+
+ImageD3D *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const
+{
+ ASSERT(index.getLevelIndex() < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(index.hasLayer());
+ ASSERT((index.getLayerIndex() == 0 && mLayerCounts[index.getLevelIndex()] == 0) ||
+ index.getLayerIndex() < mLayerCounts[index.getLevelIndex()]);
+ ASSERT(index.getType() == gl::TextureType::_2DArray);
+ return (mImageArray[index.getLevelIndex()]
+ ? mImageArray[index.getLevelIndex()][index.getLayerIndex()]
+ : nullptr);
+}
+
+GLsizei TextureD3D_2DArray::getLayerCount(int level) const
+{
+ ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ return mLayerCounts[level];
+}
+
+GLsizei TextureD3D_2DArray::getWidth(GLint level) const
+{
+ return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0)
+ ? mImageArray[level][0]->getWidth()
+ : 0;
+}
+
+GLsizei TextureD3D_2DArray::getHeight(GLint level) const
+{
+ return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0)
+ ? mImageArray[level][0]->getHeight()
+ : 0;
+}
+
+GLenum TextureD3D_2DArray::getInternalFormat(GLint level) const
+{
+ return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0)
+ ? mImageArray[level][0]->getInternalFormat()
+ : GL_NONE;
+}
+
+bool TextureD3D_2DArray::isDepth(GLint level) const
+{
+ return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
+}
+
+bool TextureD3D_2DArray::isSRGB(GLint level) const
+{
+ return gl::GetSizedInternalFormatInfo(getInternalFormat(level)).colorEncoding == GL_SRGB;
+}
+
+angle::Result TextureD3D_2DArray::setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::setImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+
+ ANGLE_TRY(
+ redefineImage(context, index.getLevelIndex(), formatInfo.sizedInternalFormat, size, false));
+
+ ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
+
+ GLuint inputDepthPitch = 0;
+ ANGLE_CHECK_GL_MATH(contextD3D, formatInfo.computeDepthPitch(
+ type, size.width, size.height, unpack.alignment,
+ unpack.rowLength, unpack.imageHeight, &inputDepthPitch));
+
+ for (int i = 0; i < size.depth; i++)
+ {
+ const ptrdiff_t layerOffset = (inputDepthPitch * i);
+ gl::ImageIndex layerIndex = gl::ImageIndex::Make2DArray(index.getLevelIndex(), i);
+ ANGLE_TRY(
+ setImageImpl(context, layerIndex, type, unpack, unpackBuffer, pixels, layerOffset));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::setSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels)
+{
+ ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
+
+ ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);
+ const gl::InternalFormat &formatInfo =
+ gl::GetInternalFormatInfo(getInternalFormat(index.getLevelIndex()), type);
+ GLuint inputDepthPitch = 0;
+ ANGLE_CHECK_GL_MATH(contextD3D, formatInfo.computeDepthPitch(
+ type, area.width, area.height, unpack.alignment,
+ unpack.rowLength, unpack.imageHeight, &inputDepthPitch));
+
+ for (int i = 0; i < area.depth; i++)
+ {
+ int layer = area.z + i;
+ const ptrdiff_t layerOffset = (inputDepthPitch * i);
+
+ gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
+
+ gl::ImageIndex layerIndex = gl::ImageIndex::Make2DArray(index.getLevelIndex(), layer);
+ ANGLE_TRY(TextureD3D::subImage(context, layerIndex, layerArea, format, type, unpack,
+ unpackBuffer, pixels, layerOffset));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::setCompressedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);
+
+ ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
+
+ // compressed formats don't have separate sized internal formats-- we can just use the
+ // compressed format directly
+ ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormat, size, false));
+
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
+ GLuint inputDepthPitch = 0;
+ ANGLE_CHECK_GL_MATH(
+ contextD3D, formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0, 0,
+ &inputDepthPitch));
+
+ for (int i = 0; i < size.depth; i++)
+ {
+ const ptrdiff_t layerOffset = (inputDepthPitch * i);
+
+ gl::ImageIndex layerIndex = gl::ImageIndex::Make2DArray(index.getLevelIndex(), i);
+ ANGLE_TRY(setCompressedImageImpl(context, layerIndex, unpack, pixels, layerOffset));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::setCompressedSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);
+
+ ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
+
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(format);
+ GLuint inputDepthPitch = 0;
+ ANGLE_CHECK_GL_MATH(
+ contextD3D, formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0,
+ &inputDepthPitch));
+
+ for (int i = 0; i < area.depth; i++)
+ {
+ int layer = area.z + i;
+ const ptrdiff_t layerOffset = (inputDepthPitch * i);
+
+ gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
+
+ gl::ImageIndex layerIndex = gl::ImageIndex::Make2DArray(index.getLevelIndex(), layer);
+ ANGLE_TRY(TextureD3D::subImageCompressed(context, layerIndex, layerArea, format, unpack,
+ pixels, layerOffset));
+ ANGLE_TRY(commitRegion(context, layerIndex, layerArea));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::copyImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ gl::Framebuffer *source)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::copySubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ gl::Framebuffer *source)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);
+
+ gl::Extents fbSize = source->getReadColorAttachment()->getSize();
+ gl::Rectangle clippedSourceArea;
+ if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, fbSize.width, fbSize.height),
+ &clippedSourceArea))
+ {
+ return angle::Result::Continue;
+ }
+ const gl::Offset clippedDestOffset(destOffset.x + clippedSourceArea.x - sourceArea.x,
+ destOffset.y + clippedSourceArea.y - sourceArea.y,
+ destOffset.z);
+
+ if (!canCreateRenderTargetForImage(index))
+ {
+ gl::Offset destLayerOffset(clippedDestOffset.x, clippedDestOffset.y, 0);
+ ANGLE_TRY(mImageArray[index.getLevelIndex()][clippedDestOffset.z]->copyFromFramebuffer(
+ context, destLayerOffset, clippedSourceArea, source));
+ mDirtyImages = true;
+ onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
+ }
+ else
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+
+ if (isValidLevel(index.getLevelIndex()))
+ {
+ ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
+ ANGLE_TRY(
+ mRenderer->copyImage2DArray(context, source, clippedSourceArea,
+ gl::GetUnsizedFormat(getInternalFormat(getBaseLevel())),
+ clippedDestOffset, mTexStorage, index.getLevelIndex()));
+ }
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::copyTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ GLenum type,
+ GLint sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);
+
+ gl::TextureType sourceType = source->getType();
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+ gl::Extents size(
+ static_cast<int>(source->getWidth(NonCubeTextureTypeToTarget(sourceType), sourceLevel)),
+ static_cast<int>(source->getHeight(NonCubeTextureTypeToTarget(sourceType), sourceLevel)),
+ static_cast<int>(source->getDepth(NonCubeTextureTypeToTarget(sourceType), sourceLevel)));
+
+ ANGLE_TRY(redefineImage(context, index.getLevelIndex(), internalFormatInfo.sizedInternalFormat,
+ size, false));
+
+ gl::Box sourceBox(0, 0, 0, size.width, size.height, size.depth);
+ gl::Offset destOffset(0, 0, 0);
+
+ gl::ImageIndex destIndex =
+ gl::ImageIndex::Make2DArrayRange(index.getLevelIndex(), 0, size.depth);
+
+ if (!isSRGB(index.getLevelIndex()) &&
+ canCreateRenderTargetForImage(
+ gl::ImageIndex::Make2DArrayRange(index.getLevelIndex(), 0, size.depth)))
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+ ASSERT(isValidLevel(index.getLevelIndex()));
+ ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
+ ANGLE_TRY(mRenderer->copyTexture(context, source, sourceLevel, gl::TextureTarget::_2DArray,
+ sourceBox, internalFormatInfo.format,
+ internalFormatInfo.type, destOffset, mTexStorage,
+ index.getTarget(), index.getLevelIndex(), unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+ }
+ else
+ {
+ for (int i = 0; i < size.depth; i++)
+ {
+ gl::ImageIndex currentSourceDepthIndex = gl::ImageIndex::Make2DArray(sourceLevel, i);
+ gl::ImageIndex currentDestDepthIndex =
+ gl::ImageIndex::Make2DArray(index.getLevelIndex(), i);
+ ImageD3D *sourceImage = nullptr;
+ ImageD3D *destImage = nullptr;
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+
+ ANGLE_TRY(getImageAndSyncFromStorage(context, currentDestDepthIndex, &destImage));
+ ANGLE_TRY(sourceD3D->getImageAndSyncFromStorage(context, currentSourceDepthIndex,
+ &sourceImage));
+ gl::Box imageBox(sourceBox.x, sourceBox.y, 0, sourceBox.width, sourceBox.height, 1);
+ ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, imageBox, destOffset,
+ unpackFlipY, unpackPremultiplyAlpha,
+ unpackUnmultiplyAlpha));
+ }
+
+ mDirtyImages = true;
+
+ gl::Box destRegion(destOffset.x, destOffset.y, destOffset.z, sourceBox.width,
+ sourceBox.height, sourceBox.depth);
+ ANGLE_TRY(commitRegion(context, destIndex, destRegion));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::copySubTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ GLint sourceLevel,
+ const gl::Box &sourceBox,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source)
+{
+ ASSERT(index.getTarget() == gl::TextureTarget::_2DArray);
+
+ gl::ImageIndex destIndex = gl::ImageIndex::Make2DArrayRange(
+ static_cast<GLint>(index.getLevelIndex()), destOffset.z, sourceBox.depth - destOffset.z);
+
+ if (!isSRGB(destIndex.getLevelIndex()) && canCreateRenderTargetForImage(destIndex))
+ {
+ ANGLE_TRY(ensureRenderTarget(context));
+ ASSERT(isValidLevel(destIndex.getLevelIndex()));
+ ANGLE_TRY(updateStorageLevel(context, destIndex.getLevelIndex()));
+
+ const gl::InternalFormat &internalFormatInfo =
+ gl::GetSizedInternalFormatInfo(getInternalFormat(destIndex.getLevelIndex()));
+ ANGLE_TRY(mRenderer->copyTexture(context, source, sourceLevel, gl::TextureTarget::_2DArray,
+ sourceBox, internalFormatInfo.format,
+ internalFormatInfo.type, destOffset, mTexStorage,
+ index.getTarget(), index.getLevelIndex(), unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha));
+ }
+ else
+ {
+ for (int i = 0; i < sourceBox.depth; i++)
+ {
+ gl::ImageIndex currentSourceIndex =
+ gl::ImageIndex::Make2DArray(sourceLevel, i + sourceBox.z);
+ gl::ImageIndex currentDestIndex =
+ gl::ImageIndex::Make2DArray(index.getLevelIndex(), i + destOffset.z);
+
+ gl::Box currentLayerBox(sourceBox.x, sourceBox.y, 0, sourceBox.width, sourceBox.height,
+ 1);
+
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+ ImageD3D *sourceImage = nullptr;
+ ANGLE_TRY(
+ sourceD3D->getImageAndSyncFromStorage(context, currentSourceIndex, &sourceImage));
+
+ ImageD3D *destImage = nullptr;
+ ANGLE_TRY(getImageAndSyncFromStorage(context, currentDestIndex, &destImage));
+
+ ANGLE_TRY(mRenderer->copyImage(context, destImage, sourceImage, currentLayerBox,
+ destOffset, unpackFlipY, unpackPremultiplyAlpha,
+ unpackUnmultiplyAlpha));
+ }
+
+ mDirtyImages = true;
+
+ gl::Box destRegion(destOffset.x, destOffset.y, destOffset.z, sourceBox.width,
+ sourceBox.height, sourceBox.depth);
+ ANGLE_TRY(commitRegion(context, destIndex, destRegion));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::setStorage(const gl::Context *context,
+ gl::TextureType type,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size)
+{
+ ASSERT(type == gl::TextureType::_2DArray);
+
+ deleteImages();
+
+ for (size_t level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ gl::Extents levelLayerSize(std::max(1, size.width >> level),
+ std::max(1, size.height >> level), 1);
+
+ mLayerCounts[level] = (level < levels ? size.depth : 0);
+
+ if (mLayerCounts[level] > 0)
+ {
+ // Create new images for this level
+ mImageArray[level] = new ImageD3D *[mLayerCounts[level]];
+
+ for (int layer = 0; layer < mLayerCounts[level]; layer++)
+ {
+ mImageArray[level][layer] = mRenderer->createImage();
+ mImageArray[level][layer]->redefine(gl::TextureType::_2DArray, internalFormat,
+ levelLayerSize, true);
+ }
+ }
+ }
+
+ // TODO(geofflang): Verify storage creation had no errors
+ BindFlags bindFlags;
+ bindFlags.renderTarget = IsRenderTargetUsage(mState.getUsage());
+ TexStoragePointer storage = {mRenderer->createTextureStorage2DArray(
+ internalFormat, bindFlags, size.width, size.height, size.depth,
+ static_cast<int>(levels), mState.getLabel()),
+ context};
+
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
+
+ ANGLE_TRY(updateStorage(context));
+
+ mImmutable = true;
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::bindTexImage(const gl::Context *context, egl::Surface *surface)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::releaseTexImage(const gl::Context *context)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::initMipmapImages(const gl::Context *context)
+{
+ const GLuint baseLevel = mState.getEffectiveBaseLevel();
+ const GLuint maxLevel = mState.getMipmapMaxLevel();
+ int baseWidth = getLevelZeroWidth();
+ int baseHeight = getLevelZeroHeight();
+ int baseDepth = getLayerCount(getBaseLevel());
+ GLenum baseFormat = getBaseLevelInternalFormat();
+
+ // Purge array levels baseLevel + 1 through q and reset them to represent the generated mipmap
+ // levels.
+ for (GLuint level = baseLevel + 1u; level <= maxLevel; level++)
+ {
+ ASSERT((baseWidth >> level) > 0 || (baseHeight >> level) > 0);
+ gl::Extents levelLayerSize(std::max(baseWidth >> level, 1),
+ std::max(baseHeight >> level, 1), baseDepth);
+ ANGLE_TRY(redefineImage(context, level, baseFormat, levelLayerSize, false));
+ }
+
+ // We should be mip-complete now so generate the storage.
+ ANGLE_TRY(initializeStorage(context, BindFlags::RenderTarget()));
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ // ensure the underlying texture is created
+ ANGLE_TRY(ensureRenderTarget(context));
+ ANGLE_TRY(updateStorageLevel(context, index.getLevelIndex()));
+ return mTexStorage->getRenderTarget(context, index, samples, outRT);
+}
+
+angle::Result TextureD3D_2DArray::initializeStorage(const gl::Context *context, BindFlags bindFlags)
+{
+ // Only initialize the first time this texture is used as a render target or shader resource
+ if (mTexStorage)
+ {
+ return angle::Result::Continue;
+ }
+
+ // do not attempt to create storage for nonexistant data
+ if (!isLevelComplete(getBaseLevel()))
+ {
+ return angle::Result::Continue;
+ }
+
+ bindFlags.renderTarget |= IsRenderTargetUsage(mState.getUsage());
+
+ TexStoragePointer storage;
+ ANGLE_TRY(createCompleteStorage(context, bindFlags, &storage));
+
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
+
+ ASSERT(mTexStorage);
+
+ // flush image data to the storage
+ ANGLE_TRY(updateStorage(context));
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outStorage) const
+{
+ GLsizei width = getLevelZeroWidth();
+ GLsizei height = getLevelZeroHeight();
+ GLsizei depth = getLayerCount(getBaseLevel());
+ GLenum internalFormat = getBaseLevelInternalFormat();
+
+ ASSERT(width > 0 && height > 0 && depth > 0);
+
+ // use existing storage level count, when previously specified by TexStorage*D
+ GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
+
+ // TODO(geofflang): Verify storage creation succeeds
+ *outStorage = {mRenderer->createTextureStorage2DArray(internalFormat, bindFlags, width, height,
+ depth, levels, mState.getLabel()),
+ context};
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage)
+{
+ gl::TexLevelMask copyImageMask;
+ copyImageMask.set();
+
+ ANGLE_TRY(releaseTexStorage(context, copyImageMask));
+ mTexStorage = newCompleteTexStorage;
+ mTexStorageObserverBinding.bind(mTexStorage);
+ mDirtyImages = true;
+
+ // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only
+ ASSERT(!mTexStorage->isManaged());
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DArray::updateStorage(const gl::Context *context)
+{
+ if (!mDirtyImages)
+ {
+ return angle::Result::Continue;
+ }
+
+ ASSERT(mTexStorage != nullptr);
+ GLint storageLevels = mTexStorage->getLevelCount();
+ for (int level = 0; level < storageLevels; level++)
+ {
+ if (isLevelComplete(level))
+ {
+ ANGLE_TRY(updateStorageLevel(context, level));
+ }
+ }
+
+ mDirtyImages = false;
+ return angle::Result::Continue;
+}
+
+bool TextureD3D_2DArray::isValidLevel(int level) const
+{
+ return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0);
+}
+
+bool TextureD3D_2DArray::isLevelComplete(int level) const
+{
+ ASSERT(level >= 0 && level < (int)ArraySize(mImageArray));
+
+ if (isImmutable())
+ {
+ return true;
+ }
+
+ GLsizei width = getLevelZeroWidth();
+ GLsizei height = getLevelZeroHeight();
+
+ if (width <= 0 || height <= 0)
+ {
+ return false;
+ }
+
+ // Layers check needs to happen after the above checks, otherwise out-of-range base level may be
+ // queried.
+ GLsizei layers = getLayerCount(getBaseLevel());
+
+ if (layers <= 0)
+ {
+ return false;
+ }
+
+ if (level == static_cast<int>(getBaseLevel()))
+ {
+ return true;
+ }
+
+ if (getInternalFormat(level) != getInternalFormat(getBaseLevel()))
+ {
+ return false;
+ }
+
+ if (getWidth(level) != std::max(1, width >> level))
+ {
+ return false;
+ }
+
+ if (getHeight(level) != std::max(1, height >> level))
+ {
+ return false;
+ }
+
+ if (getLayerCount(level) != layers)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool TextureD3D_2DArray::isImageComplete(const gl::ImageIndex &index) const
+{
+ return isLevelComplete(index.getLevelIndex());
+}
+
+angle::Result TextureD3D_2DArray::updateStorageLevel(const gl::Context *context, int level)
+{
+ ASSERT(level >= 0 && level < static_cast<int>(ArraySize(mLayerCounts)));
+ ASSERT(isLevelComplete(level));
+
+ for (int layer = 0; layer < mLayerCounts[level]; layer++)
+ {
+ ASSERT(mImageArray[level] != nullptr && mImageArray[level][layer] != nullptr);
+ if (mImageArray[level][layer]->isDirty())
+ {
+ gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
+ gl::Box region(0, 0, 0, getWidth(level), getHeight(level), 1);
+ ANGLE_TRY(commitRegion(context, index, region));
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+void TextureD3D_2DArray::deleteImages()
+{
+ for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level)
+ {
+ for (int layer = 0; layer < mLayerCounts[level]; ++layer)
+ {
+ delete mImageArray[level][layer];
+ }
+ delete[] mImageArray[level];
+ mImageArray[level] = nullptr;
+ mLayerCounts[level] = 0;
+ }
+}
+
+angle::Result TextureD3D_2DArray::redefineImage(const gl::Context *context,
+ GLint level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease)
+{
+ // If there currently is a corresponding storage texture image, it has these parameters
+ const int storageWidth = std::max(1, getLevelZeroWidth() >> level);
+ const int storageHeight = std::max(1, getLevelZeroHeight() >> level);
+ const GLuint baseLevel = getBaseLevel();
+ const GLenum storageFormat = getBaseLevelInternalFormat();
+
+ int storageDepth = 0;
+ if (baseLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ storageDepth = getLayerCount(baseLevel);
+ }
+
+ // Only reallocate the layers if the size doesn't match
+ if (size.depth != mLayerCounts[level])
+ {
+ for (int layer = 0; layer < mLayerCounts[level]; layer++)
+ {
+ SafeDelete(mImageArray[level][layer]);
+ }
+ SafeDeleteArray(mImageArray[level]);
+ mLayerCounts[level] = size.depth;
+
+ if (size.depth > 0)
+ {
+ mImageArray[level] = new ImageD3D *[size.depth];
+ for (int layer = 0; layer < mLayerCounts[level]; layer++)
+ {
+ mImageArray[level][layer] = mRenderer->createImage();
+ }
+ }
+ }
+
+ if (mTexStorage)
+ {
+ const int storageLevels = mTexStorage->getLevelCount();
+
+ if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth ||
+ size.height != storageHeight || size.depth != storageDepth ||
+ internalformat != storageFormat) // Discard mismatched storage
+ {
+ markAllImagesDirty();
+
+ gl::TexLevelMask copyImageMask;
+ copyImageMask.set();
+ copyImageMask.set(level, false);
+
+ ANGLE_TRY(releaseTexStorage(context, copyImageMask));
+ }
+ }
+
+ if (size.depth > 0)
+ {
+ for (int layer = 0; layer < mLayerCounts[level]; layer++)
+ {
+ mImageArray[level][layer]->redefine(gl::TextureType::_2DArray, internalformat,
+ gl::Extents(size.width, size.height, 1),
+ forceRelease);
+ mDirtyImages = mDirtyImages || mImageArray[level][layer]->isDirty();
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+gl::ImageIndexIterator TextureD3D_2DArray::imageIterator() const
+{
+ return gl::ImageIndexIterator::Make2DArray(0, mTexStorage->getLevelCount(), mLayerCounts);
+}
+
+gl::ImageIndex TextureD3D_2DArray::getImageIndex(GLint mip, GLint layer) const
+{
+ return gl::ImageIndex::Make2DArray(mip, layer);
+}
+
+bool TextureD3D_2DArray::isValidIndex(const gl::ImageIndex &index) const
+{
+ // Check for having a storage and the right type of index
+ if (!mTexStorage || index.getType() != gl::TextureType::_2DArray)
+ {
+ return false;
+ }
+
+ // Check the mip index
+ if (index.getLevelIndex() < 0 || index.getLevelIndex() >= mTexStorage->getLevelCount())
+ {
+ return false;
+ }
+
+ // Check the layer index
+ return (!index.hasLayer() || (index.getLayerIndex() >= 0 &&
+ index.getLayerIndex() < mLayerCounts[index.getLevelIndex()]));
+}
+
+void TextureD3D_2DArray::markAllImagesDirty()
+{
+ for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++)
+ {
+ for (int dirtyLayer = 0; dirtyLayer < mLayerCounts[dirtyLevel]; dirtyLayer++)
+ {
+ mImageArray[dirtyLevel][dirtyLayer]->markDirty();
+ }
+ }
+ mDirtyImages = true;
+}
+
+TextureD3DImmutableBase::TextureD3DImmutableBase(const gl::TextureState &state,
+ RendererD3D *renderer)
+ : TextureD3D(state, renderer)
+{}
+
+TextureD3DImmutableBase::~TextureD3DImmutableBase() {}
+
+ImageD3D *TextureD3DImmutableBase::getImage(const gl::ImageIndex &index) const
+{
+ return nullptr;
+}
+
+angle::Result TextureD3DImmutableBase::setImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3DImmutableBase::setSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3DImmutableBase::setCompressedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3DImmutableBase::setCompressedSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3DImmutableBase::copyImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ gl::Framebuffer *source)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3DImmutableBase::copySubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ gl::Framebuffer *source)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3DImmutableBase::bindTexImage(const gl::Context *context,
+ egl::Surface *surface)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3DImmutableBase::releaseTexImage(const gl::Context *context)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+TextureD3D_External::TextureD3D_External(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureD3DImmutableBase(state, renderer)
+{}
+
+TextureD3D_External::~TextureD3D_External() {}
+
+GLsizei TextureD3D_External::getLayerCount(int level) const
+{
+ return 1;
+}
+
+angle::Result TextureD3D_External::setImageExternal(const gl::Context *context,
+ gl::TextureType type,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc)
+{
+ ASSERT(type == gl::TextureType::External);
+
+ ANGLE_TRY(releaseTexStorage(context, gl::TexLevelMask()));
+
+ // If the stream is null, the external image is unbound and we release the storage
+ if (stream != nullptr)
+ {
+ mTexStorage = mRenderer->createTextureStorageExternal(stream, desc, mState.getLabel());
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_External::setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image)
+{
+ EGLImageD3D *eglImaged3d = GetImplAs<EGLImageD3D>(image);
+
+ // Pass in the RenderTargetD3D here: createTextureStorage can't generate an error.
+ RenderTargetD3D *renderTargetD3D = nullptr;
+ ANGLE_TRY(eglImaged3d->getRenderTarget(context, &renderTargetD3D));
+
+ ANGLE_TRY(releaseTexStorage(context, gl::TexLevelMask()));
+ mTexStorage =
+ mRenderer->createTextureStorageEGLImage(eglImaged3d, renderTargetD3D, mState.getLabel());
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_External::initMipmapImages(const gl::Context *context)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureD3D_External::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+bool TextureD3D_External::isImageComplete(const gl::ImageIndex &index) const
+{
+ return (index.getLevelIndex() == 0) ? (mTexStorage != nullptr) : false;
+}
+
+angle::Result TextureD3D_External::initializeStorage(const gl::Context *context,
+ BindFlags bindFlags)
+{
+ // Texture storage is created when an external image is bound
+ ASSERT(mTexStorage);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_External::createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outStorage) const
+{
+ UNREACHABLE();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_External::setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage)
+{
+ UNREACHABLE();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_External::updateStorage(const gl::Context *context)
+{
+ // Texture storage does not need to be updated since it is already loaded with the latest
+ // external image
+ ASSERT(mTexStorage);
+ return angle::Result::Continue;
+}
+
+gl::ImageIndexIterator TextureD3D_External::imageIterator() const
+{
+ return gl::ImageIndexIterator::Make2D(0, mTexStorage->getLevelCount());
+}
+
+gl::ImageIndex TextureD3D_External::getImageIndex(GLint mip, GLint /*layer*/) const
+{
+ // "layer" does not apply to 2D Textures.
+ return gl::ImageIndex::Make2D(mip);
+}
+
+bool TextureD3D_External::isValidIndex(const gl::ImageIndex &index) const
+{
+ return (mTexStorage && index.getType() == gl::TextureType::External &&
+ index.getLevelIndex() == 0);
+}
+
+void TextureD3D_External::markAllImagesDirty()
+{
+ UNREACHABLE();
+}
+
+TextureD3D_2DMultisample::TextureD3D_2DMultisample(const gl::TextureState &state,
+ RendererD3D *renderer)
+ : TextureD3DImmutableBase(state, renderer)
+{}
+
+TextureD3D_2DMultisample::~TextureD3D_2DMultisample() {}
+
+angle::Result TextureD3D_2DMultisample::setStorageMultisample(const gl::Context *context,
+ gl::TextureType type,
+ GLsizei samples,
+ GLint internalformat,
+ const gl::Extents &size,
+ bool fixedSampleLocations)
+{
+ ASSERT(type == gl::TextureType::_2DMultisample && size.depth == 1);
+
+ // We allocate storage immediately instead of doing it lazily like other TextureD3D classes do.
+ // This requires less state in this class.
+ TexStoragePointer storage = {mRenderer->createTextureStorage2DMultisample(
+ internalformat, size.width, size.height, static_cast<int>(0),
+ samples, fixedSampleLocations, mState.getLabel()),
+ context};
+
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
+
+ mImmutable = true;
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DMultisample::setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DMultisample::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(!index.hasLayer());
+
+ // ensure the underlying texture is created
+ ANGLE_TRY(ensureRenderTarget(context));
+
+ return mTexStorage->getRenderTarget(context, index, samples, outRT);
+}
+
+gl::ImageIndexIterator TextureD3D_2DMultisample::imageIterator() const
+{
+ return gl::ImageIndexIterator::Make2DMultisample();
+}
+
+gl::ImageIndex TextureD3D_2DMultisample::getImageIndex(GLint mip, GLint layer) const
+{
+ return gl::ImageIndex::Make2DMultisample();
+}
+
+bool TextureD3D_2DMultisample::isValidIndex(const gl::ImageIndex &index) const
+{
+ return (mTexStorage && index.getType() == gl::TextureType::_2DMultisample &&
+ index.getLevelIndex() == 0);
+}
+
+GLsizei TextureD3D_2DMultisample::getLayerCount(int level) const
+{
+ return 1;
+}
+
+void TextureD3D_2DMultisample::markAllImagesDirty() {}
+
+angle::Result TextureD3D_2DMultisample::initializeStorage(const gl::Context *context,
+ BindFlags bindFlags)
+{
+ // initializeStorage should only be called in a situation where the texture already has storage
+ // associated with it (storage is created in setStorageMultisample).
+ ASSERT(mTexStorage);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DMultisample::createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outStorage) const
+{
+ UNREACHABLE();
+ *outStorage = {mTexStorage, context};
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DMultisample::setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage)
+{
+ // These textures are immutable, so this should only be ever called once.
+ ASSERT(!mTexStorage);
+ mTexStorage = newCompleteTexStorage;
+ mTexStorageObserverBinding.bind(mTexStorage);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DMultisample::updateStorage(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DMultisample::initMipmapImages(const gl::Context *context)
+{
+ UNREACHABLE();
+ return angle::Result::Continue;
+}
+
+bool TextureD3D_2DMultisample::isImageComplete(const gl::ImageIndex &index) const
+{
+ return true;
+}
+
+TextureD3D_2DMultisampleArray::TextureD3D_2DMultisampleArray(const gl::TextureState &state,
+ RendererD3D *renderer)
+ : TextureD3DImmutableBase(state, renderer)
+{}
+
+TextureD3D_2DMultisampleArray::~TextureD3D_2DMultisampleArray() {}
+
+angle::Result TextureD3D_2DMultisampleArray::setStorageMultisample(const gl::Context *context,
+ gl::TextureType type,
+ GLsizei samples,
+ GLint internalformat,
+ const gl::Extents &size,
+ bool fixedSampleLocations)
+{
+ ASSERT(type == gl::TextureType::_2DMultisampleArray);
+
+ mLayerCount = size.depth;
+
+ TexStoragePointer storage = {
+ mRenderer->createTextureStorage2DMultisampleArray(internalformat, size.width, size.height,
+ size.depth, static_cast<int>(0), samples,
+ fixedSampleLocations, mState.getLabel()),
+ context};
+
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
+
+ mImmutable = true;
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DMultisampleArray::setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DMultisampleArray::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ // ensure the underlying texture is created
+ ANGLE_TRY(ensureRenderTarget(context));
+
+ return mTexStorage->getRenderTarget(context, index, samples, outRT);
+}
+
+gl::ImageIndexIterator TextureD3D_2DMultisampleArray::imageIterator() const
+{
+ return gl::ImageIndexIterator::Make2DMultisampleArray(&mLayerCount);
+}
+
+gl::ImageIndex TextureD3D_2DMultisampleArray::getImageIndex(GLint mip, GLint layer) const
+{
+ return gl::ImageIndex::Make2DMultisampleArray(layer);
+}
+
+bool TextureD3D_2DMultisampleArray::isValidIndex(const gl::ImageIndex &index) const
+{
+ return (mTexStorage && index.getType() == gl::TextureType::_2DMultisampleArray &&
+ index.getLevelIndex() == 0);
+}
+
+GLsizei TextureD3D_2DMultisampleArray::getLayerCount(int level) const
+{
+ return mLayerCount;
+}
+
+void TextureD3D_2DMultisampleArray::markAllImagesDirty() {}
+
+angle::Result TextureD3D_2DMultisampleArray::initializeStorage(const gl::Context *context,
+ BindFlags bindFlags)
+{
+ // initializeStorage should only be called in a situation where the texture already has storage
+ // associated with it (storage is created in setStorageMultisample).
+ ASSERT(mTexStorage);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DMultisampleArray::createCompleteStorage(
+ const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outStorage) const
+{
+ UNREACHABLE();
+ *outStorage = {mTexStorage, context};
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DMultisampleArray::setCompleteTexStorage(
+ const gl::Context *context,
+ TextureStorage *newCompleteTexStorage)
+{
+ // These textures are immutable, so this should only be ever called once.
+ ASSERT(!mTexStorage);
+ mTexStorage = newCompleteTexStorage;
+ mTexStorageObserverBinding.bind(mTexStorage);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DMultisampleArray::updateStorage(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_2DMultisampleArray::initMipmapImages(const gl::Context *context)
+{
+ UNIMPLEMENTED();
+ return angle::Result::Continue;
+}
+
+bool TextureD3D_2DMultisampleArray::isImageComplete(const gl::ImageIndex &index) const
+{
+ return true;
+}
+
+TextureD3D_Buffer::TextureD3D_Buffer(const gl::TextureState &state, RendererD3D *renderer)
+ : TextureD3D(state, renderer), mInternalFormat(GL_INVALID_ENUM)
+{}
+
+TextureD3D_Buffer::~TextureD3D_Buffer() {}
+
+angle::Result TextureD3D_Buffer::setImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Buffer::setSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Buffer::setCompressedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Buffer::setCompressedSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Buffer::copyImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ gl::Framebuffer *source)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Buffer::copySubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ gl::Framebuffer *source)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Buffer::bindTexImage(const gl::Context *context, egl::Surface *surface)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Buffer::releaseTexImage(const gl::Context *context)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+GLsizei TextureD3D_Buffer::getLayerCount(int level) const
+{
+ return 1;
+}
+
+angle::Result TextureD3D_Buffer::initMipmapImages(const gl::Context *context)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Stop;
+}
+
+bool TextureD3D_Buffer::isImageComplete(const gl::ImageIndex &index) const
+{
+ return (index.getLevelIndex() == 0) ? (mTexStorage != nullptr) : false;
+}
+
+angle::Result TextureD3D_Buffer::initializeStorage(const gl::Context *context, BindFlags bindFlags)
+{
+ ASSERT(mTexStorage);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Buffer::createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outStorage) const
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Buffer::setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage)
+{
+ ANGLE_TRY(releaseTexStorage(context, gl::TexLevelMask()));
+ mTexStorage = newCompleteTexStorage;
+ mTexStorageObserverBinding.bind(mTexStorage);
+
+ mDirtyImages = true;
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Buffer::updateStorage(const gl::Context *context)
+{
+ ASSERT(mTexStorage);
+ return angle::Result::Continue;
+}
+
+gl::ImageIndexIterator TextureD3D_Buffer::imageIterator() const
+{
+ return gl::ImageIndexIterator::MakeBuffer();
+}
+
+gl::ImageIndex TextureD3D_Buffer::getImageIndex(GLint mip, GLint layer) const
+{
+ return gl::ImageIndex::MakeBuffer();
+}
+
+bool TextureD3D_Buffer::isValidIndex(const gl::ImageIndex &index) const
+{
+ return (mTexStorage && index.getType() == gl::TextureType::Buffer &&
+ index.getLevelIndex() == 0);
+}
+
+void TextureD3D_Buffer::markAllImagesDirty()
+{
+ UNREACHABLE();
+}
+
+angle::Result TextureD3D_Buffer::setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Buffer::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<ContextD3D>(context));
+ return angle::Result::Continue;
+}
+
+ImageD3D *TextureD3D_Buffer::getImage(const gl::ImageIndex &index) const
+{
+ return nullptr;
+}
+
+angle::Result TextureD3D_Buffer::setBuffer(const gl::Context *context, GLenum internalFormat)
+{
+ ASSERT(mState.getType() == gl::TextureType::Buffer);
+ TexStoragePointer storage;
+ storage.reset(mRenderer->createTextureStorageBuffer(mState.getBuffer(), internalFormat,
+ mState.getLabel()));
+ ANGLE_TRY(setCompleteTexStorage(context, storage.get()));
+ storage.release();
+ mInternalFormat = internalFormat;
+ mImmutable = false;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureD3D_Buffer::syncState(const gl::Context *context,
+ const gl::Texture::DirtyBits &dirtyBits,
+ gl::Command source)
+{
+ ASSERT(mState.getType() == gl::TextureType::Buffer);
+ if (dirtyBits.test(gl::Texture::DirtyBitType::DIRTY_BIT_IMPLEMENTATION) &&
+ mState.getBuffer().get() != nullptr)
+ {
+ // buffer data have been changed. Buffer data may out of sync
+ // give up the old TexStorage, create a new one.
+ // this may not efficient, since staging buffer may be patially updated.
+ ANGLE_TRY(setBuffer(context, mInternalFormat));
+ }
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/TextureD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/TextureD3D.h
new file mode 100644
index 0000000000..a87806b3e7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/TextureD3D.h
@@ -0,0 +1,1050 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureD3D.h: Implementations of the Texture interfaces shared betweeen the D3D backends.
+
+#ifndef LIBANGLE_RENDERER_D3D_TEXTURED3D_H_
+#define LIBANGLE_RENDERER_D3D_TEXTURED3D_H_
+
+#include "common/Color.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/TextureImpl.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class EGLImageD3D;
+class ImageD3D;
+class RendererD3D;
+class RenderTargetD3D;
+class TextureStorage;
+
+class TextureD3D : public TextureImpl, public angle::ObserverInterface
+{
+ public:
+ TextureD3D(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D() override;
+
+ void onDestroy(const gl::Context *context) override;
+
+ angle::Result getNativeTexture(const gl::Context *context, TextureStorage **outStorage);
+
+ bool hasDirtyImages() const { return mDirtyImages; }
+ void resetDirty() { mDirtyImages = false; }
+
+ virtual ImageD3D *getImage(const gl::ImageIndex &index) const = 0;
+ virtual GLsizei getLayerCount(int level) const = 0;
+
+ angle::Result getImageAndSyncFromStorage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ ImageD3D **outImage);
+
+ GLint getBaseLevelWidth() const;
+ GLint getBaseLevelHeight() const;
+ GLenum getBaseLevelInternalFormat() const;
+
+ angle::Result setStorage(const gl::Context *context,
+ gl::TextureType type,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) override;
+
+ angle::Result setStorageMultisample(const gl::Context *context,
+ gl::TextureType type,
+ GLsizei samples,
+ GLint internalformat,
+ const gl::Extents &size,
+ bool fixedSampleLocations) override;
+
+ angle::Result setBuffer(const gl::Context *context, GLenum internalFormat) override;
+
+ angle::Result setStorageExternalMemory(const gl::Context *context,
+ gl::TextureType type,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ gl::MemoryObject *memoryObject,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext) override;
+
+ bool isImmutable() const { return mImmutable; }
+
+ virtual angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) = 0;
+
+ // Returns an iterator over all "Images" for this particular Texture.
+ virtual gl::ImageIndexIterator imageIterator() const = 0;
+
+ // Returns an ImageIndex for a particular "Image". 3D Textures do not have images for
+ // slices of their depth texures, so 3D textures ignore the layer parameter.
+ virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const = 0;
+ virtual bool isValidIndex(const gl::ImageIndex &index) const = 0;
+
+ angle::Result setImageExternal(const gl::Context *context,
+ gl::TextureType type,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) override;
+ angle::Result generateMipmap(const gl::Context *context) override;
+ bool hasStorage() const { return mTexStorage != nullptr; }
+ TextureStorage *getStorage();
+ ImageD3D *getBaseLevelImage() const;
+
+ angle::Result getAttachmentRenderTarget(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
+ GLsizei samples,
+ FramebufferAttachmentRenderTarget **rtOut) override;
+
+ angle::Result setBaseLevel(const gl::Context *context, GLuint baseLevel) override;
+
+ angle::Result syncState(const gl::Context *context,
+ const gl::Texture::DirtyBits &dirtyBits,
+ gl::Command source) override;
+
+ angle::Result initializeContents(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex) override;
+
+ GLsizei getRenderToTextureSamples();
+
+ angle::Result ensureUnorderedAccess(const gl::Context *context);
+ angle::Result onLabelUpdate(const gl::Context *context) override;
+
+ // ObserverInterface implementation.
+ void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
+
+ protected:
+ angle::Result setImageImpl(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels,
+ ptrdiff_t layerOffset);
+ angle::Result subImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels,
+ ptrdiff_t layerOffset);
+ angle::Result setCompressedImageImpl(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels,
+ ptrdiff_t layerOffset);
+ angle::Result subImageCompressed(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels,
+ ptrdiff_t layerOffset);
+ bool isFastUnpackable(const gl::Buffer *unpackBuffer,
+ const gl::PixelUnpackState &unpack,
+ GLenum sizedInternalFormat);
+ angle::Result fastUnpackPixels(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels,
+ const gl::Box &destArea,
+ GLenum sizedInternalFormat,
+ GLenum type,
+ RenderTargetD3D *destRenderTarget);
+
+ GLint getLevelZeroWidth() const;
+ GLint getLevelZeroHeight() const;
+ virtual GLint getLevelZeroDepth() const;
+
+ GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const;
+ virtual angle::Result initMipmapImages(const gl::Context *context) = 0;
+ bool isBaseImageZeroSize() const;
+ virtual bool isImageComplete(const gl::ImageIndex &index) const = 0;
+
+ bool canCreateRenderTargetForImage(const gl::ImageIndex &index) const;
+ angle::Result ensureBindFlags(const gl::Context *context, BindFlags bindFlags);
+ angle::Result ensureRenderTarget(const gl::Context *context);
+
+ virtual angle::Result createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outTexStorage) const = 0;
+ virtual angle::Result setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) = 0;
+ angle::Result commitRegion(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &region);
+
+ angle::Result releaseTexStorage(const gl::Context *context,
+ const gl::TexLevelMask &copyStorageToImagesMask);
+
+ GLuint getBaseLevel() const { return mBaseLevel; }
+
+ virtual void markAllImagesDirty() = 0;
+
+ GLint getBaseLevelDepth() const;
+
+ RendererD3D *mRenderer;
+
+ bool mDirtyImages;
+
+ bool mImmutable;
+ TextureStorage *mTexStorage;
+ angle::ObserverBinding mTexStorageObserverBinding;
+
+ private:
+ virtual angle::Result initializeStorage(const gl::Context *context, BindFlags bindFlags) = 0;
+
+ virtual angle::Result updateStorage(const gl::Context *context) = 0;
+
+ bool couldUseSetData() const;
+ bool shouldUseSetData(const ImageD3D *image) const;
+
+ angle::Result generateMipmapUsingImages(const gl::Context *context, const GLuint maxLevel);
+
+ GLuint mBaseLevel;
+};
+
+class TextureD3D_2D : public TextureD3D
+{
+ public:
+ TextureD3D_2D(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D_2D() override;
+
+ void onDestroy(const gl::Context *context) override;
+
+ ImageD3D *getImage(int level, int layer) const;
+ ImageD3D *getImage(const gl::ImageIndex &index) const override;
+ GLsizei getLayerCount(int level) const override;
+
+ GLsizei getWidth(GLint level) const;
+ GLsizei getHeight(GLint level) const;
+ GLenum getInternalFormat(GLint level) const;
+ bool isDepth(GLint level) const;
+ bool isSRGB(GLint level) const;
+
+ angle::Result setImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels) override;
+ angle::Result setSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels) override;
+
+ angle::Result setCompressedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+ angle::Result setCompressedSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+
+ angle::Result copyImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ gl::Framebuffer *source) override;
+ angle::Result copySubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ gl::Framebuffer *source) override;
+
+ angle::Result copyTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ GLenum type,
+ GLint sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source) override;
+ angle::Result copySubTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ GLint sourceLevel,
+ const gl::Box &sourceBox,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source) override;
+ angle::Result copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source) override;
+
+ angle::Result setStorage(const gl::Context *context,
+ gl::TextureType type,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) override;
+
+ angle::Result bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+ angle::Result releaseTexImage(const gl::Context *context) override;
+
+ angle::Result setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image) override;
+
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ gl::ImageIndexIterator imageIterator() const override;
+ gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+ bool isValidIndex(const gl::ImageIndex &index) const override;
+
+ protected:
+ void markAllImagesDirty() override;
+
+ private:
+ angle::Result initializeStorage(const gl::Context *context, BindFlags bindFlags) override;
+ angle::Result createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outTexStorage) const override;
+ angle::Result setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) override;
+
+ angle::Result updateStorage(const gl::Context *context) override;
+ angle::Result initMipmapImages(const gl::Context *context) override;
+
+ bool isValidLevel(int level) const;
+ bool isLevelComplete(int level) const;
+ bool isImageComplete(const gl::ImageIndex &index) const override;
+
+ angle::Result updateStorageLevel(const gl::Context *context, int level);
+
+ angle::Result redefineImage(const gl::Context *context,
+ size_t level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease);
+
+ bool mEGLImageTarget;
+ gl::TexLevelArray<std::unique_ptr<ImageD3D>> mImageArray;
+};
+
+class TextureD3D_Cube : public TextureD3D
+{
+ public:
+ TextureD3D_Cube(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D_Cube() override;
+
+ void onDestroy(const gl::Context *context) override;
+
+ ImageD3D *getImage(int level, int layer) const;
+ ImageD3D *getImage(const gl::ImageIndex &index) const override;
+ GLsizei getLayerCount(int level) const override;
+
+ GLenum getInternalFormat(GLint level, GLint layer) const;
+ bool isDepth(GLint level, GLint layer) const;
+ bool isSRGB(GLint level, GLint layer) const;
+
+ angle::Result setImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels) override;
+ angle::Result setSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels) override;
+
+ angle::Result setCompressedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+ angle::Result setCompressedSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+
+ angle::Result copyImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ gl::Framebuffer *source) override;
+ angle::Result copySubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ gl::Framebuffer *source) override;
+
+ angle::Result copyTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ GLenum type,
+ GLint sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source) override;
+ angle::Result copySubTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ GLint sourceLevel,
+ const gl::Box &sourceBox,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source) override;
+
+ angle::Result setStorage(const gl::Context *context,
+ gl::TextureType type,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) override;
+
+ angle::Result bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+ angle::Result releaseTexImage(const gl::Context *context) override;
+
+ angle::Result setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image) override;
+
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ gl::ImageIndexIterator imageIterator() const override;
+ gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+ bool isValidIndex(const gl::ImageIndex &index) const override;
+
+ protected:
+ void markAllImagesDirty() override;
+
+ private:
+ angle::Result initializeStorage(const gl::Context *context, BindFlags bindFlags) override;
+ angle::Result createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outTexStorage) const override;
+ angle::Result setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) override;
+
+ angle::Result updateStorage(const gl::Context *context) override;
+ angle::Result initMipmapImages(const gl::Context *context) override;
+
+ bool isValidFaceLevel(int faceIndex, int level) const;
+ bool isFaceLevelComplete(int faceIndex, int level) const;
+ bool isCubeComplete() const;
+ bool isImageComplete(const gl::ImageIndex &index) const override;
+ angle::Result updateStorageFaceLevel(const gl::Context *context, int faceIndex, int level);
+
+ angle::Result redefineImage(const gl::Context *context,
+ int faceIndex,
+ GLint level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease);
+
+ std::array<gl::TexLevelArray<std::unique_ptr<ImageD3D>>, 6> mImageArray;
+};
+
+class TextureD3D_3D : public TextureD3D
+{
+ public:
+ TextureD3D_3D(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D_3D() override;
+
+ void onDestroy(const gl::Context *context) override;
+
+ ImageD3D *getImage(int level, int layer) const;
+ ImageD3D *getImage(const gl::ImageIndex &index) const override;
+ GLsizei getLayerCount(int level) const override;
+
+ GLsizei getWidth(GLint level) const;
+ GLsizei getHeight(GLint level) const;
+ GLsizei getDepth(GLint level) const;
+ GLenum getInternalFormat(GLint level) const;
+ bool isDepth(GLint level) const;
+ bool isSRGB(GLint level) const;
+
+ angle::Result setImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels) override;
+ angle::Result setSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels) override;
+
+ angle::Result setCompressedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+ angle::Result setCompressedSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+
+ angle::Result copyImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ gl::Framebuffer *source) override;
+ angle::Result copySubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ gl::Framebuffer *source) override;
+
+ angle::Result copyTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ GLenum type,
+ GLint sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source) override;
+ angle::Result copySubTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ GLint sourceLevel,
+ const gl::Box &sourceBox,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source) override;
+
+ angle::Result setStorage(const gl::Context *context,
+ gl::TextureType type,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) override;
+
+ angle::Result bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+ angle::Result releaseTexImage(const gl::Context *context) override;
+
+ angle::Result setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image) override;
+
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ gl::ImageIndexIterator imageIterator() const override;
+ gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+ bool isValidIndex(const gl::ImageIndex &index) const override;
+
+ protected:
+ void markAllImagesDirty() override;
+ GLint getLevelZeroDepth() const override;
+
+ private:
+ angle::Result initializeStorage(const gl::Context *context, BindFlags bindFlags) override;
+ angle::Result createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outStorage) const override;
+ angle::Result setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) override;
+
+ angle::Result updateStorage(const gl::Context *context) override;
+ angle::Result initMipmapImages(const gl::Context *context) override;
+
+ bool isValidLevel(int level) const;
+ bool isLevelComplete(int level) const;
+ bool isImageComplete(const gl::ImageIndex &index) const override;
+ angle::Result updateStorageLevel(const gl::Context *context, int level);
+
+ angle::Result redefineImage(const gl::Context *context,
+ GLint level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease);
+
+ gl::TexLevelArray<std::unique_ptr<ImageD3D>> mImageArray;
+};
+
+class TextureD3D_2DArray : public TextureD3D
+{
+ public:
+ TextureD3D_2DArray(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D_2DArray() override;
+
+ void onDestroy(const gl::Context *context) override;
+
+ virtual ImageD3D *getImage(int level, int layer) const;
+ ImageD3D *getImage(const gl::ImageIndex &index) const override;
+ GLsizei getLayerCount(int level) const override;
+
+ GLsizei getWidth(GLint level) const;
+ GLsizei getHeight(GLint level) const;
+ GLenum getInternalFormat(GLint level) const;
+ bool isDepth(GLint level) const;
+
+ angle::Result setImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels) override;
+ angle::Result setSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels) override;
+
+ angle::Result setCompressedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+ angle::Result setCompressedSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+
+ angle::Result copyImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ gl::Framebuffer *source) override;
+ angle::Result copySubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ gl::Framebuffer *source) override;
+
+ angle::Result copyTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ GLenum type,
+ GLint sourceLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source) override;
+ angle::Result copySubTexture(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ GLint sourceLevel,
+ const gl::Box &sourceBox,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const gl::Texture *source) override;
+
+ angle::Result setStorage(const gl::Context *context,
+ gl::TextureType type,
+ size_t levels,
+ GLenum internalFormat,
+ const gl::Extents &size) override;
+
+ angle::Result bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+ angle::Result releaseTexImage(const gl::Context *context) override;
+
+ angle::Result setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image) override;
+
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ gl::ImageIndexIterator imageIterator() const override;
+ gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+ bool isValidIndex(const gl::ImageIndex &index) const override;
+
+ protected:
+ void markAllImagesDirty() override;
+
+ private:
+ angle::Result initializeStorage(const gl::Context *context, BindFlags bindFlags) override;
+ angle::Result createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outStorage) const override;
+ angle::Result setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) override;
+
+ angle::Result updateStorage(const gl::Context *context) override;
+ angle::Result initMipmapImages(const gl::Context *context) override;
+
+ bool isValidLevel(int level) const;
+ bool isLevelComplete(int level) const;
+ bool isImageComplete(const gl::ImageIndex &index) const override;
+ bool isSRGB(GLint level) const;
+ angle::Result updateStorageLevel(const gl::Context *context, int level);
+
+ void deleteImages();
+ angle::Result redefineImage(const gl::Context *context,
+ GLint level,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease);
+
+ // Storing images as an array of single depth textures since D3D11 treats each array level of a
+ // Texture2D object as a separate subresource. Each layer would have to be looped over
+ // to update all the texture layers since they cannot all be updated at once and it makes the
+ // most sense for the Image class to not have to worry about layer subresource as well as mip
+ // subresources.
+ GLsizei mLayerCounts[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ ImageD3D **mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+};
+
+// Base class for immutable textures. These don't support manipulation of individual texture images.
+class TextureD3DImmutableBase : public TextureD3D
+{
+ public:
+ TextureD3DImmutableBase(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3DImmutableBase() override;
+
+ ImageD3D *getImage(const gl::ImageIndex &index) const override;
+ angle::Result setImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels) override;
+ angle::Result setSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels) override;
+
+ angle::Result setCompressedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+ angle::Result setCompressedSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+
+ angle::Result copyImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ gl::Framebuffer *source) override;
+ angle::Result copySubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ gl::Framebuffer *source) override;
+
+ angle::Result bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+ angle::Result releaseTexImage(const gl::Context *context) override;
+};
+
+class TextureD3D_External : public TextureD3DImmutableBase
+{
+ public:
+ TextureD3D_External(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D_External() override;
+
+ GLsizei getLayerCount(int level) const override;
+
+ angle::Result setImageExternal(const gl::Context *context,
+ gl::TextureType type,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc) override;
+
+ angle::Result setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image) override;
+
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ gl::ImageIndexIterator imageIterator() const override;
+ gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+ bool isValidIndex(const gl::ImageIndex &index) const override;
+
+ protected:
+ void markAllImagesDirty() override;
+
+ private:
+ angle::Result initializeStorage(const gl::Context *context, BindFlags bindFlags) override;
+ angle::Result createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outTexStorage) const override;
+ angle::Result setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) override;
+
+ angle::Result updateStorage(const gl::Context *context) override;
+ angle::Result initMipmapImages(const gl::Context *context) override;
+
+ bool isImageComplete(const gl::ImageIndex &index) const override;
+};
+
+class TextureD3D_2DMultisample : public TextureD3DImmutableBase
+{
+ public:
+ TextureD3D_2DMultisample(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D_2DMultisample() override;
+
+ angle::Result setStorageMultisample(const gl::Context *context,
+ gl::TextureType type,
+ GLsizei samples,
+ GLint internalformat,
+ const gl::Extents &size,
+ bool fixedSampleLocations) override;
+
+ angle::Result setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image) override;
+
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ gl::ImageIndexIterator imageIterator() const override;
+ gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+ bool isValidIndex(const gl::ImageIndex &index) const override;
+
+ GLsizei getLayerCount(int level) const override;
+
+ protected:
+ void markAllImagesDirty() override;
+
+ angle::Result setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) override;
+
+ angle::Result updateStorage(const gl::Context *context) override;
+
+ private:
+ angle::Result initializeStorage(const gl::Context *context, BindFlags bindFlags) override;
+ angle::Result createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outTexStorage) const override;
+ angle::Result initMipmapImages(const gl::Context *context) override;
+
+ bool isImageComplete(const gl::ImageIndex &index) const override;
+};
+
+class TextureD3D_2DMultisampleArray : public TextureD3DImmutableBase
+{
+ public:
+ TextureD3D_2DMultisampleArray(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D_2DMultisampleArray() override;
+
+ angle::Result setStorageMultisample(const gl::Context *context,
+ gl::TextureType type,
+ GLsizei samples,
+ GLint internalformat,
+ const gl::Extents &size,
+ bool fixedSampleLocations) override;
+
+ angle::Result setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image) override;
+
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ gl::ImageIndexIterator imageIterator() const override;
+ gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+ bool isValidIndex(const gl::ImageIndex &index) const override;
+
+ GLsizei getLayerCount(int level) const override;
+
+ protected:
+ void markAllImagesDirty() override;
+
+ angle::Result setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) override;
+
+ angle::Result updateStorage(const gl::Context *context) override;
+
+ private:
+ angle::Result initializeStorage(const gl::Context *context, BindFlags bindFlags) override;
+ angle::Result createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outTexStorage) const override;
+ angle::Result initMipmapImages(const gl::Context *context) override;
+
+ bool isImageComplete(const gl::ImageIndex &index) const override;
+
+ GLsizei mLayerCount;
+};
+
+class TextureD3D_Buffer : public TextureD3D
+{
+ public:
+ TextureD3D_Buffer(const gl::TextureState &data, RendererD3D *renderer);
+ ~TextureD3D_Buffer() override;
+
+ ImageD3D *getImage(const gl::ImageIndex &index) const override;
+
+ angle::Result setBuffer(const gl::Context *context, GLenum internalFormat) override;
+
+ angle::Result setImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels) override;
+ angle::Result setSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ const uint8_t *pixels) override;
+
+ angle::Result setCompressedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLenum internalFormat,
+ const gl::Extents &size,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+ angle::Result setCompressedSubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ GLenum format,
+ const gl::PixelUnpackState &unpack,
+ size_t imageSize,
+ const uint8_t *pixels) override;
+
+ angle::Result copyImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Rectangle &sourceArea,
+ GLenum internalFormat,
+ gl::Framebuffer *source) override;
+ angle::Result copySubImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ gl::Framebuffer *source) override;
+
+ angle::Result bindTexImage(const gl::Context *context, egl::Surface *surface) override;
+ angle::Result releaseTexImage(const gl::Context *context) override;
+
+ angle::Result setEGLImageTarget(const gl::Context *context,
+ gl::TextureType type,
+ egl::Image *image) override;
+
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ GLsizei getLayerCount(int level) const override;
+
+ angle::Result syncState(const gl::Context *context,
+ const gl::Texture::DirtyBits &dirtyBits,
+ gl::Command source) override;
+
+ gl::ImageIndexIterator imageIterator() const override;
+ gl::ImageIndex getImageIndex(GLint mip, GLint layer) const override;
+ bool isValidIndex(const gl::ImageIndex &index) const override;
+
+ protected:
+ void markAllImagesDirty() override;
+
+ private:
+ angle::Result initializeStorage(const gl::Context *context, BindFlags bindFlags) override;
+ angle::Result createCompleteStorage(const gl::Context *context,
+ BindFlags bindFlags,
+ TexStoragePointer *outTexStorage) const override;
+ angle::Result setCompleteTexStorage(const gl::Context *context,
+ TextureStorage *newCompleteTexStorage) override;
+
+ angle::Result updateStorage(const gl::Context *context) override;
+ angle::Result initMipmapImages(const gl::Context *context) override;
+
+ bool isImageComplete(const gl::ImageIndex &index) const override;
+
+ GLenum mInternalFormat;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_TEXTURED3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/TextureStorage.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/TextureStorage.h
new file mode 100644
index 0000000000..fc073f8b5a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/TextureStorage.h
@@ -0,0 +1,135 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureStorage.h: Defines the abstract rx::TextureStorage class.
+
+#ifndef LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
+#define LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
+
+#include "common/debug.h"
+#include "libANGLE/angletypes.h"
+
+#include <GLES2/gl2.h>
+#include <stdint.h>
+
+namespace gl
+{
+class Context;
+class ImageIndex;
+struct Box;
+struct PixelUnpackState;
+} // namespace gl
+
+namespace angle
+{
+class Subject;
+} // namespace angle
+
+namespace rx
+{
+class SwapChainD3D;
+class RenderTargetD3D;
+class ImageD3D;
+
+// Dirty bit messages from TextureStorage
+constexpr size_t kTextureStorageObserverMessageIndex = 0;
+
+class TextureStorage : public angle::Subject
+{
+ public:
+ TextureStorage(const std::string &label) : mKHRDebugLabel(label) {}
+ ~TextureStorage() override {}
+
+ virtual angle::Result onDestroy(const gl::Context *context);
+
+ virtual int getTopLevel() const = 0;
+ virtual bool isRenderTarget() const = 0;
+ virtual bool isUnorderedAccess() const = 0;
+ virtual bool isManaged() const = 0;
+ virtual bool supportsNativeMipmapFunction() const = 0;
+ virtual int getLevelCount() const = 0;
+
+ virtual angle::Result findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const = 0;
+ virtual angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) = 0;
+ virtual angle::Result generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex) = 0;
+
+ virtual angle::Result copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage) = 0;
+ virtual angle::Result setData(const gl::Context *context,
+ const gl::ImageIndex &index,
+ ImageD3D *image,
+ const gl::Box *destBox,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixelData) = 0;
+
+ // This is a no-op for most implementations of TextureStorage. Some (e.g. TextureStorage11_2D)
+ // might override it.
+ virtual angle::Result useLevelZeroWorkaroundTexture(const gl::Context *context,
+ bool useLevelZeroTexture);
+
+ virtual void invalidateTextures() {}
+
+ // RenderToTexture methods
+ virtual angle::Result releaseMultisampledTexStorageForLevel(size_t level);
+ virtual angle::Result resolveTexture(const gl::Context *context);
+ virtual GLsizei getRenderToTextureSamples() const;
+
+ // Called by outer object when label has changed via KHR_debug extension
+ void setLabel(const std::string &newLabel);
+
+ protected:
+ virtual void onLabelUpdate() {}
+
+ const angle::Subject *mSubject;
+ std::string mKHRDebugLabel;
+};
+
+inline angle::Result TextureStorage::onDestroy(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+inline angle::Result TextureStorage::useLevelZeroWorkaroundTexture(const gl::Context *context,
+ bool useLevelZeroTexture)
+{
+ return angle::Result::Continue;
+}
+
+inline angle::Result TextureStorage::releaseMultisampledTexStorageForLevel(size_t level)
+{
+ return angle::Result::Continue;
+}
+
+inline angle::Result TextureStorage::resolveTexture(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+inline GLsizei TextureStorage::getRenderToTextureSamples() const
+{
+ return 0;
+}
+
+inline void TextureStorage::setLabel(const std::string &newLabel)
+{
+ mKHRDebugLabel = newLabel;
+ onLabelUpdate();
+}
+
+using TexStoragePointer = angle::UniqueObjectPointer<TextureStorage, gl::Context>;
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexBuffer.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexBuffer.cpp
new file mode 100644
index 0000000000..acb27adfcc
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexBuffer.cpp
@@ -0,0 +1,308 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface
+// class with derivations, classes that perform graphics API agnostic vertex buffer operations.
+
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
+
+#include "common/mathutil.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/ContextD3D.h"
+
+namespace rx
+{
+
+// VertexBuffer Implementation
+unsigned int VertexBuffer::mNextSerial = 1;
+
+VertexBuffer::VertexBuffer() : mRefCount(1)
+{
+ updateSerial();
+}
+
+VertexBuffer::~VertexBuffer() {}
+
+void VertexBuffer::updateSerial()
+{
+ mSerial = mNextSerial++;
+}
+
+unsigned int VertexBuffer::getSerial() const
+{
+ return mSerial;
+}
+
+void VertexBuffer::addRef()
+{
+ mRefCount++;
+}
+
+void VertexBuffer::release()
+{
+ ASSERT(mRefCount > 0);
+ mRefCount--;
+
+ if (mRefCount == 0)
+ {
+ delete this;
+ }
+}
+
+// VertexBufferInterface Implementation
+VertexBufferInterface::VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic)
+ : mFactory(factory), mVertexBuffer(factory->createVertexBuffer()), mDynamic(dynamic)
+{}
+
+VertexBufferInterface::~VertexBufferInterface()
+{
+ if (mVertexBuffer)
+ {
+ mVertexBuffer->release();
+ mVertexBuffer = nullptr;
+ }
+}
+
+unsigned int VertexBufferInterface::getSerial() const
+{
+ ASSERT(mVertexBuffer);
+ return mVertexBuffer->getSerial();
+}
+
+unsigned int VertexBufferInterface::getBufferSize() const
+{
+ ASSERT(mVertexBuffer);
+ return mVertexBuffer->getBufferSize();
+}
+
+angle::Result VertexBufferInterface::setBufferSize(const gl::Context *context, unsigned int size)
+{
+ ASSERT(mVertexBuffer);
+ if (mVertexBuffer->getBufferSize() == 0)
+ {
+ return mVertexBuffer->initialize(context, size, mDynamic);
+ }
+
+ return mVertexBuffer->setBufferSize(context, size);
+}
+
+angle::Result VertexBufferInterface::getSpaceRequired(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance,
+ unsigned int *spaceInBytesOut) const
+{
+ unsigned int spaceRequired = 0;
+ ANGLE_TRY(mFactory->getVertexSpaceRequired(context, attrib, binding, count, instances,
+ baseInstance, &spaceRequired));
+
+ // Align to 16-byte boundary
+ unsigned int alignedSpaceRequired = roundUpPow2(spaceRequired, 16u);
+ ANGLE_CHECK_GL_ALLOC(GetImplAs<ContextD3D>(context), alignedSpaceRequired >= spaceRequired);
+
+ *spaceInBytesOut = alignedSpaceRequired;
+ return angle::Result::Continue;
+}
+
+angle::Result VertexBufferInterface::discard(const gl::Context *context)
+{
+ ASSERT(mVertexBuffer);
+ return mVertexBuffer->discard(context);
+}
+
+VertexBuffer *VertexBufferInterface::getVertexBuffer() const
+{
+ ASSERT(mVertexBuffer);
+ return mVertexBuffer;
+}
+
+// StreamingVertexBufferInterface Implementation
+StreamingVertexBufferInterface::StreamingVertexBufferInterface(BufferFactoryD3D *factory)
+ : VertexBufferInterface(factory, true), mWritePosition(0), mReservedSpace(0)
+{}
+
+angle::Result StreamingVertexBufferInterface::initialize(const gl::Context *context,
+ std::size_t initialSize)
+{
+ return setBufferSize(context, static_cast<unsigned int>(initialSize));
+}
+
+void StreamingVertexBufferInterface::reset()
+{
+ if (mVertexBuffer)
+ {
+ mVertexBuffer->release();
+ mVertexBuffer = mFactory->createVertexBuffer();
+ }
+}
+
+StreamingVertexBufferInterface::~StreamingVertexBufferInterface() {}
+
+angle::Result StreamingVertexBufferInterface::reserveSpace(const gl::Context *context,
+ unsigned int size)
+{
+ unsigned int curBufferSize = getBufferSize();
+ if (size > curBufferSize)
+ {
+ ANGLE_TRY(setBufferSize(context, std::max(size, 3 * curBufferSize / 2)));
+ mWritePosition = 0;
+ }
+ else if (mWritePosition + size > curBufferSize)
+ {
+ ANGLE_TRY(discard(context));
+ mWritePosition = 0;
+ }
+
+ mReservedSpace = size;
+ return angle::Result::Continue;
+}
+
+angle::Result StreamingVertexBufferInterface::storeDynamicAttribute(
+ const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ gl::VertexAttribType currentValueType,
+ GLint start,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance,
+ unsigned int *outStreamOffset,
+ const uint8_t *sourceData)
+{
+ unsigned int spaceRequired = 0;
+ ANGLE_TRY(
+ getSpaceRequired(context, attrib, binding, count, instances, baseInstance, &spaceRequired));
+
+ // Protect against integer overflow
+ angle::CheckedNumeric<unsigned int> checkedPosition(mWritePosition);
+ checkedPosition += spaceRequired;
+ ANGLE_CHECK_GL_ALLOC(GetImplAs<ContextD3D>(context), checkedPosition.IsValid());
+
+ mReservedSpace = 0;
+
+ size_t adjustedCount = count;
+ GLuint divisor = binding.getDivisor();
+
+ if (instances != 0 && divisor != 0)
+ {
+ // The attribute is an instanced attribute and it's an draw instance call
+ // Extra number of elements are copied at the beginning to make sure
+ // the driver is referencing the correct data with non-zero baseInstance
+ adjustedCount += UnsignedCeilDivide(baseInstance, divisor);
+ }
+
+ ANGLE_TRY(mVertexBuffer->storeVertexAttributes(context, attrib, binding, currentValueType,
+ start, adjustedCount, instances, mWritePosition,
+ sourceData));
+
+ if (outStreamOffset)
+ {
+ *outStreamOffset = mWritePosition;
+ }
+
+ mWritePosition += spaceRequired;
+
+ return angle::Result::Continue;
+}
+
+angle::Result StreamingVertexBufferInterface::reserveVertexSpace(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance)
+{
+ unsigned int requiredSpace = 0;
+ ANGLE_TRY(mFactory->getVertexSpaceRequired(context, attrib, binding, count, instances,
+ baseInstance, &requiredSpace));
+
+ // Align to 16-byte boundary
+ auto alignedRequiredSpace = rx::CheckedRoundUp(requiredSpace, 16u);
+ alignedRequiredSpace += mReservedSpace;
+
+ // Protect against integer overflow
+ ANGLE_CHECK_GL_ALLOC(GetImplAs<ContextD3D>(context), alignedRequiredSpace.IsValid());
+
+ ANGLE_TRY(reserveSpace(context, alignedRequiredSpace.ValueOrDie()));
+
+ return angle::Result::Continue;
+}
+
+// StaticVertexBufferInterface Implementation
+StaticVertexBufferInterface::AttributeSignature::AttributeSignature()
+ : formatID(angle::FormatID::NONE), stride(0), offset(0)
+{}
+
+bool StaticVertexBufferInterface::AttributeSignature::matchesAttribute(
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding) const
+{
+ size_t attribStride = ComputeVertexAttributeStride(attrib, binding);
+
+ if (formatID != attrib.format->id || static_cast<GLuint>(stride) != attribStride)
+ {
+ return false;
+ }
+
+ size_t attribOffset =
+ (static_cast<size_t>(ComputeVertexAttributeOffset(attrib, binding)) % attribStride);
+ return (offset == attribOffset);
+}
+
+void StaticVertexBufferInterface::AttributeSignature::set(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding)
+{
+ formatID = attrib.format->id;
+ offset = stride = static_cast<GLuint>(ComputeVertexAttributeStride(attrib, binding));
+ offset = static_cast<size_t>(ComputeVertexAttributeOffset(attrib, binding)) %
+ ComputeVertexAttributeStride(attrib, binding);
+}
+
+StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory)
+ : VertexBufferInterface(factory, false)
+{}
+
+StaticVertexBufferInterface::~StaticVertexBufferInterface() {}
+
+bool StaticVertexBufferInterface::matchesAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding) const
+{
+ return mSignature.matchesAttribute(attrib, binding);
+}
+
+void StaticVertexBufferInterface::setAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding)
+{
+ return mSignature.set(attrib, binding);
+}
+
+angle::Result StaticVertexBufferInterface::storeStaticAttribute(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ const uint8_t *sourceData)
+{
+ unsigned int spaceRequired = 0;
+ ANGLE_TRY(getSpaceRequired(context, attrib, binding, count, instances, 0, &spaceRequired));
+ ANGLE_TRY(setBufferSize(context, spaceRequired));
+
+ ASSERT(attrib.enabled);
+ ANGLE_TRY(mVertexBuffer->storeVertexAttributes(context, attrib, binding,
+ gl::VertexAttribType::InvalidEnum, start, count,
+ instances, 0, sourceData));
+
+ mSignature.set(attrib, binding);
+ mVertexBuffer->hintUnmapResource();
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexBuffer.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexBuffer.h
new file mode 100644
index 0000000000..45a16c6bf5
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexBuffer.h
@@ -0,0 +1,189 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexBuffer.h: Defines the abstract VertexBuffer class and VertexBufferInterface
+// class with derivations, classes that perform graphics API agnostic vertex buffer operations.
+
+#ifndef LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_
+#define LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_
+
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/Format.h"
+
+#include <GLES2/gl2.h>
+
+#include <cstddef>
+#include <cstdint>
+#include <vector>
+
+namespace gl
+{
+class Context;
+struct VertexAttribute;
+class VertexBinding;
+struct VertexAttribCurrentValueData;
+} // namespace gl
+
+namespace rx
+{
+class BufferFactoryD3D;
+
+// Use a ref-counting scheme with self-deletion on release. We do this so that we can more
+// easily manage the static buffer cache, without deleting currently bound buffers.
+class VertexBuffer : angle::NonCopyable
+{
+ public:
+ VertexBuffer();
+
+ virtual angle::Result initialize(const gl::Context *context,
+ unsigned int size,
+ bool dynamicUsage) = 0;
+
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+ // function.
+ virtual angle::Result storeVertexAttributes(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ gl::VertexAttribType currentValueType,
+ GLint start,
+ size_t count,
+ GLsizei instances,
+ unsigned int offset,
+ const uint8_t *sourceData) = 0;
+
+ virtual unsigned int getBufferSize() const = 0;
+ virtual angle::Result setBufferSize(const gl::Context *context, unsigned int size) = 0;
+ virtual angle::Result discard(const gl::Context *context) = 0;
+
+ unsigned int getSerial() const;
+
+ // This may be overridden (e.g. by VertexBuffer11) if necessary.
+ virtual void hintUnmapResource() {}
+
+ // Reference counting.
+ void addRef();
+ void release();
+
+ protected:
+ void updateSerial();
+ virtual ~VertexBuffer();
+
+ private:
+ unsigned int mSerial;
+ static unsigned int mNextSerial;
+ unsigned int mRefCount;
+};
+
+class VertexBufferInterface : angle::NonCopyable
+{
+ public:
+ VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic);
+ virtual ~VertexBufferInterface();
+
+ unsigned int getBufferSize() const;
+ bool empty() const { return getBufferSize() == 0; }
+
+ unsigned int getSerial() const;
+
+ VertexBuffer *getVertexBuffer() const;
+
+ protected:
+ angle::Result discard(const gl::Context *context);
+
+ angle::Result setBufferSize(const gl::Context *context, unsigned int size);
+
+ angle::Result getSpaceRequired(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance,
+ unsigned int *spaceInBytesOut) const;
+ BufferFactoryD3D *const mFactory;
+ VertexBuffer *mVertexBuffer;
+ bool mDynamic;
+};
+
+class StreamingVertexBufferInterface : public VertexBufferInterface
+{
+ public:
+ StreamingVertexBufferInterface(BufferFactoryD3D *factory);
+ ~StreamingVertexBufferInterface() override;
+
+ angle::Result initialize(const gl::Context *context, std::size_t initialSize);
+ void reset();
+
+ angle::Result storeDynamicAttribute(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ gl::VertexAttribType currentValueType,
+ GLint start,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance,
+ unsigned int *outStreamOffset,
+ const uint8_t *sourceData);
+
+ angle::Result reserveVertexSpace(const gl::Context *context,
+ const gl::VertexAttribute &attribute,
+ const gl::VertexBinding &binding,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance);
+
+ private:
+ angle::Result reserveSpace(const gl::Context *context, unsigned int size);
+
+ unsigned int mWritePosition;
+ unsigned int mReservedSpace;
+};
+
+class StaticVertexBufferInterface : public VertexBufferInterface
+{
+ public:
+ explicit StaticVertexBufferInterface(BufferFactoryD3D *factory);
+ ~StaticVertexBufferInterface() override;
+
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using these
+ // functions.
+ angle::Result storeStaticAttribute(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ GLint start,
+ GLsizei count,
+ GLsizei instances,
+ const uint8_t *sourceData);
+
+ bool matchesAttribute(const gl::VertexAttribute &attribute,
+ const gl::VertexBinding &binding) const;
+
+ void setAttribute(const gl::VertexAttribute &attribute, const gl::VertexBinding &binding);
+
+ private:
+ class AttributeSignature final : angle::NonCopyable
+ {
+ public:
+ AttributeSignature();
+
+ bool matchesAttribute(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding) const;
+
+ void set(const gl::VertexAttribute &attrib, const gl::VertexBinding &binding);
+
+ private:
+ angle::FormatID formatID;
+ GLuint stride;
+ size_t offset;
+ };
+
+ AttributeSignature mSignature;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexDataManager.cpp
new file mode 100644
index 0000000000..6b989c9e80
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexDataManager.cpp
@@ -0,0 +1,683 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexDataManager.h: Defines the VertexDataManager, a class that
+// runs the Buffer translation process.
+
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+
+#include "common/bitset_utils.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/ContextD3D.h"
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
+
+using namespace angle;
+
+namespace rx
+{
+namespace
+{
+enum
+{
+ INITIAL_STREAM_BUFFER_SIZE = 1024 * 1024
+};
+// This has to be at least 4k or else it fails on ATI cards.
+enum
+{
+ CONSTANT_VERTEX_BUFFER_SIZE = 4096
+};
+
+// Warning: ensure the binding matches attrib.bindingIndex before using these functions.
+int64_t GetMaxAttributeByteOffsetForDraw(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ int64_t elementCount)
+{
+ CheckedNumeric<int64_t> stride = ComputeVertexAttributeStride(attrib, binding);
+ CheckedNumeric<int64_t> offset = ComputeVertexAttributeOffset(attrib, binding);
+ CheckedNumeric<int64_t> size = ComputeVertexAttributeTypeSize(attrib);
+
+ ASSERT(elementCount > 0);
+
+ CheckedNumeric<int64_t> result =
+ stride * (CheckedNumeric<int64_t>(elementCount) - 1) + size + offset;
+ return result.ValueOrDefault(std::numeric_limits<int64_t>::max());
+}
+
+// Warning: ensure the binding matches attrib.bindingIndex before using these functions.
+int ElementsInBuffer(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ unsigned int size)
+{
+ angle::CheckedNumeric<int64_t> bufferSize(size);
+ angle::CheckedNumeric<int64_t> stride = ComputeVertexAttributeStride(attrib, binding);
+ angle::CheckedNumeric<int64_t> offset = ComputeVertexAttributeOffset(attrib, binding);
+ angle::CheckedNumeric<int64_t> elementSize = ComputeVertexAttributeTypeSize(attrib);
+
+ auto elementsInBuffer = (bufferSize - (offset % stride) + (stride - elementSize)) / stride;
+ auto elementsInBufferInt = elementsInBuffer.Cast<int>();
+
+ return elementsInBufferInt.ValueOrDefault(0);
+}
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+bool DirectStoragePossible(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding)
+{
+ // Current value attribs may not use direct storage.
+ if (!attrib.enabled)
+ {
+ return false;
+ }
+
+ gl::Buffer *buffer = binding.getBuffer().get();
+ if (!buffer)
+ {
+ return false;
+ }
+
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+ ASSERT(bufferD3D);
+ if (!bufferD3D->supportsDirectBinding())
+ {
+ return false;
+ }
+
+ // Alignment restrictions: In D3D, vertex data must be aligned to the format stride, or to a
+ // 4-byte boundary, whichever is smaller. (Undocumented, and experimentally confirmed)
+ size_t alignment = 4;
+
+ // TODO(jmadill): add VertexFormatCaps
+ BufferFactoryD3D *factory = bufferD3D->getFactory();
+
+ angle::FormatID vertexFormatID = attrib.format->id;
+
+ // CPU-converted vertex data must be converted (naturally).
+ if ((factory->getVertexConversionType(vertexFormatID) & VERTEX_CONVERT_CPU) != 0)
+ {
+ return false;
+ }
+
+ if (attrib.format->vertexAttribType != gl::VertexAttribType::Float)
+ {
+ unsigned int elementSize = 0;
+ angle::Result error =
+ factory->getVertexSpaceRequired(context, attrib, binding, 1, 0, 0, &elementSize);
+ ASSERT(error == angle::Result::Continue);
+ alignment = std::min<size_t>(elementSize, 4);
+ }
+
+ GLintptr offset = ComputeVertexAttributeOffset(attrib, binding);
+ // Final alignment check - unaligned data must be converted.
+ return (static_cast<size_t>(ComputeVertexAttributeStride(attrib, binding)) % alignment == 0) &&
+ (static_cast<size_t>(offset) % alignment == 0);
+}
+} // anonymous namespace
+
+TranslatedAttribute::TranslatedAttribute()
+ : active(false),
+ attribute(nullptr),
+ binding(nullptr),
+ currentValueType(gl::VertexAttribType::InvalidEnum),
+ baseOffset(0),
+ usesFirstVertexOffset(false),
+ stride(0),
+ vertexBuffer(),
+ storage(nullptr),
+ serial(0),
+ divisor(0)
+{}
+
+TranslatedAttribute::TranslatedAttribute(const TranslatedAttribute &other) = default;
+
+angle::Result TranslatedAttribute::computeOffset(const gl::Context *context,
+ GLint startVertex,
+ unsigned int *offsetOut) const
+{
+ if (!usesFirstVertexOffset)
+ {
+ *offsetOut = baseOffset;
+ return angle::Result::Continue;
+ }
+
+ CheckedNumeric<unsigned int> offset(baseOffset);
+ CheckedNumeric<unsigned int> checkedStride(stride);
+
+ offset += checkedStride * static_cast<unsigned int>(startVertex);
+ ANGLE_CHECK_GL_MATH(GetImplAs<ContextD3D>(context), offset.IsValid());
+ *offsetOut = offset.ValueOrDie();
+ return angle::Result::Continue;
+}
+
+// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+VertexStorageType ClassifyAttributeStorage(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding)
+{
+ // If attribute is disabled, we use the current value.
+ if (!attrib.enabled)
+ {
+ return VertexStorageType::CURRENT_VALUE;
+ }
+
+ // If specified with immediate data, we must use dynamic storage.
+ gl::Buffer *buffer = binding.getBuffer().get();
+ if (!buffer)
+ {
+ return VertexStorageType::DYNAMIC;
+ }
+
+ // Check if the buffer supports direct storage.
+ if (DirectStoragePossible(context, attrib, binding))
+ {
+ return VertexStorageType::DIRECT;
+ }
+
+ // Otherwise the storage is static or dynamic.
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+ ASSERT(bufferD3D);
+ switch (bufferD3D->getUsage())
+ {
+ case D3DBufferUsage::DYNAMIC:
+ return VertexStorageType::DYNAMIC;
+ case D3DBufferUsage::STATIC:
+ return VertexStorageType::STATIC;
+ default:
+ UNREACHABLE();
+ return VertexStorageType::UNKNOWN;
+ }
+}
+
+VertexDataManager::CurrentValueState::CurrentValueState(BufferFactoryD3D *factory)
+ : buffer(new StreamingVertexBufferInterface(factory)), offset(0)
+{
+ data.Values.FloatValues[0] = std::numeric_limits<float>::quiet_NaN();
+ data.Values.FloatValues[1] = std::numeric_limits<float>::quiet_NaN();
+ data.Values.FloatValues[2] = std::numeric_limits<float>::quiet_NaN();
+ data.Values.FloatValues[3] = std::numeric_limits<float>::quiet_NaN();
+ data.Type = gl::VertexAttribType::Float;
+}
+
+VertexDataManager::CurrentValueState::CurrentValueState(CurrentValueState &&other)
+{
+ std::swap(buffer, other.buffer);
+ std::swap(data, other.data);
+ std::swap(offset, other.offset);
+}
+
+VertexDataManager::CurrentValueState::~CurrentValueState() {}
+
+VertexDataManager::VertexDataManager(BufferFactoryD3D *factory)
+ : mFactory(factory), mStreamingBuffer(factory)
+{
+ mCurrentValueCache.reserve(gl::MAX_VERTEX_ATTRIBS);
+ for (int currentValueIndex = 0; currentValueIndex < gl::MAX_VERTEX_ATTRIBS; ++currentValueIndex)
+ {
+ mCurrentValueCache.emplace_back(factory);
+ }
+}
+
+VertexDataManager::~VertexDataManager() {}
+
+angle::Result VertexDataManager::initialize(const gl::Context *context)
+{
+ return mStreamingBuffer.initialize(context, INITIAL_STREAM_BUFFER_SIZE);
+}
+
+void VertexDataManager::deinitialize()
+{
+ mStreamingBuffer.reset();
+ mCurrentValueCache.clear();
+}
+
+angle::Result VertexDataManager::prepareVertexData(
+ const gl::Context *context,
+ GLint start,
+ GLsizei count,
+ std::vector<TranslatedAttribute> *translatedAttribs,
+ GLsizei instances)
+{
+ const gl::State &state = context->getState();
+ const gl::ProgramExecutable *executable = state.getProgramExecutable();
+ const gl::VertexArray *vertexArray = state.getVertexArray();
+ const auto &vertexAttributes = vertexArray->getVertexAttributes();
+ const auto &vertexBindings = vertexArray->getVertexBindings();
+
+ mDynamicAttribsMaskCache.reset();
+
+ translatedAttribs->clear();
+
+ for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex)
+ {
+ // Skip attrib locations the program doesn't use.
+ if (!executable->isAttribLocationActive(attribIndex))
+ continue;
+
+ const auto &attrib = vertexAttributes[attribIndex];
+ const auto &binding = vertexBindings[attrib.bindingIndex];
+
+ // Resize automatically puts in empty attribs
+ translatedAttribs->resize(attribIndex + 1);
+
+ TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex];
+ auto currentValueData = state.getVertexAttribCurrentValue(attribIndex);
+
+ // Record the attribute now
+ translated->active = true;
+ translated->attribute = &attrib;
+ translated->binding = &binding;
+ translated->currentValueType = currentValueData.Type;
+ translated->divisor = binding.getDivisor();
+
+ switch (ClassifyAttributeStorage(context, attrib, binding))
+ {
+ case VertexStorageType::STATIC:
+ {
+ // Store static attribute.
+ ANGLE_TRY(StoreStaticAttrib(context, translated));
+ break;
+ }
+ case VertexStorageType::DYNAMIC:
+ // Dynamic attributes must be handled together.
+ mDynamicAttribsMaskCache.set(attribIndex);
+ break;
+ case VertexStorageType::DIRECT:
+ // Update translated data for direct attributes.
+ StoreDirectAttrib(context, translated);
+ break;
+ case VertexStorageType::CURRENT_VALUE:
+ {
+ ANGLE_TRY(storeCurrentValue(context, currentValueData, translated, attribIndex));
+ break;
+ }
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+
+ if (mDynamicAttribsMaskCache.none())
+ {
+ return angle::Result::Continue;
+ }
+
+ // prepareVertexData is only called by Renderer9 which don't support baseInstance
+ ANGLE_TRY(storeDynamicAttribs(context, translatedAttribs, mDynamicAttribsMaskCache, start,
+ count, instances, 0u));
+
+ PromoteDynamicAttribs(context, *translatedAttribs, mDynamicAttribsMaskCache, count);
+
+ return angle::Result::Continue;
+}
+
+// static
+void VertexDataManager::StoreDirectAttrib(const gl::Context *context,
+ TranslatedAttribute *directAttrib)
+{
+ ASSERT(directAttrib->attribute && directAttrib->binding);
+ const auto &attrib = *directAttrib->attribute;
+ const auto &binding = *directAttrib->binding;
+
+ gl::Buffer *buffer = binding.getBuffer().get();
+ ASSERT(buffer);
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+
+ ASSERT(DirectStoragePossible(context, attrib, binding));
+ directAttrib->vertexBuffer.set(nullptr);
+ directAttrib->storage = bufferD3D;
+ directAttrib->serial = bufferD3D->getSerial();
+ directAttrib->stride = static_cast<unsigned int>(ComputeVertexAttributeStride(attrib, binding));
+ directAttrib->baseOffset =
+ static_cast<unsigned int>(ComputeVertexAttributeOffset(attrib, binding));
+
+ // Instanced vertices do not apply the 'start' offset
+ directAttrib->usesFirstVertexOffset = (binding.getDivisor() == 0);
+}
+
+// static
+angle::Result VertexDataManager::StoreStaticAttrib(const gl::Context *context,
+ TranslatedAttribute *translated)
+{
+ ASSERT(translated->attribute && translated->binding);
+ const auto &attrib = *translated->attribute;
+ const auto &binding = *translated->binding;
+
+ gl::Buffer *buffer = binding.getBuffer().get();
+ ASSERT(buffer && attrib.enabled && !DirectStoragePossible(context, attrib, binding));
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+
+ // Compute source data pointer
+ const uint8_t *sourceData = nullptr;
+ const int offset = static_cast<int>(ComputeVertexAttributeOffset(attrib, binding));
+
+ ANGLE_TRY(bufferD3D->getData(context, &sourceData));
+
+ if (sourceData)
+ {
+ sourceData += offset;
+ }
+
+ unsigned int streamOffset = 0;
+
+ translated->storage = nullptr;
+ ANGLE_TRY(bufferD3D->getFactory()->getVertexSpaceRequired(context, attrib, binding, 1, 0, 0,
+ &translated->stride));
+
+ auto *staticBuffer = bufferD3D->getStaticVertexBuffer(attrib, binding);
+ ASSERT(staticBuffer);
+
+ if (staticBuffer->empty())
+ {
+ // Convert the entire buffer
+ int totalCount =
+ ElementsInBuffer(attrib, binding, static_cast<unsigned int>(bufferD3D->getSize()));
+ int startIndex = offset / static_cast<int>(ComputeVertexAttributeStride(attrib, binding));
+
+ if (totalCount > 0)
+ {
+ ANGLE_TRY(staticBuffer->storeStaticAttribute(context, attrib, binding, -startIndex,
+ totalCount, 0, sourceData));
+ }
+ }
+
+ unsigned int firstElementOffset =
+ (static_cast<unsigned int>(offset) /
+ static_cast<unsigned int>(ComputeVertexAttributeStride(attrib, binding))) *
+ translated->stride;
+
+ VertexBuffer *vertexBuffer = staticBuffer->getVertexBuffer();
+
+ CheckedNumeric<unsigned int> checkedOffset(streamOffset);
+ checkedOffset += firstElementOffset;
+
+ ANGLE_CHECK_GL_MATH(GetImplAs<ContextD3D>(context), checkedOffset.IsValid());
+
+ translated->vertexBuffer.set(vertexBuffer);
+ translated->serial = vertexBuffer->getSerial();
+ translated->baseOffset = streamOffset + firstElementOffset;
+
+ // Instanced vertices do not apply the 'start' offset
+ translated->usesFirstVertexOffset = (binding.getDivisor() == 0);
+
+ return angle::Result::Continue;
+}
+
+angle::Result VertexDataManager::storeDynamicAttribs(
+ const gl::Context *context,
+ std::vector<TranslatedAttribute> *translatedAttribs,
+ const gl::AttributesMask &dynamicAttribsMask,
+ GLint start,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance)
+{
+ // Instantiating this class will ensure the streaming buffer is never left mapped.
+ class StreamingBufferUnmapper final : NonCopyable
+ {
+ public:
+ StreamingBufferUnmapper(StreamingVertexBufferInterface *streamingBuffer)
+ : mStreamingBuffer(streamingBuffer)
+ {
+ ASSERT(mStreamingBuffer);
+ }
+ ~StreamingBufferUnmapper() { mStreamingBuffer->getVertexBuffer()->hintUnmapResource(); }
+
+ private:
+ StreamingVertexBufferInterface *mStreamingBuffer;
+ };
+
+ // Will trigger unmapping on return.
+ StreamingBufferUnmapper localUnmapper(&mStreamingBuffer);
+
+ // Reserve the required space for the dynamic buffers.
+ for (auto attribIndex : dynamicAttribsMask)
+ {
+ const auto &dynamicAttrib = (*translatedAttribs)[attribIndex];
+ ANGLE_TRY(
+ reserveSpaceForAttrib(context, dynamicAttrib, start, count, instances, baseInstance));
+ }
+
+ // Store dynamic attributes
+ for (auto attribIndex : dynamicAttribsMask)
+ {
+ auto *dynamicAttrib = &(*translatedAttribs)[attribIndex];
+ ANGLE_TRY(
+ storeDynamicAttrib(context, dynamicAttrib, start, count, instances, baseInstance));
+ }
+
+ return angle::Result::Continue;
+}
+
+void VertexDataManager::PromoteDynamicAttribs(
+ const gl::Context *context,
+ const std::vector<TranslatedAttribute> &translatedAttribs,
+ const gl::AttributesMask &dynamicAttribsMask,
+ size_t count)
+{
+ for (auto attribIndex : dynamicAttribsMask)
+ {
+ const auto &dynamicAttrib = translatedAttribs[attribIndex];
+ ASSERT(dynamicAttrib.attribute && dynamicAttrib.binding);
+ const auto &binding = *dynamicAttrib.binding;
+
+ gl::Buffer *buffer = binding.getBuffer().get();
+ if (buffer)
+ {
+ // Note: this multiplication can overflow. It should not be a security problem.
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+ size_t typeSize = ComputeVertexAttributeTypeSize(*dynamicAttrib.attribute);
+ bufferD3D->promoteStaticUsage(context, count * typeSize);
+ }
+ }
+}
+
+angle::Result VertexDataManager::reserveSpaceForAttrib(const gl::Context *context,
+ const TranslatedAttribute &translatedAttrib,
+ GLint start,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance)
+{
+ ASSERT(translatedAttrib.attribute && translatedAttrib.binding);
+ const auto &attrib = *translatedAttrib.attribute;
+ const auto &binding = *translatedAttrib.binding;
+
+ ASSERT(!DirectStoragePossible(context, attrib, binding));
+
+ gl::Buffer *buffer = binding.getBuffer().get();
+ BufferD3D *bufferD3D = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
+ ASSERT(!bufferD3D || bufferD3D->getStaticVertexBuffer(attrib, binding) == nullptr);
+
+ size_t totalCount = gl::ComputeVertexBindingElementCount(binding.getDivisor(), count,
+ static_cast<size_t>(instances));
+ // TODO(jiajia.qin@intel.com): force the index buffer to clamp any out of range indices instead
+ // of invalid operation here.
+ if (bufferD3D)
+ {
+ // Vertices do not apply the 'start' offset when the divisor is non-zero even when doing
+ // a non-instanced draw call
+ GLint firstVertexIndex = binding.getDivisor() > 0
+ ? UnsignedCeilDivide(baseInstance, binding.getDivisor())
+ : start;
+ int64_t maxVertexCount =
+ static_cast<int64_t>(firstVertexIndex) + static_cast<int64_t>(totalCount);
+
+ int64_t maxByte = GetMaxAttributeByteOffsetForDraw(attrib, binding, maxVertexCount);
+
+ ASSERT(bufferD3D->getSize() <= static_cast<size_t>(std::numeric_limits<int64_t>::max()));
+ ANGLE_CHECK(GetImplAs<ContextD3D>(context),
+ maxByte <= static_cast<int64_t>(bufferD3D->getSize()),
+ "Vertex buffer is not big enough for the draw call.", GL_INVALID_OPERATION);
+ }
+ return mStreamingBuffer.reserveVertexSpace(context, attrib, binding, totalCount, instances,
+ baseInstance);
+}
+
+angle::Result VertexDataManager::storeDynamicAttrib(const gl::Context *context,
+ TranslatedAttribute *translated,
+ GLint start,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance)
+{
+ ASSERT(translated->attribute && translated->binding);
+ const auto &attrib = *translated->attribute;
+ const auto &binding = *translated->binding;
+
+ gl::Buffer *buffer = binding.getBuffer().get();
+ ASSERT(buffer || attrib.pointer);
+ ASSERT(attrib.enabled);
+
+ BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
+
+ // Instanced vertices do not apply the 'start' offset
+ GLint firstVertexIndex =
+ (binding.getDivisor() > 0 ? UnsignedCeilDivide(baseInstance, binding.getDivisor()) : start);
+
+ // Compute source data pointer
+ const uint8_t *sourceData = nullptr;
+
+ if (buffer)
+ {
+ ANGLE_TRY(storage->getData(context, &sourceData));
+ sourceData += static_cast<int>(ComputeVertexAttributeOffset(attrib, binding));
+ }
+ else
+ {
+ // Attributes using client memory ignore the VERTEX_ATTRIB_BINDING state.
+ // https://www.opengl.org/registry/specs/ARB/vertex_attrib_binding.txt
+ sourceData = static_cast<const uint8_t *>(attrib.pointer);
+ }
+
+ unsigned int streamOffset = 0;
+
+ translated->storage = nullptr;
+ ANGLE_TRY(
+ mFactory->getVertexSpaceRequired(context, attrib, binding, 1, 0, 0, &translated->stride));
+
+ size_t totalCount = gl::ComputeVertexBindingElementCount(binding.getDivisor(), count,
+ static_cast<size_t>(instances));
+
+ ANGLE_TRY(mStreamingBuffer.storeDynamicAttribute(
+ context, attrib, binding, translated->currentValueType, firstVertexIndex,
+ static_cast<GLsizei>(totalCount), instances, baseInstance, &streamOffset, sourceData));
+
+ VertexBuffer *vertexBuffer = mStreamingBuffer.getVertexBuffer();
+
+ translated->vertexBuffer.set(vertexBuffer);
+ translated->serial = vertexBuffer->getSerial();
+ translated->baseOffset = streamOffset;
+ translated->usesFirstVertexOffset = false;
+
+ return angle::Result::Continue;
+}
+
+angle::Result VertexDataManager::storeCurrentValue(
+ const gl::Context *context,
+ const gl::VertexAttribCurrentValueData &currentValue,
+ TranslatedAttribute *translated,
+ size_t attribIndex)
+{
+ CurrentValueState *cachedState = &mCurrentValueCache[attribIndex];
+ StreamingVertexBufferInterface &buffer = *cachedState->buffer;
+
+ if (buffer.getBufferSize() == 0)
+ {
+ ANGLE_TRY(buffer.initialize(context, CONSTANT_VERTEX_BUFFER_SIZE));
+ }
+
+ if (cachedState->data != currentValue)
+ {
+ ASSERT(translated->attribute && translated->binding);
+ const auto &attrib = *translated->attribute;
+ const auto &binding = *translated->binding;
+
+ ANGLE_TRY(buffer.reserveVertexSpace(context, attrib, binding, 1, 0, 0));
+
+ const uint8_t *sourceData =
+ reinterpret_cast<const uint8_t *>(currentValue.Values.FloatValues);
+ unsigned int streamOffset;
+ ANGLE_TRY(buffer.storeDynamicAttribute(context, attrib, binding, currentValue.Type, 0, 1, 0,
+ 0, &streamOffset, sourceData));
+
+ buffer.getVertexBuffer()->hintUnmapResource();
+
+ cachedState->data = currentValue;
+ cachedState->offset = streamOffset;
+ }
+
+ translated->vertexBuffer.set(buffer.getVertexBuffer());
+
+ translated->storage = nullptr;
+ translated->serial = buffer.getSerial();
+ translated->divisor = 0;
+ translated->stride = 0;
+ translated->baseOffset = static_cast<unsigned int>(cachedState->offset);
+ translated->usesFirstVertexOffset = false;
+
+ return angle::Result::Continue;
+}
+
+// VertexBufferBinding implementation
+VertexBufferBinding::VertexBufferBinding() : mBoundVertexBuffer(nullptr) {}
+
+VertexBufferBinding::VertexBufferBinding(const VertexBufferBinding &other)
+ : mBoundVertexBuffer(other.mBoundVertexBuffer)
+{
+ if (mBoundVertexBuffer)
+ {
+ mBoundVertexBuffer->addRef();
+ }
+}
+
+VertexBufferBinding::~VertexBufferBinding()
+{
+ if (mBoundVertexBuffer)
+ {
+ mBoundVertexBuffer->release();
+ }
+}
+
+VertexBufferBinding &VertexBufferBinding::operator=(const VertexBufferBinding &other)
+{
+ mBoundVertexBuffer = other.mBoundVertexBuffer;
+ if (mBoundVertexBuffer)
+ {
+ mBoundVertexBuffer->addRef();
+ }
+ return *this;
+}
+
+void VertexBufferBinding::set(VertexBuffer *vertexBuffer)
+{
+ if (mBoundVertexBuffer == vertexBuffer)
+ return;
+
+ if (mBoundVertexBuffer)
+ {
+ mBoundVertexBuffer->release();
+ }
+ if (vertexBuffer)
+ {
+ vertexBuffer->addRef();
+ }
+
+ mBoundVertexBuffer = vertexBuffer;
+}
+
+VertexBuffer *VertexBufferBinding::get() const
+{
+ return mBoundVertexBuffer;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexDataManager.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexDataManager.h
new file mode 100644
index 0000000000..50400db027
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/VertexDataManager.h
@@ -0,0 +1,163 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexDataManager.h: Defines the VertexDataManager, a class that
+// runs the Buffer translation process.
+
+#ifndef LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_
+#define LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
+
+namespace gl
+{
+class State;
+struct VertexAttribute;
+class VertexBinding;
+struct VertexAttribCurrentValueData;
+} // namespace gl
+
+namespace rx
+{
+class BufferD3D;
+class BufferFactoryD3D;
+class StreamingVertexBufferInterface;
+class VertexBuffer;
+
+class VertexBufferBinding final
+{
+ public:
+ VertexBufferBinding();
+ VertexBufferBinding(const VertexBufferBinding &other);
+ ~VertexBufferBinding();
+
+ void set(VertexBuffer *vertexBuffer);
+ VertexBuffer *get() const;
+ VertexBufferBinding &operator=(const VertexBufferBinding &other);
+
+ private:
+ VertexBuffer *mBoundVertexBuffer;
+};
+
+struct TranslatedAttribute
+{
+ TranslatedAttribute();
+ TranslatedAttribute(const TranslatedAttribute &other);
+
+ // Computes the correct offset from baseOffset, usesFirstVertexOffset, stride and startVertex.
+ // Can throw an error on integer overflow.
+ angle::Result computeOffset(const gl::Context *context,
+ GLint startVertex,
+ unsigned int *offsetOut) const;
+
+ bool active;
+
+ const gl::VertexAttribute *attribute;
+ const gl::VertexBinding *binding;
+ gl::VertexAttribType currentValueType;
+ unsigned int baseOffset;
+ bool usesFirstVertexOffset;
+ unsigned int stride; // 0 means not to advance the read pointer at all
+
+ VertexBufferBinding vertexBuffer;
+ BufferD3D *storage;
+ unsigned int serial;
+ unsigned int divisor;
+};
+
+enum class VertexStorageType
+{
+ UNKNOWN,
+ STATIC, // Translate the vertex data once and re-use it.
+ DYNAMIC, // Translate the data every frame into a ring buffer.
+ DIRECT, // Bind a D3D buffer directly without any translation.
+ CURRENT_VALUE, // Use a single value for the attribute.
+};
+
+// Given a vertex attribute, return the type of storage it will use.
+VertexStorageType ClassifyAttributeStorage(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding);
+
+class VertexDataManager : angle::NonCopyable
+{
+ public:
+ VertexDataManager(BufferFactoryD3D *factory);
+ virtual ~VertexDataManager();
+
+ angle::Result initialize(const gl::Context *context);
+ void deinitialize();
+
+ angle::Result prepareVertexData(const gl::Context *context,
+ GLint start,
+ GLsizei count,
+ std::vector<TranslatedAttribute> *translatedAttribs,
+ GLsizei instances);
+
+ static void StoreDirectAttrib(const gl::Context *context, TranslatedAttribute *directAttrib);
+
+ static angle::Result StoreStaticAttrib(const gl::Context *context,
+ TranslatedAttribute *translated);
+
+ angle::Result storeDynamicAttribs(const gl::Context *context,
+ std::vector<TranslatedAttribute> *translatedAttribs,
+ const gl::AttributesMask &dynamicAttribsMask,
+ GLint start,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance);
+
+ // Promote static usage of dynamic buffers.
+ static void PromoteDynamicAttribs(const gl::Context *context,
+ const std::vector<TranslatedAttribute> &translatedAttribs,
+ const gl::AttributesMask &dynamicAttribsMask,
+ size_t count);
+
+ angle::Result storeCurrentValue(const gl::Context *context,
+ const gl::VertexAttribCurrentValueData &currentValue,
+ TranslatedAttribute *translated,
+ size_t attribIndex);
+
+ private:
+ struct CurrentValueState final : angle::NonCopyable
+ {
+ CurrentValueState(BufferFactoryD3D *factory);
+ CurrentValueState(CurrentValueState &&other);
+ ~CurrentValueState();
+
+ std::unique_ptr<StreamingVertexBufferInterface> buffer;
+ gl::VertexAttribCurrentValueData data;
+ size_t offset;
+ };
+
+ angle::Result reserveSpaceForAttrib(const gl::Context *context,
+ const TranslatedAttribute &translatedAttrib,
+ GLint start,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance);
+
+ angle::Result storeDynamicAttrib(const gl::Context *context,
+ TranslatedAttribute *translated,
+ GLint start,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance);
+
+ BufferFactoryD3D *const mFactory;
+
+ StreamingVertexBufferInterface mStreamingBuffer;
+ std::vector<CurrentValueState> mCurrentValueCache;
+ gl::AttributesMask mDynamicAttribsMaskCache;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
new file mode 100644
index 0000000000..b78ecc5dee
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
@@ -0,0 +1,1943 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Blit11.cpp: Texture copy utility class.
+
+#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
+
+#include <float.h>
+
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/trace.h"
+
+namespace rx
+{
+
+namespace
+{
+
+// Include inline shaders in the anonymous namespace to make sure no symbols are exported
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h"
+
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h"
+
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h"
+
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h"
+
+void StretchedBlitNearest_RowByRow(const gl::Box &sourceArea,
+ const gl::Box &destArea,
+ const gl::Rectangle &clippedDestArea,
+ const gl::Extents &sourceSize,
+ unsigned int sourceRowPitch,
+ unsigned int destRowPitch,
+ size_t pixelSize,
+ const uint8_t *sourceData,
+ uint8_t *destData)
+{
+ int srcHeightSubOne = (sourceArea.height - 1);
+ size_t copySize = pixelSize * clippedDestArea.width;
+ size_t srcOffset = sourceArea.x * pixelSize;
+ size_t destOffset = clippedDestArea.x * pixelSize;
+
+ for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++)
+ {
+ // TODO: Fix divide by zero when height == 1. http://anglebug.com/6099
+ float yPerc = static_cast<float>(y - destArea.y) / (destArea.height - 1);
+
+ // Interpolate using the original source rectangle to determine which row to sample from
+ // while clamping to the edges
+ unsigned int readRow = static_cast<unsigned int>(
+ gl::clamp(sourceArea.y + floor(yPerc * srcHeightSubOne + 0.5f), 0, srcHeightSubOne));
+ unsigned int writeRow = y;
+
+ const uint8_t *sourceRow = sourceData + readRow * sourceRowPitch + srcOffset;
+ uint8_t *destRow = destData + writeRow * destRowPitch + destOffset;
+ memcpy(destRow, sourceRow, copySize);
+ }
+}
+
+void StretchedBlitNearest_PixelByPixel(const gl::Box &sourceArea,
+ const gl::Box &destArea,
+ const gl::Rectangle &clippedDestArea,
+ const gl::Extents &sourceSize,
+ unsigned int sourceRowPitch,
+ unsigned int destRowPitch,
+ ptrdiff_t readOffset,
+ ptrdiff_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ const uint8_t *sourceData,
+ uint8_t *destData)
+{
+ auto xMax = clippedDestArea.x + clippedDestArea.width;
+ auto yMax = clippedDestArea.y + clippedDestArea.height;
+
+ for (int writeRow = clippedDestArea.y; writeRow < yMax; writeRow++)
+ {
+ // Interpolate using the original source rectangle to determine which row to sample from
+ // while clamping to the edges
+ float yPerc = static_cast<float>(writeRow - destArea.y) / (destArea.height - 1);
+ float yRounded = floor(yPerc * (sourceArea.height - 1) + 0.5f);
+ unsigned int readRow =
+ static_cast<unsigned int>(gl::clamp(sourceArea.y + yRounded, 0, sourceSize.height - 1));
+
+ for (int writeColumn = clippedDestArea.x; writeColumn < xMax; writeColumn++)
+ {
+ // Interpolate the original source rectangle to determine which column to sample
+ // from while clamping to the edges
+ float xPerc = static_cast<float>(writeColumn - destArea.x) / (destArea.width - 1);
+ float xRounded = floor(xPerc * (sourceArea.width - 1) + 0.5f);
+ unsigned int readColumn = static_cast<unsigned int>(
+ gl::clamp(sourceArea.x + xRounded, 0, sourceSize.width - 1));
+
+ const uint8_t *sourcePixel =
+ sourceData + readRow * sourceRowPitch + readColumn * srcPixelStride + readOffset;
+
+ uint8_t *destPixel =
+ destData + writeRow * destRowPitch + writeColumn * destPixelStride + writeOffset;
+
+ memcpy(destPixel, sourcePixel, copySize);
+ }
+ }
+}
+
+void StretchedBlitNearest(const gl::Box &sourceArea,
+ const gl::Box &destArea,
+ const gl::Rectangle &clipRect,
+ const gl::Extents &sourceSize,
+ unsigned int sourceRowPitch,
+ unsigned int destRowPitch,
+ ptrdiff_t readOffset,
+ ptrdiff_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ const uint8_t *sourceData,
+ uint8_t *destData)
+{
+ gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height);
+ if (!gl::ClipRectangle(clippedDestArea, clipRect, &clippedDestArea))
+ {
+ return;
+ }
+
+ // Determine if entire rows can be copied at once instead of each individual pixel. There
+ // must be no out of bounds lookups, whole rows copies, and no scale.
+ if (sourceArea.width == clippedDestArea.width && sourceArea.x >= 0 &&
+ sourceArea.x + sourceArea.width <= sourceSize.width && copySize == srcPixelStride &&
+ copySize == destPixelStride)
+ {
+ StretchedBlitNearest_RowByRow(sourceArea, destArea, clippedDestArea, sourceSize,
+ sourceRowPitch, destRowPitch, srcPixelStride, sourceData,
+ destData);
+ }
+ else
+ {
+ StretchedBlitNearest_PixelByPixel(sourceArea, destArea, clippedDestArea, sourceSize,
+ sourceRowPitch, destRowPitch, readOffset, writeOffset,
+ copySize, srcPixelStride, destPixelStride, sourceData,
+ destData);
+ }
+}
+
+using DepthStencilLoader = void(const float *, uint8_t *);
+
+void LoadDepth16(const float *source, uint8_t *dest)
+{
+ uint32_t convertedDepth = gl::floatToNormalized<16, uint32_t>(source[0]);
+ memcpy(dest, &convertedDepth, 2u);
+}
+
+void LoadDepth24(const float *source, uint8_t *dest)
+{
+ uint32_t convertedDepth = gl::floatToNormalized<24, uint32_t>(source[0]);
+ memcpy(dest, &convertedDepth, 3u);
+}
+
+void LoadStencilHelper(const float *source, uint8_t *dest)
+{
+ uint32_t convertedStencil = gl::getShiftedData<8, 0>(static_cast<uint32_t>(source[1]));
+ memcpy(dest, &convertedStencil, 1u);
+}
+
+void LoadStencil8(const float *source, uint8_t *dest)
+{
+ // STENCIL_INDEX8 is implemented with D24S8, with the depth bits unused. Writes zero for safety.
+ float zero = 0.0f;
+ LoadDepth24(&zero, &dest[0]);
+ LoadStencilHelper(source, &dest[3]);
+}
+
+void LoadDepth24Stencil8(const float *source, uint8_t *dest)
+{
+ LoadDepth24(source, &dest[0]);
+ LoadStencilHelper(source, &dest[3]);
+}
+
+void LoadDepth32F(const float *source, uint8_t *dest)
+{
+ memcpy(dest, source, sizeof(float));
+}
+
+void LoadDepth32FStencil8(const float *source, uint8_t *dest)
+{
+ LoadDepth32F(source, &dest[0]);
+ LoadStencilHelper(source, &dest[4]);
+}
+
+template <DepthStencilLoader loader>
+void CopyDepthStencil(const gl::Box &sourceArea,
+ const gl::Box &destArea,
+ const gl::Rectangle &clippedDestArea,
+ const gl::Extents &sourceSize,
+ unsigned int sourceRowPitch,
+ unsigned int destRowPitch,
+ ptrdiff_t readOffset,
+ ptrdiff_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ const uint8_t *sourceData,
+ uint8_t *destData)
+{
+ // No stretching or subregions are supported, only full blits.
+ ASSERT(sourceArea == destArea);
+ ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
+ sourceSize.depth == 1);
+ ASSERT(clippedDestArea.width == sourceSize.width &&
+ clippedDestArea.height == sourceSize.height);
+ ASSERT(readOffset == 0 && writeOffset == 0);
+ ASSERT(destArea.x == 0 && destArea.y == 0);
+
+ for (int row = 0; row < destArea.height; ++row)
+ {
+ for (int column = 0; column < destArea.width; ++column)
+ {
+ ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride;
+ const float *sourcePixel = reinterpret_cast<const float *>(sourceData + offset);
+
+ uint8_t *destPixel = destData + row * destRowPitch + column * destPixelStride;
+
+ loader(sourcePixel, destPixel);
+ }
+ }
+}
+
+void Depth32FStencil8ToDepth32F(const float *source, float *dest)
+{
+ *dest = *source;
+}
+
+void Depth24Stencil8ToDepth32F(const uint32_t *source, float *dest)
+{
+ uint32_t normDepth = source[0] & 0x00FFFFFF;
+ float floatDepth = gl::normalizedToFloat<24>(normDepth);
+ *dest = floatDepth;
+}
+
+void BlitD24S8ToD32F(const gl::Box &sourceArea,
+ const gl::Box &destArea,
+ const gl::Rectangle &clippedDestArea,
+ const gl::Extents &sourceSize,
+ unsigned int sourceRowPitch,
+ unsigned int destRowPitch,
+ ptrdiff_t readOffset,
+ ptrdiff_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ const uint8_t *sourceData,
+ uint8_t *destData)
+{
+ // No stretching or subregions are supported, only full blits.
+ ASSERT(sourceArea == destArea);
+ ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
+ sourceSize.depth == 1);
+ ASSERT(clippedDestArea.width == sourceSize.width &&
+ clippedDestArea.height == sourceSize.height);
+ ASSERT(readOffset == 0 && writeOffset == 0);
+ ASSERT(destArea.x == 0 && destArea.y == 0);
+
+ for (int row = 0; row < destArea.height; ++row)
+ {
+ for (int column = 0; column < destArea.width; ++column)
+ {
+ ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride;
+ const uint32_t *sourcePixel = reinterpret_cast<const uint32_t *>(sourceData + offset);
+
+ float *destPixel =
+ reinterpret_cast<float *>(destData + row * destRowPitch + column * destPixelStride);
+
+ Depth24Stencil8ToDepth32F(sourcePixel, destPixel);
+ }
+ }
+}
+
+void BlitD32FS8ToD32F(const gl::Box &sourceArea,
+ const gl::Box &destArea,
+ const gl::Rectangle &clippedDestArea,
+ const gl::Extents &sourceSize,
+ unsigned int sourceRowPitch,
+ unsigned int destRowPitch,
+ ptrdiff_t readOffset,
+ ptrdiff_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ const uint8_t *sourceData,
+ uint8_t *destData)
+{
+ // No stretching or subregions are supported, only full blits.
+ ASSERT(sourceArea == destArea);
+ ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
+ sourceSize.depth == 1);
+ ASSERT(clippedDestArea.width == sourceSize.width &&
+ clippedDestArea.height == sourceSize.height);
+ ASSERT(readOffset == 0 && writeOffset == 0);
+ ASSERT(destArea.x == 0 && destArea.y == 0);
+
+ for (int row = 0; row < destArea.height; ++row)
+ {
+ for (int column = 0; column < destArea.width; ++column)
+ {
+ ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride;
+ const float *sourcePixel = reinterpret_cast<const float *>(sourceData + offset);
+ float *destPixel =
+ reinterpret_cast<float *>(destData + row * destRowPitch + column * destPixelStride);
+
+ Depth32FStencil8ToDepth32F(sourcePixel, destPixel);
+ }
+ }
+}
+
+Blit11::BlitConvertFunction *GetCopyDepthStencilFunction(GLenum internalFormat)
+{
+ switch (internalFormat)
+ {
+ case GL_DEPTH_COMPONENT16:
+ return &CopyDepthStencil<LoadDepth16>;
+ case GL_DEPTH_COMPONENT24:
+ return &CopyDepthStencil<LoadDepth24>;
+ case GL_DEPTH_COMPONENT32F:
+ return &CopyDepthStencil<LoadDepth32F>;
+ case GL_STENCIL_INDEX8:
+ return &CopyDepthStencil<LoadStencil8>;
+ case GL_DEPTH24_STENCIL8:
+ return &CopyDepthStencil<LoadDepth24Stencil8>;
+ case GL_DEPTH32F_STENCIL8:
+ return &CopyDepthStencil<LoadDepth32FStencil8>;
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+
+inline void GenerateVertexCoords(const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ float *x1,
+ float *y1,
+ float *x2,
+ float *y2,
+ float *u1,
+ float *v1,
+ float *u2,
+ float *v2)
+{
+ *x1 = (destArea.x / float(destSize.width)) * 2.0f - 1.0f;
+ *y1 = ((destSize.height - destArea.y - destArea.height) / float(destSize.height)) * 2.0f - 1.0f;
+ *x2 = ((destArea.x + destArea.width) / float(destSize.width)) * 2.0f - 1.0f;
+ *y2 = ((destSize.height - destArea.y) / float(destSize.height)) * 2.0f - 1.0f;
+
+ *u1 = sourceArea.x / float(sourceSize.width);
+ *v1 = sourceArea.y / float(sourceSize.height);
+ *u2 = (sourceArea.x + sourceArea.width) / float(sourceSize.width);
+ *v2 = (sourceArea.y + sourceArea.height) / float(sourceSize.height);
+}
+
+void Write2DVertices(const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ void *outVertices,
+ unsigned int *outStride,
+ unsigned int *outVertexCount,
+ D3D11_PRIMITIVE_TOPOLOGY *outTopology)
+{
+ float x1, y1, x2, y2, u1, v1, u2, v2;
+ GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1,
+ &u2, &v2);
+
+ d3d11::PositionTexCoordVertex *vertices =
+ static_cast<d3d11::PositionTexCoordVertex *>(outVertices);
+
+ d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2);
+ d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1);
+ d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2);
+ d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1);
+
+ *outStride = sizeof(d3d11::PositionTexCoordVertex);
+ *outVertexCount = 4;
+ *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
+}
+
+void Write3DVertices(const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ void *outVertices,
+ unsigned int *outStride,
+ unsigned int *outVertexCount,
+ D3D11_PRIMITIVE_TOPOLOGY *outTopology)
+{
+ ASSERT(sourceSize.depth > 0 && destSize.depth > 0);
+
+ float x1, y1, x2, y2, u1, v1, u2, v2;
+ GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1,
+ &u2, &v2);
+
+ d3d11::PositionLayerTexCoord3DVertex *vertices =
+ static_cast<d3d11::PositionLayerTexCoord3DVertex *>(outVertices);
+
+ for (int i = 0; i < destSize.depth; i++)
+ {
+ float readDepth = (float)i / std::max(destSize.depth - 1, 1);
+
+ d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 0], x1, y1, i, u1, v2, readDepth);
+ d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 1], x1, y2, i, u1, v1, readDepth);
+ d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 2], x2, y1, i, u2, v2, readDepth);
+
+ d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 3], x1, y2, i, u1, v1, readDepth);
+ d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 4], x2, y2, i, u2, v1, readDepth);
+ d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 5], x2, y1, i, u2, v2, readDepth);
+ }
+
+ *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex);
+ *outVertexCount = destSize.depth * 6;
+ *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+}
+
+unsigned int GetSwizzleIndex(GLenum swizzle)
+{
+ unsigned int colorIndex = 0;
+
+ switch (swizzle)
+ {
+ case GL_RED:
+ colorIndex = 0;
+ break;
+ case GL_GREEN:
+ colorIndex = 1;
+ break;
+ case GL_BLUE:
+ colorIndex = 2;
+ break;
+ case GL_ALPHA:
+ colorIndex = 3;
+ break;
+ case GL_ZERO:
+ colorIndex = 4;
+ break;
+ case GL_ONE:
+ colorIndex = 5;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return colorIndex;
+}
+
+D3D11_BLEND_DESC GetAlphaMaskBlendStateDesc()
+{
+ D3D11_BLEND_DESC desc;
+ memset(&desc, 0, sizeof(desc));
+ desc.RenderTarget[0].BlendEnable = TRUE;
+ desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
+ desc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
+ desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
+ desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
+ desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
+ desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
+ desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED |
+ D3D11_COLOR_WRITE_ENABLE_GREEN |
+ D3D11_COLOR_WRITE_ENABLE_BLUE;
+ return desc;
+}
+
+D3D11_INPUT_ELEMENT_DESC quad2DLayout[] = {
+ {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
+ {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
+};
+
+D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = {
+ {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
+ {"LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
+ {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
+};
+
+DXGI_FORMAT GetStencilSRVFormat(const d3d11::Format &formatSet)
+{
+ switch (formatSet.texFormat)
+ {
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ return DXGI_FORMAT_X24_TYPELESS_G8_UINT;
+ default:
+ UNREACHABLE();
+ return DXGI_FORMAT_UNKNOWN;
+ }
+}
+
+} // namespace
+
+#include "libANGLE/renderer/d3d/d3d11/Blit11Helper_autogen.inc"
+
+Blit11::Shader::Shader() = default;
+
+Blit11::Shader::Shader(Shader &&other) = default;
+
+Blit11::Shader::~Shader() = default;
+
+Blit11::Shader &Blit11::Shader::operator=(Blit11::Shader &&other) = default;
+
+Blit11::Blit11(Renderer11 *renderer)
+ : mRenderer(renderer),
+ mResourcesInitialized(false),
+ mVertexBuffer(),
+ mPointSampler(),
+ mLinearSampler(),
+ mScissorEnabledRasterizerState(),
+ mScissorDisabledRasterizerState(),
+ mDepthStencilState(),
+ mQuad2DIL(quad2DLayout,
+ ArraySize(quad2DLayout),
+ g_VS_Passthrough2D,
+ ArraySize(g_VS_Passthrough2D),
+ "Blit11 2D input layout"),
+ mQuad2DVS(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), "Blit11 2D vertex shader"),
+ mDepthPS(g_PS_PassthroughDepth2D,
+ ArraySize(g_PS_PassthroughDepth2D),
+ "Blit11 2D depth pixel shader"),
+ mQuad3DIL(quad3DLayout,
+ ArraySize(quad3DLayout),
+ g_VS_Passthrough3D,
+ ArraySize(g_VS_Passthrough3D),
+ "Blit11 3D input layout"),
+ mQuad3DVS(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), "Blit11 3D vertex shader"),
+ mQuad3DGS(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), "Blit11 3D geometry shader"),
+ mAlphaMaskBlendState(GetAlphaMaskBlendStateDesc(), "Blit11 Alpha Mask Blend"),
+ mSwizzleCB(),
+ mResolveDepthStencilVS(g_VS_ResolveDepthStencil,
+ ArraySize(g_VS_ResolveDepthStencil),
+ "Blit11::mResolveDepthStencilVS"),
+ mResolveDepthPS(g_PS_ResolveDepth, ArraySize(g_PS_ResolveDepth), "Blit11::mResolveDepthPS"),
+ mResolveDepthStencilPS(g_PS_ResolveDepthStencil,
+ ArraySize(g_PS_ResolveDepthStencil),
+ "Blit11::mResolveDepthStencilPS"),
+ mResolveStencilPS(g_PS_ResolveStencil,
+ ArraySize(g_PS_ResolveStencil),
+ "Blit11::mResolveStencilPS"),
+ mStencilSRV(),
+ mResolvedDepthStencilRTView()
+{}
+
+Blit11::~Blit11() {}
+
+angle::Result Blit11::initResources(const gl::Context *context)
+{
+ if (mResourcesInitialized)
+ {
+ return angle::Result::Continue;
+ }
+
+ ANGLE_TRACE_EVENT0("gpu.angle", "Blit11::initResources");
+
+ D3D11_BUFFER_DESC vbDesc;
+ vbDesc.ByteWidth =
+ static_cast<unsigned int>(std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex),
+ sizeof(d3d11::PositionTexCoordVertex)) *
+ 6 * mRenderer->getNativeCaps().max3DTextureSize);
+ vbDesc.Usage = D3D11_USAGE_DYNAMIC;
+ vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ vbDesc.MiscFlags = 0;
+ vbDesc.StructureByteStride = 0;
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, vbDesc, &mVertexBuffer));
+ mVertexBuffer.setInternalName("Blit11VertexBuffer");
+
+ D3D11_SAMPLER_DESC pointSamplerDesc;
+ pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
+ pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
+ pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
+ pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+ pointSamplerDesc.MipLODBias = 0.0f;
+ pointSamplerDesc.MaxAnisotropy = 0;
+ pointSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+ pointSamplerDesc.BorderColor[0] = 0.0f;
+ pointSamplerDesc.BorderColor[1] = 0.0f;
+ pointSamplerDesc.BorderColor[2] = 0.0f;
+ pointSamplerDesc.BorderColor[3] = 0.0f;
+ pointSamplerDesc.MinLOD = 0.0f;
+ pointSamplerDesc.MaxLOD = FLT_MAX;
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, pointSamplerDesc, &mPointSampler));
+ mPointSampler.setInternalName("Blit11PointSampler");
+
+ D3D11_SAMPLER_DESC linearSamplerDesc;
+ linearSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
+ linearSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
+ linearSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
+ linearSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+ linearSamplerDesc.MipLODBias = 0.0f;
+ linearSamplerDesc.MaxAnisotropy = 0;
+ linearSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+ linearSamplerDesc.BorderColor[0] = 0.0f;
+ linearSamplerDesc.BorderColor[1] = 0.0f;
+ linearSamplerDesc.BorderColor[2] = 0.0f;
+ linearSamplerDesc.BorderColor[3] = 0.0f;
+ linearSamplerDesc.MinLOD = 0.0f;
+ linearSamplerDesc.MaxLOD = FLT_MAX;
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, linearSamplerDesc, &mLinearSampler));
+ mLinearSampler.setInternalName("Blit11LinearSampler");
+
+ // Use a rasterizer state that will not cull so that inverted quads will not be culled
+ D3D11_RASTERIZER_DESC rasterDesc;
+ rasterDesc.FillMode = D3D11_FILL_SOLID;
+ rasterDesc.CullMode = D3D11_CULL_NONE;
+ rasterDesc.FrontCounterClockwise = FALSE;
+ rasterDesc.DepthBias = 0;
+ rasterDesc.SlopeScaledDepthBias = 0.0f;
+ rasterDesc.DepthBiasClamp = 0.0f;
+ rasterDesc.DepthClipEnable = TRUE;
+ rasterDesc.MultisampleEnable = FALSE;
+ rasterDesc.AntialiasedLineEnable = FALSE;
+
+ rasterDesc.ScissorEnable = TRUE;
+ ANGLE_TRY(mRenderer->allocateResource(context11, rasterDesc, &mScissorEnabledRasterizerState));
+ mScissorEnabledRasterizerState.setInternalName("Blit11ScissoringRasterizerState");
+
+ rasterDesc.ScissorEnable = FALSE;
+ ANGLE_TRY(mRenderer->allocateResource(context11, rasterDesc, &mScissorDisabledRasterizerState));
+ mScissorDisabledRasterizerState.setInternalName("Blit11NoScissoringRasterizerState");
+
+ D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
+ depthStencilDesc.DepthEnable = TRUE;
+ depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
+ depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
+ depthStencilDesc.StencilEnable = FALSE;
+ depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
+ depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
+ depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
+ depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, depthStencilDesc, &mDepthStencilState));
+ mDepthStencilState.setInternalName("Blit11DepthStencilState");
+
+ D3D11_BUFFER_DESC swizzleBufferDesc;
+ swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4;
+ swizzleBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+ swizzleBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ swizzleBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ swizzleBufferDesc.MiscFlags = 0;
+ swizzleBufferDesc.StructureByteStride = 0;
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, swizzleBufferDesc, &mSwizzleCB));
+ mSwizzleCB.setInternalName("Blit11SwizzleConstantBuffer");
+
+ mResourcesInitialized = true;
+
+ return angle::Result::Continue;
+}
+
+// static
+Blit11::SwizzleShaderType Blit11::GetSwizzleShaderType(GLenum type,
+ D3D11_SRV_DIMENSION dimensionality)
+{
+ switch (dimensionality)
+ {
+ case D3D11_SRV_DIMENSION_TEXTURE2D:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return SWIZZLESHADER_2D_FLOAT;
+ case GL_UNSIGNED_INT:
+ return SWIZZLESHADER_2D_UINT;
+ case GL_INT:
+ return SWIZZLESHADER_2D_INT;
+ default:
+ UNREACHABLE();
+ return SWIZZLESHADER_INVALID;
+ }
+ case D3D11_SRV_DIMENSION_TEXTURECUBE:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return SWIZZLESHADER_CUBE_FLOAT;
+ case GL_UNSIGNED_INT:
+ return SWIZZLESHADER_CUBE_UINT;
+ case GL_INT:
+ return SWIZZLESHADER_CUBE_INT;
+ default:
+ UNREACHABLE();
+ return SWIZZLESHADER_INVALID;
+ }
+ case D3D11_SRV_DIMENSION_TEXTURE3D:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return SWIZZLESHADER_3D_FLOAT;
+ case GL_UNSIGNED_INT:
+ return SWIZZLESHADER_3D_UINT;
+ case GL_INT:
+ return SWIZZLESHADER_3D_INT;
+ default:
+ UNREACHABLE();
+ return SWIZZLESHADER_INVALID;
+ }
+ case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
+ switch (type)
+ {
+ case GL_FLOAT:
+ return SWIZZLESHADER_ARRAY_FLOAT;
+ case GL_UNSIGNED_INT:
+ return SWIZZLESHADER_ARRAY_UINT;
+ case GL_INT:
+ return SWIZZLESHADER_ARRAY_INT;
+ default:
+ UNREACHABLE();
+ return SWIZZLESHADER_INVALID;
+ }
+ default:
+ UNREACHABLE();
+ return SWIZZLESHADER_INVALID;
+ }
+}
+
+angle::Result Blit11::getShaderSupport(const gl::Context *context,
+ const Shader &shader,
+ Blit11::ShaderSupport *supportOut)
+{
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ switch (shader.dimension)
+ {
+ case SHADER_2D:
+ {
+ ANGLE_TRY(mQuad2DIL.resolve(context11, mRenderer));
+ ANGLE_TRY(mQuad2DVS.resolve(context11, mRenderer));
+ supportOut->inputLayout = &mQuad2DIL.getObj();
+ supportOut->vertexShader = &mQuad2DVS.getObj();
+ supportOut->geometryShader = nullptr;
+ supportOut->vertexWriteFunction = Write2DVertices;
+ break;
+ }
+ case SHADER_3D:
+ case SHADER_2DARRAY:
+ {
+ ANGLE_TRY(mQuad3DIL.resolve(context11, mRenderer));
+ ANGLE_TRY(mQuad3DVS.resolve(context11, mRenderer));
+ ANGLE_TRY(mQuad3DGS.resolve(context11, mRenderer));
+ supportOut->inputLayout = &mQuad3DIL.getObj();
+ supportOut->vertexShader = &mQuad3DVS.getObj();
+ supportOut->geometryShader = &mQuad3DGS.getObj();
+ supportOut->vertexWriteFunction = Write3DVertices;
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Blit11::swizzleTexture(const gl::Context *context,
+ const d3d11::SharedSRV &source,
+ const d3d11::RenderTargetView &dest,
+ const gl::Extents &size,
+ const gl::SwizzleState &swizzleTarget)
+{
+ ANGLE_TRY(initResources(context));
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
+ source.get()->GetDesc(&sourceSRVDesc);
+
+ GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format);
+ if (componentType == GL_NONE)
+ {
+ // We're swizzling the depth component of a depth-stencil texture.
+ switch (sourceSRVDesc.Format)
+ {
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ componentType = GL_UNSIGNED_NORMALIZED;
+ break;
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ componentType = GL_FLOAT;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+
+ GLenum shaderType = GL_NONE;
+ switch (componentType)
+ {
+ case GL_UNSIGNED_NORMALIZED:
+ case GL_SIGNED_NORMALIZED:
+ case GL_FLOAT:
+ shaderType = GL_FLOAT;
+ break;
+ case GL_INT:
+ shaderType = GL_INT;
+ break;
+ case GL_UNSIGNED_INT:
+ shaderType = GL_UNSIGNED_INT;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ const Shader *shader = nullptr;
+ ANGLE_TRY(getSwizzleShader(context, shaderType, sourceSRVDesc.ViewDimension, &shader));
+
+ // Set vertices
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ ANGLE_TRY(mRenderer->mapResource(context, mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
+ &mappedResource));
+
+ ShaderSupport support;
+ ANGLE_TRY(getShaderSupport(context, *shader, &support));
+
+ UINT stride = 0;
+ UINT drawCount = 0;
+ D3D11_PRIMITIVE_TOPOLOGY topology;
+
+ gl::Box area(0, 0, 0, size.width, size.height, size.depth);
+ support.vertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount,
+ &topology);
+
+ deviceContext->Unmap(mVertexBuffer.get(), 0);
+
+ // Set constant buffer
+ ANGLE_TRY(mRenderer->mapResource(context, mSwizzleCB.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
+ &mappedResource));
+
+ unsigned int *swizzleIndices = static_cast<unsigned int *>(mappedResource.pData);
+ swizzleIndices[0] = GetSwizzleIndex(swizzleTarget.swizzleRed);
+ swizzleIndices[1] = GetSwizzleIndex(swizzleTarget.swizzleGreen);
+ swizzleIndices[2] = GetSwizzleIndex(swizzleTarget.swizzleBlue);
+ swizzleIndices[3] = GetSwizzleIndex(swizzleTarget.swizzleAlpha);
+
+ deviceContext->Unmap(mSwizzleCB.get(), 0);
+
+ StateManager11 *stateManager = mRenderer->getStateManager();
+
+ // Apply vertex buffer
+ stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
+
+ // Apply constant buffer
+ stateManager->setPixelConstantBuffer(0, &mSwizzleCB);
+
+ // Apply state
+ stateManager->setSimpleBlendState(nullptr);
+ stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
+ stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
+
+ // Apply shaders
+ stateManager->setInputLayout(support.inputLayout);
+ stateManager->setPrimitiveTopology(topology);
+
+ stateManager->setDrawShaders(support.vertexShader, support.geometryShader,
+ &shader->pixelShader);
+
+ // Apply render target
+ stateManager->setRenderTarget(dest.get(), nullptr);
+
+ // Set the viewport
+ stateManager->setSimpleViewport(size);
+
+ // Apply textures and sampler
+ stateManager->setSimplePixelTextureAndSampler(source, mPointSampler);
+
+ // Draw the quad
+ deviceContext->Draw(drawCount, 0);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Blit11::copyTexture(const gl::Context *context,
+ const d3d11::SharedSRV &source,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ GLenum sourceFormat,
+ const d3d11::RenderTargetView &dest,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ GLenum destFormat,
+ GLenum destTypeForDownsampling,
+ GLenum filter,
+ bool maskOffAlpha,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+ ANGLE_TRY(initResources(context));
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ // Determine if the source format is a signed integer format, the destFormat will already
+ // be GL_XXXX_INTEGER but it does not tell us if it is signed or unsigned.
+ D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
+ source.get()->GetDesc(&sourceSRVDesc);
+
+ GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format);
+
+ ASSERT(componentType != GL_NONE);
+ ASSERT(componentType != GL_SIGNED_NORMALIZED);
+ bool isSrcSigned = (componentType == GL_INT);
+
+ D3D11_RENDER_TARGET_VIEW_DESC destRTVDesc;
+ dest.get()->GetDesc(&destRTVDesc);
+
+ GLenum destComponentType = d3d11::GetComponentType(destRTVDesc.Format);
+
+ ASSERT(componentType != GL_NONE);
+ bool isDestSigned = (destComponentType == GL_INT);
+
+ ShaderDimension dimension = SHADER_INVALID;
+
+ switch (sourceSRVDesc.ViewDimension)
+ {
+ case D3D11_SRV_DIMENSION_TEXTURE2D:
+ dimension = SHADER_2D;
+ break;
+ case D3D11_SRV_DIMENSION_TEXTURE3D:
+ dimension = SHADER_3D;
+ break;
+ case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
+ dimension = SHADER_2DARRAY;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ const Shader *shader = nullptr;
+
+ ANGLE_TRY(getBlitShader(context, destFormat, sourceFormat, isSrcSigned, isDestSigned,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha, destTypeForDownsampling,
+ dimension, &shader));
+
+ ShaderSupport support;
+ ANGLE_TRY(getShaderSupport(context, *shader, &support));
+
+ // Set vertices
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ ANGLE_TRY(mRenderer->mapResource(context, mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
+ &mappedResource));
+
+ UINT stride = 0;
+ UINT drawCount = 0;
+ D3D11_PRIMITIVE_TOPOLOGY topology;
+
+ support.vertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData,
+ &stride, &drawCount, &topology);
+
+ deviceContext->Unmap(mVertexBuffer.get(), 0);
+
+ StateManager11 *stateManager = mRenderer->getStateManager();
+
+ // Apply vertex buffer
+ stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
+
+ // Apply state
+ if (maskOffAlpha)
+ {
+ ANGLE_TRY(mAlphaMaskBlendState.resolve(GetImplAs<Context11>(context), mRenderer));
+ stateManager->setSimpleBlendState(&mAlphaMaskBlendState.getObj());
+ }
+ else
+ {
+ stateManager->setSimpleBlendState(nullptr);
+ }
+ stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
+
+ if (scissor)
+ {
+ stateManager->setSimpleScissorRect(*scissor);
+ stateManager->setRasterizerState(&mScissorEnabledRasterizerState);
+ }
+ else
+ {
+ stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
+ }
+
+ // Apply shaders
+ stateManager->setInputLayout(support.inputLayout);
+ stateManager->setPrimitiveTopology(topology);
+
+ stateManager->setDrawShaders(support.vertexShader, support.geometryShader,
+ &shader->pixelShader);
+
+ // Apply render target
+ stateManager->setRenderTarget(dest.get(), nullptr);
+
+ // Set the viewport
+ stateManager->setSimpleViewport(destSize);
+
+ // Apply texture and sampler
+ switch (filter)
+ {
+ case GL_NEAREST:
+ stateManager->setSimplePixelTextureAndSampler(source, mPointSampler);
+ break;
+ case GL_LINEAR:
+ stateManager->setSimplePixelTextureAndSampler(source, mLinearSampler);
+ break;
+
+ default:
+ UNREACHABLE();
+ ANGLE_TRY_HR(GetImplAs<Context11>(context), E_FAIL,
+ "Internal error, unknown blit filter mode.");
+ }
+
+ // Draw the quad
+ deviceContext->Draw(drawCount, 0);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Blit11::copyStencil(const gl::Context *context,
+ const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor)
+{
+ return copyDepthStencilImpl(context, source, sourceSubresource, sourceArea, sourceSize, dest,
+ destSubresource, destArea, destSize, scissor, true);
+}
+
+angle::Result Blit11::copyDepth(const gl::Context *context,
+ const d3d11::SharedSRV &source,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const d3d11::DepthStencilView &dest,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor)
+{
+ ANGLE_TRY(initResources(context));
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ // Set vertices
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ ANGLE_TRY(mRenderer->mapResource(context, mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
+ &mappedResource));
+
+ UINT stride = 0;
+ UINT drawCount = 0;
+ D3D11_PRIMITIVE_TOPOLOGY topology;
+
+ Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, &stride,
+ &drawCount, &topology);
+
+ deviceContext->Unmap(mVertexBuffer.get(), 0);
+
+ StateManager11 *stateManager = mRenderer->getStateManager();
+
+ // Apply vertex buffer
+ stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
+
+ // Apply state
+ stateManager->setSimpleBlendState(nullptr);
+ stateManager->setDepthStencilState(&mDepthStencilState, 0xFFFFFFFF);
+
+ if (scissor)
+ {
+ stateManager->setSimpleScissorRect(*scissor);
+ stateManager->setRasterizerState(&mScissorEnabledRasterizerState);
+ }
+ else
+ {
+ stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
+ }
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ ANGLE_TRY(mQuad2DIL.resolve(context11, mRenderer));
+ ANGLE_TRY(mQuad2DVS.resolve(context11, mRenderer));
+ ANGLE_TRY(mDepthPS.resolve(context11, mRenderer));
+
+ // Apply shaders
+ stateManager->setInputLayout(&mQuad2DIL.getObj());
+ stateManager->setPrimitiveTopology(topology);
+
+ stateManager->setDrawShaders(&mQuad2DVS.getObj(), nullptr, &mDepthPS.getObj());
+
+ // Apply render target
+ stateManager->setRenderTarget(nullptr, dest.get());
+
+ // Set the viewport
+ stateManager->setSimpleViewport(destSize);
+
+ // Apply texture and sampler
+ stateManager->setSimplePixelTextureAndSampler(source, mPointSampler);
+
+ // Draw the quad
+ deviceContext->Draw(drawCount, 0);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Blit11::copyDepthStencil(const gl::Context *context,
+ const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor)
+{
+ return copyDepthStencilImpl(context, source, sourceSubresource, sourceArea, sourceSize, dest,
+ destSubresource, destArea, destSize, scissor, false);
+}
+
+angle::Result Blit11::copyDepthStencilImpl(const gl::Context *context,
+ const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ bool stencilOnly)
+{
+ auto srcDXGIFormat = source.getFormat();
+ const auto &srcSizeInfo = d3d11::GetDXGIFormatSizeInfo(srcDXGIFormat);
+ unsigned int srcPixelSize = srcSizeInfo.pixelBytes;
+ unsigned int copyOffset = 0;
+ unsigned int copySize = srcPixelSize;
+ auto destDXGIFormat = dest.getFormat();
+ const auto &destSizeInfo = d3d11::GetDXGIFormatSizeInfo(destDXGIFormat);
+ unsigned int destPixelSize = destSizeInfo.pixelBytes;
+
+ ASSERT(srcDXGIFormat == destDXGIFormat || destDXGIFormat == DXGI_FORMAT_R32_TYPELESS);
+
+ if (stencilOnly)
+ {
+ const auto &srcFormat = source.getFormatSet().format();
+
+ // Stencil channel should be right after the depth channel. Some views to depth/stencil
+ // resources have red channel for depth, in which case the depth channel bit width is in
+ // redBits.
+ ASSERT((srcFormat.redBits != 0) != (srcFormat.depthBits != 0));
+ GLuint depthBits = srcFormat.redBits + srcFormat.depthBits;
+ // Known formats have either 24 or 32 bits of depth.
+ ASSERT(depthBits == 24 || depthBits == 32);
+ copyOffset = depthBits / 8;
+
+ // Stencil is assumed to be 8-bit - currently this is true for all possible formats.
+ copySize = 1;
+ }
+
+ if (srcDXGIFormat != destDXGIFormat)
+ {
+ if (srcDXGIFormat == DXGI_FORMAT_R24G8_TYPELESS)
+ {
+ ASSERT(sourceArea == destArea && sourceSize == destSize && scissor == nullptr);
+ return copyAndConvert(context, source, sourceSubresource, sourceArea, sourceSize, dest,
+ destSubresource, destArea, destSize, scissor, copyOffset,
+ copyOffset, copySize, srcPixelSize, destPixelSize,
+ BlitD24S8ToD32F);
+ }
+ ASSERT(srcDXGIFormat == DXGI_FORMAT_R32G8X24_TYPELESS);
+ return copyAndConvert(context, source, sourceSubresource, sourceArea, sourceSize, dest,
+ destSubresource, destArea, destSize, scissor, copyOffset, copyOffset,
+ copySize, srcPixelSize, destPixelSize, BlitD32FS8ToD32F);
+ }
+
+ return copyAndConvert(context, source, sourceSubresource, sourceArea, sourceSize, dest,
+ destSubresource, destArea, destSize, scissor, copyOffset, copyOffset,
+ copySize, srcPixelSize, destPixelSize, StretchedBlitNearest);
+}
+
+angle::Result Blit11::copyAndConvertImpl(const gl::Context *context,
+ const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &destStaging,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ size_t readOffset,
+ size_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ BlitConvertFunction *convertFunction)
+{
+ ANGLE_TRY(initResources(context));
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ TextureHelper11 sourceStaging;
+ ANGLE_TRY(mRenderer->createStagingTexture(context, ResourceType::Texture2D,
+ source.getFormatSet(), sourceSize,
+ StagingAccess::READ, &sourceStaging));
+
+ deviceContext->CopySubresourceRegion(sourceStaging.get(), 0, 0, 0, 0, source.get(),
+ sourceSubresource, nullptr);
+
+ D3D11_MAPPED_SUBRESOURCE sourceMapping;
+ ANGLE_TRY(
+ mRenderer->mapResource(context, sourceStaging.get(), 0, D3D11_MAP_READ, 0, &sourceMapping));
+
+ D3D11_MAPPED_SUBRESOURCE destMapping;
+ angle::Result error =
+ mRenderer->mapResource(context, destStaging.get(), 0, D3D11_MAP_WRITE, 0, &destMapping);
+ if (error == angle::Result::Stop)
+ {
+ deviceContext->Unmap(sourceStaging.get(), 0);
+ return error;
+ }
+
+ // Clip dest area to the destination size
+ gl::Rectangle clipRect = gl::Rectangle(0, 0, destSize.width, destSize.height);
+
+ // Clip dest area to the scissor
+ if (scissor)
+ {
+ if (!gl::ClipRectangle(clipRect, *scissor, &clipRect))
+ {
+ return angle::Result::Continue;
+ }
+ }
+
+ convertFunction(sourceArea, destArea, clipRect, sourceSize, sourceMapping.RowPitch,
+ destMapping.RowPitch, readOffset, writeOffset, copySize, srcPixelStride,
+ destPixelStride, static_cast<const uint8_t *>(sourceMapping.pData),
+ static_cast<uint8_t *>(destMapping.pData));
+
+ deviceContext->Unmap(sourceStaging.get(), 0);
+ deviceContext->Unmap(destStaging.get(), 0);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Blit11::copyAndConvert(const gl::Context *context,
+ const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ size_t readOffset,
+ size_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ BlitConvertFunction *convertFunction)
+{
+ ANGLE_TRY(initResources(context));
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ // HACK: Create the destination staging buffer as a read/write texture so
+ // ID3D11DevicContext::UpdateSubresource can be called
+ // using it's mapped data as a source
+ TextureHelper11 destStaging;
+ ANGLE_TRY(mRenderer->createStagingTexture(context, ResourceType::Texture2D, dest.getFormatSet(),
+ destSize, StagingAccess::READ_WRITE, &destStaging));
+
+ deviceContext->CopySubresourceRegion(destStaging.get(), 0, 0, 0, 0, dest.get(), destSubresource,
+ nullptr);
+
+ ANGLE_TRY(copyAndConvertImpl(context, source, sourceSubresource, sourceArea, sourceSize,
+ destStaging, destArea, destSize, scissor, readOffset, writeOffset,
+ copySize, srcPixelStride, destPixelStride, convertFunction));
+
+ // Work around timeouts/TDRs in older NVIDIA drivers.
+ if (mRenderer->getFeatures().depthStencilBlitExtraCopy.enabled)
+ {
+ D3D11_MAPPED_SUBRESOURCE mapped;
+ ANGLE_TRY(
+ mRenderer->mapResource(context, destStaging.get(), 0, D3D11_MAP_READ, 0, &mapped));
+ deviceContext->UpdateSubresource(dest.get(), destSubresource, nullptr, mapped.pData,
+ mapped.RowPitch, mapped.DepthPitch);
+ deviceContext->Unmap(destStaging.get(), 0);
+ }
+ else
+ {
+ deviceContext->CopySubresourceRegion(dest.get(), destSubresource, 0, 0, 0,
+ destStaging.get(), 0, nullptr);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Blit11::addBlitShaderToMap(const gl::Context *context,
+ BlitShaderType blitShaderType,
+ ShaderDimension dimension,
+ const ShaderData &shaderData,
+ const char *name)
+{
+ ASSERT(mBlitShaderMap.find(blitShaderType) == mBlitShaderMap.end());
+
+ d3d11::PixelShader ps;
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), shaderData, &ps));
+ ps.setInternalName(name);
+
+ Shader shader;
+ shader.dimension = dimension;
+ shader.pixelShader = std::move(ps);
+
+ mBlitShaderMap[blitShaderType] = std::move(shader);
+ return angle::Result::Continue;
+}
+
+angle::Result Blit11::addSwizzleShaderToMap(const gl::Context *context,
+ SwizzleShaderType swizzleShaderType,
+ ShaderDimension dimension,
+ const ShaderData &shaderData,
+ const char *name)
+{
+ ASSERT(mSwizzleShaderMap.find(swizzleShaderType) == mSwizzleShaderMap.end());
+
+ d3d11::PixelShader ps;
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), shaderData, &ps));
+ ps.setInternalName(name);
+
+ Shader shader;
+ shader.dimension = dimension;
+ shader.pixelShader = std::move(ps);
+
+ mSwizzleShaderMap[swizzleShaderType] = std::move(shader);
+ return angle::Result::Continue;
+}
+
+void Blit11::clearShaderMap()
+{
+ mBlitShaderMap.clear();
+ mSwizzleShaderMap.clear();
+}
+
+Blit11::BlitShaderOperation Blit11::getBlitShaderOperation(GLenum destinationFormat,
+ GLenum sourceFormat,
+ bool isSrcSigned,
+ bool isDestSigned,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ GLenum destTypeForDownsampling)
+{
+ bool floatToIntBlit =
+ !gl::IsIntegerFormat(sourceFormat) && gl::IsIntegerFormat(destinationFormat);
+
+ if (isSrcSigned)
+ {
+ ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha);
+ switch (destinationFormat)
+ {
+ case GL_RGBA_INTEGER:
+ return RGBAI;
+ case GL_RGB_INTEGER:
+ return RGBI;
+ case GL_RG_INTEGER:
+ return RGI;
+ case GL_RED_INTEGER:
+ return RI;
+ default:
+ UNREACHABLE();
+ return OPERATION_INVALID;
+ }
+ }
+ else if (isDestSigned)
+ {
+ ASSERT(floatToIntBlit);
+
+ switch (destinationFormat)
+ {
+ case GL_RGBA_INTEGER:
+ if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
+ {
+ return RGBAF_TOI;
+ }
+ return unpackPremultiplyAlpha ? RGBAF_TOI_PREMULTIPLY : RGBAF_TOI_UNMULTIPLY;
+ case GL_RGB_INTEGER:
+ case GL_RG_INTEGER:
+ case GL_RED_INTEGER:
+ if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
+ {
+ return RGBF_TOI;
+ }
+ return unpackPremultiplyAlpha ? RGBF_TOI_PREMULTIPLY : RGBF_TOI_UNMULTIPLY;
+ default:
+ UNREACHABLE();
+ return OPERATION_INVALID;
+ }
+ }
+ else
+ {
+ // Check for the downsample formats first
+ switch (destTypeForDownsampling)
+ {
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ ASSERT(destinationFormat == GL_RGBA && !floatToIntBlit);
+ if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
+ {
+ return RGBAF_4444;
+ }
+ else if (unpackPremultiplyAlpha)
+ {
+ return RGBAF_4444_PREMULTIPLY;
+ }
+ else
+ {
+ return RGBAF_4444_UNMULTIPLY;
+ }
+
+ case GL_UNSIGNED_SHORT_5_6_5:
+ ASSERT(destinationFormat == GL_RGB && !floatToIntBlit);
+ if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
+ {
+ return RGBF_565;
+ }
+ else
+ {
+ return unpackPremultiplyAlpha ? RGBF_565_PREMULTIPLY : RGBF_565_UNMULTIPLY;
+ }
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
+ {
+ return RGBAF_5551;
+ }
+ else
+ {
+ return unpackPremultiplyAlpha ? RGBAF_5551_PREMULTIPLY : RGBAF_5551_UNMULTIPLY;
+ }
+
+ default:
+ // By default, use the regular passthrough/multiply/unmultiply shaders. The above
+ // shaders are only needed for some emulated texture formats.
+ break;
+ }
+
+ if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha || floatToIntBlit)
+ {
+ switch (destinationFormat)
+ {
+ case GL_RGBA:
+ case GL_BGRA_EXT:
+ ASSERT(!floatToIntBlit);
+ return unpackPremultiplyAlpha ? RGBAF_PREMULTIPLY : RGBAF_UNMULTIPLY;
+ case GL_RGB:
+ case GL_RG:
+ case GL_RED:
+ if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
+ {
+ return RGBF_TOUI;
+ }
+ else
+ {
+ return unpackPremultiplyAlpha ? RGBF_PREMULTIPLY : RGBF_UNMULTIPLY;
+ }
+ case GL_RGBA_INTEGER:
+ if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
+ {
+ return RGBAF_TOUI;
+ }
+ else
+ {
+ return unpackPremultiplyAlpha ? RGBAF_TOUI_PREMULTIPLY
+ : RGBAF_TOUI_UNMULTIPLY;
+ }
+ case GL_RGB_INTEGER:
+ case GL_RG_INTEGER:
+ case GL_RED_INTEGER:
+ if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
+ {
+ return RGBF_TOUI;
+ }
+ else
+ {
+ return unpackPremultiplyAlpha ? RGBF_TOUI_PREMULTIPLY
+ : RGBF_TOUI_UNMULTIPLY;
+ }
+ case GL_LUMINANCE:
+ ASSERT(!floatToIntBlit);
+ return unpackPremultiplyAlpha ? LUMAF_PREMULTIPLY : LUMAF_UNMULTIPLY;
+
+ case GL_LUMINANCE_ALPHA:
+ ASSERT(!floatToIntBlit);
+ return unpackPremultiplyAlpha ? LUMAALPHAF_PREMULTIPLY : LUMAALPHAF_UNMULTIPLY;
+ case GL_ALPHA:
+ return ALPHA;
+ default:
+ UNREACHABLE();
+ return OPERATION_INVALID;
+ }
+ }
+ else
+ {
+ switch (destinationFormat)
+ {
+ case GL_RGBA:
+ return RGBAF;
+ case GL_RGBA_INTEGER:
+ return RGBAUI;
+ case GL_BGRA_EXT:
+ return BGRAF;
+ case GL_RGB:
+ return RGBF;
+ case GL_RGB_INTEGER:
+ return RGBUI;
+ case GL_RG:
+ return RGF;
+ case GL_RG_INTEGER:
+ return RGUI;
+ case GL_RED:
+ return RF;
+ case GL_RED_INTEGER:
+ return RUI;
+ case GL_ALPHA:
+ return ALPHA;
+ case GL_LUMINANCE:
+ return LUMA;
+ case GL_LUMINANCE_ALPHA:
+ return LUMAALPHA;
+ default:
+ UNREACHABLE();
+ return OPERATION_INVALID;
+ }
+ }
+ }
+}
+
+angle::Result Blit11::getBlitShader(const gl::Context *context,
+ GLenum destFormat,
+ GLenum sourceFormat,
+ bool isSrcSigned,
+ bool isDestSigned,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ GLenum destTypeForDownsampling,
+ ShaderDimension dimension,
+ const Shader **shader)
+{
+ BlitShaderOperation blitShaderOperation = OPERATION_INVALID;
+
+ blitShaderOperation = getBlitShaderOperation(destFormat, sourceFormat, isSrcSigned,
+ isDestSigned, unpackPremultiplyAlpha,
+ unpackUnmultiplyAlpha, destTypeForDownsampling);
+
+ BlitShaderType blitShaderType = BLITSHADER_INVALID;
+
+ blitShaderType = getBlitShaderType(blitShaderOperation, dimension);
+
+ ANGLE_CHECK_HR(GetImplAs<Context11>(context), blitShaderType != BLITSHADER_INVALID,
+ "Internal blit shader type mismatch", E_FAIL);
+
+ auto blitShaderIt = mBlitShaderMap.find(blitShaderType);
+ if (blitShaderIt != mBlitShaderMap.end())
+ {
+ *shader = &blitShaderIt->second;
+ return angle::Result::Continue;
+ }
+
+ ASSERT(dimension == SHADER_2D || mRenderer->isES3Capable());
+
+ ANGLE_TRY(mapBlitShader(context, blitShaderType));
+
+ blitShaderIt = mBlitShaderMap.find(blitShaderType);
+ ASSERT(blitShaderIt != mBlitShaderMap.end());
+ *shader = &blitShaderIt->second;
+ return angle::Result::Continue;
+}
+
+angle::Result Blit11::getSwizzleShader(const gl::Context *context,
+ GLenum type,
+ D3D11_SRV_DIMENSION viewDimension,
+ const Shader **shader)
+{
+ SwizzleShaderType swizzleShaderType = GetSwizzleShaderType(type, viewDimension);
+
+ ANGLE_CHECK_HR(GetImplAs<Context11>(context), swizzleShaderType != SWIZZLESHADER_INVALID,
+ "Swizzle shader type not found", E_FAIL);
+
+ auto swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
+ if (swizzleShaderIt != mSwizzleShaderMap.end())
+ {
+ *shader = &swizzleShaderIt->second;
+ return angle::Result::Continue;
+ }
+
+ // Swizzling shaders (OpenGL ES 3+)
+ ASSERT(mRenderer->isES3Capable());
+
+ switch (swizzleShaderType)
+ {
+ case SWIZZLESHADER_2D_FLOAT:
+ ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_2D,
+ ShaderData(g_PS_SwizzleF2D),
+ "Blit11 2D F swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_2D_UINT:
+ ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_2D,
+ ShaderData(g_PS_SwizzleUI2D),
+ "Blit11 2D UI swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_2D_INT:
+ ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_2D,
+ ShaderData(g_PS_SwizzleI2D),
+ "Blit11 2D I swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_CUBE_FLOAT:
+ ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleF2DArray),
+ "Blit11 2D Cube F swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_CUBE_UINT:
+ ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleUI2DArray),
+ "Blit11 2D Cube UI swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_CUBE_INT:
+ ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleI2DArray),
+ "Blit11 2D Cube I swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_3D_FLOAT:
+ ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleF3D),
+ "Blit11 3D F swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_3D_UINT:
+ ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleUI3D),
+ "Blit11 3D UI swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_3D_INT:
+ ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleI3D),
+ "Blit11 3D I swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_ARRAY_FLOAT:
+ ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleF2DArray),
+ "Blit11 2D Array F swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_ARRAY_UINT:
+ ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleUI2DArray),
+ "Blit11 2D Array UI swizzle pixel shader"));
+ break;
+ case SWIZZLESHADER_ARRAY_INT:
+ ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
+ ShaderData(g_PS_SwizzleI2DArray),
+ "Blit11 2D Array I swizzle pixel shader"));
+ break;
+ default:
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ }
+
+ swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
+ ASSERT(swizzleShaderIt != mSwizzleShaderMap.end());
+ *shader = &swizzleShaderIt->second;
+ return angle::Result::Continue;
+}
+
+angle::Result Blit11::resolveDepth(const gl::Context *context,
+ RenderTarget11 *depth,
+ TextureHelper11 *textureOut)
+{
+ ANGLE_TRY(initResources(context));
+
+ // Multisampled depth stencil SRVs are not available in feature level 10.0
+ ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0);
+
+ const auto &extents = depth->getExtents();
+ auto *deviceContext = mRenderer->getDeviceContext();
+ auto *stateManager = mRenderer->getStateManager();
+
+ ANGLE_TRY(initResolveDepthOnly(context, depth->getFormatSet(), extents));
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ ANGLE_TRY(mResolveDepthStencilVS.resolve(context11, mRenderer));
+ ANGLE_TRY(mResolveDepthPS.resolve(context11, mRenderer));
+
+ // Apply the necessary state changes to the D3D11 immediate device context.
+ stateManager->setInputLayout(nullptr);
+ stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ stateManager->setDrawShaders(&mResolveDepthStencilVS.getObj(), nullptr,
+ &mResolveDepthPS.getObj());
+ stateManager->setRasterizerState(nullptr);
+ stateManager->setDepthStencilState(&mDepthStencilState, 0xFFFFFFFF);
+ stateManager->setRenderTargets(nullptr, 0, mResolvedDepthDSView.get());
+ stateManager->setSimpleBlendState(nullptr);
+ stateManager->setSimpleViewport(extents);
+
+ // Set the viewport
+ const d3d11::SharedSRV *srv;
+ ANGLE_TRY(depth->getShaderResourceView(context, &srv));
+
+ stateManager->setShaderResourceShared(gl::ShaderType::Fragment, 0, srv);
+
+ // Trigger the blit on the GPU.
+ deviceContext->Draw(6, 0);
+
+ *textureOut = mResolvedDepth;
+ return angle::Result::Continue;
+}
+
+angle::Result Blit11::initResolveDepthOnly(const gl::Context *context,
+ const d3d11::Format &format,
+ const gl::Extents &extents)
+{
+ if (mResolvedDepth.valid() && extents == mResolvedDepth.getExtents() &&
+ format.texFormat == mResolvedDepth.getFormat())
+ {
+ return angle::Result::Continue;
+ }
+
+ D3D11_TEXTURE2D_DESC textureDesc;
+ textureDesc.Width = extents.width;
+ textureDesc.Height = extents.height;
+ textureDesc.MipLevels = 1;
+ textureDesc.ArraySize = 1;
+ textureDesc.Format = format.texFormat;
+ textureDesc.SampleDesc.Count = 1;
+ textureDesc.SampleDesc.Quality = 0;
+ textureDesc.Usage = D3D11_USAGE_DEFAULT;
+ textureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
+ textureDesc.CPUAccessFlags = 0;
+ textureDesc.MiscFlags = 0;
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ ANGLE_TRY(mRenderer->allocateTexture(context11, textureDesc, format, &mResolvedDepth));
+ mResolvedDepth.setInternalName("Blit11::mResolvedDepth");
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Flags = 0;
+ dsvDesc.Format = format.dsvFormat;
+ dsvDesc.Texture2D.MipSlice = 0;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, dsvDesc, mResolvedDepth.get(),
+ &mResolvedDepthDSView));
+ mResolvedDepthDSView.setInternalName("Blit11::mResolvedDepthDSView");
+
+ // Possibly D3D11 bug or undefined behaviour: Clear the DSV so that our first render
+ // works as expected. Otherwise the results of the first use seem to be incorrect.
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->ClearDepthStencilView(mResolvedDepthDSView.get(), D3D11_CLEAR_DEPTH, 1.0f, 0);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Blit11::initResolveDepthStencil(const gl::Context *context,
+ const gl::Extents &extents)
+{
+ // Check if we need to recreate depth stencil view
+ if (mResolvedDepthStencil.valid() && extents == mResolvedDepthStencil.getExtents())
+ {
+ ASSERT(mResolvedDepthStencil.getFormat() == DXGI_FORMAT_R32G32_FLOAT);
+ return angle::Result::Continue;
+ }
+
+ if (mResolvedDepthStencil.valid())
+ {
+ releaseResolveDepthStencilResources();
+ }
+
+ const auto &formatSet = d3d11::Format::Get(GL_RG32F, mRenderer->getRenderer11DeviceCaps());
+
+ D3D11_TEXTURE2D_DESC textureDesc;
+ textureDesc.Width = extents.width;
+ textureDesc.Height = extents.height;
+ textureDesc.MipLevels = 1;
+ textureDesc.ArraySize = 1;
+ textureDesc.Format = formatSet.texFormat;
+ textureDesc.SampleDesc.Count = 1;
+ textureDesc.SampleDesc.Quality = 0;
+ textureDesc.Usage = D3D11_USAGE_DEFAULT;
+ textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
+ textureDesc.CPUAccessFlags = 0;
+ textureDesc.MiscFlags = 0;
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ ANGLE_TRY(
+ mRenderer->allocateTexture(context11, textureDesc, formatSet, &mResolvedDepthStencil));
+ mResolvedDepthStencil.setInternalName("Blit11::mResolvedDepthStencil");
+
+ ANGLE_TRY(mRenderer->allocateResourceNoDesc(context11, mResolvedDepthStencil.get(),
+ &mResolvedDepthStencilRTView));
+ mResolvedDepthStencilRTView.setInternalName("Blit11::mResolvedDepthStencilRTView");
+
+ return angle::Result::Continue;
+}
+
+angle::Result Blit11::resolveStencil(const gl::Context *context,
+ RenderTarget11 *depthStencil,
+ bool alsoDepth,
+ TextureHelper11 *textureOut)
+{
+ ANGLE_TRY(initResources(context));
+
+ // Multisampled depth stencil SRVs are not available in feature level 10.0
+ ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0);
+
+ const auto &extents = depthStencil->getExtents();
+
+ ANGLE_TRY(initResolveDepthStencil(context, extents));
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ auto *stateManager = mRenderer->getStateManager();
+ ID3D11Resource *stencilResource = depthStencil->getTexture().get();
+
+ // Check if we need to re-create the stencil SRV.
+ if (mStencilSRV.valid())
+ {
+ ID3D11Resource *priorResource = nullptr;
+ mStencilSRV.get()->GetResource(&priorResource);
+
+ if (stencilResource != priorResource)
+ {
+ mStencilSRV.reset();
+ }
+
+ SafeRelease(priorResource);
+ }
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ if (!mStencilSRV.valid())
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC srViewDesc;
+ srViewDesc.Format = GetStencilSRVFormat(depthStencil->getFormatSet());
+ srViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+
+ ANGLE_TRY(
+ mRenderer->allocateResource(context11, srViewDesc, stencilResource, &mStencilSRV));
+ mStencilSRV.setInternalName("Blit11::mStencilSRV");
+ }
+
+ // Notify the Renderer that all state should be invalidated.
+ ANGLE_TRY(mResolveDepthStencilVS.resolve(context11, mRenderer));
+
+ // Resolving the depth buffer works by sampling the depth in the shader using a SRV, then
+ // writing to the resolved depth buffer using SV_Depth. We can't use this method for stencil
+ // because SV_StencilRef isn't supported until HLSL 5.1/D3D11.3.
+ const d3d11::PixelShader *pixelShader = nullptr;
+ if (alsoDepth)
+ {
+ ANGLE_TRY(mResolveDepthStencilPS.resolve(context11, mRenderer));
+ pixelShader = &mResolveDepthStencilPS.getObj();
+ }
+ else
+ {
+ ANGLE_TRY(mResolveStencilPS.resolve(context11, mRenderer));
+ pixelShader = &mResolveStencilPS.getObj();
+ }
+
+ // Apply the necessary state changes to the D3D11 immediate device context.
+ stateManager->setInputLayout(nullptr);
+ stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ stateManager->setDrawShaders(&mResolveDepthStencilVS.getObj(), nullptr, pixelShader);
+ stateManager->setRasterizerState(nullptr);
+ stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
+ stateManager->setRenderTarget(mResolvedDepthStencilRTView.get(), nullptr);
+ stateManager->setSimpleBlendState(nullptr);
+
+ // Set the viewport
+ stateManager->setSimpleViewport(extents);
+ const d3d11::SharedSRV *srv;
+ ANGLE_TRY(depthStencil->getShaderResourceView(context, &srv));
+ stateManager->setShaderResourceShared(gl::ShaderType::Fragment, 0, srv);
+ stateManager->setShaderResource(gl::ShaderType::Fragment, 1, &mStencilSRV);
+
+ // Trigger the blit on the GPU.
+ deviceContext->Draw(6, 0);
+
+ gl::Box copyBox(0, 0, 0, extents.width, extents.height, 1);
+
+ ANGLE_TRY(mRenderer->createStagingTexture(context, ResourceType::Texture2D,
+ depthStencil->getFormatSet(), extents,
+ StagingAccess::READ_WRITE, textureOut));
+
+ const auto &copyFunction = GetCopyDepthStencilFunction(depthStencil->getInternalFormat());
+ const auto &dsFormatSet = depthStencil->getFormatSet();
+ const auto &dsDxgiInfo = d3d11::GetDXGIFormatSizeInfo(dsFormatSet.texFormat);
+
+ ANGLE_TRY(copyAndConvertImpl(context, mResolvedDepthStencil, 0, copyBox, extents, *textureOut,
+ copyBox, extents, nullptr, 0, 0, 0, 8u, dsDxgiInfo.pixelBytes,
+ copyFunction));
+
+ return angle::Result::Continue;
+}
+
+void Blit11::releaseResolveDepthStencilResources()
+{
+ mStencilSRV.reset();
+ mResolvedDepthStencilRTView.reset();
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Blit11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Blit11.h
new file mode 100644
index 0000000000..cef491137d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Blit11.h
@@ -0,0 +1,300 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Blit11.cpp: Texture copy utility class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#include <map>
+
+namespace rx
+{
+class Renderer11;
+
+class Blit11 : angle::NonCopyable
+{
+ public:
+ explicit Blit11(Renderer11 *renderer);
+ ~Blit11();
+
+ angle::Result swizzleTexture(const gl::Context *context,
+ const d3d11::SharedSRV &source,
+ const d3d11::RenderTargetView &dest,
+ const gl::Extents &size,
+ const gl::SwizzleState &swizzleTarget);
+
+ // Set destTypeForDownsampling to GL_NONE to skip downsampling
+ angle::Result copyTexture(const gl::Context *context,
+ const d3d11::SharedSRV &source,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ GLenum sourceFormat,
+ const d3d11::RenderTargetView &dest,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ GLenum destFormat,
+ GLenum destTypeForDownsampling,
+ GLenum filter,
+ bool maskOffAlpha,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha);
+
+ angle::Result copyStencil(const gl::Context *context,
+ const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor);
+
+ angle::Result copyDepth(const gl::Context *context,
+ const d3d11::SharedSRV &source,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const d3d11::DepthStencilView &dest,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor);
+
+ angle::Result copyDepthStencil(const gl::Context *context,
+ const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor);
+
+ angle::Result resolveDepth(const gl::Context *context,
+ RenderTarget11 *depth,
+ TextureHelper11 *textureOut);
+
+ angle::Result resolveStencil(const gl::Context *context,
+ RenderTarget11 *depthStencil,
+ bool alsoDepth,
+ TextureHelper11 *textureOut);
+
+ using BlitConvertFunction = void(const gl::Box &sourceArea,
+ const gl::Box &destArea,
+ const gl::Rectangle &clipRect,
+ const gl::Extents &sourceSize,
+ unsigned int sourceRowPitch,
+ unsigned int destRowPitch,
+ ptrdiff_t readOffset,
+ ptrdiff_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ const uint8_t *sourceData,
+ uint8_t *destData);
+
+ private:
+ enum BlitShaderOperation : unsigned int;
+ enum BlitShaderType : unsigned int;
+ enum SwizzleShaderType
+ {
+ SWIZZLESHADER_INVALID,
+ SWIZZLESHADER_2D_FLOAT,
+ SWIZZLESHADER_2D_UINT,
+ SWIZZLESHADER_2D_INT,
+ SWIZZLESHADER_CUBE_FLOAT,
+ SWIZZLESHADER_CUBE_UINT,
+ SWIZZLESHADER_CUBE_INT,
+ SWIZZLESHADER_3D_FLOAT,
+ SWIZZLESHADER_3D_UINT,
+ SWIZZLESHADER_3D_INT,
+ SWIZZLESHADER_ARRAY_FLOAT,
+ SWIZZLESHADER_ARRAY_UINT,
+ SWIZZLESHADER_ARRAY_INT,
+ };
+
+ typedef void (*WriteVertexFunction)(const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ void *outVertices,
+ unsigned int *outStride,
+ unsigned int *outVertexCount,
+ D3D11_PRIMITIVE_TOPOLOGY *outTopology);
+
+ enum ShaderDimension
+ {
+ SHADER_INVALID,
+ SHADER_2D,
+ SHADER_3D,
+ SHADER_2DARRAY
+ };
+
+ struct Shader
+ {
+ Shader();
+ Shader(Shader &&other);
+ ~Shader();
+ Shader &operator=(Shader &&other);
+
+ ShaderDimension dimension;
+ d3d11::PixelShader pixelShader;
+ };
+
+ struct ShaderSupport
+ {
+ const d3d11::InputLayout *inputLayout;
+ const d3d11::VertexShader *vertexShader;
+ const d3d11::GeometryShader *geometryShader;
+ WriteVertexFunction vertexWriteFunction;
+ };
+
+ angle::Result initResources(const gl::Context *context);
+
+ angle::Result getShaderSupport(const gl::Context *context,
+ const Shader &shader,
+ ShaderSupport *supportOut);
+
+ static BlitShaderOperation getBlitShaderOperation(GLenum destinationFormat,
+ GLenum sourceFormat,
+ bool isSrcSigned,
+ bool isDestSigned,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ GLenum destTypeForDownsampling);
+
+ static BlitShaderType getBlitShaderType(BlitShaderOperation operation,
+ ShaderDimension dimension);
+
+ static SwizzleShaderType GetSwizzleShaderType(GLenum type, D3D11_SRV_DIMENSION dimensionality);
+
+ angle::Result copyDepthStencilImpl(const gl::Context *context,
+ const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ bool stencilOnly);
+
+ angle::Result copyAndConvertImpl(const gl::Context *context,
+ const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &destStaging,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ size_t readOffset,
+ size_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ BlitConvertFunction *convertFunction);
+
+ angle::Result copyAndConvert(const gl::Context *context,
+ const TextureHelper11 &source,
+ unsigned int sourceSubresource,
+ const gl::Box &sourceArea,
+ const gl::Extents &sourceSize,
+ const TextureHelper11 &dest,
+ unsigned int destSubresource,
+ const gl::Box &destArea,
+ const gl::Extents &destSize,
+ const gl::Rectangle *scissor,
+ size_t readOffset,
+ size_t writeOffset,
+ size_t copySize,
+ size_t srcPixelStride,
+ size_t destPixelStride,
+ BlitConvertFunction *convertFunction);
+
+ angle::Result mapBlitShader(const gl::Context *context, BlitShaderType blitShaderType);
+ angle::Result addBlitShaderToMap(const gl::Context *context,
+ BlitShaderType blitShaderType,
+ ShaderDimension dimension,
+ const ShaderData &shaderData,
+ const char *name);
+
+ angle::Result getBlitShader(const gl::Context *context,
+ GLenum destFormat,
+ GLenum sourceFormat,
+ bool isSrcSigned,
+ bool isDestSigned,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ GLenum destTypeForDownsampling,
+ ShaderDimension dimension,
+ const Shader **shaderOut);
+ angle::Result getSwizzleShader(const gl::Context *context,
+ GLenum type,
+ D3D11_SRV_DIMENSION viewDimension,
+ const Shader **shaderOut);
+
+ angle::Result addSwizzleShaderToMap(const gl::Context *context,
+ SwizzleShaderType swizzleShaderType,
+ ShaderDimension dimension,
+ const ShaderData &shaderData,
+ const char *name);
+
+ void clearShaderMap();
+ void releaseResolveDepthStencilResources();
+ angle::Result initResolveDepthOnly(const gl::Context *context,
+ const d3d11::Format &format,
+ const gl::Extents &extents);
+ angle::Result initResolveDepthStencil(const gl::Context *context, const gl::Extents &extents);
+
+ Renderer11 *mRenderer;
+
+ std::map<BlitShaderType, Shader> mBlitShaderMap;
+ std::map<SwizzleShaderType, Shader> mSwizzleShaderMap;
+
+ bool mResourcesInitialized;
+ d3d11::Buffer mVertexBuffer;
+ d3d11::SamplerState mPointSampler;
+ d3d11::SamplerState mLinearSampler;
+ d3d11::RasterizerState mScissorEnabledRasterizerState;
+ d3d11::RasterizerState mScissorDisabledRasterizerState;
+ d3d11::DepthStencilState mDepthStencilState;
+
+ d3d11::LazyInputLayout mQuad2DIL;
+ d3d11::LazyShader<ID3D11VertexShader> mQuad2DVS;
+ d3d11::LazyShader<ID3D11PixelShader> mDepthPS;
+
+ d3d11::LazyInputLayout mQuad3DIL;
+ d3d11::LazyShader<ID3D11VertexShader> mQuad3DVS;
+ d3d11::LazyShader<ID3D11GeometryShader> mQuad3DGS;
+
+ d3d11::LazyBlendState mAlphaMaskBlendState;
+
+ d3d11::Buffer mSwizzleCB;
+
+ d3d11::LazyShader<ID3D11VertexShader> mResolveDepthStencilVS;
+ d3d11::LazyShader<ID3D11PixelShader> mResolveDepthPS;
+ d3d11::LazyShader<ID3D11PixelShader> mResolveDepthStencilPS;
+ d3d11::LazyShader<ID3D11PixelShader> mResolveStencilPS;
+ d3d11::ShaderResourceView mStencilSRV;
+ TextureHelper11 mResolvedDepthStencil;
+ d3d11::RenderTargetView mResolvedDepthStencilRTView;
+ TextureHelper11 mResolvedDepth;
+ d3d11::DepthStencilView mResolvedDepthDSView;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Blit11Helper_autogen.inc b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Blit11Helper_autogen.inc
new file mode 100644
index 0000000000..64d8106a18
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Blit11Helper_autogen.inc
@@ -0,0 +1,1575 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_blit11helper.py.
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Blit11Helper_autogen.inc:
+// Defines and retrieves blitshaders for the D3D11 backend.
+
+namespace
+{
+// Include inline shaders in the anonymous namespace to make sure no symbols are exported
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrougha2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d_4444_11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_4444_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_4444_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d_565_11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_565_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_565_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d_5551_11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_5551_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_5551_2d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgba_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgba_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgba_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgb_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgb_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgb_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d_4444_11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_4444_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_4444_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d_565_11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_565_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_565_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d_5551_11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_5551_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_5551_3d_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darray11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darray11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2darray11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2darray11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2darray11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2darray11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darrayui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darrayi11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darrayui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darrayi11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2darrayui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2darrayi11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2darrayui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2darrayi11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgba_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgba_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgba_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgb_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgb_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgb_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darray_4444_11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_4444_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_4444_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darray_565_11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_565_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_565_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darray_5551_11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_5551_2darray_ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_5551_2darray_ps.h"
+} // namespace
+
+enum Blit11::BlitShaderOperation : unsigned int
+{
+ RGBAF,
+ BGRAF,
+ RGBF,
+ RGF,
+ RF,
+ ALPHA,
+ LUMA,
+ LUMAALPHA,
+ RGBAUI,
+ RGBAI,
+ RGBUI,
+ RGBI,
+ RGUI,
+ RGI,
+ RUI,
+ RI,
+ RGBAF_PREMULTIPLY,
+ RGBAF_UNMULTIPLY,
+ RGBF_PREMULTIPLY,
+ RGBF_UNMULTIPLY,
+ RGBAF_TOUI,
+ RGBAF_TOUI_PREMULTIPLY,
+ RGBAF_TOUI_UNMULTIPLY,
+ RGBF_TOUI,
+ RGBF_TOUI_PREMULTIPLY,
+ RGBF_TOUI_UNMULTIPLY,
+ RGBAF_TOI,
+ RGBAF_TOI_PREMULTIPLY,
+ RGBAF_TOI_UNMULTIPLY,
+ RGBF_TOI,
+ RGBF_TOI_PREMULTIPLY,
+ RGBF_TOI_UNMULTIPLY,
+ LUMAF_PREMULTIPLY,
+ LUMAF_UNMULTIPLY,
+ LUMAALPHAF_PREMULTIPLY,
+ LUMAALPHAF_UNMULTIPLY,
+ RGBAF_4444,
+ RGBAF_4444_PREMULTIPLY,
+ RGBAF_4444_UNMULTIPLY,
+ RGBF_565,
+ RGBF_565_PREMULTIPLY,
+ RGBF_565_UNMULTIPLY,
+ RGBAF_5551,
+ RGBAF_5551_PREMULTIPLY,
+ RGBAF_5551_UNMULTIPLY,
+ OPERATION_INVALID
+};
+
+enum Blit11::BlitShaderType : unsigned int
+{
+ BLITSHADER_2D_RGBAF,
+ BLITSHADER_2D_BGRAF,
+ BLITSHADER_2D_RGBF,
+ BLITSHADER_2D_RGF,
+ BLITSHADER_2D_RF,
+ BLITSHADER_2D_ALPHA,
+ BLITSHADER_2D_LUMA,
+ BLITSHADER_2D_LUMAALPHA,
+ BLITSHADER_2D_RGBAUI,
+ BLITSHADER_2D_RGBAI,
+ BLITSHADER_2D_RGBUI,
+ BLITSHADER_2D_RGBI,
+ BLITSHADER_2D_RGUI,
+ BLITSHADER_2D_RGI,
+ BLITSHADER_2D_RUI,
+ BLITSHADER_2D_RI,
+ BLITSHADER_2D_RGBAF_PREMULTIPLY,
+ BLITSHADER_2D_RGBAF_UNMULTIPLY,
+ BLITSHADER_2D_RGBF_PREMULTIPLY,
+ BLITSHADER_2D_RGBF_UNMULTIPLY,
+ BLITSHADER_2D_RGBAF_TOUI,
+ BLITSHADER_2D_RGBAF_TOUI_PREMULTIPLY,
+ BLITSHADER_2D_RGBAF_TOUI_UNMULTIPLY,
+ BLITSHADER_2D_RGBF_TOUI,
+ BLITSHADER_2D_RGBF_TOUI_PREMULTIPLY,
+ BLITSHADER_2D_RGBF_TOUI_UNMULTIPLY,
+ BLITSHADER_2D_LUMAF_PREMULTIPLY,
+ BLITSHADER_2D_LUMAF_UNMULTIPLY,
+ BLITSHADER_2D_LUMAALPHAF_PREMULTIPLY,
+ BLITSHADER_2D_LUMAALPHAF_UNMULTIPLY,
+ BLITSHADER_2D_RGBAF_4444,
+ BLITSHADER_2D_RGBAF_4444_PREMULTIPLY,
+ BLITSHADER_2D_RGBAF_4444_UNMULTIPLY,
+ BLITSHADER_2D_RGBF_565,
+ BLITSHADER_2D_RGBF_565_PREMULTIPLY,
+ BLITSHADER_2D_RGBF_565_UNMULTIPLY,
+ BLITSHADER_2D_RGBAF_5551,
+ BLITSHADER_2D_RGBAF_5551_PREMULTIPLY,
+ BLITSHADER_2D_RGBAF_5551_UNMULTIPLY,
+ BLITSHADER_3D_RGBAF,
+ BLITSHADER_3D_BGRAF,
+ BLITSHADER_3D_RGBF,
+ BLITSHADER_3D_RGF,
+ BLITSHADER_3D_RF,
+ BLITSHADER_3D_ALPHA,
+ BLITSHADER_3D_LUMA,
+ BLITSHADER_3D_LUMAALPHA,
+ BLITSHADER_3D_RGBAUI,
+ BLITSHADER_3D_RGBAI,
+ BLITSHADER_3D_RGBUI,
+ BLITSHADER_3D_RGBI,
+ BLITSHADER_3D_RGUI,
+ BLITSHADER_3D_RGI,
+ BLITSHADER_3D_RUI,
+ BLITSHADER_3D_RI,
+ BLITSHADER_3D_RGBAF_PREMULTIPLY,
+ BLITSHADER_3D_RGBAF_UNMULTIPLY,
+ BLITSHADER_3D_RGBF_PREMULTIPLY,
+ BLITSHADER_3D_RGBF_UNMULTIPLY,
+ BLITSHADER_3D_RGBAF_TOUI,
+ BLITSHADER_3D_RGBAF_TOUI_PREMULTIPLY,
+ BLITSHADER_3D_RGBAF_TOUI_UNMULTIPLY,
+ BLITSHADER_3D_RGBF_TOUI,
+ BLITSHADER_3D_RGBF_TOUI_PREMULTIPLY,
+ BLITSHADER_3D_RGBF_TOUI_UNMULTIPLY,
+ BLITSHADER_3D_RGBAF_TOI,
+ BLITSHADER_3D_RGBAF_TOI_PREMULTIPLY,
+ BLITSHADER_3D_RGBAF_TOI_UNMULTIPLY,
+ BLITSHADER_3D_RGBF_TOI,
+ BLITSHADER_3D_RGBF_TOI_PREMULTIPLY,
+ BLITSHADER_3D_RGBF_TOI_UNMULTIPLY,
+ BLITSHADER_3D_LUMAF_PREMULTIPLY,
+ BLITSHADER_3D_LUMAF_UNMULTIPLY,
+ BLITSHADER_3D_LUMAALPHAF_PREMULTIPLY,
+ BLITSHADER_3D_LUMAALPHAF_UNMULTIPLY,
+ BLITSHADER_3D_RGBAF_4444,
+ BLITSHADER_3D_RGBAF_4444_PREMULTIPLY,
+ BLITSHADER_3D_RGBAF_4444_UNMULTIPLY,
+ BLITSHADER_3D_RGBF_565,
+ BLITSHADER_3D_RGBF_565_PREMULTIPLY,
+ BLITSHADER_3D_RGBF_565_UNMULTIPLY,
+ BLITSHADER_3D_RGBAF_5551,
+ BLITSHADER_3D_RGBAF_5551_PREMULTIPLY,
+ BLITSHADER_3D_RGBAF_5551_UNMULTIPLY,
+ BLITSHADER_2DARRAY_RGBAF,
+ BLITSHADER_2DARRAY_BGRAF,
+ BLITSHADER_2DARRAY_RGBF,
+ BLITSHADER_2DARRAY_RGF,
+ BLITSHADER_2DARRAY_RF,
+ BLITSHADER_2DARRAY_ALPHA,
+ BLITSHADER_2DARRAY_LUMA,
+ BLITSHADER_2DARRAY_LUMAALPHA,
+ BLITSHADER_2DARRAY_RGBAUI,
+ BLITSHADER_2DARRAY_RGBAI,
+ BLITSHADER_2DARRAY_RGBUI,
+ BLITSHADER_2DARRAY_RGBI,
+ BLITSHADER_2DARRAY_RGUI,
+ BLITSHADER_2DARRAY_RGI,
+ BLITSHADER_2DARRAY_RUI,
+ BLITSHADER_2DARRAY_RI,
+ BLITSHADER_2DARRAY_RGBAF_PREMULTIPLY,
+ BLITSHADER_2DARRAY_RGBAF_UNMULTIPLY,
+ BLITSHADER_2DARRAY_RGBF_PREMULTIPLY,
+ BLITSHADER_2DARRAY_RGBF_UNMULTIPLY,
+ BLITSHADER_2DARRAY_RGBAF_TOUI,
+ BLITSHADER_2DARRAY_RGBAF_TOUI_PREMULTIPLY,
+ BLITSHADER_2DARRAY_RGBAF_TOUI_UNMULTIPLY,
+ BLITSHADER_2DARRAY_RGBF_TOUI,
+ BLITSHADER_2DARRAY_RGBF_TOUI_PREMULTIPLY,
+ BLITSHADER_2DARRAY_RGBF_TOUI_UNMULTIPLY,
+ BLITSHADER_2DARRAY_RGBAF_TOI,
+ BLITSHADER_2DARRAY_RGBAF_TOI_PREMULTIPLY,
+ BLITSHADER_2DARRAY_RGBAF_TOI_UNMULTIPLY,
+ BLITSHADER_2DARRAY_RGBF_TOI,
+ BLITSHADER_2DARRAY_RGBF_TOI_PREMULTIPLY,
+ BLITSHADER_2DARRAY_RGBF_TOI_UNMULTIPLY,
+ BLITSHADER_2DARRAY_LUMAF_PREMULTIPLY,
+ BLITSHADER_2DARRAY_LUMAF_UNMULTIPLY,
+ BLITSHADER_2DARRAY_LUMAALPHAF_PREMULTIPLY,
+ BLITSHADER_2DARRAY_LUMAALPHAF_UNMULTIPLY,
+ BLITSHADER_2DARRAY_RGBAF_4444,
+ BLITSHADER_2DARRAY_RGBAF_4444_PREMULTIPLY,
+ BLITSHADER_2DARRAY_RGBAF_4444_UNMULTIPLY,
+ BLITSHADER_2DARRAY_RGBF_565,
+ BLITSHADER_2DARRAY_RGBF_565_PREMULTIPLY,
+ BLITSHADER_2DARRAY_RGBF_565_UNMULTIPLY,
+ BLITSHADER_2DARRAY_RGBAF_5551,
+ BLITSHADER_2DARRAY_RGBAF_5551_PREMULTIPLY,
+ BLITSHADER_2DARRAY_RGBAF_5551_UNMULTIPLY,
+ BLITSHADER_INVALID
+};
+
+Blit11::BlitShaderType Blit11::getBlitShaderType(BlitShaderOperation operation, ShaderDimension dimension)
+{
+ switch(operation)
+ {
+ case RGBAF:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBAF;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAF;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAF;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case BGRAF:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_BGRAF;
+ case SHADER_3D:
+ return BLITSHADER_3D_BGRAF;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_BGRAF;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBF:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBF;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBF;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBF;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGF:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGF;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGF;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGF;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RF:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RF;
+ case SHADER_3D:
+ return BLITSHADER_3D_RF;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RF;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case ALPHA:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_ALPHA;
+ case SHADER_3D:
+ return BLITSHADER_3D_ALPHA;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_ALPHA;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case LUMA:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_LUMA;
+ case SHADER_3D:
+ return BLITSHADER_3D_LUMA;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_LUMA;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case LUMAALPHA:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_LUMAALPHA;
+ case SHADER_3D:
+ return BLITSHADER_3D_LUMAALPHA;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_LUMAALPHA;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAUI:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBAUI;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAUI;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAUI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAI:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBAI;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAI;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBUI:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBUI;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBUI;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBUI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBI:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBI;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBI;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGUI:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGUI;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGUI;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGUI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGI:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGI;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGI;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RUI:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RUI;
+ case SHADER_3D:
+ return BLITSHADER_3D_RUI;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RUI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RI:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RI;
+ case SHADER_3D:
+ return BLITSHADER_3D_RI;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAF_PREMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBAF_PREMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAF_PREMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAF_PREMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAF_UNMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBAF_UNMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAF_UNMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAF_UNMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBF_PREMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBF_PREMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBF_PREMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBF_PREMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBF_UNMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBF_UNMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBF_UNMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBF_UNMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAF_TOUI:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBAF_TOUI;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAF_TOUI;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAF_TOUI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAF_TOUI_PREMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBAF_TOUI_PREMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAF_TOUI_PREMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAF_TOUI_PREMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAF_TOUI_UNMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBAF_TOUI_UNMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAF_TOUI_UNMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAF_TOUI_UNMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBF_TOUI:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBF_TOUI;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBF_TOUI;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBF_TOUI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBF_TOUI_PREMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBF_TOUI_PREMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBF_TOUI_PREMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBF_TOUI_PREMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBF_TOUI_UNMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBF_TOUI_UNMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBF_TOUI_UNMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBF_TOUI_UNMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAF_TOI:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_INVALID;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAF_TOI;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAF_TOI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAF_TOI_PREMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_INVALID;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAF_TOI_PREMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAF_TOI_PREMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAF_TOI_UNMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_INVALID;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAF_TOI_UNMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAF_TOI_UNMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBF_TOI:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_INVALID;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBF_TOI;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBF_TOI;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBF_TOI_PREMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_INVALID;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBF_TOI_PREMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBF_TOI_PREMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBF_TOI_UNMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_INVALID;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBF_TOI_UNMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBF_TOI_UNMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case LUMAF_PREMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_LUMAF_PREMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_LUMAF_PREMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_LUMAF_PREMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case LUMAF_UNMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_LUMAF_UNMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_LUMAF_UNMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_LUMAF_UNMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case LUMAALPHAF_PREMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_LUMAALPHAF_PREMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_LUMAALPHAF_PREMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_LUMAALPHAF_PREMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case LUMAALPHAF_UNMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_LUMAALPHAF_UNMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_LUMAALPHAF_UNMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_LUMAALPHAF_UNMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAF_4444:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBAF_4444;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAF_4444;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAF_4444;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAF_4444_PREMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBAF_4444_PREMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAF_4444_PREMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAF_4444_PREMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAF_4444_UNMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBAF_4444_UNMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAF_4444_UNMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAF_4444_UNMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBF_565:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBF_565;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBF_565;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBF_565;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBF_565_PREMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBF_565_PREMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBF_565_PREMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBF_565_PREMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBF_565_UNMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBF_565_UNMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBF_565_UNMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBF_565_UNMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAF_5551:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBAF_5551;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAF_5551;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAF_5551;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAF_5551_PREMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBAF_5551_PREMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAF_5551_PREMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAF_5551_PREMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ case RGBAF_5551_UNMULTIPLY:
+ switch (dimension)
+ {
+ case SHADER_2D:
+ return BLITSHADER_2D_RGBAF_5551_UNMULTIPLY;
+ case SHADER_3D:
+ return BLITSHADER_3D_RGBAF_5551_UNMULTIPLY;
+ case SHADER_2DARRAY:
+ return BLITSHADER_2DARRAY_RGBAF_5551_UNMULTIPLY;
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+ default:
+ UNREACHABLE();
+ return BLITSHADER_INVALID;
+ }
+}
+
+angle::Result Blit11::mapBlitShader(const gl::Context *context,
+ BlitShaderType blitShaderType)
+{
+ switch(blitShaderType)
+ {
+ case BLITSHADER_2D_RGBAF:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGBA2D),
+ "Blit11 2D PassthroughRGBA2D pixel shader"));
+ break;
+ case BLITSHADER_2D_BGRAF:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGBA2D),
+ "Blit11 2D PassthroughRGBA2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBF:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGB2D),
+ "Blit11 2D PassthroughRGB2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGF:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRG2D),
+ "Blit11 2D PassthroughRG2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RF:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughR2D),
+ "Blit11 2D PassthroughR2D pixel shader"));
+ break;
+ case BLITSHADER_2D_ALPHA:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughA2D),
+ "Blit11 2D PassthroughA2D pixel shader"));
+ break;
+ case BLITSHADER_2D_LUMA:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughLum2D),
+ "Blit11 2D PassthroughLum2D pixel shader"));
+ break;
+ case BLITSHADER_2D_LUMAALPHA:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughLumAlpha2D),
+ "Blit11 2D PassthroughLumAlpha2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGBA2DUI),
+ "Blit11 2D PassthroughRGBA2DUI pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGBA2DI),
+ "Blit11 2D PassthroughRGBA2DI pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGB2DUI),
+ "Blit11 2D PassthroughRGB2DUI pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGB2DI),
+ "Blit11 2D PassthroughRGB2DI pixel shader"));
+ break;
+ case BLITSHADER_2D_RGUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRG2DUI),
+ "Blit11 2D PassthroughRG2DUI pixel shader"));
+ break;
+ case BLITSHADER_2D_RGI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRG2DI),
+ "Blit11 2D PassthroughRG2DI pixel shader"));
+ break;
+ case BLITSHADER_2D_RUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughR2DUI),
+ "Blit11 2D PassthroughR2DUI pixel shader"));
+ break;
+ case BLITSHADER_2D_RI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughR2DI),
+ "Blit11 2D PassthroughR2DI pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_PM_RGBA_2D),
+ "Blit11 2D FtoF PM RGBA 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_UM_RGBA_2D),
+ "Blit11 2D FtoF UM RGBA 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_PM_RGB_2D),
+ "Blit11 2D FtoF PM RGB 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_UM_RGB_2D),
+ "Blit11 2D FtoF UM RGB 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAF_TOUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoU_PT_RGBA_2D),
+ "Blit11 2D FtoU PT RGBA 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAF_TOUI_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoU_PM_RGBA_2D),
+ "Blit11 2D FtoU PM RGBA 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAF_TOUI_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoU_UM_RGBA_2D),
+ "Blit11 2D FtoU UM RGBA 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBF_TOUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoU_PT_RGB_2D),
+ "Blit11 2D FtoU PT RGB 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBF_TOUI_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoU_PM_RGB_2D),
+ "Blit11 2D FtoU PM RGB 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBF_TOUI_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoU_UM_RGB_2D),
+ "Blit11 2D FtoU UM RGB 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_LUMAF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_PM_LUMA_2D),
+ "Blit11 2D FtoF PM LUMA 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_LUMAF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_UM_LUMA_2D),
+ "Blit11 2D FtoF UM LUMA 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_LUMAALPHAF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_PM_LUMAALPHA_2D),
+ "Blit11 2D FtoF PM LUMAALPHA 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_LUMAALPHAF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_UM_LUMAALPHA_2D),
+ "Blit11 2D FtoF UM LUMAALPHA 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAF_4444:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGBA2D_4444),
+ "Blit11 2D PassthroughRGBA2D 4444 pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAF_4444_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_PM_RGBA_4444_2D),
+ "Blit11 2D FtoF PM RGBA 4444 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAF_4444_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_UM_RGBA_4444_2D),
+ "Blit11 2D FtoF UM RGBA 4444 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBF_565:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGB2D_565),
+ "Blit11 2D PassthroughRGB2D 565 pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBF_565_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_PM_RGB_565_2D),
+ "Blit11 2D FtoF PM RGB 565 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBF_565_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_UM_RGB_565_2D),
+ "Blit11 2D FtoF UM RGB 565 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAF_5551:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_PassthroughRGBA2D_5551),
+ "Blit11 2D PassthroughRGBA2D 5551 pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAF_5551_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_PM_RGBA_5551_2D),
+ "Blit11 2D FtoF PM RGBA 5551 2D pixel shader"));
+ break;
+ case BLITSHADER_2D_RGBAF_5551_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2D,
+ ShaderData(g_PS_FtoF_UM_RGBA_5551_2D),
+ "Blit11 2D FtoF UM RGBA 5551 2D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGBA3D),
+ "Blit11 3D PassthroughRGBA3D pixel shader"));
+ break;
+ case BLITSHADER_3D_BGRAF:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGBA3D),
+ "Blit11 3D PassthroughRGBA3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBF:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGB3D),
+ "Blit11 3D PassthroughRGB3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGF:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRG3D),
+ "Blit11 3D PassthroughRG3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RF:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughR3D),
+ "Blit11 3D PassthroughR3D pixel shader"));
+ break;
+ case BLITSHADER_3D_ALPHA:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGBA3D),
+ "Blit11 3D PassthroughRGBA3D pixel shader"));
+ break;
+ case BLITSHADER_3D_LUMA:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughLum3D),
+ "Blit11 3D PassthroughLum3D pixel shader"));
+ break;
+ case BLITSHADER_3D_LUMAALPHA:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughLumAlpha3D),
+ "Blit11 3D PassthroughLumAlpha3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGBA3DUI),
+ "Blit11 3D PassthroughRGBA3DUI pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGBA3DI),
+ "Blit11 3D PassthroughRGBA3DI pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGB3DUI),
+ "Blit11 3D PassthroughRGB3DUI pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGB3DI),
+ "Blit11 3D PassthroughRGB3DI pixel shader"));
+ break;
+ case BLITSHADER_3D_RGUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRG3DUI),
+ "Blit11 3D PassthroughRG3DUI pixel shader"));
+ break;
+ case BLITSHADER_3D_RGI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRG3DI),
+ "Blit11 3D PassthroughRG3DI pixel shader"));
+ break;
+ case BLITSHADER_3D_RUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughR3DUI),
+ "Blit11 3D PassthroughR3DUI pixel shader"));
+ break;
+ case BLITSHADER_3D_RI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughR3DI),
+ "Blit11 3D PassthroughR3DI pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoF_PM_RGBA_3D),
+ "Blit11 3D FtoF PM RGBA 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoF_UM_RGBA_3D),
+ "Blit11 3D FtoF UM RGBA 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoF_PM_RGB_3D),
+ "Blit11 3D FtoF PM RGB 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoF_UM_RGB_3D),
+ "Blit11 3D FtoF UM RGB 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF_TOUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoU_PT_RGBA_3D),
+ "Blit11 3D FtoU PT RGBA 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF_TOUI_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoU_PM_RGBA_3D),
+ "Blit11 3D FtoU PM RGBA 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF_TOUI_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoU_UM_RGBA_3D),
+ "Blit11 3D FtoU UM RGBA 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBF_TOUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoU_PT_RGB_3D),
+ "Blit11 3D FtoU PT RGB 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBF_TOUI_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoU_PM_RGB_3D),
+ "Blit11 3D FtoU PM RGB 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBF_TOUI_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoU_UM_RGB_3D),
+ "Blit11 3D FtoU UM RGB 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF_TOI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoI_PT_RGBA_3D),
+ "Blit11 3D FtoI PT RGBA 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF_TOI_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoI_PM_RGBA_3D),
+ "Blit11 3D FtoI PM RGBA 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF_TOI_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoI_UM_RGBA_3D),
+ "Blit11 3D FtoI UM RGBA 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBF_TOI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoI_PT_RGB_3D),
+ "Blit11 3D FtoI PT RGB 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBF_TOI_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoI_PM_RGB_3D),
+ "Blit11 3D FtoI PM RGB 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBF_TOI_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoI_UM_RGB_3D),
+ "Blit11 3D FtoI UM RGB 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_LUMAF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoF_PM_LUMA_3D),
+ "Blit11 3D FtoF PM LUMA 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_LUMAF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoF_UM_LUMA_3D),
+ "Blit11 3D FtoF UM LUMA 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_LUMAALPHAF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoF_PM_LUMAALPHA_3D),
+ "Blit11 3D FtoF PM LUMAALPHA 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_LUMAALPHAF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoF_UM_LUMAALPHA_3D),
+ "Blit11 3D FtoF UM LUMAALPHA 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF_4444:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGBA3D_4444),
+ "Blit11 3D PassthroughRGBA3D 4444 pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF_4444_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoF_PM_RGBA_4444_3D),
+ "Blit11 3D FtoF PM RGBA 4444 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF_4444_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoF_UM_RGBA_4444_3D),
+ "Blit11 3D FtoF UM RGBA 4444 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBF_565:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGB3D_565),
+ "Blit11 3D PassthroughRGB3D 565 pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBF_565_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoF_PM_RGB_565_3D),
+ "Blit11 3D FtoF PM RGB 565 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBF_565_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoF_UM_RGB_565_3D),
+ "Blit11 3D FtoF UM RGB 565 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF_5551:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_PassthroughRGBA3D_5551),
+ "Blit11 3D PassthroughRGBA3D 5551 pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF_5551_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoF_PM_RGBA_5551_3D),
+ "Blit11 3D FtoF PM RGBA 5551 3D pixel shader"));
+ break;
+ case BLITSHADER_3D_RGBAF_5551_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_3D,
+ ShaderData(g_PS_FtoF_UM_RGBA_5551_3D),
+ "Blit11 3D FtoF UM RGBA 5551 3D pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAF:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughRGBA2DArray),
+ "Blit11 2DArray PassthroughRGBA2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_BGRAF:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughRGBA2DArray),
+ "Blit11 2DArray PassthroughRGBA2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBF:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughRGB2DArray),
+ "Blit11 2DArray PassthroughRGB2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGF:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughRG2DArray),
+ "Blit11 2DArray PassthroughRG2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RF:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughR2DArray),
+ "Blit11 2DArray PassthroughR2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_ALPHA:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughRGBA2DArray),
+ "Blit11 2DArray PassthroughRGBA2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_LUMA:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughLum2DArray),
+ "Blit11 2DArray PassthroughLum2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_LUMAALPHA:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughLumAlpha2DArray),
+ "Blit11 2DArray PassthroughLumAlpha2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughRGBA2DArrayUI),
+ "Blit11 2DArray PassthroughRGBA2DArrayUI pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughRGBA2DArrayI),
+ "Blit11 2DArray PassthroughRGBA2DArrayI pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughRGB2DArrayUI),
+ "Blit11 2DArray PassthroughRGB2DArrayUI pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughRGB2DArrayI),
+ "Blit11 2DArray PassthroughRGB2DArrayI pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughRG2DArrayUI),
+ "Blit11 2DArray PassthroughRG2DArrayUI pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughRG2DArrayI),
+ "Blit11 2DArray PassthroughRG2DArrayI pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughR2DArrayUI),
+ "Blit11 2DArray PassthroughR2DArrayUI pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughR2DArrayI),
+ "Blit11 2DArray PassthroughR2DArrayI pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoF_PM_RGBA_2DArray),
+ "Blit11 2DArray FtoF PM RGBA 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoF_UM_RGBA_2DArray),
+ "Blit11 2DArray FtoF UM RGBA 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoF_PM_RGB_2DArray),
+ "Blit11 2DArray FtoF PM RGB 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoF_UM_RGB_2DArray),
+ "Blit11 2DArray FtoF UM RGB 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAF_TOUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoU_PT_RGBA_2DArray),
+ "Blit11 2DArray FtoU PT RGBA 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAF_TOUI_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoU_PM_RGBA_2DArray),
+ "Blit11 2DArray FtoU PM RGBA 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAF_TOUI_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoU_UM_RGBA_2DArray),
+ "Blit11 2DArray FtoU UM RGBA 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBF_TOUI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoU_PT_RGB_2DArray),
+ "Blit11 2DArray FtoU PT RGB 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBF_TOUI_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoU_PM_RGB_2DArray),
+ "Blit11 2DArray FtoU PM RGB 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBF_TOUI_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoU_UM_RGB_2DArray),
+ "Blit11 2DArray FtoU UM RGB 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAF_TOI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoI_PT_RGBA_2DArray),
+ "Blit11 2DArray FtoI PT RGBA 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAF_TOI_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoI_PM_RGBA_2DArray),
+ "Blit11 2DArray FtoI PM RGBA 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAF_TOI_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoI_UM_RGBA_2DArray),
+ "Blit11 2DArray FtoI UM RGBA 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBF_TOI:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoI_PT_RGB_2DArray),
+ "Blit11 2DArray FtoI PT RGB 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBF_TOI_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoI_PM_RGB_2DArray),
+ "Blit11 2DArray FtoI PM RGB 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBF_TOI_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoI_UM_RGB_2DArray),
+ "Blit11 2DArray FtoI UM RGB 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_LUMAF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoF_PM_LUMA_2DArray),
+ "Blit11 2DArray FtoF PM LUMA 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_LUMAF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoF_UM_LUMA_2DArray),
+ "Blit11 2DArray FtoF UM LUMA 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_LUMAALPHAF_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoF_PM_LUMAALPHA_2DArray),
+ "Blit11 2DArray FtoF PM LUMAALPHA 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_LUMAALPHAF_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoF_UM_LUMAALPHA_2DArray),
+ "Blit11 2DArray FtoF UM LUMAALPHA 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAF_4444:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughRGBA2DArray_4444),
+ "Blit11 2DArray PassthroughRGBA2DArray 4444 pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAF_4444_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoF_PM_RGBA_4444_2DArray),
+ "Blit11 2DArray FtoF PM RGBA 4444 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAF_4444_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoF_UM_RGBA_4444_2DArray),
+ "Blit11 2DArray FtoF UM RGBA 4444 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBF_565:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughRGB2DArray_565),
+ "Blit11 2DArray PassthroughRGB2DArray 565 pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBF_565_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoF_PM_RGB_565_2DArray),
+ "Blit11 2DArray FtoF PM RGB 565 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBF_565_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoF_UM_RGB_565_2DArray),
+ "Blit11 2DArray FtoF UM RGB 565 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAF_5551:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_PassthroughRGBA2DArray_5551),
+ "Blit11 2DArray PassthroughRGBA2DArray 5551 pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAF_5551_PREMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoF_PM_RGBA_5551_2DArray),
+ "Blit11 2DArray FtoF PM RGBA 5551 2DArray pixel shader"));
+ break;
+ case BLITSHADER_2DARRAY_RGBAF_5551_UNMULTIPLY:
+ ANGLE_TRY(addBlitShaderToMap(context, blitShaderType, SHADER_2DARRAY,
+ ShaderData(g_PS_FtoF_UM_RGBA_5551_2DArray),
+ "Blit11 2DArray FtoF UM RGBA 5551 2DArray pixel shader"));
+ break;
+ default:
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ }
+
+ return angle::Result::Continue;
+}
+
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
new file mode 100644
index 0000000000..8cc265f288
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
@@ -0,0 +1,1888 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Buffer11.cpp Defines the Buffer11 class.
+
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+
+#include <memory>
+
+#include "common/MemoryBuffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace rx
+{
+
+namespace
+{
+
+template <typename T>
+GLuint ReadIndexValueFromIndices(const uint8_t *data, size_t index)
+{
+ return reinterpret_cast<const T *>(data)[index];
+}
+typedef GLuint (*ReadIndexValueFunction)(const uint8_t *data, size_t index);
+
+enum class CopyResult
+{
+ RECREATED,
+ NOT_RECREATED,
+};
+
+void CalculateConstantBufferParams(GLintptr offset,
+ GLsizeiptr size,
+ UINT *outFirstConstant,
+ UINT *outNumConstants)
+{
+ // The offset must be aligned to 256 bytes (should have been enforced by glBindBufferRange).
+ ASSERT(offset % 256 == 0);
+
+ // firstConstant and numConstants are expressed in constants of 16-bytes. Furthermore they must
+ // be a multiple of 16 constants.
+ *outFirstConstant = static_cast<UINT>(offset / 16);
+
+ // The GL size is not required to be aligned to a 256 bytes boundary.
+ // Round the size up to a 256 bytes boundary then express the results in constants of 16-bytes.
+ *outNumConstants = static_cast<UINT>(rx::roundUpPow2(size, static_cast<GLsizeiptr>(256)) / 16);
+
+ // Since the size is rounded up, firstConstant + numConstants may be bigger than the actual size
+ // of the buffer. This behaviour is explictly allowed according to the documentation on
+ // ID3D11DeviceContext1::PSSetConstantBuffers1
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx
+}
+
+} // anonymous namespace
+
+namespace gl_d3d11
+{
+
+D3D11_MAP GetD3DMapTypeFromBits(BufferUsage usage, GLbitfield access)
+{
+ bool readBit = ((access & GL_MAP_READ_BIT) != 0);
+ bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0);
+
+ ASSERT(readBit || writeBit);
+
+ // Note : we ignore the discard bit, because in D3D11, staging buffers
+ // don't accept the map-discard flag (discard only works for DYNAMIC usage)
+
+ if (readBit && !writeBit)
+ {
+ return D3D11_MAP_READ;
+ }
+ else if (writeBit && !readBit)
+ {
+ // Special case for uniform storage - we only allow full buffer updates.
+ return usage == BUFFER_USAGE_UNIFORM || usage == BUFFER_USAGE_STRUCTURED
+ ? D3D11_MAP_WRITE_DISCARD
+ : D3D11_MAP_WRITE;
+ }
+ else if (writeBit && readBit)
+ {
+ return D3D11_MAP_READ_WRITE;
+ }
+ else
+ {
+ UNREACHABLE();
+ return D3D11_MAP_READ;
+ }
+}
+} // namespace gl_d3d11
+
+// Each instance of Buffer11::BufferStorage is specialized for a class of D3D binding points
+// - vertex/transform feedback buffers
+// - index buffers
+// - pixel unpack buffers
+// - uniform buffers
+class Buffer11::BufferStorage : angle::NonCopyable
+{
+ public:
+ virtual ~BufferStorage() {}
+
+ DataRevision getDataRevision() const { return mRevision; }
+ BufferUsage getUsage() const { return mUsage; }
+ size_t getSize() const { return mBufferSize; }
+ void setDataRevision(DataRevision rev) { mRevision = rev; }
+
+ virtual bool isCPUAccessible(GLbitfield access) const = 0;
+
+ virtual bool isGPUAccessible() const = 0;
+
+ virtual angle::Result copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset,
+ CopyResult *resultOut) = 0;
+ virtual angle::Result resize(const gl::Context *context, size_t size, bool preserveData) = 0;
+
+ virtual angle::Result map(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut) = 0;
+ virtual void unmap() = 0;
+
+ angle::Result setData(const gl::Context *context,
+ const uint8_t *data,
+ size_t offset,
+ size_t size);
+
+ void setStructureByteStride(unsigned int structureByteStride);
+
+ protected:
+ BufferStorage(Renderer11 *renderer, BufferUsage usage);
+
+ Renderer11 *mRenderer;
+ DataRevision mRevision;
+ const BufferUsage mUsage;
+ size_t mBufferSize;
+};
+
+// A native buffer storage represents an underlying D3D11 buffer for a particular
+// type of storage.
+class Buffer11::NativeStorage : public Buffer11::BufferStorage
+{
+ public:
+ NativeStorage(Renderer11 *renderer, BufferUsage usage, const angle::Subject *onStorageChanged);
+ ~NativeStorage() override;
+
+ bool isCPUAccessible(GLbitfield access) const override;
+
+ bool isGPUAccessible() const override { return true; }
+
+ const d3d11::Buffer &getBuffer() const { return mBuffer; }
+ angle::Result copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset,
+ CopyResult *resultOut) override;
+ angle::Result resize(const gl::Context *context, size_t size, bool preserveData) override;
+
+ angle::Result map(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut) override;
+ void unmap() override;
+
+ angle::Result getSRVForFormat(const gl::Context *context,
+ DXGI_FORMAT srvFormat,
+ const d3d11::ShaderResourceView **srvOut);
+ angle::Result getRawUAV(const gl::Context *context,
+ unsigned int offset,
+ unsigned int size,
+ d3d11::UnorderedAccessView **uavOut);
+
+ protected:
+ d3d11::Buffer mBuffer;
+ const angle::Subject *mOnStorageChanged;
+
+ private:
+ static void FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
+ Renderer11 *renderer,
+ BufferUsage usage,
+ unsigned int bufferSize);
+ void clearSRVs();
+ void clearUAVs();
+
+ std::map<DXGI_FORMAT, d3d11::ShaderResourceView> mBufferResourceViews;
+ std::map<std::pair<unsigned int, unsigned int>, d3d11::UnorderedAccessView> mBufferRawUAVs;
+};
+
+class Buffer11::StructuredBufferStorage : public Buffer11::NativeStorage
+{
+ public:
+ StructuredBufferStorage(Renderer11 *renderer,
+ BufferUsage usage,
+ const angle::Subject *onStorageChanged);
+ ~StructuredBufferStorage() override;
+ angle::Result resizeStructuredBuffer(const gl::Context *context,
+ unsigned int size,
+ unsigned int structureByteStride);
+ angle::Result getStructuredBufferRangeSRV(const gl::Context *context,
+ unsigned int offset,
+ unsigned int size,
+ unsigned int structureByteStride,
+ const d3d11::ShaderResourceView **bufferOut);
+
+ private:
+ d3d11::ShaderResourceView mStructuredBufferResourceView;
+};
+
+// A emulated indexed buffer storage represents an underlying D3D11 buffer for data
+// that has been expanded to match the indices list used. This storage is only
+// used for FL9_3 pointsprite rendering emulation.
+class Buffer11::EmulatedIndexedStorage : public Buffer11::BufferStorage
+{
+ public:
+ EmulatedIndexedStorage(Renderer11 *renderer);
+ ~EmulatedIndexedStorage() override;
+
+ bool isCPUAccessible(GLbitfield access) const override { return true; }
+
+ bool isGPUAccessible() const override { return false; }
+
+ angle::Result getBuffer(const gl::Context *context,
+ SourceIndexData *indexInfo,
+ const TranslatedAttribute &attribute,
+ GLint startVertex,
+ const d3d11::Buffer **bufferOut);
+
+ angle::Result copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset,
+ CopyResult *resultOut) override;
+
+ angle::Result resize(const gl::Context *context, size_t size, bool preserveData) override;
+
+ angle::Result map(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut) override;
+ void unmap() override;
+
+ private:
+ d3d11::Buffer mBuffer; // contains expanded data for use by D3D
+ angle::MemoryBuffer mMemoryBuffer; // original data (not expanded)
+ angle::MemoryBuffer mIndicesMemoryBuffer; // indices data
+};
+
+// Pack storage represents internal storage for pack buffers. We implement pack buffers
+// as CPU memory, tied to a staging texture, for asynchronous texture readback.
+class Buffer11::PackStorage : public Buffer11::BufferStorage
+{
+ public:
+ explicit PackStorage(Renderer11 *renderer);
+ ~PackStorage() override;
+
+ bool isCPUAccessible(GLbitfield access) const override { return true; }
+
+ bool isGPUAccessible() const override { return false; }
+
+ angle::Result copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset,
+ CopyResult *resultOut) override;
+ angle::Result resize(const gl::Context *context, size_t size, bool preserveData) override;
+
+ angle::Result map(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut) override;
+ void unmap() override;
+
+ angle::Result packPixels(const gl::Context *context,
+ const gl::FramebufferAttachment &readAttachment,
+ const PackPixelsParams &params);
+
+ private:
+ angle::Result flushQueuedPackCommand(const gl::Context *context);
+
+ TextureHelper11 mStagingTexture;
+ angle::MemoryBuffer mMemoryBuffer;
+ std::unique_ptr<PackPixelsParams> mQueuedPackCommand;
+ PackPixelsParams mPackParams;
+ bool mDataModified;
+};
+
+// System memory storage stores a CPU memory buffer with our buffer data.
+// For dynamic data, it's much faster to update the CPU memory buffer than
+// it is to update a D3D staging buffer and read it back later.
+class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage
+{
+ public:
+ explicit SystemMemoryStorage(Renderer11 *renderer);
+ ~SystemMemoryStorage() override {}
+
+ bool isCPUAccessible(GLbitfield access) const override { return true; }
+
+ bool isGPUAccessible() const override { return false; }
+
+ angle::Result copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset,
+ CopyResult *resultOut) override;
+ angle::Result resize(const gl::Context *context, size_t size, bool preserveData) override;
+
+ angle::Result map(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut) override;
+ void unmap() override;
+
+ angle::MemoryBuffer *getSystemCopy() { return &mSystemCopy; }
+
+ protected:
+ angle::MemoryBuffer mSystemCopy;
+};
+
+Buffer11::Buffer11(const gl::BufferState &state, Renderer11 *renderer)
+ : BufferD3D(state, renderer),
+ mRenderer(renderer),
+ mSize(0),
+ mMappedStorage(nullptr),
+ mBufferStorages({}),
+ mLatestBufferStorage(nullptr),
+ mDeallocThresholds({}),
+ mIdleness({}),
+ mConstantBufferStorageAdditionalSize(0),
+ mMaxConstantBufferLruCount(0),
+ mStructuredBufferStorageAdditionalSize(0),
+ mMaxStructuredBufferLruCount(0)
+{}
+
+Buffer11::~Buffer11()
+{
+ for (BufferStorage *&storage : mBufferStorages)
+ {
+ SafeDelete(storage);
+ }
+
+ for (auto &p : mConstantBufferRangeStoragesCache)
+ {
+ SafeDelete(p.second.storage);
+ }
+
+ for (auto &p : mStructuredBufferRangeStoragesCache)
+ {
+ SafeDelete(p.second.storage);
+ }
+
+ mRenderer->onBufferDelete(this);
+}
+
+angle::Result Buffer11::setData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ gl::BufferUsage usage)
+{
+ updateD3DBufferUsage(context, usage);
+ return setSubData(context, target, data, size, 0);
+}
+
+angle::Result Buffer11::getData(const gl::Context *context, const uint8_t **outData)
+{
+ if (mSize == 0)
+ {
+ // TODO(http://anglebug.com/2840): This ensures that we don't crash or assert in robust
+ // buffer access behavior mode if there are buffers without any data. However, technically
+ // it should still be possible to draw, with fetches from this buffer returning zero.
+ return angle::Result::Stop;
+ }
+
+ SystemMemoryStorage *systemMemoryStorage = nullptr;
+ ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_SYSTEM_MEMORY, &systemMemoryStorage));
+
+ ASSERT(systemMemoryStorage->getSize() >= mSize);
+
+ *outData = systemMemoryStorage->getSystemCopy()->data();
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::setSubData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ size_t offset)
+{
+ size_t requiredSize = size + offset;
+
+ if (data && size > 0)
+ {
+ // Use system memory storage for dynamic buffers.
+ // Try using a constant storage for constant buffers
+ BufferStorage *writeBuffer = nullptr;
+ if (target == gl::BufferBinding::Uniform)
+ {
+ // If we are a very large uniform buffer, keep system memory storage around so that we
+ // aren't forced to read back from a constant buffer. We also check the workaround for
+ // Intel - this requires us to use system memory so we don't end up having to copy from
+ // a constant buffer to a staging buffer.
+ // TODO(jmadill): Use Context caps.
+ if (offset == 0 && size >= mSize &&
+ size <= static_cast<UINT>(mRenderer->getNativeCaps().maxUniformBlockSize) &&
+ !mRenderer->getFeatures().useSystemMemoryForConstantBuffers.enabled)
+ {
+ BufferStorage *latestStorage = nullptr;
+ ANGLE_TRY(getLatestBufferStorage(context, &latestStorage));
+ if (latestStorage && (latestStorage->getUsage() == BUFFER_USAGE_STRUCTURED))
+ {
+ ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_STRUCTURED, &writeBuffer));
+ }
+ else
+ {
+ ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_UNIFORM, &writeBuffer));
+ }
+ }
+ else
+ {
+ ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_SYSTEM_MEMORY, &writeBuffer));
+ }
+ }
+ else if (supportsDirectBinding())
+ {
+ ANGLE_TRY(getStagingStorage(context, &writeBuffer));
+ }
+ else
+ {
+ ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_SYSTEM_MEMORY, &writeBuffer));
+ }
+
+ ASSERT(writeBuffer);
+
+ // Explicitly resize the staging buffer, preserving data if the new data will not
+ // completely fill the buffer
+ if (writeBuffer->getSize() < requiredSize)
+ {
+ bool preserveData = (offset > 0);
+ ANGLE_TRY(writeBuffer->resize(context, requiredSize, preserveData));
+ }
+
+ ANGLE_TRY(writeBuffer->setData(context, static_cast<const uint8_t *>(data), offset, size));
+ onStorageUpdate(writeBuffer);
+ }
+
+ mSize = std::max(mSize, requiredSize);
+ invalidateStaticData(context);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::copySubData(const gl::Context *context,
+ BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size)
+{
+ Buffer11 *sourceBuffer = GetAs<Buffer11>(source);
+ ASSERT(sourceBuffer != nullptr);
+
+ BufferStorage *copyDest = nullptr;
+ ANGLE_TRY(getLatestBufferStorage(context, &copyDest));
+
+ if (!copyDest)
+ {
+ ANGLE_TRY(getStagingStorage(context, &copyDest));
+ }
+
+ BufferStorage *copySource = nullptr;
+ ANGLE_TRY(sourceBuffer->getLatestBufferStorage(context, &copySource));
+
+ if (!copySource)
+ {
+ ANGLE_TRY(sourceBuffer->getStagingStorage(context, &copySource));
+ }
+
+ ASSERT(copySource && copyDest);
+
+ // A staging buffer is needed if there is no cpu-cpu or gpu-gpu copy path avaiable.
+ if (!copyDest->isGPUAccessible() && !copySource->isCPUAccessible(GL_MAP_READ_BIT))
+ {
+ ANGLE_TRY(sourceBuffer->getStagingStorage(context, &copySource));
+ }
+ else if (!copySource->isGPUAccessible() && !copyDest->isCPUAccessible(GL_MAP_WRITE_BIT))
+ {
+ ANGLE_TRY(getStagingStorage(context, &copyDest));
+ }
+
+ // D3D11 does not allow overlapped copies until 11.1, and only if the
+ // device supports D3D11_FEATURE_DATA_D3D11_OPTIONS::CopyWithOverlap
+ // Get around this via a different source buffer
+ if (copySource == copyDest)
+ {
+ if (copySource->getUsage() == BUFFER_USAGE_STAGING)
+ {
+ ANGLE_TRY(
+ getBufferStorage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, &copySource));
+ }
+ else
+ {
+ ANGLE_TRY(getStagingStorage(context, &copySource));
+ }
+ }
+
+ CopyResult copyResult = CopyResult::NOT_RECREATED;
+ ANGLE_TRY(copyDest->copyFromStorage(context, copySource, sourceOffset, size, destOffset,
+ &copyResult));
+ onStorageUpdate(copyDest);
+
+ mSize = std::max<size_t>(mSize, destOffset + size);
+ invalidateStaticData(context);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::map(const gl::Context *context, GLenum access, void **mapPtr)
+{
+ // GL_OES_mapbuffer uses an enum instead of a bitfield for it's access, convert to a bitfield
+ // and call mapRange.
+ ASSERT(access == GL_WRITE_ONLY_OES);
+ return mapRange(context, 0, mSize, GL_MAP_WRITE_BIT, mapPtr);
+}
+
+angle::Result Buffer11::mapRange(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ void **mapPtr)
+{
+ ASSERT(!mMappedStorage);
+
+ BufferStorage *latestStorage = nullptr;
+ ANGLE_TRY(getLatestBufferStorage(context, &latestStorage));
+
+ if (latestStorage && (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
+ latestStorage->getUsage() == BUFFER_USAGE_STAGING))
+ {
+ // Latest storage is mappable.
+ mMappedStorage = latestStorage;
+ }
+ else
+ {
+ // Fall back to using the staging buffer if the latest storage does not exist or is not
+ // CPU-accessible.
+ ANGLE_TRY(getStagingStorage(context, &mMappedStorage));
+ }
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+ ANGLE_CHECK_GL_ALLOC(context11, mMappedStorage);
+
+ if ((access & GL_MAP_WRITE_BIT) > 0)
+ {
+ // Update the data revision immediately, since the data might be changed at any time
+ onStorageUpdate(mMappedStorage);
+ invalidateStaticData(context);
+ }
+
+ uint8_t *mappedBuffer = nullptr;
+ ANGLE_TRY(mMappedStorage->map(context, offset, length, access, &mappedBuffer));
+ ASSERT(mappedBuffer);
+
+ *mapPtr = static_cast<void *>(mappedBuffer);
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::unmap(const gl::Context *context, GLboolean *result)
+{
+ ASSERT(mMappedStorage);
+ mMappedStorage->unmap();
+ mMappedStorage = nullptr;
+
+ // TODO: detect if we had corruption. if so, return false.
+ *result = GL_TRUE;
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::markTransformFeedbackUsage(const gl::Context *context)
+{
+ ANGLE_TRY(markBufferUsage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK));
+ return angle::Result::Continue;
+}
+
+void Buffer11::updateDeallocThreshold(BufferUsage usage)
+{
+ // The following strategy was tuned on the Oort online benchmark (http://oortonline.gl/)
+ // as well as a custom microbenchmark (IndexConversionPerfTest.Run/index_range_d3d11)
+
+ // First readback: 8 unmodified uses before we free buffer memory.
+ // After that, double the threshold each time until we reach the max.
+ if (mDeallocThresholds[usage] == 0)
+ {
+ mDeallocThresholds[usage] = 8;
+ }
+ else if (mDeallocThresholds[usage] < std::numeric_limits<unsigned int>::max() / 2u)
+ {
+ mDeallocThresholds[usage] *= 2u;
+ }
+ else
+ {
+ mDeallocThresholds[usage] = std::numeric_limits<unsigned int>::max();
+ }
+}
+
+// Free the storage if we decide it isn't being used very often.
+angle::Result Buffer11::checkForDeallocation(const gl::Context *context, BufferUsage usage)
+{
+ mIdleness[usage]++;
+
+ BufferStorage *&storage = mBufferStorages[usage];
+ if (storage != nullptr && mIdleness[usage] > mDeallocThresholds[usage])
+ {
+ BufferStorage *latestStorage = nullptr;
+ ANGLE_TRY(getLatestBufferStorage(context, &latestStorage));
+ if (latestStorage != storage)
+ {
+ SafeDelete(storage);
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+// Keep system memory when we are using it for the canonical version of data.
+bool Buffer11::canDeallocateSystemMemory() const
+{
+ // Must keep system memory on Intel.
+ if (mRenderer->getFeatures().useSystemMemoryForConstantBuffers.enabled)
+ {
+ return false;
+ }
+
+ return (!mBufferStorages[BUFFER_USAGE_UNIFORM] ||
+ mSize <= static_cast<size_t>(mRenderer->getNativeCaps().maxUniformBlockSize));
+}
+
+void Buffer11::markBufferUsage(BufferUsage usage)
+{
+ mIdleness[usage] = 0;
+}
+
+angle::Result Buffer11::markBufferUsage(const gl::Context *context, BufferUsage usage)
+{
+ BufferStorage *bufferStorage = nullptr;
+ ANGLE_TRY(getBufferStorage(context, usage, &bufferStorage));
+
+ if (bufferStorage)
+ {
+ onStorageUpdate(bufferStorage);
+ }
+
+ invalidateStaticData(context);
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::garbageCollection(const gl::Context *context, BufferUsage currentUsage)
+{
+ if (currentUsage != BUFFER_USAGE_SYSTEM_MEMORY && canDeallocateSystemMemory())
+ {
+ ANGLE_TRY(checkForDeallocation(context, BUFFER_USAGE_SYSTEM_MEMORY));
+ }
+
+ if (currentUsage != BUFFER_USAGE_STAGING)
+ {
+ ANGLE_TRY(checkForDeallocation(context, BUFFER_USAGE_STAGING));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::getBuffer(const gl::Context *context,
+ BufferUsage usage,
+ ID3D11Buffer **bufferOut)
+{
+ NativeStorage *storage = nullptr;
+ ANGLE_TRY(getBufferStorage(context, usage, &storage));
+ *bufferOut = storage->getBuffer().get();
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::getEmulatedIndexedBuffer(const gl::Context *context,
+ SourceIndexData *indexInfo,
+ const TranslatedAttribute &attribute,
+ GLint startVertex,
+ ID3D11Buffer **bufferOut)
+{
+ ASSERT(indexInfo);
+
+ EmulatedIndexedStorage *emulatedStorage = nullptr;
+ ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_EMULATED_INDEXED_VERTEX, &emulatedStorage));
+
+ const d3d11::Buffer *nativeBuffer = nullptr;
+ ANGLE_TRY(
+ emulatedStorage->getBuffer(context, indexInfo, attribute, startVertex, &nativeBuffer));
+ *bufferOut = nativeBuffer->get();
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::getConstantBufferRange(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size,
+ const d3d11::Buffer **bufferOut,
+ UINT *firstConstantOut,
+ UINT *numConstantsOut)
+{
+ NativeStorage *bufferStorage = nullptr;
+ if ((offset == 0 &&
+ size < static_cast<GLsizeiptr>(mRenderer->getNativeCaps().maxUniformBlockSize)) ||
+ mRenderer->getRenderer11DeviceCaps().supportsConstantBufferOffsets)
+ {
+ ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_UNIFORM, &bufferStorage));
+ CalculateConstantBufferParams(offset, size, firstConstantOut, numConstantsOut);
+ }
+ else
+ {
+ ANGLE_TRY(getConstantBufferRangeStorage(context, offset, size, &bufferStorage));
+ *firstConstantOut = 0;
+ *numConstantsOut = 0;
+ }
+
+ *bufferOut = &bufferStorage->getBuffer();
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::markRawBufferUsage(const gl::Context *context)
+{
+ ANGLE_TRY(markBufferUsage(context, BUFFER_USAGE_RAW_UAV));
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::markTypedBufferUsage(const gl::Context *context)
+{
+ ANGLE_TRY(markBufferUsage(context, BUFFER_USAGE_TYPED_UAV));
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::getRawUAVRange(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size,
+ d3d11::UnorderedAccessView **uavOut)
+{
+ NativeStorage *nativeStorage = nullptr;
+ ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_RAW_UAV, &nativeStorage));
+
+ return nativeStorage->getRawUAV(context, static_cast<unsigned int>(offset),
+ static_cast<unsigned int>(size), uavOut);
+}
+
+angle::Result Buffer11::getSRV(const gl::Context *context,
+ DXGI_FORMAT srvFormat,
+ const d3d11::ShaderResourceView **srvOut)
+{
+ NativeStorage *nativeStorage = nullptr;
+ ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_PIXEL_UNPACK, &nativeStorage));
+ return nativeStorage->getSRVForFormat(context, srvFormat, srvOut);
+}
+
+angle::Result Buffer11::packPixels(const gl::Context *context,
+ const gl::FramebufferAttachment &readAttachment,
+ const PackPixelsParams &params)
+{
+ PackStorage *packStorage = nullptr;
+ ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_PIXEL_PACK, &packStorage));
+
+ ASSERT(packStorage);
+ ANGLE_TRY(packStorage->packPixels(context, readAttachment, params));
+ onStorageUpdate(packStorage);
+
+ return angle::Result::Continue;
+}
+
+size_t Buffer11::getTotalCPUBufferMemoryBytes() const
+{
+ size_t allocationSize = 0;
+
+ BufferStorage *staging = mBufferStorages[BUFFER_USAGE_STAGING];
+ allocationSize += staging ? staging->getSize() : 0;
+
+ BufferStorage *sysMem = mBufferStorages[BUFFER_USAGE_SYSTEM_MEMORY];
+ allocationSize += sysMem ? sysMem->getSize() : 0;
+
+ return allocationSize;
+}
+
+template <typename StorageOutT>
+angle::Result Buffer11::getBufferStorage(const gl::Context *context,
+ BufferUsage usage,
+ StorageOutT **storageOut)
+{
+ ASSERT(0 <= usage && usage < BUFFER_USAGE_COUNT);
+ BufferStorage *&newStorage = mBufferStorages[usage];
+
+ if (!newStorage)
+ {
+ newStorage = allocateStorage(usage);
+ }
+
+ markBufferUsage(usage);
+
+ // resize buffer
+ if (newStorage->getSize() < mSize)
+ {
+ ANGLE_TRY(newStorage->resize(context, mSize, true));
+ }
+
+ ASSERT(newStorage);
+
+ ANGLE_TRY(updateBufferStorage(context, newStorage, 0, mSize));
+ ANGLE_TRY(garbageCollection(context, usage));
+
+ *storageOut = GetAs<StorageOutT>(newStorage);
+ return angle::Result::Continue;
+}
+
+Buffer11::BufferStorage *Buffer11::allocateStorage(BufferUsage usage)
+{
+ updateDeallocThreshold(usage);
+ switch (usage)
+ {
+ case BUFFER_USAGE_PIXEL_PACK:
+ return new PackStorage(mRenderer);
+ case BUFFER_USAGE_SYSTEM_MEMORY:
+ return new SystemMemoryStorage(mRenderer);
+ case BUFFER_USAGE_EMULATED_INDEXED_VERTEX:
+ return new EmulatedIndexedStorage(mRenderer);
+ case BUFFER_USAGE_INDEX:
+ case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
+ return new NativeStorage(mRenderer, usage, this);
+ case BUFFER_USAGE_STRUCTURED:
+ return new StructuredBufferStorage(mRenderer, usage, nullptr);
+ default:
+ return new NativeStorage(mRenderer, usage, nullptr);
+ }
+}
+
+angle::Result Buffer11::getConstantBufferRangeStorage(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size,
+ Buffer11::NativeStorage **storageOut)
+{
+ BufferStorage *newStorage;
+ {
+ // Keep the cacheEntry in a limited scope because it may be invalidated later in the code if
+ // we need to reclaim some space.
+ BufferCacheEntry *cacheEntry = &mConstantBufferRangeStoragesCache[offset];
+
+ if (!cacheEntry->storage)
+ {
+ cacheEntry->storage = allocateStorage(BUFFER_USAGE_UNIFORM);
+ cacheEntry->lruCount = ++mMaxConstantBufferLruCount;
+ }
+
+ cacheEntry->lruCount = ++mMaxConstantBufferLruCount;
+ newStorage = cacheEntry->storage;
+ }
+
+ markBufferUsage(BUFFER_USAGE_UNIFORM);
+
+ if (newStorage->getSize() < static_cast<size_t>(size))
+ {
+ size_t maximumAllowedAdditionalSize = 2 * getSize();
+
+ size_t sizeDelta = size - newStorage->getSize();
+
+ while (mConstantBufferStorageAdditionalSize + sizeDelta > maximumAllowedAdditionalSize)
+ {
+ auto iter = std::min_element(
+ std::begin(mConstantBufferRangeStoragesCache),
+ std::end(mConstantBufferRangeStoragesCache),
+ [](const BufferCache::value_type &a, const BufferCache::value_type &b) {
+ return a.second.lruCount < b.second.lruCount;
+ });
+
+ ASSERT(iter->second.storage != newStorage);
+ ASSERT(mConstantBufferStorageAdditionalSize >= iter->second.storage->getSize());
+
+ mConstantBufferStorageAdditionalSize -= iter->second.storage->getSize();
+ SafeDelete(iter->second.storage);
+ mConstantBufferRangeStoragesCache.erase(iter);
+ }
+
+ ANGLE_TRY(newStorage->resize(context, size, false));
+ mConstantBufferStorageAdditionalSize += sizeDelta;
+
+ // We don't copy the old data when resizing the constant buffer because the data may be
+ // out-of-date therefore we reset the data revision and let updateBufferStorage() handle the
+ // copy.
+ newStorage->setDataRevision(0);
+ }
+
+ ANGLE_TRY(updateBufferStorage(context, newStorage, offset, size));
+ ANGLE_TRY(garbageCollection(context, BUFFER_USAGE_UNIFORM));
+ *storageOut = GetAs<NativeStorage>(newStorage);
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::getStructuredBufferRangeSRV(const gl::Context *context,
+ unsigned int offset,
+ unsigned int size,
+ unsigned int structureByteStride,
+ const d3d11::ShaderResourceView **srvOut)
+{
+ BufferStorage *newStorage;
+
+ {
+ // Keep the cacheEntry in a limited scope because it may be invalidated later in the code if
+ // we need to reclaim some space.
+ StructuredBufferKey structuredBufferKey = StructuredBufferKey(offset, structureByteStride);
+ BufferCacheEntry *cacheEntry = &mStructuredBufferRangeStoragesCache[structuredBufferKey];
+
+ if (!cacheEntry->storage)
+ {
+ cacheEntry->storage = allocateStorage(BUFFER_USAGE_STRUCTURED);
+ cacheEntry->lruCount = ++mMaxStructuredBufferLruCount;
+ }
+
+ cacheEntry->lruCount = ++mMaxStructuredBufferLruCount;
+ newStorage = cacheEntry->storage;
+ }
+
+ StructuredBufferStorage *structuredBufferStorage = GetAs<StructuredBufferStorage>(newStorage);
+
+ markBufferUsage(BUFFER_USAGE_STRUCTURED);
+
+ if (newStorage->getSize() < static_cast<size_t>(size))
+ {
+ size_t maximumAllowedAdditionalSize = 2 * getSize();
+
+ size_t sizeDelta = static_cast<size_t>(size) - newStorage->getSize();
+
+ while (mStructuredBufferStorageAdditionalSize + sizeDelta > maximumAllowedAdditionalSize)
+ {
+ auto iter = std::min_element(std::begin(mStructuredBufferRangeStoragesCache),
+ std::end(mStructuredBufferRangeStoragesCache),
+ [](const StructuredBufferCache::value_type &a,
+ const StructuredBufferCache::value_type &b) {
+ return a.second.lruCount < b.second.lruCount;
+ });
+
+ ASSERT(iter->second.storage != newStorage);
+ ASSERT(mStructuredBufferStorageAdditionalSize >= iter->second.storage->getSize());
+
+ mStructuredBufferStorageAdditionalSize -= iter->second.storage->getSize();
+ SafeDelete(iter->second.storage);
+ mStructuredBufferRangeStoragesCache.erase(iter);
+ }
+
+ ANGLE_TRY(
+ structuredBufferStorage->resizeStructuredBuffer(context, size, structureByteStride));
+ mStructuredBufferStorageAdditionalSize += sizeDelta;
+
+ // We don't copy the old data when resizing the structured buffer because the data may be
+ // out-of-date therefore we reset the data revision and let updateBufferStorage() handle the
+ // copy.
+ newStorage->setDataRevision(0);
+ }
+
+ ANGLE_TRY(updateBufferStorage(context, newStorage, offset, static_cast<size_t>(size)));
+ ANGLE_TRY(garbageCollection(context, BUFFER_USAGE_STRUCTURED));
+ ANGLE_TRY(structuredBufferStorage->getStructuredBufferRangeSRV(context, offset, size,
+ structureByteStride, srvOut));
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::updateBufferStorage(const gl::Context *context,
+ BufferStorage *storage,
+ size_t sourceOffset,
+ size_t storageSize)
+{
+ BufferStorage *latestBuffer = nullptr;
+ ANGLE_TRY(getLatestBufferStorage(context, &latestBuffer));
+
+ ASSERT(storage);
+
+ if (!latestBuffer)
+ {
+ onStorageUpdate(storage);
+ return angle::Result::Continue;
+ }
+
+ if (latestBuffer->getDataRevision() <= storage->getDataRevision())
+ {
+ return angle::Result::Continue;
+ }
+
+ if (latestBuffer->getSize() == 0 || storage->getSize() == 0)
+ {
+ return angle::Result::Continue;
+ }
+
+ // Copy through a staging buffer if we're copying from or to a non-staging, mappable
+ // buffer storage. This is because we can't map a GPU buffer, and copy CPU
+ // data directly. If we're already using a staging buffer we're fine.
+ if (latestBuffer->getUsage() != BUFFER_USAGE_STAGING &&
+ storage->getUsage() != BUFFER_USAGE_STAGING &&
+ (!latestBuffer->isCPUAccessible(GL_MAP_READ_BIT) ||
+ !storage->isCPUAccessible(GL_MAP_WRITE_BIT)))
+ {
+ NativeStorage *stagingBuffer = nullptr;
+ ANGLE_TRY(getStagingStorage(context, &stagingBuffer));
+
+ CopyResult copyResult = CopyResult::NOT_RECREATED;
+ ANGLE_TRY(stagingBuffer->copyFromStorage(context, latestBuffer, 0, latestBuffer->getSize(),
+ 0, &copyResult));
+ onCopyStorage(stagingBuffer, latestBuffer);
+
+ latestBuffer = stagingBuffer;
+ }
+
+ CopyResult copyResult = CopyResult::NOT_RECREATED;
+ ANGLE_TRY(
+ storage->copyFromStorage(context, latestBuffer, sourceOffset, storageSize, 0, &copyResult));
+ // If the D3D buffer has been recreated, we should update our serial.
+ if (copyResult == CopyResult::RECREATED)
+ {
+ updateSerial();
+ }
+ onCopyStorage(storage, latestBuffer);
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::getLatestBufferStorage(const gl::Context *context,
+ Buffer11::BufferStorage **storageOut) const
+{
+ // resize buffer
+ if (mLatestBufferStorage && mLatestBufferStorage->getSize() < mSize)
+ {
+ ANGLE_TRY(mLatestBufferStorage->resize(context, mSize, true));
+ }
+
+ *storageOut = mLatestBufferStorage;
+ return angle::Result::Continue;
+}
+
+template <typename StorageOutT>
+angle::Result Buffer11::getStagingStorage(const gl::Context *context, StorageOutT **storageOut)
+{
+ return getBufferStorage(context, BUFFER_USAGE_STAGING, storageOut);
+}
+
+size_t Buffer11::getSize() const
+{
+ return mSize;
+}
+
+bool Buffer11::supportsDirectBinding() const
+{
+ // Do not support direct buffers for dynamic data. The streaming buffer
+ // offers better performance for data which changes every frame.
+ return (mUsage == D3DBufferUsage::STATIC);
+}
+
+void Buffer11::initializeStaticData(const gl::Context *context)
+{
+ BufferD3D::initializeStaticData(context);
+ onStateChange(angle::SubjectMessage::SubjectChanged);
+}
+
+void Buffer11::invalidateStaticData(const gl::Context *context)
+{
+ BufferD3D::invalidateStaticData(context);
+ onStateChange(angle::SubjectMessage::SubjectChanged);
+}
+
+void Buffer11::onCopyStorage(BufferStorage *dest, BufferStorage *source)
+{
+ ASSERT(source && mLatestBufferStorage);
+ dest->setDataRevision(source->getDataRevision());
+
+ // Only update the latest buffer storage if our usage index is lower. See comment in header.
+ if (dest->getUsage() < mLatestBufferStorage->getUsage())
+ {
+ mLatestBufferStorage = dest;
+ }
+}
+
+void Buffer11::onStorageUpdate(BufferStorage *updatedStorage)
+{
+ updatedStorage->setDataRevision(updatedStorage->getDataRevision() + 1);
+ mLatestBufferStorage = updatedStorage;
+}
+
+// Buffer11::BufferStorage implementation
+
+Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage)
+ : mRenderer(renderer), mRevision(0), mUsage(usage), mBufferSize(0)
+{}
+
+angle::Result Buffer11::BufferStorage::setData(const gl::Context *context,
+ const uint8_t *data,
+ size_t offset,
+ size_t size)
+{
+ ASSERT(isCPUAccessible(GL_MAP_WRITE_BIT));
+
+ // Uniform storage can have a different internal size than the buffer size. Ensure we don't
+ // overflow.
+ size_t mapSize = std::min(size, mBufferSize - offset);
+
+ uint8_t *writePointer = nullptr;
+ ANGLE_TRY(map(context, offset, mapSize, GL_MAP_WRITE_BIT, &writePointer));
+
+ memcpy(writePointer, data, mapSize);
+
+ unmap();
+
+ return angle::Result::Continue;
+}
+
+// Buffer11::NativeStorage implementation
+
+Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer,
+ BufferUsage usage,
+ const angle::Subject *onStorageChanged)
+ : BufferStorage(renderer, usage), mBuffer(), mOnStorageChanged(onStorageChanged)
+{}
+
+Buffer11::NativeStorage::~NativeStorage()
+{
+ clearSRVs();
+ clearUAVs();
+}
+
+bool Buffer11::NativeStorage::isCPUAccessible(GLbitfield access) const
+{
+ if ((access & GL_MAP_READ_BIT) != 0)
+ {
+ // Read is more exclusive than write mappability.
+ return (mUsage == BUFFER_USAGE_STAGING);
+ }
+ ASSERT((access & GL_MAP_WRITE_BIT) != 0);
+ return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_UNIFORM ||
+ mUsage == BUFFER_USAGE_STRUCTURED);
+}
+
+// Returns true if it recreates the direct buffer
+angle::Result Buffer11::NativeStorage::copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset,
+ CopyResult *resultOut)
+{
+ size_t requiredSize = destOffset + size;
+
+ // (Re)initialize D3D buffer if needed
+ bool preserveData = (destOffset > 0);
+ if (!mBuffer.valid() || mBufferSize < requiredSize)
+ {
+ ANGLE_TRY(resize(context, requiredSize, preserveData));
+ *resultOut = CopyResult::RECREATED;
+ }
+ else
+ {
+ *resultOut = CopyResult::NOT_RECREATED;
+ }
+
+ size_t clampedSize = size;
+ if (mUsage == BUFFER_USAGE_UNIFORM)
+ {
+ clampedSize = std::min(clampedSize, mBufferSize - destOffset);
+ }
+
+ if (clampedSize == 0)
+ {
+ return angle::Result::Continue;
+ }
+
+ if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
+ source->getUsage() == BUFFER_USAGE_SYSTEM_MEMORY)
+ {
+ ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT) && isCPUAccessible(GL_MAP_WRITE_BIT));
+
+ // Uniform buffers must be mapped with write/discard.
+ ASSERT(!(preserveData && mUsage == BUFFER_USAGE_UNIFORM));
+
+ uint8_t *sourcePointer = nullptr;
+ ANGLE_TRY(source->map(context, sourceOffset, clampedSize, GL_MAP_READ_BIT, &sourcePointer));
+
+ auto err = setData(context, sourcePointer, destOffset, clampedSize);
+ source->unmap();
+ ANGLE_TRY(err);
+ }
+ else
+ {
+ D3D11_BOX srcBox;
+ srcBox.left = static_cast<unsigned int>(sourceOffset);
+ srcBox.right = static_cast<unsigned int>(sourceOffset + clampedSize);
+ srcBox.top = 0;
+ srcBox.bottom = 1;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ const d3d11::Buffer *sourceBuffer = &GetAs<NativeStorage>(source)->getBuffer();
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->CopySubresourceRegion(mBuffer.get(), 0,
+ static_cast<unsigned int>(destOffset), 0, 0,
+ sourceBuffer->get(), 0, &srcBox);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::NativeStorage::resize(const gl::Context *context,
+ size_t size,
+ bool preserveData)
+{
+ if (size == 0)
+ {
+ mBuffer.reset();
+ mBufferSize = 0;
+ return angle::Result::Continue;
+ }
+
+ D3D11_BUFFER_DESC bufferDesc;
+ FillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast<unsigned int>(size));
+
+ d3d11::Buffer newBuffer;
+ ANGLE_TRY(
+ mRenderer->allocateResource(SafeGetImplAs<Context11>(context), bufferDesc, &newBuffer));
+ newBuffer.setInternalName("Buffer11::NativeStorage");
+
+ if (mBuffer.valid() && preserveData)
+ {
+ // We don't call resize if the buffer is big enough already.
+ ASSERT(mBufferSize <= size);
+
+ D3D11_BOX srcBox;
+ srcBox.left = 0;
+ srcBox.right = static_cast<unsigned int>(mBufferSize);
+ srcBox.top = 0;
+ srcBox.bottom = 1;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->CopySubresourceRegion(newBuffer.get(), 0, 0, 0, 0, mBuffer.get(), 0,
+ &srcBox);
+ }
+
+ // No longer need the old buffer
+ mBuffer = std::move(newBuffer);
+
+ mBufferSize = bufferDesc.ByteWidth;
+
+ // Free the SRVs.
+ clearSRVs();
+
+ // Free the UAVs.
+ clearUAVs();
+
+ // Notify that the storage has changed.
+ if (mOnStorageChanged)
+ {
+ mOnStorageChanged->onStateChange(angle::SubjectMessage::SubjectChanged);
+ }
+
+ return angle::Result::Continue;
+}
+
+// static
+void Buffer11::NativeStorage::FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
+ Renderer11 *renderer,
+ BufferUsage usage,
+ unsigned int bufferSize)
+{
+ bufferDesc->ByteWidth = bufferSize;
+ bufferDesc->MiscFlags = 0;
+ bufferDesc->StructureByteStride = 0;
+
+ switch (usage)
+ {
+ case BUFFER_USAGE_STAGING:
+ bufferDesc->Usage = D3D11_USAGE_STAGING;
+ bufferDesc->BindFlags = 0;
+ bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+ break;
+
+ case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
+ bufferDesc->Usage = D3D11_USAGE_DEFAULT;
+ bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER;
+
+ if (renderer->isES3Capable())
+ {
+ bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT;
+ }
+
+ bufferDesc->CPUAccessFlags = 0;
+ break;
+
+ case BUFFER_USAGE_INDEX:
+ bufferDesc->Usage = D3D11_USAGE_DEFAULT;
+ bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER;
+ bufferDesc->CPUAccessFlags = 0;
+ break;
+
+ case BUFFER_USAGE_INDIRECT:
+ bufferDesc->MiscFlags = D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS;
+ bufferDesc->Usage = D3D11_USAGE_DEFAULT;
+ bufferDesc->BindFlags = 0;
+ bufferDesc->CPUAccessFlags = 0;
+ break;
+
+ case BUFFER_USAGE_PIXEL_UNPACK:
+ bufferDesc->Usage = D3D11_USAGE_DEFAULT;
+ bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ bufferDesc->CPUAccessFlags = 0;
+ break;
+
+ case BUFFER_USAGE_UNIFORM:
+ bufferDesc->Usage = D3D11_USAGE_DYNAMIC;
+ bufferDesc->BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+
+ // Constant buffers must be of a limited size, and aligned to 16 byte boundaries
+ // For our purposes we ignore any buffer data past the maximum constant buffer size
+ bufferDesc->ByteWidth = roundUpPow2(bufferDesc->ByteWidth, 16u);
+
+ // Note: it seems that D3D11 allows larger buffers on some platforms, but not all.
+ // (Windows 10 seems to allow larger constant buffers, but not Windows 7)
+ if (!renderer->getRenderer11DeviceCaps().supportsConstantBufferOffsets)
+ {
+ bufferDesc->ByteWidth = std::min<UINT>(
+ bufferDesc->ByteWidth,
+ static_cast<UINT>(renderer->getNativeCaps().maxUniformBlockSize));
+ }
+ break;
+
+ case BUFFER_USAGE_RAW_UAV:
+ bufferDesc->MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS;
+ bufferDesc->BindFlags = D3D11_BIND_UNORDERED_ACCESS;
+ bufferDesc->Usage = D3D11_USAGE_DEFAULT;
+ bufferDesc->CPUAccessFlags = 0;
+ break;
+ case BUFFER_USAGE_TYPED_UAV:
+ bufferDesc->BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
+ bufferDesc->Usage = D3D11_USAGE_DEFAULT;
+ bufferDesc->CPUAccessFlags = 0;
+ bufferDesc->MiscFlags = 0;
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+angle::Result Buffer11::NativeStorage::map(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut)
+{
+ ASSERT(isCPUAccessible(access));
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(mUsage, access);
+ UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0);
+
+ ANGLE_TRY(
+ mRenderer->mapResource(context, mBuffer.get(), 0, d3dMapType, d3dMapFlag, &mappedResource));
+ ASSERT(mappedResource.pData);
+ *mapPointerOut = static_cast<uint8_t *>(mappedResource.pData) + offset;
+ return angle::Result::Continue;
+}
+
+void Buffer11::NativeStorage::unmap()
+{
+ ASSERT(isCPUAccessible(GL_MAP_WRITE_BIT) || isCPUAccessible(GL_MAP_READ_BIT));
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ context->Unmap(mBuffer.get(), 0);
+}
+
+angle::Result Buffer11::NativeStorage::getSRVForFormat(const gl::Context *context,
+ DXGI_FORMAT srvFormat,
+ const d3d11::ShaderResourceView **srvOut)
+{
+ auto bufferSRVIt = mBufferResourceViews.find(srvFormat);
+
+ if (bufferSRVIt != mBufferResourceViews.end())
+ {
+ *srvOut = &bufferSRVIt->second;
+ return angle::Result::Continue;
+ }
+
+ const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(srvFormat);
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc;
+ bufferSRVDesc.Buffer.ElementOffset = 0;
+ bufferSRVDesc.Buffer.ElementWidth = static_cast<UINT>(mBufferSize) / dxgiFormatInfo.pixelBytes;
+ bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
+ bufferSRVDesc.Format = srvFormat;
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), bufferSRVDesc,
+ mBuffer.get(), &mBufferResourceViews[srvFormat]));
+
+ *srvOut = &mBufferResourceViews[srvFormat];
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::NativeStorage::getRawUAV(const gl::Context *context,
+ unsigned int offset,
+ unsigned int size,
+ d3d11::UnorderedAccessView **uavOut)
+{
+ ASSERT(offset + size <= mBufferSize);
+
+ auto bufferRawUAV = mBufferRawUAVs.find({offset, size});
+ if (bufferRawUAV != mBufferRawUAVs.end())
+ {
+ *uavOut = &bufferRawUAV->second;
+ return angle::Result::Continue;
+ }
+
+ D3D11_UNORDERED_ACCESS_VIEW_DESC bufferUAVDesc;
+
+ // DXGI_FORMAT_R32_TYPELESS uses 4 bytes per element
+ constexpr int kBytesToElement = 4;
+ bufferUAVDesc.Buffer.FirstElement = offset / kBytesToElement;
+ bufferUAVDesc.Buffer.NumElements = size / kBytesToElement;
+ bufferUAVDesc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
+ bufferUAVDesc.Format = DXGI_FORMAT_R32_TYPELESS; // Format must be DXGI_FORMAT_R32_TYPELESS,
+ // when creating Raw Unordered Access View
+ bufferUAVDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), bufferUAVDesc,
+ mBuffer.get(), &mBufferRawUAVs[{offset, size}]));
+ *uavOut = &mBufferRawUAVs[{offset, size}];
+ return angle::Result::Continue;
+}
+
+void Buffer11::NativeStorage::clearSRVs()
+{
+ mBufferResourceViews.clear();
+}
+
+void Buffer11::NativeStorage::clearUAVs()
+{
+ mBufferRawUAVs.clear();
+}
+
+Buffer11::StructuredBufferStorage::StructuredBufferStorage(Renderer11 *renderer,
+ BufferUsage usage,
+ const angle::Subject *onStorageChanged)
+ : NativeStorage(renderer, usage, onStorageChanged), mStructuredBufferResourceView()
+{}
+
+Buffer11::StructuredBufferStorage::~StructuredBufferStorage()
+{
+ mStructuredBufferResourceView.reset();
+}
+
+angle::Result Buffer11::StructuredBufferStorage::resizeStructuredBuffer(
+ const gl::Context *context,
+ unsigned int size,
+ unsigned int structureByteStride)
+{
+ if (size == 0)
+ {
+ mBuffer.reset();
+ mBufferSize = 0;
+ return angle::Result::Continue;
+ }
+
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = size;
+ bufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
+ bufferDesc.StructureByteStride = structureByteStride;
+ bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+ bufferDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+
+ d3d11::Buffer newBuffer;
+ ANGLE_TRY(
+ mRenderer->allocateResource(SafeGetImplAs<Context11>(context), bufferDesc, &newBuffer));
+ newBuffer.setInternalName("Buffer11::StructuredBufferStorage");
+
+ // No longer need the old buffer
+ mBuffer = std::move(newBuffer);
+
+ mBufferSize = static_cast<size_t>(bufferDesc.ByteWidth);
+
+ mStructuredBufferResourceView.reset();
+
+ // Notify that the storage has changed.
+ if (mOnStorageChanged)
+ {
+ mOnStorageChanged->onStateChange(angle::SubjectMessage::SubjectChanged);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::StructuredBufferStorage::getStructuredBufferRangeSRV(
+ const gl::Context *context,
+ unsigned int offset,
+ unsigned int size,
+ unsigned int structureByteStride,
+ const d3d11::ShaderResourceView **srvOut)
+{
+ if (mStructuredBufferResourceView.valid())
+ {
+ *srvOut = &mStructuredBufferResourceView;
+ return angle::Result::Continue;
+ }
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc = {};
+ bufferSRVDesc.BufferEx.NumElements = structureByteStride == 0u ? 1 : size / structureByteStride;
+ bufferSRVDesc.BufferEx.FirstElement = 0;
+ bufferSRVDesc.BufferEx.Flags = 0;
+ bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX;
+ bufferSRVDesc.Format = DXGI_FORMAT_UNKNOWN;
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), bufferSRVDesc,
+ mBuffer.get(), &mStructuredBufferResourceView));
+
+ *srvOut = &mStructuredBufferResourceView;
+ return angle::Result::Continue;
+}
+
+// Buffer11::EmulatedIndexStorage implementation
+Buffer11::EmulatedIndexedStorage::EmulatedIndexedStorage(Renderer11 *renderer)
+ : BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mBuffer()
+{}
+
+Buffer11::EmulatedIndexedStorage::~EmulatedIndexedStorage() {}
+
+angle::Result Buffer11::EmulatedIndexedStorage::getBuffer(const gl::Context *context,
+ SourceIndexData *indexInfo,
+ const TranslatedAttribute &attribute,
+ GLint startVertex,
+ const d3d11::Buffer **bufferOut)
+{
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ // If a change in the indices applied from the last draw call is detected, then the emulated
+ // indexed buffer needs to be invalidated. After invalidation, the change detected flag should
+ // be cleared to avoid unnecessary recreation of the buffer.
+ if (!mBuffer.valid() || indexInfo->srcIndicesChanged)
+ {
+ mBuffer.reset();
+
+ // Copy the source index data. This ensures that the lifetime of the indices pointer
+ // stays with this storage until the next time we invalidate.
+ size_t indicesDataSize = 0;
+ switch (indexInfo->srcIndexType)
+ {
+ case gl::DrawElementsType::UnsignedInt:
+ indicesDataSize = sizeof(GLuint) * indexInfo->srcCount;
+ break;
+ case gl::DrawElementsType::UnsignedShort:
+ indicesDataSize = sizeof(GLushort) * indexInfo->srcCount;
+ break;
+ case gl::DrawElementsType::UnsignedByte:
+ indicesDataSize = sizeof(GLubyte) * indexInfo->srcCount;
+ break;
+ default:
+ indicesDataSize = sizeof(GLushort) * indexInfo->srcCount;
+ break;
+ }
+
+ ANGLE_CHECK_GL_ALLOC(context11, mIndicesMemoryBuffer.resize(indicesDataSize));
+
+ memcpy(mIndicesMemoryBuffer.data(), indexInfo->srcIndices, indicesDataSize);
+
+ indexInfo->srcIndicesChanged = false;
+ }
+
+ if (!mBuffer.valid())
+ {
+ unsigned int offset = 0;
+ ANGLE_TRY(attribute.computeOffset(context, startVertex, &offset));
+
+ // Expand the memory storage upon request and cache the results.
+ unsigned int expandedDataSize =
+ static_cast<unsigned int>((indexInfo->srcCount * attribute.stride) + offset);
+ angle::MemoryBuffer expandedData;
+ ANGLE_CHECK_GL_ALLOC(context11, expandedData.resize(expandedDataSize));
+
+ // Clear the contents of the allocated buffer
+ ZeroMemory(expandedData.data(), expandedDataSize);
+
+ uint8_t *curr = expandedData.data();
+ const uint8_t *ptr = static_cast<const uint8_t *>(indexInfo->srcIndices);
+
+ // Ensure that we start in the correct place for the emulated data copy operation to
+ // maintain offset behaviors.
+ curr += offset;
+
+ ReadIndexValueFunction readIndexValue = ReadIndexValueFromIndices<GLushort>;
+
+ switch (indexInfo->srcIndexType)
+ {
+ case gl::DrawElementsType::UnsignedInt:
+ readIndexValue = ReadIndexValueFromIndices<GLuint>;
+ break;
+ case gl::DrawElementsType::UnsignedShort:
+ readIndexValue = ReadIndexValueFromIndices<GLushort>;
+ break;
+ case gl::DrawElementsType::UnsignedByte:
+ readIndexValue = ReadIndexValueFromIndices<GLubyte>;
+ break;
+ default:
+ UNREACHABLE();
+ return angle::Result::Stop;
+ }
+
+ // Iterate over the cached index data and copy entries indicated into the emulated buffer.
+ for (GLuint i = 0; i < indexInfo->srcCount; i++)
+ {
+ GLuint idx = readIndexValue(ptr, i);
+ memcpy(curr, mMemoryBuffer.data() + (attribute.stride * idx), attribute.stride);
+ curr += attribute.stride;
+ }
+
+ // Finally, initialize the emulated indexed native storage object with the newly copied data
+ // and free the temporary buffers used.
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = expandedDataSize;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.StructureByteStride = 0;
+ bufferDesc.Usage = D3D11_USAGE_DEFAULT;
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.CPUAccessFlags = 0;
+
+ D3D11_SUBRESOURCE_DATA subResourceData = {expandedData.data(), 0, 0};
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), bufferDesc,
+ &subResourceData, &mBuffer));
+ mBuffer.setInternalName("Buffer11::EmulatedIndexedStorage");
+ }
+
+ *bufferOut = &mBuffer;
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::EmulatedIndexedStorage::copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset,
+ CopyResult *resultOut)
+{
+ ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT));
+ uint8_t *sourceData = nullptr;
+ ANGLE_TRY(source->map(context, sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
+ ASSERT(destOffset + size <= mMemoryBuffer.size());
+ memcpy(mMemoryBuffer.data() + destOffset, sourceData, size);
+ source->unmap();
+ *resultOut = CopyResult::RECREATED;
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::EmulatedIndexedStorage::resize(const gl::Context *context,
+ size_t size,
+ bool preserveData)
+{
+ if (mMemoryBuffer.size() < size)
+ {
+ Context11 *context11 = GetImplAs<Context11>(context);
+ ANGLE_CHECK_GL_ALLOC(context11, mMemoryBuffer.resize(size));
+ mBufferSize = size;
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::EmulatedIndexedStorage::map(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut)
+{
+ ASSERT(!mMemoryBuffer.empty() && offset + length <= mMemoryBuffer.size());
+ *mapPointerOut = mMemoryBuffer.data() + offset;
+ return angle::Result::Continue;
+}
+
+void Buffer11::EmulatedIndexedStorage::unmap()
+{
+ // No-op
+}
+
+// Buffer11::PackStorage implementation
+
+Buffer11::PackStorage::PackStorage(Renderer11 *renderer)
+ : BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), mStagingTexture(), mDataModified(false)
+{}
+
+Buffer11::PackStorage::~PackStorage() {}
+
+angle::Result Buffer11::PackStorage::copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset,
+ CopyResult *resultOut)
+{
+ ANGLE_TRY(flushQueuedPackCommand(context));
+
+ // For all use cases of pack buffers, we must copy through a readable buffer.
+ ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT));
+ uint8_t *sourceData = nullptr;
+ ANGLE_TRY(source->map(context, sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
+ ASSERT(destOffset + size <= mMemoryBuffer.size());
+ memcpy(mMemoryBuffer.data() + destOffset, sourceData, size);
+ source->unmap();
+ *resultOut = CopyResult::NOT_RECREATED;
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::PackStorage::resize(const gl::Context *context,
+ size_t size,
+ bool preserveData)
+{
+ if (size != mBufferSize)
+ {
+ Context11 *context11 = GetImplAs<Context11>(context);
+ ANGLE_CHECK_GL_ALLOC(context11, mMemoryBuffer.resize(size));
+ mBufferSize = size;
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::PackStorage::map(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut)
+{
+ ASSERT(offset + length <= getSize());
+ // TODO: fast path
+ // We might be able to optimize out one or more memcpy calls by detecting when
+ // and if D3D packs the staging texture memory identically to how we would fill
+ // the pack buffer according to the current pack state.
+
+ ANGLE_TRY(flushQueuedPackCommand(context));
+
+ mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0);
+
+ *mapPointerOut = mMemoryBuffer.data() + offset;
+ return angle::Result::Continue;
+}
+
+void Buffer11::PackStorage::unmap()
+{
+ // No-op
+}
+
+angle::Result Buffer11::PackStorage::packPixels(const gl::Context *context,
+ const gl::FramebufferAttachment &readAttachment,
+ const PackPixelsParams &params)
+{
+ ANGLE_TRY(flushQueuedPackCommand(context));
+
+ RenderTarget11 *renderTarget = nullptr;
+ ANGLE_TRY(readAttachment.getRenderTarget(context, 0, &renderTarget));
+
+ const TextureHelper11 &srcTexture = renderTarget->getTexture();
+ ASSERT(srcTexture.valid());
+ unsigned int srcSubresource = renderTarget->getSubresourceIndex();
+
+ mQueuedPackCommand.reset(new PackPixelsParams(params));
+
+ gl::Extents srcTextureSize(params.area.width, params.area.height, 1);
+ if (!mStagingTexture.get() || mStagingTexture.getFormat() != srcTexture.getFormat() ||
+ mStagingTexture.getExtents() != srcTextureSize)
+ {
+ ANGLE_TRY(mRenderer->createStagingTexture(context, srcTexture.getTextureType(),
+ srcTexture.getFormatSet(), srcTextureSize,
+ StagingAccess::READ, &mStagingTexture));
+ }
+
+ // ReadPixels from multisampled FBOs isn't supported in current GL
+ ASSERT(srcTexture.getSampleCount() <= 1);
+
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+ D3D11_BOX srcBox;
+ srcBox.left = params.area.x;
+ srcBox.right = params.area.x + params.area.width;
+ srcBox.top = params.area.y;
+ srcBox.bottom = params.area.y + params.area.height;
+
+ // Select the correct layer from a 3D attachment
+ srcBox.front = 0;
+ if (mStagingTexture.is3D())
+ {
+ srcBox.front = static_cast<UINT>(readAttachment.layer());
+ }
+ srcBox.back = srcBox.front + 1;
+
+ // Asynchronous copy
+ immediateContext->CopySubresourceRegion(mStagingTexture.get(), 0, 0, 0, 0, srcTexture.get(),
+ srcSubresource, &srcBox);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::PackStorage::flushQueuedPackCommand(const gl::Context *context)
+{
+ ASSERT(mMemoryBuffer.size() > 0);
+
+ if (mQueuedPackCommand)
+ {
+ ANGLE_TRY(mRenderer->packPixels(context, mStagingTexture, *mQueuedPackCommand,
+ mMemoryBuffer.data()));
+ mQueuedPackCommand.reset(nullptr);
+ }
+
+ return angle::Result::Continue;
+}
+
+// Buffer11::SystemMemoryStorage implementation
+
+Buffer11::SystemMemoryStorage::SystemMemoryStorage(Renderer11 *renderer)
+ : Buffer11::BufferStorage(renderer, BUFFER_USAGE_SYSTEM_MEMORY)
+{}
+
+angle::Result Buffer11::SystemMemoryStorage::copyFromStorage(const gl::Context *context,
+ BufferStorage *source,
+ size_t sourceOffset,
+ size_t size,
+ size_t destOffset,
+ CopyResult *resultOut)
+{
+ ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT));
+ uint8_t *sourceData = nullptr;
+ ANGLE_TRY(source->map(context, sourceOffset, size, GL_MAP_READ_BIT, &sourceData));
+ ASSERT(destOffset + size <= mSystemCopy.size());
+ memcpy(mSystemCopy.data() + destOffset, sourceData, size);
+ source->unmap();
+ *resultOut = CopyResult::RECREATED;
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::SystemMemoryStorage::resize(const gl::Context *context,
+ size_t size,
+ bool preserveData)
+{
+ if (mSystemCopy.size() < size)
+ {
+ Context11 *context11 = GetImplAs<Context11>(context);
+ ANGLE_CHECK_GL_ALLOC(context11, mSystemCopy.resize(size));
+ mBufferSize = size;
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer11::SystemMemoryStorage::map(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ uint8_t **mapPointerOut)
+{
+ ASSERT(!mSystemCopy.empty() && offset + length <= mSystemCopy.size());
+ *mapPointerOut = mSystemCopy.data() + offset;
+ return angle::Result::Continue;
+}
+
+void Buffer11::SystemMemoryStorage::unmap()
+{
+ // No-op
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Buffer11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
new file mode 100644
index 0000000000..b24bd1a48b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
@@ -0,0 +1,234 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Buffer11.h: Defines the rx::Buffer11 class which implements rx::BufferImpl via rx::BufferD3D.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
+
+#include <array>
+#include <map>
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+}
+
+namespace rx
+{
+struct PackPixelsParams;
+class Renderer11;
+struct SourceIndexData;
+struct TranslatedAttribute;
+
+// The order of this enum governs priority of 'getLatestBufferStorage'.
+enum BufferUsage
+{
+ BUFFER_USAGE_SYSTEM_MEMORY,
+ BUFFER_USAGE_STAGING,
+ BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK,
+ BUFFER_USAGE_INDEX,
+ BUFFER_USAGE_INDIRECT,
+ BUFFER_USAGE_PIXEL_UNPACK,
+ BUFFER_USAGE_PIXEL_PACK,
+ BUFFER_USAGE_UNIFORM,
+ BUFFER_USAGE_STRUCTURED,
+ BUFFER_USAGE_EMULATED_INDEXED_VERTEX,
+ BUFFER_USAGE_RAW_UAV,
+ BUFFER_USAGE_TYPED_UAV,
+
+ BUFFER_USAGE_COUNT,
+};
+
+typedef size_t DataRevision;
+
+class Buffer11 : public BufferD3D
+{
+ public:
+ Buffer11(const gl::BufferState &state, Renderer11 *renderer);
+ ~Buffer11() override;
+
+ angle::Result getBuffer(const gl::Context *context,
+ BufferUsage usage,
+ ID3D11Buffer **bufferOut);
+ angle::Result getEmulatedIndexedBuffer(const gl::Context *context,
+ SourceIndexData *indexInfo,
+ const TranslatedAttribute &attribute,
+ GLint startVertex,
+ ID3D11Buffer **bufferOut);
+ angle::Result getConstantBufferRange(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size,
+ const d3d11::Buffer **bufferOut,
+ UINT *firstConstantOut,
+ UINT *numConstantsOut);
+ angle::Result getStructuredBufferRangeSRV(const gl::Context *context,
+ unsigned int offset,
+ unsigned int size,
+ unsigned int structureByteStride,
+ const d3d11::ShaderResourceView **srvOut);
+ angle::Result getSRV(const gl::Context *context,
+ DXGI_FORMAT srvFormat,
+ const d3d11::ShaderResourceView **srvOut);
+ angle::Result getRawUAVRange(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size,
+ d3d11::UnorderedAccessView **uavOut);
+
+ angle::Result getTypedUAVRange(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size,
+ DXGI_FORMAT format,
+ d3d11::UnorderedAccessView **uavOut);
+
+ angle::Result markRawBufferUsage(const gl::Context *context);
+ angle::Result markTypedBufferUsage(const gl::Context *context);
+ bool isMapped() const { return mMappedStorage != nullptr; }
+ angle::Result packPixels(const gl::Context *context,
+ const gl::FramebufferAttachment &readAttachment,
+ const PackPixelsParams &params);
+ size_t getTotalCPUBufferMemoryBytes() const;
+
+ // BufferD3D implementation
+ size_t getSize() const override;
+ bool supportsDirectBinding() const override;
+ angle::Result getData(const gl::Context *context, const uint8_t **outData) override;
+ void initializeStaticData(const gl::Context *context) override;
+ void invalidateStaticData(const gl::Context *context) override;
+
+ // BufferImpl implementation
+ angle::Result setData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ gl::BufferUsage usage) override;
+ angle::Result setSubData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ size_t offset) override;
+ angle::Result copySubData(const gl::Context *context,
+ BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size) override;
+ angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override;
+ angle::Result mapRange(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ void **mapPtr) override;
+ angle::Result unmap(const gl::Context *context, GLboolean *result) override;
+ angle::Result markTransformFeedbackUsage(const gl::Context *context) override;
+
+ private:
+ class BufferStorage;
+ class EmulatedIndexedStorage;
+ class NativeStorage;
+ class PackStorage;
+ class SystemMemoryStorage;
+ class StructuredBufferStorage;
+
+ struct BufferCacheEntry
+ {
+ BufferCacheEntry() : storage(nullptr), lruCount(0) {}
+
+ BufferStorage *storage;
+ unsigned int lruCount;
+ };
+
+ struct StructuredBufferKey
+ {
+ StructuredBufferKey(unsigned int offsetIn, unsigned int structureByteStrideIn)
+ : offset(offsetIn), structureByteStride(structureByteStrideIn)
+ {}
+ bool operator<(const StructuredBufferKey &rhs) const
+ {
+ return std::tie(offset, structureByteStride) <
+ std::tie(rhs.offset, rhs.structureByteStride);
+ }
+ unsigned int offset;
+ unsigned int structureByteStride;
+ };
+
+ void markBufferUsage(BufferUsage usage);
+ angle::Result markBufferUsage(const gl::Context *context, BufferUsage usage);
+ angle::Result garbageCollection(const gl::Context *context, BufferUsage currentUsage);
+
+ angle::Result updateBufferStorage(const gl::Context *context,
+ BufferStorage *storage,
+ size_t sourceOffset,
+ size_t storageSize);
+
+ angle::Result getNativeStorageForUAV(const gl::Context *context,
+ Buffer11::NativeStorage **storageOut);
+
+ template <typename StorageOutT>
+ angle::Result getBufferStorage(const gl::Context *context,
+ BufferUsage usage,
+ StorageOutT **storageOut);
+
+ template <typename StorageOutT>
+ angle::Result getStagingStorage(const gl::Context *context, StorageOutT **storageOut);
+
+ angle::Result getLatestBufferStorage(const gl::Context *context,
+ BufferStorage **storageOut) const;
+
+ angle::Result getConstantBufferRangeStorage(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size,
+ NativeStorage **storageOut);
+
+ BufferStorage *allocateStorage(BufferUsage usage);
+ void updateDeallocThreshold(BufferUsage usage);
+
+ // Free the storage if we decide it isn't being used very often.
+ angle::Result checkForDeallocation(const gl::Context *context, BufferUsage usage);
+
+ // For some cases of uniform buffer storage, we can't deallocate system memory storage.
+ bool canDeallocateSystemMemory() const;
+
+ // Updates data revisions and latest storage.
+ void onCopyStorage(BufferStorage *dest, BufferStorage *source);
+ void onStorageUpdate(BufferStorage *updatedStorage);
+
+ Renderer11 *mRenderer;
+ size_t mSize;
+
+ BufferStorage *mMappedStorage;
+
+ // Buffer storages are sorted by usage. It's important that the latest buffer storage picks
+ // the lowest usage in the case where two storages are tied on data revision - this ensures
+ // we never do anything dangerous like map a uniform buffer over a staging or system memory
+ // copy.
+ std::array<BufferStorage *, BUFFER_USAGE_COUNT> mBufferStorages;
+ BufferStorage *mLatestBufferStorage;
+
+ // These two arrays are used to track when to free unused storage.
+ std::array<unsigned int, BUFFER_USAGE_COUNT> mDeallocThresholds;
+ std::array<unsigned int, BUFFER_USAGE_COUNT> mIdleness;
+
+ // Cache of D3D11 constant buffer for specific ranges of buffer data.
+ // This is used to emulate UBO ranges on 11.0 devices.
+ // Constant buffers are indexed by there start offset.
+ typedef std::map<GLintptr /*offset*/, BufferCacheEntry> BufferCache;
+ BufferCache mConstantBufferRangeStoragesCache;
+ size_t mConstantBufferStorageAdditionalSize;
+ unsigned int mMaxConstantBufferLruCount;
+
+ typedef std::map<StructuredBufferKey, BufferCacheEntry> StructuredBufferCache;
+ StructuredBufferCache mStructuredBufferRangeStoragesCache;
+ size_t mStructuredBufferStorageAdditionalSize;
+ unsigned int mMaxStructuredBufferLruCount;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
new file mode 100644
index 0000000000..d85b18b840
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
@@ -0,0 +1,813 @@
+
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Clear11.cpp: Framebuffer clear utility class.
+
+#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
+
+#include <algorithm>
+
+#include "libANGLE/Context.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/trace.h"
+
+// Precompiled shaders
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11_fl9vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewgs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewvs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/cleardepth11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps1.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps2.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps3.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps4.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps5.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps6.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps7.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps8.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps1.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps2.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps3.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps4.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps5.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps6.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps7.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps8.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps1.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps2.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps3.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps4.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps5.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps6.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps7.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps8.h"
+
+namespace rx
+{
+
+namespace
+{
+constexpr uint32_t g_ConstantBufferSize = sizeof(RtvDsvClearInfo<float>);
+constexpr uint32_t g_VertexSize = sizeof(d3d11::PositionVertex);
+
+// Updates color, depth and alpha components of cached CB if necessary.
+// Returns true if any constants are updated, false otherwise.
+template <typename T>
+bool UpdateDataCache(RtvDsvClearInfo<T> *dataCache,
+ const gl::Color<T> &color,
+ const float *zValue,
+ const uint32_t numRtvs,
+ const uint8_t writeMask)
+{
+ bool cacheDirty = false;
+
+ if (numRtvs > 0)
+ {
+ const bool writeRGB = (writeMask & ~D3D11_COLOR_WRITE_ENABLE_ALPHA) != 0;
+ if (writeRGB && memcmp(&dataCache->r, &color.red, sizeof(T) * 3) != 0)
+ {
+ dataCache->r = color.red;
+ dataCache->g = color.green;
+ dataCache->b = color.blue;
+ cacheDirty = true;
+ }
+
+ const bool writeAlpha = (writeMask & D3D11_COLOR_WRITE_ENABLE_ALPHA) != 0;
+ if (writeAlpha && (dataCache->a != color.alpha))
+ {
+ dataCache->a = color.alpha;
+ cacheDirty = true;
+ }
+ }
+
+ if (zValue)
+ {
+ const float clampedZValue = gl::clamp01(*zValue);
+
+ if (clampedZValue != dataCache->z)
+ {
+ dataCache->z = clampedZValue;
+ cacheDirty = true;
+ }
+ }
+
+ return cacheDirty;
+}
+
+} // anonymous namespace
+
+#define CLEARPS(Index) \
+ d3d11::LazyShader<ID3D11PixelShader>(g_PS_Clear##Index, ArraySize(g_PS_Clear##Index), \
+ "Clear11 PS " ANGLE_STRINGIFY(Index))
+
+Clear11::ShaderManager::ShaderManager()
+ : mIl9(),
+ mVs9(g_VS_Clear_FL9, ArraySize(g_VS_Clear_FL9), "Clear11 VS FL9"),
+ mPsFloat9(g_PS_ClearFloat_FL9, ArraySize(g_PS_ClearFloat_FL9), "Clear11 PS FloatFL9"),
+ mVs(g_VS_Clear, ArraySize(g_VS_Clear), "Clear11 VS"),
+ mVsMultiview(g_VS_Multiview_Clear, ArraySize(g_VS_Multiview_Clear), "Clear11 VS Multiview"),
+ mGsMultiview(g_GS_Multiview_Clear, ArraySize(g_GS_Multiview_Clear), "Clear11 GS Multiview"),
+ mPsDepth(g_PS_ClearDepth, ArraySize(g_PS_ClearDepth), "Clear11 PS Depth"),
+ mPsFloat{{CLEARPS(Float1), CLEARPS(Float2), CLEARPS(Float3), CLEARPS(Float4), CLEARPS(Float5),
+ CLEARPS(Float6), CLEARPS(Float7), CLEARPS(Float8)}},
+ mPsUInt{{CLEARPS(Uint1), CLEARPS(Uint2), CLEARPS(Uint3), CLEARPS(Uint4), CLEARPS(Uint5),
+ CLEARPS(Uint6), CLEARPS(Uint7), CLEARPS(Uint8)}},
+ mPsSInt{{CLEARPS(Sint1), CLEARPS(Sint2), CLEARPS(Sint3), CLEARPS(Sint4), CLEARPS(Sint5),
+ CLEARPS(Sint6), CLEARPS(Sint7), CLEARPS(Sint8)}}
+{}
+
+#undef CLEARPS
+
+Clear11::ShaderManager::~ShaderManager() {}
+
+angle::Result Clear11::ShaderManager::getShadersAndLayout(const gl::Context *context,
+ Renderer11 *renderer,
+ const INT clearType,
+ const uint32_t numRTs,
+ const bool hasLayeredLayout,
+ const d3d11::InputLayout **il,
+ const d3d11::VertexShader **vs,
+ const d3d11::GeometryShader **gs,
+ const d3d11::PixelShader **ps)
+{
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ if (renderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ ASSERT(clearType == GL_FLOAT);
+
+ ANGLE_TRY(mVs9.resolve(context11, renderer));
+ ANGLE_TRY(mPsFloat9.resolve(context11, renderer));
+
+ if (!mIl9.valid())
+ {
+ const D3D11_INPUT_ELEMENT_DESC ilDesc[] = {
+ {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}};
+
+ InputElementArray ilDescArray(ilDesc);
+ ShaderData vertexShader(g_VS_Clear_FL9);
+
+ ANGLE_TRY(renderer->allocateResource(context11, ilDescArray, &vertexShader, &mIl9));
+ }
+
+ *vs = &mVs9.getObj();
+ *gs = nullptr;
+ *il = &mIl9;
+ *ps = &mPsFloat9.getObj();
+ return angle::Result::Continue;
+ }
+
+ if (!hasLayeredLayout)
+ {
+ ANGLE_TRY(mVs.resolve(context11, renderer));
+ *vs = &mVs.getObj();
+ *gs = nullptr;
+ }
+ else
+ {
+ // For layered framebuffers we have to use the multi-view versions of the VS and GS.
+ ANGLE_TRY(mVsMultiview.resolve(context11, renderer));
+ ANGLE_TRY(mGsMultiview.resolve(context11, renderer));
+ *vs = &mVsMultiview.getObj();
+ *gs = &mGsMultiview.getObj();
+ }
+
+ *il = nullptr;
+
+ if (numRTs == 0)
+ {
+ ANGLE_TRY(mPsDepth.resolve(context11, renderer));
+ *ps = &mPsDepth.getObj();
+ return angle::Result::Continue;
+ }
+
+ switch (clearType)
+ {
+ case GL_FLOAT:
+ ANGLE_TRY(mPsFloat[numRTs - 1].resolve(context11, renderer));
+ *ps = &mPsFloat[numRTs - 1].getObj();
+ break;
+ case GL_UNSIGNED_INT:
+ ANGLE_TRY(mPsUInt[numRTs - 1].resolve(context11, renderer));
+ *ps = &mPsUInt[numRTs - 1].getObj();
+ break;
+ case GL_INT:
+ ANGLE_TRY(mPsSInt[numRTs - 1].resolve(context11, renderer));
+ *ps = &mPsSInt[numRTs - 1].getObj();
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return angle::Result::Continue;
+}
+
+Clear11::Clear11(Renderer11 *renderer)
+ : mRenderer(renderer),
+ mResourcesInitialized(false),
+ mScissorEnabledRasterizerState(),
+ mScissorDisabledRasterizerState(),
+ mShaderManager(),
+ mConstantBuffer(),
+ mVertexBuffer(),
+ mShaderData({})
+{}
+
+Clear11::~Clear11() {}
+
+angle::Result Clear11::ensureResourcesInitialized(const gl::Context *context)
+{
+ if (mResourcesInitialized)
+ {
+ return angle::Result::Continue;
+ }
+
+ ANGLE_TRACE_EVENT0("gpu.angle", "Clear11::ensureResourcesInitialized");
+
+ static_assert((sizeof(RtvDsvClearInfo<float>) == sizeof(RtvDsvClearInfo<int>)),
+ "Size of rx::RtvDsvClearInfo<float> is not equal to rx::RtvDsvClearInfo<int>");
+
+ static_assert(
+ (sizeof(RtvDsvClearInfo<float>) == sizeof(RtvDsvClearInfo<uint32_t>)),
+ "Size of rx::RtvDsvClearInfo<float> is not equal to rx::RtvDsvClearInfo<uint32_t>");
+
+ static_assert((sizeof(RtvDsvClearInfo<float>) % 16 == 0),
+ "The size of RtvDsvClearInfo<float> should be a multiple of 16bytes.");
+
+ // Create Rasterizer States
+ D3D11_RASTERIZER_DESC rsDesc;
+ rsDesc.FillMode = D3D11_FILL_SOLID;
+ rsDesc.CullMode = D3D11_CULL_NONE;
+ rsDesc.FrontCounterClockwise = FALSE;
+ rsDesc.DepthBias = 0;
+ rsDesc.DepthBiasClamp = 0.0f;
+ rsDesc.SlopeScaledDepthBias = 0.0f;
+ rsDesc.DepthClipEnable = TRUE;
+ rsDesc.ScissorEnable = FALSE;
+ rsDesc.MultisampleEnable = FALSE;
+ rsDesc.AntialiasedLineEnable = FALSE;
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, rsDesc, &mScissorDisabledRasterizerState));
+ mScissorDisabledRasterizerState.setInternalName("Clear11RasterizerStateWithScissorDisabled");
+
+ rsDesc.ScissorEnable = TRUE;
+ ANGLE_TRY(mRenderer->allocateResource(context11, rsDesc, &mScissorEnabledRasterizerState));
+ mScissorEnabledRasterizerState.setInternalName("Clear11RasterizerStateWithScissorEnabled");
+
+ // Initialize Depthstencil state with defaults
+ mDepthStencilStateKey.depthTest = false;
+ mDepthStencilStateKey.depthMask = false;
+ mDepthStencilStateKey.depthFunc = GL_ALWAYS;
+ mDepthStencilStateKey.stencilWritemask = static_cast<GLuint>(-1);
+ mDepthStencilStateKey.stencilBackWritemask = static_cast<GLuint>(-1);
+ mDepthStencilStateKey.stencilBackMask = 0;
+ mDepthStencilStateKey.stencilTest = false;
+ mDepthStencilStateKey.stencilMask = 0;
+ mDepthStencilStateKey.stencilFail = GL_REPLACE;
+ mDepthStencilStateKey.stencilPassDepthFail = GL_REPLACE;
+ mDepthStencilStateKey.stencilPassDepthPass = GL_REPLACE;
+ mDepthStencilStateKey.stencilFunc = GL_ALWAYS;
+ mDepthStencilStateKey.stencilBackFail = GL_REPLACE;
+ mDepthStencilStateKey.stencilBackPassDepthFail = GL_REPLACE;
+ mDepthStencilStateKey.stencilBackPassDepthPass = GL_REPLACE;
+ mDepthStencilStateKey.stencilBackFunc = GL_ALWAYS;
+
+ // Initialize BlendStateKey with defaults
+ mBlendStateKey.blendStateExt = gl::BlendStateExt(mRenderer->getNativeCaps().maxDrawBuffers);
+
+ mResourcesInitialized = true;
+ return angle::Result::Continue;
+}
+
+bool Clear11::useVertexBuffer() const
+{
+ return (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3);
+}
+
+angle::Result Clear11::ensureConstantBufferCreated(const gl::Context *context)
+{
+ if (mConstantBuffer.valid())
+ {
+ return angle::Result::Continue;
+ }
+
+ // Create constant buffer for color & depth data
+
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = g_ConstantBufferSize;
+ bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+ bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.StructureByteStride = 0;
+
+ D3D11_SUBRESOURCE_DATA initialData;
+ initialData.pSysMem = &mShaderData;
+ initialData.SysMemPitch = g_ConstantBufferSize;
+ initialData.SysMemSlicePitch = g_ConstantBufferSize;
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), bufferDesc, &initialData,
+ &mConstantBuffer));
+ mConstantBuffer.setInternalName("Clear11ConstantBuffer");
+ return angle::Result::Continue;
+}
+
+angle::Result Clear11::ensureVertexBufferCreated(const gl::Context *context)
+{
+ ASSERT(useVertexBuffer());
+
+ if (mVertexBuffer.valid())
+ {
+ return angle::Result::Continue;
+ }
+
+ // Create vertex buffer with vertices for a quad covering the entire surface
+
+ static_assert((sizeof(d3d11::PositionVertex) % 16) == 0,
+ "d3d11::PositionVertex should be a multiple of 16 bytes");
+ const d3d11::PositionVertex vbData[6] = {{-1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, -1.0f, 0.0f, 1.0f},
+ {-1.0f, -1.0f, 0.0f, 1.0f}, {-1.0f, 1.0f, 0.0f, 1.0f},
+ {1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, -1.0f, 0.0f, 1.0f}};
+
+ const UINT vbSize = sizeof(vbData);
+
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = vbSize;
+ bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.CPUAccessFlags = 0;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.StructureByteStride = 0;
+
+ D3D11_SUBRESOURCE_DATA initialData;
+ initialData.pSysMem = vbData;
+ initialData.SysMemPitch = vbSize;
+ initialData.SysMemSlicePitch = initialData.SysMemPitch;
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), bufferDesc, &initialData,
+ &mVertexBuffer));
+ mVertexBuffer.setInternalName("Clear11VertexBuffer");
+ return angle::Result::Continue;
+}
+
+angle::Result Clear11::clearFramebuffer(const gl::Context *context,
+ const ClearParameters &clearParams,
+ const gl::FramebufferState &fboData)
+{
+ ANGLE_TRY(ensureResourcesInitialized(context));
+
+ // Iterate over the color buffers which require clearing and determine if they can be
+ // cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView.
+ // This requires:
+ // 1) The render target is being cleared to a float value (will be cast to integer when clearing
+ // integer render targets as expected but does not work the other way around)
+ // 2) The format of the render target has no color channels that are currently masked out.
+ // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special
+ // work.
+ //
+ // If these conditions are met, and:
+ // - No scissored clear is needed, then clear using ID3D11DeviceContext::ClearRenderTargetView.
+ // - A scissored clear is needed then clear using ID3D11DeviceContext1::ClearView if available.
+ // Otherwise perform a shader based clear.
+ //
+ // Also determine if the DSV can be cleared withID3D11DeviceContext::ClearDepthStencilView by
+ // checking if the stencil write mask covers the entire stencil.
+ //
+ // To clear the remaining buffers, a shader based clear is performed:
+ // - The appropriate ShaderManagers (VS & PS) for the clearType is set
+ // - A CB containing the clear color and Z values is bound
+ // - An IL and VB are bound (for FL93 and below)
+ // - ScissorRect/Raststate/Viewport set as required
+ // - Blendstate set containing appropriate colorMasks
+ // - DepthStencilState set with appropriate parameters for a z or stencil clear if required
+ // - Color and/or Z buffers to be cleared are bound
+ // - Primitive covering entire clear area is drawn
+
+ gl::Extents framebufferSize;
+
+ const auto *depthStencilAttachment = fboData.getDepthOrStencilAttachment();
+ if (depthStencilAttachment != nullptr)
+ {
+ framebufferSize = depthStencilAttachment->getSize();
+ }
+ else
+ {
+ const gl::FramebufferAttachment *colorAttachment = fboData.getFirstColorAttachment();
+ ASSERT(colorAttachment);
+ framebufferSize = colorAttachment->getSize();
+ }
+
+ bool needScissoredClear = false;
+ D3D11_RECT scissorRect;
+ if (clearParams.scissorEnabled)
+ {
+ if (clearParams.scissor.x >= framebufferSize.width ||
+ clearParams.scissor.y >= framebufferSize.height || clearParams.scissor.width == 0 ||
+ clearParams.scissor.height == 0)
+ {
+ // The check assumes that the viewport offsets are not negative as according to the
+ // OVR_multiview2 spec.
+ // Scissor rect is outside the renderbuffer or is an empty rect.
+ return angle::Result::Continue;
+ }
+
+ if (clearParams.scissor.x + clearParams.scissor.width <= 0 ||
+ clearParams.scissor.y + clearParams.scissor.height <= 0)
+ {
+ // Scissor rect is outside the renderbuffer.
+ return angle::Result::Continue;
+ }
+ needScissoredClear =
+ clearParams.scissor.x > 0 || clearParams.scissor.y > 0 ||
+ clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width ||
+ clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height;
+
+ if (needScissoredClear)
+ {
+ // Apply viewport offsets to compute the final scissor rectangles.
+ // Even in multiview all layers share the same viewport and scissor.
+ scissorRect.left = clearParams.scissor.x;
+ scissorRect.right = scissorRect.left + clearParams.scissor.width;
+ scissorRect.top = clearParams.scissor.y;
+ scissorRect.bottom = scissorRect.top + clearParams.scissor.height;
+ }
+ }
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
+
+ std::array<ID3D11RenderTargetView *, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvs;
+ std::array<uint8_t, D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT> rtvMasks = {};
+
+ uint32_t numRtvs = 0;
+ uint8_t commonColorMask = 0;
+
+ const auto &colorAttachments = fboData.getColorAttachments();
+ for (auto colorAttachmentIndex : fboData.getEnabledDrawBuffers())
+ {
+ const uint8_t colorMask = gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(
+ colorAttachmentIndex, clearParams.colorMask);
+
+ commonColorMask |= colorMask;
+
+ const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachmentIndex];
+
+ if (!clearParams.clearColor[colorAttachmentIndex])
+ {
+ continue;
+ }
+
+ RenderTarget11 *renderTarget = nullptr;
+ ANGLE_TRY(attachment.getRenderTarget(context, attachment.getRenderToTextureSamples(),
+ &renderTarget));
+
+ const gl::InternalFormat &formatInfo = *attachment.getFormat().info;
+
+ if (clearParams.colorType == GL_FLOAT &&
+ !(formatInfo.componentType == GL_FLOAT ||
+ formatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
+ formatInfo.componentType == GL_SIGNED_NORMALIZED))
+ {
+ WARN() << "It is undefined behaviour to clear a render buffer which is not "
+ "normalized fixed point or floating-point to floating point values (color "
+ "attachment "
+ << colorAttachmentIndex << " has internal format " << attachment.getFormat()
+ << ").";
+ }
+
+ bool r, g, b, a;
+ gl::BlendStateExt::UnpackColorMask(colorMask, &r, &g, &b, &a);
+ if ((formatInfo.redBits == 0 || !r) && (formatInfo.greenBits == 0 || !g) &&
+ (formatInfo.blueBits == 0 || !b) && (formatInfo.alphaBits == 0 || !a))
+ {
+ // Every channel either does not exist in the render target or is masked out
+ continue;
+ }
+
+ const auto &framebufferRTV = renderTarget->getRenderTargetView();
+ ASSERT(framebufferRTV.valid());
+
+ bool canClearView = mRenderer->getRenderer11DeviceCaps().supportsClearView;
+ if (canClearView &&
+ mRenderer->getFeatures().emulateClearViewAfterDualSourceBlending.enabled)
+ {
+ // Check the current state to see if we were using dual source blending
+ const auto isDualSource = [](const auto blend) {
+ switch (blend)
+ {
+ case D3D11_BLEND_SRC1_COLOR:
+ case D3D11_BLEND_INV_SRC1_COLOR:
+ case D3D11_BLEND_SRC1_ALPHA:
+ case D3D11_BLEND_INV_SRC1_ALPHA:
+ return true;
+ default:
+ return false;
+ }
+ };
+ FLOAT blendFactor[4];
+ UINT sampleMask;
+ ID3D11BlendState *blendState;
+ deviceContext->OMGetBlendState(&blendState, blendFactor, &sampleMask);
+ if (blendState)
+ {
+ D3D11_BLEND_DESC blendDesc;
+ blendState->GetDesc(&blendDesc);
+ // You can only use dual source blending on slot 0 so only check there
+ if (isDualSource(blendDesc.RenderTarget[0].SrcBlend) ||
+ isDualSource(blendDesc.RenderTarget[0].DestBlend) ||
+ isDualSource(blendDesc.RenderTarget[0].SrcBlendAlpha) ||
+ isDualSource(blendDesc.RenderTarget[0].DestBlendAlpha))
+ {
+ canClearView = false;
+ }
+ }
+ }
+
+ if (needScissoredClear && mRenderer->getFeatures().scissoredClearArtifacts.enabled)
+ {
+ canClearView = false;
+ }
+
+ if ((!canClearView && needScissoredClear) || clearParams.colorType != GL_FLOAT ||
+ (formatInfo.redBits > 0 && !r) || (formatInfo.greenBits > 0 && !g) ||
+ (formatInfo.blueBits > 0 && !b) || (formatInfo.alphaBits > 0 && !a))
+ {
+ rtvs[numRtvs] = framebufferRTV.get();
+ rtvMasks[numRtvs] = gl_d3d11::GetColorMask(formatInfo) & colorMask;
+ numRtvs++;
+ }
+ else
+ {
+ // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is
+ // possible
+
+ const auto &nativeFormat = renderTarget->getFormatSet().format();
+
+ // Check if the actual format has a channel that the internal format does not and
+ // set them to the default values
+ float clearValues[4] = {
+ ((formatInfo.redBits == 0 && nativeFormat.redBits > 0) ? 0.0f
+ : clearParams.colorF.red),
+ ((formatInfo.greenBits == 0 && nativeFormat.greenBits > 0)
+ ? 0.0f
+ : clearParams.colorF.green),
+ ((formatInfo.blueBits == 0 && nativeFormat.blueBits > 0) ? 0.0f
+ : clearParams.colorF.blue),
+ ((formatInfo.alphaBits == 0 && nativeFormat.alphaBits > 0)
+ ? 1.0f
+ : clearParams.colorF.alpha),
+ };
+
+ if (formatInfo.alphaBits == 1)
+ {
+ // Some drivers do not correctly handle calling Clear() on a format with 1-bit
+ // alpha. They can incorrectly round all non-zero values up to 1.0f. Note that
+ // WARP does not do this. We should handle the rounding for them instead.
+ clearValues[3] = (clearParams.colorF.alpha >= 0.5f) ? 1.0f : 0.0f;
+ }
+
+ if (needScissoredClear)
+ {
+ // We shouldn't reach here if deviceContext1 is unavailable.
+ ASSERT(deviceContext1);
+ deviceContext1->ClearView(framebufferRTV.get(), clearValues, &scissorRect, 1);
+ if (mRenderer->getFeatures().callClearTwice.enabled)
+ {
+ deviceContext1->ClearView(framebufferRTV.get(), clearValues, &scissorRect, 1);
+ }
+ }
+ else
+ {
+ deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues);
+ if (mRenderer->getFeatures().callClearTwice.enabled)
+ {
+ deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues);
+ }
+ }
+ }
+ }
+
+ ID3D11DepthStencilView *dsv = nullptr;
+
+ if (clearParams.clearDepth || clearParams.clearStencil)
+ {
+ RenderTarget11 *depthStencilRenderTarget = nullptr;
+
+ ASSERT(depthStencilAttachment != nullptr);
+ ANGLE_TRY(depthStencilAttachment->getRenderTarget(
+ context, depthStencilAttachment->getRenderToTextureSamples(),
+ &depthStencilRenderTarget));
+
+ dsv = depthStencilRenderTarget->getDepthStencilView().get();
+ ASSERT(dsv != nullptr);
+
+ const auto &nativeFormat = depthStencilRenderTarget->getFormatSet().format();
+ const auto *stencilAttachment = fboData.getStencilAttachment();
+
+ uint32_t stencilUnmasked =
+ (stencilAttachment != nullptr) ? (1 << nativeFormat.stencilBits) - 1 : 0;
+ bool needMaskedStencilClear =
+ clearParams.clearStencil &&
+ (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
+
+ if (!needScissoredClear && !needMaskedStencilClear)
+ {
+ const UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) |
+ (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0);
+ const FLOAT depthClear = gl::clamp01(clearParams.depthValue);
+ const UINT8 stencilClear = clearParams.stencilValue & 0xFF;
+
+ deviceContext->ClearDepthStencilView(dsv, clearFlags, depthClear, stencilClear);
+
+ dsv = nullptr;
+ }
+ }
+
+ if (numRtvs == 0 && dsv == nullptr)
+ {
+ return angle::Result::Continue;
+ }
+
+ // Clear the remaining render targets and depth stencil in one pass by rendering a quad:
+ //
+ // IA/VS: Vertices containing position and color members are passed through to the next stage.
+ // The vertex position has XY coordinates equal to clip extents and a Z component equal to the
+ // Z clear value. The vertex color contains the clear color.
+ //
+ // Rasterizer: Viewport scales the VS output over the entire surface and depending on whether
+ // or not scissoring is enabled the appropriate scissor rect and rasterizerState with or without
+ // the scissor test enabled is set as well.
+ //
+ // DepthStencilTest: DepthTesting, DepthWrites, StencilMask and StencilWrites will be enabled or
+ // disabled or set depending on what the input depthStencil clear parameters are. Since the PS
+ // is not writing out depth or rejecting pixels, this should happen prior to the PS stage.
+ //
+ // PS: Will write out the color values passed through from the previous stage to all outputs.
+ //
+ // OM: BlendState will perform the required color masking and output to RTV(s).
+
+ //
+ // ======================================================================================
+ //
+ // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render-
+ // buffer that is not normalized fixed point or floating point with floating point values
+ // are undefined so we can just write floats to them and D3D11 will bit cast them to
+ // integers.
+ //
+ // Also, we don't have to worry about attempting to clear a normalized fixed/floating point
+ // buffer with integer values because there is no gl API call which would allow it,
+ // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to
+ // be a compatible clear type.
+
+ ASSERT(numRtvs <= static_cast<uint32_t>(mRenderer->getNativeCaps().maxDrawBuffers));
+
+ // Setup BlendStateKey parameters
+ mBlendStateKey.blendStateExt.setColorMask(false, false, false, false);
+ for (size_t i = 0; i < numRtvs; i++)
+ {
+ mBlendStateKey.blendStateExt.setColorMaskIndexed(i, rtvMasks[i]);
+ }
+
+ mBlendStateKey.rtvMax = static_cast<uint16_t>(numRtvs);
+
+ // Get BlendState
+ const d3d11::BlendState *blendState = nullptr;
+ ANGLE_TRY(mRenderer->getBlendState(context, mBlendStateKey, &blendState));
+
+ const d3d11::DepthStencilState *dsState = nullptr;
+ const float *zValue = nullptr;
+
+ if (dsv)
+ {
+ // Setup DepthStencilStateKey
+ mDepthStencilStateKey.depthTest = clearParams.clearDepth;
+ mDepthStencilStateKey.depthMask = clearParams.clearDepth;
+ mDepthStencilStateKey.stencilWritemask = clearParams.stencilWriteMask;
+ mDepthStencilStateKey.stencilTest = clearParams.clearStencil;
+
+ // Get DepthStencilState
+ ANGLE_TRY(mRenderer->getDepthStencilState(context, mDepthStencilStateKey, &dsState));
+ zValue = clearParams.clearDepth ? &clearParams.depthValue : nullptr;
+ }
+
+ bool dirtyCb = false;
+
+ // Compare the input color/z values against the CB cache and update it if necessary
+ switch (clearParams.colorType)
+ {
+ case GL_FLOAT:
+ dirtyCb =
+ UpdateDataCache(&mShaderData, clearParams.colorF, zValue, numRtvs, commonColorMask);
+ break;
+ case GL_UNSIGNED_INT:
+ dirtyCb = UpdateDataCache(reinterpret_cast<RtvDsvClearInfo<uint32_t> *>(&mShaderData),
+ clearParams.colorUI, zValue, numRtvs, commonColorMask);
+ break;
+ case GL_INT:
+ dirtyCb = UpdateDataCache(reinterpret_cast<RtvDsvClearInfo<int> *>(&mShaderData),
+ clearParams.colorI, zValue, numRtvs, commonColorMask);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ ANGLE_TRY(ensureConstantBufferCreated(context));
+
+ if (dirtyCb)
+ {
+ // Update the constant buffer with the updated cache contents
+ // TODO(Shahmeer): Consider using UpdateSubresource1 D3D11_COPY_DISCARD where possible.
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ ANGLE_TRY(mRenderer->mapResource(context, mConstantBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD,
+ 0, &mappedResource));
+
+ memcpy(mappedResource.pData, &mShaderData, g_ConstantBufferSize);
+ deviceContext->Unmap(mConstantBuffer.get(), 0);
+ }
+
+ auto *stateManager = mRenderer->getStateManager();
+
+ // Set the viewport to be the same size as the framebuffer.
+ stateManager->setSimpleViewport(framebufferSize);
+
+ // Apply state
+ stateManager->setSimpleBlendState(blendState);
+
+ const UINT stencilValue = clearParams.stencilValue & 0xFF;
+ stateManager->setDepthStencilState(dsState, stencilValue);
+
+ if (needScissoredClear)
+ {
+ stateManager->setRasterizerState(&mScissorEnabledRasterizerState);
+ }
+ else
+ {
+ stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
+ }
+
+ // Get Shaders
+ const d3d11::VertexShader *vs = nullptr;
+ const d3d11::GeometryShader *gs = nullptr;
+ const d3d11::InputLayout *il = nullptr;
+ const d3d11::PixelShader *ps = nullptr;
+ const bool hasLayeredLayout = (fboData.isMultiview());
+ ANGLE_TRY(mShaderManager.getShadersAndLayout(context, mRenderer, clearParams.colorType, numRtvs,
+ hasLayeredLayout, &il, &vs, &gs, &ps));
+
+ // Apply Shaders
+ stateManager->setDrawShaders(vs, gs, ps);
+ stateManager->setPixelConstantBuffer(0, &mConstantBuffer);
+
+ // Bind IL & VB if needed
+ stateManager->setIndexBuffer(nullptr, DXGI_FORMAT_UNKNOWN, 0);
+ stateManager->setInputLayout(il);
+
+ if (useVertexBuffer())
+ {
+ ANGLE_TRY(ensureVertexBufferCreated(context));
+ stateManager->setSingleVertexBuffer(&mVertexBuffer, g_VertexSize, 0);
+ }
+ else
+ {
+ stateManager->setSingleVertexBuffer(nullptr, 0, 0);
+ }
+
+ stateManager->setPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+
+ // Apply render targets
+ stateManager->setRenderTargets(&rtvs[0], numRtvs, dsv);
+
+ if (needScissoredClear)
+ {
+ stateManager->setScissorRectD3D(scissorRect);
+ }
+ // Draw the fullscreen quad.
+ if (!hasLayeredLayout)
+ {
+ deviceContext->Draw(6, 0);
+ }
+ else
+ {
+ ASSERT(hasLayeredLayout);
+ deviceContext->DrawInstanced(6, static_cast<UINT>(fboData.getNumViews()), 0, 0);
+ }
+
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Clear11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Clear11.h
new file mode 100644
index 0000000000..2e2eca5e80
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Clear11.h
@@ -0,0 +1,102 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Clear11.h: Framebuffer clear utility class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_
+
+#include <map>
+#include <vector>
+
+#include "libANGLE/Error.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+class Renderer11;
+class RenderTarget11;
+struct ClearParameters;
+
+template <typename T>
+struct RtvDsvClearInfo
+{
+ T r, g, b, a;
+ float z;
+ float c1padding[3];
+};
+
+class Clear11 : angle::NonCopyable
+{
+ public:
+ explicit Clear11(Renderer11 *renderer);
+ ~Clear11();
+
+ // Clears the framebuffer with the supplied clear parameters, assumes that the framebuffer is
+ // currently applied.
+ angle::Result clearFramebuffer(const gl::Context *context,
+ const ClearParameters &clearParams,
+ const gl::FramebufferState &fboData);
+
+ private:
+ class ShaderManager final : angle::NonCopyable
+ {
+ public:
+ ShaderManager();
+ ~ShaderManager();
+ angle::Result getShadersAndLayout(const gl::Context *context,
+ Renderer11 *renderer,
+ const INT clearType,
+ const uint32_t numRTs,
+ const bool hasLayeredLayout,
+ const d3d11::InputLayout **il,
+ const d3d11::VertexShader **vs,
+ const d3d11::GeometryShader **gs,
+ const d3d11::PixelShader **ps);
+
+ private:
+ constexpr static size_t kNumShaders = D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
+
+ d3d11::InputLayout mIl9;
+ d3d11::LazyShader<ID3D11VertexShader> mVs9;
+ d3d11::LazyShader<ID3D11PixelShader> mPsFloat9;
+ d3d11::LazyShader<ID3D11VertexShader> mVs;
+ d3d11::LazyShader<ID3D11VertexShader> mVsMultiview;
+ d3d11::LazyShader<ID3D11GeometryShader> mGsMultiview;
+ d3d11::LazyShader<ID3D11PixelShader> mPsDepth;
+ std::array<d3d11::LazyShader<ID3D11PixelShader>, kNumShaders> mPsFloat;
+ std::array<d3d11::LazyShader<ID3D11PixelShader>, kNumShaders> mPsUInt;
+ std::array<d3d11::LazyShader<ID3D11PixelShader>, kNumShaders> mPsSInt;
+ };
+
+ bool useVertexBuffer() const;
+ angle::Result ensureConstantBufferCreated(const gl::Context *context);
+ angle::Result ensureVertexBufferCreated(const gl::Context *context);
+ angle::Result ensureResourcesInitialized(const gl::Context *context);
+
+ Renderer11 *mRenderer;
+ bool mResourcesInitialized;
+
+ // States
+ d3d11::RasterizerState mScissorEnabledRasterizerState;
+ d3d11::RasterizerState mScissorDisabledRasterizerState;
+ gl::DepthStencilState mDepthStencilStateKey;
+ d3d11::BlendStateKey mBlendStateKey;
+
+ // Shaders and shader resources
+ ShaderManager mShaderManager;
+ d3d11::Buffer mConstantBuffer;
+ d3d11::Buffer mVertexBuffer;
+
+ // Buffer data and draw parameters
+ RtvDsvClearInfo<float> mShaderData;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Context11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
new file mode 100644
index 0000000000..f3b13f678a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
@@ -0,0 +1,1048 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context11:
+// D3D11-specific functionality associated with a GL Context.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+
+#include "common/entry_points_enum_autogen.h"
+#include "common/string_utils.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Context.inl.h"
+#include "libANGLE/MemoryProgramCache.h"
+#include "libANGLE/renderer/OverlayImpl.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/SamplerD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
+#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Program11.h"
+#include "libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+
+namespace
+{
+ANGLE_INLINE bool DrawCallHasDynamicAttribs(const gl::Context *context)
+{
+ VertexArray11 *vertexArray11 = GetImplAs<VertexArray11>(context->getState().getVertexArray());
+ return vertexArray11->hasActiveDynamicAttrib(context);
+}
+
+bool DrawCallHasStreamingVertexArrays(const gl::Context *context, gl::PrimitiveMode mode)
+{
+ // Direct drawing doesn't support dynamic attribute storage since it needs the first and count
+ // to translate when applyVertexBuffer. GL_LINE_LOOP and GL_TRIANGLE_FAN are not supported
+ // either since we need to simulate them in D3D.
+ if (DrawCallHasDynamicAttribs(context) || mode == gl::PrimitiveMode::LineLoop ||
+ mode == gl::PrimitiveMode::TriangleFan)
+ {
+ return true;
+ }
+
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(context->getState().getProgram());
+ if (InstancedPointSpritesActive(programD3D, mode))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool DrawCallHasStreamingElementArray(const gl::Context *context, gl::DrawElementsType srcType)
+{
+ const gl::State &glState = context->getState();
+ gl::Buffer *elementArrayBuffer = glState.getVertexArray()->getElementArrayBuffer();
+
+ bool primitiveRestartWorkaround =
+ UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), srcType);
+ const gl::DrawElementsType dstType =
+ (srcType == gl::DrawElementsType::UnsignedInt || primitiveRestartWorkaround)
+ ? gl::DrawElementsType::UnsignedInt
+ : gl::DrawElementsType::UnsignedShort;
+
+ // Not clear where the offset comes from here.
+ switch (ClassifyIndexStorage(glState, elementArrayBuffer, srcType, dstType, 0))
+ {
+ case IndexStorageType::Dynamic:
+ return true;
+ case IndexStorageType::Direct:
+ return false;
+ case IndexStorageType::Static:
+ {
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(elementArrayBuffer);
+ StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer();
+ return (staticBuffer->getBufferSize() == 0 || staticBuffer->getIndexType() != dstType);
+ }
+ default:
+ UNREACHABLE();
+ return true;
+ }
+}
+
+template <typename IndirectBufferT>
+angle::Result ReadbackIndirectBuffer(const gl::Context *context,
+ const void *indirect,
+ const IndirectBufferT **bufferPtrOut)
+{
+ const gl::State &glState = context->getState();
+ gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
+ ASSERT(drawIndirectBuffer);
+ Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
+ uintptr_t offset = reinterpret_cast<uintptr_t>(indirect);
+
+ const uint8_t *bufferData = nullptr;
+ ANGLE_TRY(storage->getData(context, &bufferData));
+ ASSERT(bufferData);
+
+ *bufferPtrOut = reinterpret_cast<const IndirectBufferT *>(bufferData + offset);
+ return angle::Result::Continue;
+}
+} // anonymous namespace
+
+Context11::Context11(const gl::State &state, gl::ErrorSet *errorSet, Renderer11 *renderer)
+ : ContextD3D(state, errorSet), mRenderer(renderer)
+{}
+
+Context11::~Context11() {}
+
+angle::Result Context11::initialize()
+{
+ return angle::Result::Continue;
+}
+
+void Context11::onDestroy(const gl::Context *context)
+{
+ mIncompleteTextures.onDestroy(context);
+}
+
+CompilerImpl *Context11::createCompiler()
+{
+ if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ return new CompilerD3D(SH_HLSL_4_0_FL9_3_OUTPUT);
+ }
+ else
+ {
+ return new CompilerD3D(SH_HLSL_4_1_OUTPUT);
+ }
+}
+
+ShaderImpl *Context11::createShader(const gl::ShaderState &data)
+{
+ return new ShaderD3D(data, mRenderer);
+}
+
+ProgramImpl *Context11::createProgram(const gl::ProgramState &data)
+{
+ return new Program11(data, mRenderer);
+}
+
+FramebufferImpl *Context11::createFramebuffer(const gl::FramebufferState &data)
+{
+ return new Framebuffer11(data, mRenderer);
+}
+
+TextureImpl *Context11::createTexture(const gl::TextureState &state)
+{
+ switch (state.getType())
+ {
+ case gl::TextureType::_2D:
+ // GL_TEXTURE_VIDEO_IMAGE_WEBGL maps to native 2D texture on Windows platform
+ case gl::TextureType::VideoImage:
+ return new TextureD3D_2D(state, mRenderer);
+ case gl::TextureType::CubeMap:
+ return new TextureD3D_Cube(state, mRenderer);
+ case gl::TextureType::_3D:
+ return new TextureD3D_3D(state, mRenderer);
+ case gl::TextureType::_2DArray:
+ return new TextureD3D_2DArray(state, mRenderer);
+ case gl::TextureType::External:
+ return new TextureD3D_External(state, mRenderer);
+ case gl::TextureType::_2DMultisample:
+ return new TextureD3D_2DMultisample(state, mRenderer);
+ case gl::TextureType::_2DMultisampleArray:
+ return new TextureD3D_2DMultisampleArray(state, mRenderer);
+ case gl::TextureType::Buffer:
+ return new TextureD3D_Buffer(state, mRenderer);
+ default:
+ UNREACHABLE();
+ }
+
+ return nullptr;
+}
+
+RenderbufferImpl *Context11::createRenderbuffer(const gl::RenderbufferState &state)
+{
+ return new RenderbufferD3D(state, mRenderer);
+}
+
+BufferImpl *Context11::createBuffer(const gl::BufferState &state)
+{
+ Buffer11 *buffer = new Buffer11(state, mRenderer);
+ mRenderer->onBufferCreate(buffer);
+ return buffer;
+}
+
+VertexArrayImpl *Context11::createVertexArray(const gl::VertexArrayState &data)
+{
+ return new VertexArray11(data);
+}
+
+QueryImpl *Context11::createQuery(gl::QueryType type)
+{
+ return new Query11(mRenderer, type);
+}
+
+FenceNVImpl *Context11::createFenceNV()
+{
+ return new FenceNV11(mRenderer);
+}
+
+SyncImpl *Context11::createSync()
+{
+ return new Sync11(mRenderer);
+}
+
+TransformFeedbackImpl *Context11::createTransformFeedback(const gl::TransformFeedbackState &state)
+{
+ return new TransformFeedback11(state, mRenderer);
+}
+
+SamplerImpl *Context11::createSampler(const gl::SamplerState &state)
+{
+ return new SamplerD3D(state);
+}
+
+ProgramPipelineImpl *Context11::createProgramPipeline(const gl::ProgramPipelineState &data)
+{
+ return new ProgramPipeline11(data);
+}
+
+MemoryObjectImpl *Context11::createMemoryObject()
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+SemaphoreImpl *Context11::createSemaphore()
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+OverlayImpl *Context11::createOverlay(const gl::OverlayState &state)
+{
+ // Not implemented.
+ return new OverlayImpl(state);
+}
+
+angle::Result Context11::flush(const gl::Context *context)
+{
+ return mRenderer->flush(this);
+}
+
+angle::Result Context11::finish(const gl::Context *context)
+{
+ return mRenderer->finish(this);
+}
+
+angle::Result Context11::drawArrays(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count)
+{
+ ASSERT(count > 0);
+ ANGLE_TRY(mRenderer->getStateManager()->updateState(
+ context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0, 0, true));
+ return mRenderer->drawArrays(context, mode, first, count, 0, 0, false);
+}
+
+angle::Result Context11::drawArraysInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount)
+{
+ ASSERT(count > 0);
+ ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, first, count,
+ gl::DrawElementsType::InvalidEnum, nullptr,
+ instanceCount, 0, 0, true));
+ return mRenderer->drawArrays(context, mode, first, count, instanceCount, 0, true);
+}
+
+angle::Result Context11::drawArraysInstancedBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount,
+ GLuint baseInstance)
+{
+ ASSERT(count > 0);
+ ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, first, count,
+ gl::DrawElementsType::InvalidEnum, nullptr,
+ instanceCount, 0, baseInstance, true));
+ return mRenderer->drawArrays(context, mode, first, count, instanceCount, baseInstance, true);
+}
+
+ANGLE_INLINE angle::Result Context11::drawElementsImpl(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei indexCount,
+ gl::DrawElementsType indexType,
+ const void *indices,
+ GLsizei instanceCount,
+ GLint baseVertex,
+ GLuint baseInstance,
+ bool promoteDynamic,
+ bool isInstancedDraw)
+{
+ ASSERT(indexCount > 0);
+
+ if (DrawCallHasDynamicAttribs(context))
+ {
+ gl::IndexRange indexRange;
+ ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(
+ context, indexType, indexCount, indices, &indexRange));
+ GLint startVertex;
+ ANGLE_TRY(ComputeStartVertex(GetImplAs<Context11>(context), indexRange, baseVertex,
+ &startVertex));
+ ANGLE_TRY(mRenderer->getStateManager()->updateState(
+ context, mode, startVertex, indexCount, indexType, indices, instanceCount, baseVertex,
+ baseInstance, promoteDynamic));
+ return mRenderer->drawElements(context, mode, startVertex, indexCount, indexType, indices,
+ instanceCount, baseVertex, baseInstance, isInstancedDraw);
+ }
+ else
+ {
+ ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, 0, indexCount, indexType,
+ indices, instanceCount, baseVertex,
+ baseInstance, promoteDynamic));
+ return mRenderer->drawElements(context, mode, 0, indexCount, indexType, indices,
+ instanceCount, baseVertex, baseInstance, isInstancedDraw);
+ }
+}
+
+angle::Result Context11::drawElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices)
+{
+ return drawElementsImpl(context, mode, count, type, indices, 0, 0, 0, true, false);
+}
+
+angle::Result Context11::drawElementsBaseVertex(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLint baseVertex)
+{
+ return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0, true, false);
+}
+
+angle::Result Context11::drawElementsInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances)
+{
+ return drawElementsImpl(context, mode, count, type, indices, instances, 0, 0, true, true);
+}
+
+angle::Result Context11::drawElementsInstancedBaseVertex(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances,
+ GLint baseVertex)
+{
+ return drawElementsImpl(context, mode, count, type, indices, instances, baseVertex, 0, true,
+ true);
+}
+
+angle::Result Context11::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances,
+ GLint baseVertex,
+ GLuint baseInstance)
+{
+ return drawElementsImpl(context, mode, count, type, indices, instances, baseVertex,
+ baseInstance, true, true);
+}
+
+angle::Result Context11::drawRangeElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices)
+{
+ return drawElementsImpl(context, mode, count, type, indices, 0, 0, 0, true, false);
+}
+
+angle::Result Context11::drawRangeElementsBaseVertex(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLint baseVertex)
+{
+ return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0, true, false);
+}
+
+angle::Result Context11::drawArraysIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const void *indirect)
+{
+ if (DrawCallHasStreamingVertexArrays(context, mode))
+ {
+ const gl::DrawArraysIndirectCommand *cmd = nullptr;
+ ANGLE_TRY(ReadbackIndirectBuffer(context, indirect, &cmd));
+
+ ANGLE_TRY(mRenderer->getStateManager()->updateState(
+ context, mode, cmd->first, cmd->count, gl::DrawElementsType::InvalidEnum, nullptr,
+ cmd->instanceCount, 0, 0, true));
+ return mRenderer->drawArrays(context, mode, cmd->first, cmd->count, cmd->instanceCount,
+ cmd->baseInstance, true);
+ }
+ else
+ {
+ ANGLE_TRY(mRenderer->getStateManager()->updateState(
+ context, mode, 0, 0, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0, 0, true));
+ return mRenderer->drawArraysIndirect(context, indirect);
+ }
+}
+
+angle::Result Context11::drawElementsIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType type,
+ const void *indirect)
+{
+ if (DrawCallHasStreamingVertexArrays(context, mode) ||
+ DrawCallHasStreamingElementArray(context, type))
+ {
+ const gl::DrawElementsIndirectCommand *cmd = nullptr;
+ ANGLE_TRY(ReadbackIndirectBuffer(context, indirect, &cmd));
+
+ const GLuint typeBytes = gl::GetDrawElementsTypeSize(type);
+ const void *indices =
+ reinterpret_cast<const void *>(static_cast<uintptr_t>(cmd->firstIndex * typeBytes));
+
+ // We must explicitly resolve the index range for the slow-path indirect drawElements to
+ // make sure we are using the correct 'baseVertex'. This parameter does not exist for the
+ // direct drawElements.
+ gl::IndexRange indexRange;
+ ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(context, type, cmd->count,
+ indices, &indexRange));
+
+ GLint startVertex;
+ ANGLE_TRY(ComputeStartVertex(GetImplAs<Context11>(context), indexRange, cmd->baseVertex,
+ &startVertex));
+
+ ANGLE_TRY(mRenderer->getStateManager()->updateState(
+ context, mode, startVertex, cmd->count, type, indices, cmd->primCount, cmd->baseVertex,
+ cmd->baseInstance, true));
+ return mRenderer->drawElements(context, mode, static_cast<GLint>(indexRange.start),
+ cmd->count, type, indices, cmd->primCount, 0, 0, true);
+ }
+ else
+ {
+ ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, 0, 0, type, nullptr, 0,
+ 0, 0, true));
+ return mRenderer->drawElementsIndirect(context, indirect);
+ }
+}
+
+#define DRAW_ARRAYS__ \
+ { \
+ ANGLE_TRY(mRenderer->getStateManager()->updateState( \
+ context, mode, firsts[drawID], counts[drawID], gl::DrawElementsType::InvalidEnum, \
+ nullptr, 0, 0, 0, false)); \
+ ANGLE_TRY( \
+ mRenderer->drawArrays(context, mode, firsts[drawID], counts[drawID], 0, 0, false)); \
+ }
+#define DRAW_ARRAYS_INSTANCED_ \
+ { \
+ ANGLE_TRY(mRenderer->getStateManager()->updateState( \
+ context, mode, firsts[drawID], counts[drawID], gl::DrawElementsType::InvalidEnum, \
+ nullptr, instanceCounts[drawID], 0, 0, false)); \
+ ANGLE_TRY(mRenderer->drawArrays(context, mode, firsts[drawID], counts[drawID], \
+ instanceCounts[drawID], 0, true)); \
+ }
+#define DRAW_ARRAYS_INSTANCED_BASE_INSTANCE \
+ { \
+ ANGLE_TRY(mRenderer->getStateManager()->updateState( \
+ context, mode, firsts[drawID], counts[drawID], gl::DrawElementsType::InvalidEnum, \
+ nullptr, instanceCounts[drawID], 0, baseInstances[drawID], false)); \
+ ANGLE_TRY(mRenderer->drawArrays(context, mode, firsts[drawID], counts[drawID], \
+ instanceCounts[drawID], baseInstances[drawID], true)); \
+ }
+#define DRAW_ELEMENTS__ \
+ { \
+ ANGLE_TRY(drawElementsImpl(context, mode, counts[drawID], type, indices[drawID], 0, 0, 0, \
+ false, false)); \
+ }
+#define DRAW_ELEMENTS_INSTANCED_ \
+ { \
+ ANGLE_TRY(drawElementsImpl(context, mode, counts[drawID], type, indices[drawID], \
+ instanceCounts[drawID], 0, 0, false, true)); \
+ }
+#define DRAW_ELEMENTS_INSTANCED_BASE_VERTEX_BASE_INSTANCE \
+ { \
+ ANGLE_TRY(drawElementsImpl(context, mode, counts[drawID], type, indices[drawID], \
+ instanceCounts[drawID], baseVertices[drawID], \
+ baseInstances[drawID], false, true)); \
+ }
+
+#define DRAW_CALL(drawType, instanced, bvbi) DRAW_##drawType##instanced##bvbi
+
+#define MULTI_DRAW_BLOCK(drawType, instanced, bvbi, hasDrawID, hasBaseVertex, hasBaseInstance) \
+ for (GLsizei drawID = 0; drawID < drawcount; ++drawID) \
+ { \
+ if (ANGLE_NOOP_DRAW(instanced)) \
+ { \
+ continue; \
+ } \
+ ANGLE_SET_DRAW_ID_UNIFORM(hasDrawID)(drawID); \
+ ANGLE_SET_BASE_VERTEX_UNIFORM(hasBaseVertex)(baseVertices[drawID]); \
+ ANGLE_SET_BASE_INSTANCE_UNIFORM(hasBaseInstance)(baseInstances[drawID]); \
+ ASSERT(counts[drawID] > 0); \
+ DRAW_CALL(drawType, instanced, bvbi); \
+ ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced); \
+ gl::MarkShaderStorageUsage(context); \
+ }
+
+angle::Result Context11::multiDrawArrays(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ GLsizei drawcount)
+{
+ gl::Program *programObject = context->getState().getLinkedProgram(context);
+ const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
+ if (hasDrawID)
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _, _, 1, 0, 0)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _, _, 0, 0, 0)
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Context11::multiDrawArraysInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount)
+{
+ gl::Program *programObject = context->getState().getLinkedProgram(context);
+ const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
+ if (hasDrawID)
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 1, 0, 0)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 0, 0, 0)
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Context11::multiDrawArraysIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride)
+{
+ return rx::MultiDrawArraysIndirectGeneral(this, context, mode, indirect, drawcount, stride);
+}
+
+angle::Result Context11::multiDrawElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ GLsizei drawcount)
+{
+ gl::Program *programObject = context->getState().getLinkedProgram(context);
+ const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
+ if (hasDrawID)
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _, _, 1, 0, 0)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _, _, 0, 0, 0)
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Context11::multiDrawElementsInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount)
+{
+ gl::Program *programObject = context->getState().getLinkedProgram(context);
+ const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
+ if (hasDrawID)
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 1, 0, 0)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 0, 0, 0)
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Context11::multiDrawElementsIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType type,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride)
+{
+ return rx::MultiDrawElementsIndirectGeneral(this, context, mode, type, indirect, drawcount,
+ stride);
+}
+
+angle::Result Context11::multiDrawArraysInstancedBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ const GLuint *baseInstances,
+ GLsizei drawcount)
+{
+ gl::Program *programObject = context->getState().getLinkedProgram(context);
+ const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
+ const bool hasBaseInstance = programObject && programObject->hasBaseInstanceUniform();
+ ResetBaseVertexBaseInstance resetUniforms(programObject, false, hasBaseInstance);
+
+ if (hasDrawID && hasBaseInstance)
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 1)
+ }
+ else if (hasDrawID)
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 0)
+ }
+ else if (hasBaseInstance)
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 1)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 0)
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Context11::multiDrawElementsInstancedBaseVertexBaseInstance(
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount)
+{
+ gl::Program *programObject = context->getState().getLinkedProgram(context);
+ const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
+ const bool hasBaseVertex = programObject && programObject->hasBaseVertexUniform();
+ const bool hasBaseInstance = programObject && programObject->hasBaseInstanceUniform();
+ ResetBaseVertexBaseInstance resetUniforms(programObject, hasBaseVertex, hasBaseInstance);
+
+ if (hasDrawID)
+ {
+ if (hasBaseVertex)
+ {
+ if (hasBaseInstance)
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 1)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 0)
+ }
+ }
+ else
+ {
+ if (hasBaseInstance)
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 1)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 0)
+ }
+ }
+ }
+ else
+ {
+ if (hasBaseVertex)
+ {
+ if (hasBaseInstance)
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 1)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 0)
+ }
+ }
+ else
+ {
+ if (hasBaseInstance)
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 1)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 0)
+ }
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+gl::GraphicsResetStatus Context11::getResetStatus()
+{
+ return mRenderer->getResetStatus();
+}
+
+angle::Result Context11::insertEventMarker(GLsizei length, const char *marker)
+{
+ mRenderer->getDebugAnnotatorContext()->setMarker(marker);
+ return angle::Result::Continue;
+}
+
+angle::Result Context11::pushGroupMarker(GLsizei length, const char *marker)
+{
+ mRenderer->getDebugAnnotatorContext()->beginEvent(angle::EntryPoint::GLPushGroupMarkerEXT,
+ marker, marker);
+ mMarkerStack.push(std::string(marker));
+ return angle::Result::Continue;
+}
+
+angle::Result Context11::popGroupMarker()
+{
+ const char *marker = nullptr;
+ if (!mMarkerStack.empty())
+ {
+ marker = mMarkerStack.top().c_str();
+ mMarkerStack.pop();
+ mRenderer->getDebugAnnotatorContext()->endEvent(marker,
+ angle::EntryPoint::GLPopGroupMarkerEXT);
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result Context11::pushDebugGroup(const gl::Context *context,
+ GLenum source,
+ GLuint id,
+ const std::string &message)
+{
+ // Fall through to the EXT_debug_marker functions
+ return pushGroupMarker(static_cast<GLsizei>(message.size()), message.c_str());
+}
+
+angle::Result Context11::popDebugGroup(const gl::Context *context)
+{
+ // Fall through to the EXT_debug_marker functions
+ return popGroupMarker();
+}
+
+angle::Result Context11::syncState(const gl::Context *context,
+ const gl::State::DirtyBits &dirtyBits,
+ const gl::State::DirtyBits &bitMask,
+ gl::Command command)
+{
+ mRenderer->getStateManager()->syncState(context, dirtyBits, command);
+ return angle::Result::Continue;
+}
+
+GLint Context11::getGPUDisjoint()
+{
+ return mRenderer->getGPUDisjoint();
+}
+
+GLint64 Context11::getTimestamp()
+{
+ return mRenderer->getTimestamp();
+}
+
+angle::Result Context11::onMakeCurrent(const gl::Context *context)
+{
+ // Immediately return if the device has been lost.
+ if (!mRenderer->getDevice())
+ {
+ return angle::Result::Continue;
+ }
+
+ return mRenderer->getStateManager()->onMakeCurrent(context);
+}
+
+gl::Caps Context11::getNativeCaps() const
+{
+ gl::Caps caps = mRenderer->getNativeCaps();
+
+ // For pixel shaders, the render targets and unordered access views share the same resource
+ // slots, so the maximum number of fragment shader outputs depends on the current context
+ // version:
+ // - If current context is ES 3.0 and below, we use D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT(8)
+ // as the value of max draw buffers because UAVs are not used.
+ // - If current context is ES 3.1 and the feature level is 11_0, the RTVs and UAVs share 8
+ // slots. As ES 3.1 requires at least 1 atomic counter buffer in compute shaders, the value
+ // of max combined shader output resources is limited to 7, thus only 7 RTV slots can be
+ // used simultaneously.
+ // - If current context is ES 3.1 and the feature level is 11_1, the RTVs and UAVs share 64
+ // slots. Currently we allocate 60 slots for combined shader output resources, so we can use
+ // at most D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT(8) RTVs simultaneously.
+ if (mState.getClientVersion() >= gl::ES_3_1 &&
+ mRenderer->getRenderer11DeviceCaps().featureLevel == D3D_FEATURE_LEVEL_11_0)
+ {
+ caps.maxDrawBuffers = caps.maxCombinedShaderOutputResources;
+ caps.maxColorAttachments = caps.maxCombinedShaderOutputResources;
+ }
+
+ return caps;
+}
+
+const gl::TextureCapsMap &Context11::getNativeTextureCaps() const
+{
+ return mRenderer->getNativeTextureCaps();
+}
+
+const gl::Extensions &Context11::getNativeExtensions() const
+{
+ return mRenderer->getNativeExtensions();
+}
+
+const gl::Limitations &Context11::getNativeLimitations() const
+{
+ return mRenderer->getNativeLimitations();
+}
+
+ShPixelLocalStorageType Context11::getNativePixelLocalStorageType() const
+{
+ return mRenderer->getNativePixelLocalStorageType();
+}
+
+angle::Result Context11::dispatchCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ)
+{
+ return mRenderer->dispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ);
+}
+
+angle::Result Context11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
+{
+ return mRenderer->dispatchComputeIndirect(context, indirect);
+}
+
+angle::Result Context11::triggerDrawCallProgramRecompilation(const gl::Context *context,
+ gl::PrimitiveMode drawMode)
+{
+ const auto &glState = context->getState();
+ const auto *va11 = GetImplAs<VertexArray11>(glState.getVertexArray());
+ const auto *drawFBO = glState.getDrawFramebuffer();
+ gl::Program *program = glState.getProgram();
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+
+ programD3D->updateCachedInputLayout(va11->getCurrentStateSerial(), glState);
+ programD3D->updateCachedOutputLayout(context, drawFBO);
+
+ bool recompileVS = !programD3D->hasVertexExecutableForCachedInputLayout();
+ bool recompileGS = !programD3D->hasGeometryExecutableForPrimitiveType(glState, drawMode);
+ bool recompilePS = !programD3D->hasPixelExecutableForCachedOutputLayout();
+
+ if (!recompileVS && !recompileGS && !recompilePS)
+ {
+ return angle::Result::Continue;
+ }
+
+ // Load the compiler if necessary and recompile the programs.
+ ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(this));
+
+ gl::InfoLog infoLog;
+
+ if (recompileVS)
+ {
+ ShaderExecutableD3D *vertexExe = nullptr;
+ ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(this, &vertexExe, &infoLog));
+ if (!programD3D->hasVertexExecutableForCachedInputLayout())
+ {
+ ASSERT(infoLog.getLength() > 0);
+ ERR() << "Error compiling dynamic vertex executable: " << infoLog.str();
+ ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic vertex executable");
+ }
+ }
+
+ if (recompileGS)
+ {
+ ShaderExecutableD3D *geometryExe = nullptr;
+ ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(this, glState, drawMode,
+ &geometryExe, &infoLog));
+ if (!programD3D->hasGeometryExecutableForPrimitiveType(glState, drawMode))
+ {
+ ASSERT(infoLog.getLength() > 0);
+ ERR() << "Error compiling dynamic geometry executable: " << infoLog.str();
+ ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic geometry executable");
+ }
+ }
+
+ if (recompilePS)
+ {
+ ShaderExecutableD3D *pixelExe = nullptr;
+ ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(this, &pixelExe, &infoLog));
+ if (!programD3D->hasPixelExecutableForCachedOutputLayout())
+ {
+ ASSERT(infoLog.getLength() > 0);
+ ERR() << "Error compiling dynamic pixel executable: " << infoLog.str();
+ ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic pixel executable");
+ }
+ }
+
+ // Refresh the program cache entry.
+ if (mMemoryProgramCache)
+ {
+ ANGLE_TRY(mMemoryProgramCache->updateProgram(context, program));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Context11::triggerDispatchCallProgramRecompilation(const gl::Context *context)
+{
+ const auto &glState = context->getState();
+ gl::Program *program = glState.getProgram();
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+
+ programD3D->updateCachedComputeImage2DBindLayout(context);
+
+ bool recompileCS = !programD3D->hasComputeExecutableForCachedImage2DBindLayout();
+
+ if (!recompileCS)
+ {
+ return angle::Result::Continue;
+ }
+
+ // Load the compiler if necessary and recompile the programs.
+ ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(this));
+
+ gl::InfoLog infoLog;
+
+ ShaderExecutableD3D *computeExe = nullptr;
+ ANGLE_TRY(
+ programD3D->getComputeExecutableForImage2DBindLayout(context, this, &computeExe, &infoLog));
+ if (!programD3D->hasComputeExecutableForCachedImage2DBindLayout())
+ {
+ ASSERT(infoLog.getLength() > 0);
+ ERR() << "Dynamic recompilation error log: " << infoLog.str();
+ ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic compute executable");
+ }
+
+ // Refresh the program cache entry.
+ if (mMemoryProgramCache)
+ {
+ ANGLE_TRY(mMemoryProgramCache->updateProgram(context, program));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Context11::memoryBarrier(const gl::Context *context, GLbitfield barriers)
+{
+ return angle::Result::Continue;
+}
+
+angle::Result Context11::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
+{
+ return angle::Result::Continue;
+}
+
+angle::Result Context11::getIncompleteTexture(const gl::Context *context,
+ gl::TextureType type,
+ gl::Texture **textureOut)
+{
+ return mIncompleteTextures.getIncompleteTexture(context, type, gl::SamplerFormat::Float, this,
+ textureOut);
+}
+
+angle::Result Context11::initializeMultisampleTextureToBlack(const gl::Context *context,
+ gl::Texture *glTexture)
+{
+ ASSERT(glTexture->getType() == gl::TextureType::_2DMultisample);
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(glTexture);
+ gl::ImageIndex index = gl::ImageIndex::Make2DMultisample();
+ RenderTargetD3D *renderTarget = nullptr;
+ GLsizei texSamples = textureD3D->getRenderToTextureSamples();
+ ANGLE_TRY(textureD3D->getRenderTarget(context, index, texSamples, &renderTarget));
+ return mRenderer->clearRenderTarget(context, renderTarget, gl::ColorF(0.0f, 0.0f, 0.0f, 1.0f),
+ 1.0f, 0);
+}
+
+void Context11::handleResult(HRESULT hr,
+ const char *message,
+ const char *file,
+ const char *function,
+ unsigned int line)
+{
+ ASSERT(FAILED(hr));
+
+ GLenum glErrorCode = DefaultGLErrorCode(hr);
+
+ std::stringstream errorStream;
+ errorStream << "Internal D3D11 error: " << gl::FmtHR(hr);
+
+ if (d3d11::isDeviceLostError(hr))
+ {
+ HRESULT removalReason = mRenderer->getDevice()->GetDeviceRemovedReason();
+ errorStream << " (removal reason: " << gl::FmtHR(removalReason) << ")";
+ mRenderer->notifyDeviceLost();
+ }
+
+ errorStream << ": " << message;
+
+ mErrors->handleError(glErrorCode, errorStream.str().c_str(), file, function, line);
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Context11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Context11.h
new file mode 100644
index 0000000000..5f84e410b5
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Context11.h
@@ -0,0 +1,282 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context11:
+// D3D11-specific functionality associated with a GL Context.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_
+
+#include <stack>
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/d3d/ContextD3D.h"
+
+namespace rx
+{
+class Renderer11;
+
+class Context11 : public ContextD3D, public MultisampleTextureInitializer
+{
+ public:
+ Context11(const gl::State &state, gl::ErrorSet *errorSet, Renderer11 *renderer);
+ ~Context11() override;
+
+ angle::Result initialize() override;
+ void onDestroy(const gl::Context *context) override;
+
+ // Shader creation
+ CompilerImpl *createCompiler() override;
+ ShaderImpl *createShader(const gl::ShaderState &data) override;
+ ProgramImpl *createProgram(const gl::ProgramState &data) override;
+
+ // Framebuffer creation
+ FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) override;
+
+ // Texture creation
+ TextureImpl *createTexture(const gl::TextureState &state) override;
+
+ // Renderbuffer creation
+ RenderbufferImpl *createRenderbuffer(const gl::RenderbufferState &state) override;
+
+ // Buffer creation
+ BufferImpl *createBuffer(const gl::BufferState &state) override;
+
+ // Vertex Array creation
+ VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override;
+
+ // Query and Fence creation
+ QueryImpl *createQuery(gl::QueryType type) override;
+ FenceNVImpl *createFenceNV() override;
+ SyncImpl *createSync() override;
+
+ // Transform Feedback creation
+ TransformFeedbackImpl *createTransformFeedback(
+ const gl::TransformFeedbackState &state) override;
+
+ // Sampler object creation
+ SamplerImpl *createSampler(const gl::SamplerState &state) override;
+
+ // Program Pipeline object creation
+ ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override;
+
+ // Memory object creation.
+ MemoryObjectImpl *createMemoryObject() override;
+
+ // Semaphore creation.
+ SemaphoreImpl *createSemaphore() override;
+
+ // Overlay creation.
+ OverlayImpl *createOverlay(const gl::OverlayState &state) override;
+
+ // Flush and finish.
+ angle::Result flush(const gl::Context *context) override;
+ angle::Result finish(const gl::Context *context) override;
+
+ // Drawing methods.
+ angle::Result drawArrays(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count) override;
+ angle::Result drawArraysInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount) override;
+ angle::Result drawArraysInstancedBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount,
+ GLuint baseInstance) override;
+
+ angle::Result drawElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices) override;
+ angle::Result drawElementsBaseVertex(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLint baseVertex) override;
+ angle::Result drawElementsInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances) override;
+ angle::Result drawElementsInstancedBaseVertex(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances,
+ GLint baseVertex) override;
+ angle::Result drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances,
+ GLint baseVertex,
+ GLuint baseInstance) override;
+ angle::Result drawRangeElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices) override;
+ angle::Result drawRangeElementsBaseVertex(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLint baseVertex) override;
+ angle::Result drawArraysIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const void *indirect) override;
+ angle::Result drawElementsIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType type,
+ const void *indirect) override;
+
+ angle::Result multiDrawArrays(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ GLsizei drawcount) override;
+ angle::Result multiDrawArraysInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount) override;
+ angle::Result multiDrawArraysIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride) override;
+ angle::Result multiDrawElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ GLsizei drawcount) override;
+ angle::Result multiDrawElementsInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount) override;
+ angle::Result multiDrawElementsIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType type,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride) override;
+ angle::Result multiDrawArraysInstancedBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ const GLuint *baseInstances,
+ GLsizei drawcount) override;
+ angle::Result multiDrawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount) override;
+
+ // Device loss
+ gl::GraphicsResetStatus getResetStatus() override;
+
+ // EXT_debug_marker
+ angle::Result insertEventMarker(GLsizei length, const char *marker) override;
+ angle::Result pushGroupMarker(GLsizei length, const char *marker) override;
+ angle::Result popGroupMarker() override;
+
+ // KHR_debug
+ angle::Result pushDebugGroup(const gl::Context *context,
+ GLenum source,
+ GLuint id,
+ const std::string &message) override;
+ angle::Result popDebugGroup(const gl::Context *context) override;
+
+ // State sync with dirty bits.
+ angle::Result syncState(const gl::Context *context,
+ const gl::State::DirtyBits &dirtyBits,
+ const gl::State::DirtyBits &bitMask,
+ gl::Command command) override;
+
+ // Disjoint timer queries
+ GLint getGPUDisjoint() override;
+ GLint64 getTimestamp() override;
+
+ // Context switching
+ angle::Result onMakeCurrent(const gl::Context *context) override;
+
+ // Caps queries
+ gl::Caps getNativeCaps() const override;
+ const gl::TextureCapsMap &getNativeTextureCaps() const override;
+ const gl::Extensions &getNativeExtensions() const override;
+ const gl::Limitations &getNativeLimitations() const override;
+ ShPixelLocalStorageType getNativePixelLocalStorageType() const override;
+
+ Renderer11 *getRenderer() const { return mRenderer; }
+
+ angle::Result dispatchCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ) override;
+ angle::Result dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) override;
+
+ angle::Result memoryBarrier(const gl::Context *context, GLbitfield barriers) override;
+ angle::Result memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) override;
+
+ angle::Result triggerDrawCallProgramRecompilation(const gl::Context *context,
+ gl::PrimitiveMode drawMode);
+ angle::Result triggerDispatchCallProgramRecompilation(const gl::Context *context);
+ angle::Result getIncompleteTexture(const gl::Context *context,
+ gl::TextureType type,
+ gl::Texture **textureOut);
+
+ angle::Result initializeMultisampleTextureToBlack(const gl::Context *context,
+ gl::Texture *glTexture) override;
+
+ void handleResult(HRESULT hr,
+ const char *message,
+ const char *file,
+ const char *function,
+ unsigned int line) override;
+
+ private:
+ angle::Result drawElementsImpl(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei indexCount,
+ gl::DrawElementsType indexType,
+ const void *indices,
+ GLsizei instanceCount,
+ GLint baseVertex,
+ GLuint baseInstance,
+ bool promoteDynamic,
+ bool isInstancedDraw);
+
+ Renderer11 *mRenderer;
+ IncompleteTextureSet mIncompleteTextures;
+ std::stack<std::string> mMarkerStack;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
new file mode 100644
index 0000000000..2b947d8957
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
@@ -0,0 +1,148 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DebugAnnotator11.cpp: D3D11 helpers for adding trace annotations.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h"
+
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#include <versionhelpers.h>
+
+#include "common/system_utils.h"
+
+namespace rx
+{
+
+// DebugAnnotator11 implementation
+DebugAnnotator11::DebugAnnotator11() {}
+
+DebugAnnotator11::~DebugAnnotator11() {}
+
+void DebugAnnotator11::beginEvent(gl::Context *context,
+ angle::EntryPoint entryPoint,
+ const char *eventName,
+ const char *eventMessage)
+{
+ angle::LoggingAnnotator::beginEvent(context, entryPoint, eventName, eventMessage);
+ if (!context)
+ {
+ return;
+ }
+ Renderer11 *renderer11 = GetImplAs<Context11>(context)->getRenderer();
+ renderer11->getDebugAnnotatorContext()->beginEvent(entryPoint, eventName, eventMessage);
+}
+
+void DebugAnnotator11::endEvent(gl::Context *context,
+ const char *eventName,
+ angle::EntryPoint entryPoint)
+{
+ angle::LoggingAnnotator::endEvent(context, eventName, entryPoint);
+ if (!context)
+ {
+ return;
+ }
+ Renderer11 *renderer11 = GetImplAs<Context11>(context)->getRenderer();
+ renderer11->getDebugAnnotatorContext()->endEvent(eventName, entryPoint);
+}
+
+void DebugAnnotator11::setMarker(gl::Context *context, const char *markerName)
+{
+ angle::LoggingAnnotator::setMarker(context, markerName);
+ if (!context)
+ {
+ return;
+ }
+ Renderer11 *renderer11 = GetImplAs<Context11>(context)->getRenderer();
+ renderer11->getDebugAnnotatorContext()->setMarker(markerName);
+}
+
+bool DebugAnnotator11::getStatus(const gl::Context *context)
+{
+ if (!context)
+ {
+ return false;
+ }
+ Renderer11 *renderer11 = GetImplAs<Context11>(context)->getRenderer();
+ return renderer11->getDebugAnnotatorContext()->getStatus();
+}
+
+// DebugAnnotatorContext11 implemenetation
+DebugAnnotatorContext11::DebugAnnotatorContext11() = default;
+
+DebugAnnotatorContext11::~DebugAnnotatorContext11() = default;
+
+void DebugAnnotatorContext11::beginEvent(angle::EntryPoint entryPoint,
+ const char *eventName,
+ const char *eventMessage)
+{
+ if (loggingEnabledForThisThread())
+ {
+ std::mbstate_t state = std::mbstate_t();
+ std::mbsrtowcs(mWCharMessage, &eventMessage, kMaxMessageLength, &state);
+ mUserDefinedAnnotation->BeginEvent(mWCharMessage);
+ }
+}
+
+void DebugAnnotatorContext11::endEvent(const char *eventName, angle::EntryPoint entryPoint)
+{
+ if (loggingEnabledForThisThread())
+ {
+ mUserDefinedAnnotation->EndEvent();
+ }
+}
+
+void DebugAnnotatorContext11::setMarker(const char *markerName)
+{
+ if (loggingEnabledForThisThread())
+ {
+ std::mbstate_t state = std::mbstate_t();
+ std::mbsrtowcs(mWCharMessage, &markerName, kMaxMessageLength, &state);
+ mUserDefinedAnnotation->SetMarker(mWCharMessage);
+ }
+}
+
+bool DebugAnnotatorContext11::getStatus() const
+{
+ if (loggingEnabledForThisThread())
+ {
+ return !!(mUserDefinedAnnotation->GetStatus());
+ }
+
+ return false;
+}
+
+bool DebugAnnotatorContext11::loggingEnabledForThisThread() const
+{
+ return mUserDefinedAnnotation != nullptr &&
+ angle::GetCurrentThreadUniqueId() == mAnnotationThread;
+}
+
+void DebugAnnotatorContext11::initialize(ID3D11DeviceContext *context)
+{
+#if !defined(ANGLE_ENABLE_WINDOWS_UWP)
+ // ID3DUserDefinedAnnotation.GetStatus only works on Windows10 or greater.
+ // Returning true unconditionally from DebugAnnotatorContext11::getStatus() means
+ // writing out all compiled shaders to temporary files even if debugging
+ // tools are not attached. See rx::ShaderD3D::prepareSourceAndReturnOptions.
+ // If you want debug annotations, you must use Windows 10.
+ if (IsWindows10OrGreater())
+#endif
+ {
+ mAnnotationThread = angle::GetCurrentThreadUniqueId();
+ mUserDefinedAnnotation.Attach(
+ d3d11::DynamicCastComObject<ID3DUserDefinedAnnotation>(context));
+ }
+}
+
+void DebugAnnotatorContext11::release()
+{
+ mUserDefinedAnnotation.Reset();
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
new file mode 100644
index 0000000000..0356636762
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
@@ -0,0 +1,60 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DebugAnnotator11.h: D3D11 helpers for adding trace annotations.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_
+
+#include "libANGLE/LoggingAnnotator.h"
+
+namespace rx
+{
+
+// Note: To avoid any race conditions between threads, this class has no private data;
+// DebugAnnotatorContext11 will be retrieved from Context11.
+class DebugAnnotator11 : public angle::LoggingAnnotator
+{
+ public:
+ DebugAnnotator11();
+ ~DebugAnnotator11() override;
+ void beginEvent(gl::Context *context,
+ angle::EntryPoint entryPoint,
+ const char *eventName,
+ const char *eventMessage) override;
+ void endEvent(gl::Context *context,
+ const char *eventName,
+ angle::EntryPoint entryPoint) override;
+ void setMarker(gl::Context *context, const char *markerName) override;
+ bool getStatus(const gl::Context *context) override;
+};
+
+class DebugAnnotatorContext11
+{
+ public:
+ DebugAnnotatorContext11();
+ ~DebugAnnotatorContext11();
+ void initialize(ID3D11DeviceContext *context);
+ void release();
+ void beginEvent(angle::EntryPoint entryPoint, const char *eventName, const char *eventMessage);
+ void endEvent(const char *eventName, angle::EntryPoint entryPoint);
+ void setMarker(const char *markerName);
+ bool getStatus() const;
+
+ private:
+ bool loggingEnabledForThisThread() const;
+
+ angle::ComPtr<ID3DUserDefinedAnnotation> mUserDefinedAnnotation;
+ static constexpr size_t kMaxMessageLength = 256;
+ wchar_t mWCharMessage[kMaxMessageLength];
+
+ // Only log annotations from the thread used to initialize the debug annotator
+ uint64_t mAnnotationThread;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.cpp
new file mode 100644
index 0000000000..ff2fc8056c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.cpp
@@ -0,0 +1,209 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+namespace rx
+{
+ExternalImageSiblingImpl11::ExternalImageSiblingImpl11(Renderer11 *renderer,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs)
+ : mRenderer(renderer), mBuffer(buffer), mAttribs(attribs)
+{}
+
+ExternalImageSiblingImpl11::~ExternalImageSiblingImpl11() {}
+
+egl::Error ExternalImageSiblingImpl11::initialize(const egl::Display *display)
+{
+ const angle::Format *angleFormat = nullptr;
+ ANGLE_TRY(mRenderer->getD3DTextureInfo(nullptr, static_cast<IUnknown *>(mBuffer), mAttribs,
+ &mWidth, &mHeight, &mSamples, &mFormat, &angleFormat,
+ &mArraySlice));
+ ID3D11Texture2D *texture =
+ d3d11::DynamicCastComObject<ID3D11Texture2D>(static_cast<IUnknown *>(mBuffer));
+ ASSERT(texture != nullptr);
+ // TextureHelper11 will release texture on destruction.
+ mTexture.set(texture, d3d11::Format::Get(angleFormat->glInternalFormat,
+ mRenderer->getRenderer11DeviceCaps()));
+ D3D11_TEXTURE2D_DESC textureDesc = {};
+ mTexture.getDesc(&textureDesc);
+
+ IDXGIResource *resource = d3d11::DynamicCastComObject<IDXGIResource>(mTexture.get());
+ ASSERT(resource != nullptr);
+ DXGI_USAGE resourceUsage = 0;
+ resource->GetUsage(&resourceUsage);
+ SafeRelease(resource);
+
+ mIsRenderable = (textureDesc.BindFlags & D3D11_BIND_RENDER_TARGET) &&
+ (resourceUsage & DXGI_USAGE_RENDER_TARGET_OUTPUT) &&
+ !(resourceUsage & DXGI_USAGE_READ_ONLY);
+
+ mIsTexturable = (textureDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE) &&
+ (resourceUsage & DXGI_USAGE_SHADER_INPUT);
+
+ mIsTextureArray = (textureDesc.ArraySize > 1);
+
+ return egl::NoError();
+}
+
+gl::Format ExternalImageSiblingImpl11::getFormat() const
+{
+ return mFormat;
+}
+
+bool ExternalImageSiblingImpl11::isRenderable(const gl::Context *context) const
+{
+ return mIsRenderable;
+}
+
+bool ExternalImageSiblingImpl11::isTexturable(const gl::Context *context) const
+{
+ return mIsTexturable;
+}
+
+bool ExternalImageSiblingImpl11::isYUV() const
+{
+ return false;
+}
+
+bool ExternalImageSiblingImpl11::hasProtectedContent() const
+{
+ return false;
+}
+
+gl::Extents ExternalImageSiblingImpl11::getSize() const
+{
+ return gl::Extents(mWidth, mHeight, 1);
+}
+
+size_t ExternalImageSiblingImpl11::getSamples() const
+{
+ return mSamples;
+}
+
+angle::Result ExternalImageSiblingImpl11::getAttachmentRenderTarget(
+ const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
+ GLsizei samples,
+ FramebufferAttachmentRenderTarget **rtOut)
+{
+ ANGLE_TRY(createRenderTarget(context));
+ *rtOut = mRenderTarget.get();
+ return angle::Result::Continue;
+}
+
+angle::Result ExternalImageSiblingImpl11::initializeContents(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+angle::Result ExternalImageSiblingImpl11::createRenderTarget(const gl::Context *context)
+{
+ if (mRenderTarget)
+ return angle::Result::Continue;
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+ const d3d11::Format &formatInfo = mTexture.getFormatSet();
+
+ d3d11::RenderTargetView rtv;
+ if (mIsRenderable)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = formatInfo.rtvFormat;
+ if (mIsTextureArray)
+ {
+ if (mSamples == 0)
+ {
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = 0;
+ rtvDesc.Texture2DArray.FirstArraySlice = mArraySlice;
+ rtvDesc.Texture2DArray.ArraySize = 1;
+ }
+ else
+ {
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
+ rtvDesc.Texture2DMSArray.FirstArraySlice = mArraySlice;
+ rtvDesc.Texture2DMSArray.ArraySize = 1;
+ }
+ }
+ else
+ {
+ if (mSamples == 0)
+ {
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = 0;
+ }
+ else
+ {
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
+ }
+ }
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, mTexture.get(), &rtv));
+ rtv.setInternalName("getAttachmentRenderTarget.RTV");
+ }
+
+ d3d11::SharedSRV srv;
+ if (mIsTexturable)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = formatInfo.srvFormat;
+ if (mIsTextureArray)
+ {
+ if (mSamples == 0)
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.Texture2DArray.MostDetailedMip = 0;
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = mArraySlice;
+ srvDesc.Texture2DArray.ArraySize = 1;
+ }
+ else
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
+ srvDesc.Texture2DArray.FirstArraySlice = mArraySlice;
+ srvDesc.Texture2DArray.ArraySize = 1;
+ }
+ }
+ else
+ {
+ if (mSamples == 0)
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MostDetailedMip = 0;
+ srvDesc.Texture2D.MipLevels = 1;
+ }
+ else
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ }
+ }
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, srvDesc, mTexture.get(), &srv));
+ srv.setInternalName("getAttachmentRenderTarget.SRV");
+ }
+ d3d11::SharedSRV blitSrv = srv.makeCopy();
+
+ mRenderTarget = std::make_unique<TextureRenderTarget11>(
+ std::move(rtv), mTexture, std::move(srv), std::move(blitSrv), mFormat.info->internalFormat,
+ formatInfo, mWidth, mHeight, 1, mSamples);
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.h
new file mode 100644
index 0000000000..3c57120ba2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.h
@@ -0,0 +1,70 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_EXTERNALIMAGESIBLINGIMPL11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_EXTERNALIMAGESIBLINGIMPL11_H_
+
+#include "libANGLE/renderer/ImageImpl.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+
+class Renderer11;
+class RenderTargetD3D;
+
+class ExternalImageSiblingImpl11 : public ExternalImageSiblingImpl
+{
+ public:
+ ExternalImageSiblingImpl11(Renderer11 *renderer,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs);
+ ~ExternalImageSiblingImpl11() override;
+
+ // ExternalImageSiblingImpl interface
+ egl::Error initialize(const egl::Display *display) override;
+ gl::Format getFormat() const override;
+ bool isRenderable(const gl::Context *context) const override;
+ bool isTexturable(const gl::Context *context) const override;
+ bool isYUV() const override;
+ bool hasProtectedContent() const override;
+ gl::Extents getSize() const override;
+ size_t getSamples() const override;
+
+ // FramebufferAttachmentObjectImpl interface
+ angle::Result getAttachmentRenderTarget(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex,
+ GLsizei samples,
+ FramebufferAttachmentRenderTarget **rtOut) override;
+ angle::Result initializeContents(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex) override;
+
+ private:
+ angle::Result createRenderTarget(const gl::Context *context);
+
+ Renderer11 *mRenderer;
+ EGLClientBuffer mBuffer;
+ egl::AttributeMap mAttribs;
+
+ TextureHelper11 mTexture;
+
+ gl::Format mFormat = gl::Format::Invalid();
+ bool mIsRenderable = false;
+ bool mIsTexturable = false;
+ bool mIsTextureArray = false;
+ EGLint mWidth = 0;
+ EGLint mHeight = 0;
+ GLsizei mSamples = 0;
+ UINT mArraySlice = 0;
+
+ std::unique_ptr<RenderTargetD3D> mRenderTarget;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_EXTERNALIMAGESIBLINGIMPL11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp
new file mode 100644
index 0000000000..38a7331b00
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp
@@ -0,0 +1,234 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Fence11.cpp: Defines the rx::FenceNV11 and rx::Sync11 classes which implement
+// rx::FenceNVImpl and rx::SyncImpl.
+
+#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+//
+// Template helpers for set and test operations.
+//
+
+template <class FenceClass>
+angle::Result FenceSetHelper(const gl::Context *context, FenceClass *fence)
+{
+ if (!fence->mQuery)
+ {
+ D3D11_QUERY_DESC queryDesc;
+ queryDesc.Query = D3D11_QUERY_EVENT;
+ queryDesc.MiscFlags = 0;
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+ HRESULT result = fence->mRenderer->getDevice()->CreateQuery(&queryDesc, &fence->mQuery);
+ ANGLE_TRY_HR(context11, result, "Failed to create event query");
+ }
+
+ fence->mRenderer->getDeviceContext()->End(fence->mQuery);
+ return angle::Result::Continue;
+}
+
+template <class FenceClass>
+angle::Result FenceTestHelper(const gl::Context *context,
+ FenceClass *fence,
+ bool flushCommandBuffer,
+ GLboolean *outFinished)
+{
+ ASSERT(fence->mQuery);
+
+ UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH);
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+ HRESULT result =
+ fence->mRenderer->getDeviceContext()->GetData(fence->mQuery, nullptr, 0, getDataFlags);
+ ANGLE_TRY_HR(context11, result, "Failed to get query data");
+
+ ASSERT(result == S_OK || result == S_FALSE);
+ *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE);
+ return angle::Result::Continue;
+}
+
+//
+// FenceNV11
+//
+
+FenceNV11::FenceNV11(Renderer11 *renderer) : FenceNVImpl(), mRenderer(renderer), mQuery(nullptr) {}
+
+FenceNV11::~FenceNV11()
+{
+ SafeRelease(mQuery);
+}
+
+angle::Result FenceNV11::set(const gl::Context *context, GLenum condition)
+{
+ return FenceSetHelper(context, this);
+}
+
+angle::Result FenceNV11::test(const gl::Context *context, GLboolean *outFinished)
+{
+ return FenceTestHelper(context, this, true, outFinished);
+}
+
+angle::Result FenceNV11::finish(const gl::Context *context)
+{
+ GLboolean finished = GL_FALSE;
+
+ int loopCount = 0;
+ while (finished != GL_TRUE)
+ {
+ loopCount++;
+ ANGLE_TRY(FenceTestHelper(context, this, true, &finished));
+
+ bool checkDeviceLost = (loopCount % kPollingD3DDeviceLostCheckFrequency) == 0;
+ if (checkDeviceLost && mRenderer->testDeviceLost())
+ {
+ ANGLE_TRY_HR(GetImplAs<Context11>(context), DXGI_ERROR_DRIVER_INTERNAL_ERROR,
+ "Device was lost while querying result of an event query.");
+ }
+
+ ScheduleYield();
+ }
+
+ return angle::Result::Continue;
+}
+
+//
+// Sync11
+//
+
+// Important note on accurate timers in Windows:
+//
+// QueryPerformanceCounter has a few major issues, including being 10x as expensive to call
+// as timeGetTime on laptops and "jumping" during certain hardware events.
+//
+// See the comments at the top of the Chromium source file "chromium/src/base/time/time_win.cc"
+// https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time_win.cc
+//
+// We still opt to use QPC. In the present and moving forward, most newer systems will not suffer
+// from buggy implementations.
+
+Sync11::Sync11(Renderer11 *renderer) : SyncImpl(), mRenderer(renderer), mQuery(nullptr)
+{
+ LARGE_INTEGER counterFreqency = {};
+ BOOL success = QueryPerformanceFrequency(&counterFreqency);
+ ASSERT(success);
+
+ mCounterFrequency = counterFreqency.QuadPart;
+}
+
+Sync11::~Sync11()
+{
+ SafeRelease(mQuery);
+}
+
+angle::Result Sync11::set(const gl::Context *context, GLenum condition, GLbitfield flags)
+{
+ ASSERT(condition == GL_SYNC_GPU_COMMANDS_COMPLETE && flags == 0);
+ return FenceSetHelper(context, this);
+}
+
+angle::Result Sync11::clientWait(const gl::Context *context,
+ GLbitfield flags,
+ GLuint64 timeout,
+ GLenum *outResult)
+{
+ ASSERT(outResult);
+
+ bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0);
+
+ *outResult = GL_WAIT_FAILED;
+
+ GLboolean result = GL_FALSE;
+ ANGLE_TRY(FenceTestHelper(context, this, flushCommandBuffer, &result));
+
+ if (result == GL_TRUE)
+ {
+ *outResult = GL_ALREADY_SIGNALED;
+ return angle::Result::Continue;
+ }
+
+ if (timeout == 0)
+ {
+ *outResult = GL_TIMEOUT_EXPIRED;
+ return angle::Result::Continue;
+ }
+
+ LARGE_INTEGER currentCounter = {};
+ BOOL success = QueryPerformanceCounter(&currentCounter);
+ ASSERT(success);
+
+ LONGLONG timeoutInSeconds = static_cast<LONGLONG>(timeout / 1000000000ull);
+ LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds;
+
+ // Extremely unlikely, but if mCounterFrequency is large enough, endCounter can wrap
+ if (endCounter < currentCounter.QuadPart)
+ {
+ endCounter = MAXLONGLONG;
+ }
+
+ int loopCount = 0;
+ while (currentCounter.QuadPart < endCounter && !result)
+ {
+ loopCount++;
+ ScheduleYield();
+ success = QueryPerformanceCounter(&currentCounter);
+ ASSERT(success);
+
+ *outResult = GL_WAIT_FAILED;
+
+ ANGLE_TRY(FenceTestHelper(context, this, flushCommandBuffer, &result));
+
+ bool checkDeviceLost = (loopCount % kPollingD3DDeviceLostCheckFrequency) == 0;
+ if (checkDeviceLost && mRenderer->testDeviceLost())
+ {
+ *outResult = GL_WAIT_FAILED;
+ ANGLE_TRY_HR(GetImplAs<Context11>(context), DXGI_ERROR_DRIVER_INTERNAL_ERROR,
+ "Device was lost while querying result of an event query.");
+ }
+ }
+
+ if (currentCounter.QuadPart >= endCounter)
+ {
+ *outResult = GL_TIMEOUT_EXPIRED;
+ }
+ else
+ {
+ *outResult = GL_CONDITION_SATISFIED;
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Sync11::serverWait(const gl::Context *context, GLbitfield flags, GLuint64 timeout)
+{
+ // Because our API is currently designed to be called from a single thread, we don't need to do
+ // extra work for a server-side fence. GPU commands issued after the fence is created will
+ // always be processed after the fence is signaled.
+ return angle::Result::Continue;
+}
+
+angle::Result Sync11::getStatus(const gl::Context *context, GLint *outResult)
+{
+ GLboolean result = GL_FALSE;
+
+ // The spec does not specify any way to report errors during the status test (e.g. device
+ // lost) so we report the fence is unblocked in case of error or signaled.
+ *outResult = GL_SIGNALED;
+ ANGLE_TRY(FenceTestHelper(context, this, false, &result));
+
+ *outResult = (result ? GL_SIGNALED : GL_UNSIGNALED);
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Fence11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Fence11.h
new file mode 100644
index 0000000000..e35ff6b71c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Fence11.h
@@ -0,0 +1,76 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Fence11.h: Defines the rx::FenceNV11 and rx::Sync11 classes which implement rx::FenceNVImpl
+// and rx::SyncImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_
+
+#include "libANGLE/renderer/FenceNVImpl.h"
+#include "libANGLE/renderer/SyncImpl.h"
+
+namespace rx
+{
+class Renderer11;
+
+class FenceNV11 : public FenceNVImpl
+{
+ public:
+ explicit FenceNV11(Renderer11 *renderer);
+ ~FenceNV11() override;
+
+ void onDestroy(const gl::Context *context) override {}
+ angle::Result set(const gl::Context *context, GLenum condition) override;
+ angle::Result test(const gl::Context *context, GLboolean *outFinished) override;
+ angle::Result finish(const gl::Context *context) override;
+
+ private:
+ template <class T>
+ friend angle::Result FenceSetHelper(const gl::Context *context, T *fence);
+ template <class T>
+ friend angle::Result FenceTestHelper(const gl::Context *context,
+ T *fence,
+ bool flushCommandBuffer,
+ GLboolean *outFinished);
+
+ Renderer11 *mRenderer;
+ ID3D11Query *mQuery;
+};
+
+class Sync11 : public SyncImpl
+{
+ public:
+ explicit Sync11(Renderer11 *renderer);
+ ~Sync11() override;
+
+ angle::Result set(const gl::Context *context, GLenum condition, GLbitfield flags) override;
+ angle::Result clientWait(const gl::Context *context,
+ GLbitfield flags,
+ GLuint64 timeout,
+ GLenum *outResult) override;
+ angle::Result serverWait(const gl::Context *context,
+ GLbitfield flags,
+ GLuint64 timeout) override;
+ angle::Result getStatus(const gl::Context *context, GLint *outResult) override;
+
+ private:
+ template <class T>
+ friend angle::Result FenceSetHelper(const gl::Context *context, T *fence);
+ template <class T>
+ friend angle::Result FenceTestHelper(const gl::Context *context,
+ T *fence,
+ bool flushCommandBuffer,
+ GLboolean *outFinished);
+
+ Renderer11 *mRenderer;
+ ID3D11Query *mQuery;
+ LONGLONG mCounterFrequency;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
new file mode 100644
index 0000000000..e6516ff521
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
@@ -0,0 +1,452 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Framebuffer11.cpp: Implements the Framebuffer11 class.
+
+#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
+
+#include "common/bitset_utils.h"
+#include "common/debug.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace
+{
+angle::Result MarkAttachmentsDirty(const gl::Context *context,
+ const gl::FramebufferAttachment *attachment)
+{
+ if (attachment->type() == GL_TEXTURE)
+ {
+ gl::Texture *texture = attachment->getTexture();
+
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+
+ TextureStorage *texStorage = nullptr;
+ ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage));
+
+ if (texStorage)
+ {
+ TextureStorage11 *texStorage11 = GetAs<TextureStorage11>(texStorage);
+ ASSERT(texStorage11);
+
+ texStorage11->markLevelDirty(attachment->mipLevel());
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+UINT GetAttachmentLayer(const gl::FramebufferAttachment *attachment)
+{
+ if (attachment->type() == GL_TEXTURE &&
+ attachment->getTexture()->getType() == gl::TextureType::_3D)
+ {
+ return attachment->layer();
+ }
+ return 0;
+}
+
+} // anonymous namespace
+
+Framebuffer11::Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer)
+ : FramebufferD3D(data, renderer), mRenderer(renderer)
+{
+ ASSERT(mRenderer != nullptr);
+}
+
+Framebuffer11::~Framebuffer11() {}
+
+angle::Result Framebuffer11::markAttachmentsDirty(const gl::Context *context) const
+{
+ const auto &colorAttachments = mState.getColorAttachments();
+ for (size_t drawBuffer : mState.getEnabledDrawBuffers())
+ {
+ const gl::FramebufferAttachment &colorAttachment = colorAttachments[drawBuffer];
+ ASSERT(colorAttachment.isAttached());
+ ANGLE_TRY(MarkAttachmentsDirty(context, &colorAttachment));
+ }
+
+ const gl::FramebufferAttachment *dsAttachment = mState.getDepthOrStencilAttachment();
+ if (dsAttachment)
+ {
+ ANGLE_TRY(MarkAttachmentsDirty(context, dsAttachment));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Framebuffer11::clearImpl(const gl::Context *context,
+ const ClearParameters &clearParams)
+{
+ Clear11 *clearer = mRenderer->getClearer();
+
+ const gl::FramebufferAttachment *colorAttachment = mState.getFirstColorAttachment();
+ if (clearParams.scissorEnabled == true && colorAttachment != nullptr &&
+ UsePresentPathFast(mRenderer, colorAttachment))
+ {
+ // If the current framebuffer is using the default colorbuffer, and present path fast is
+ // active, and the scissor rect is enabled, then we should invert the scissor rect
+ // vertically
+ ClearParameters presentPathFastClearParams = clearParams;
+ gl::Extents framebufferSize = colorAttachment->getSize();
+ presentPathFastClearParams.scissor.y = framebufferSize.height -
+ presentPathFastClearParams.scissor.y -
+ presentPathFastClearParams.scissor.height;
+ ANGLE_TRY(clearer->clearFramebuffer(context, presentPathFastClearParams, mState));
+ }
+ else
+ {
+ ANGLE_TRY(clearer->clearFramebuffer(context, clearParams, mState));
+ }
+
+ ANGLE_TRY(markAttachmentsDirty(context));
+
+ return angle::Result::Continue;
+}
+
+angle::Result Framebuffer11::invalidate(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments)
+{
+ return invalidateBase(context, count, attachments, false);
+}
+
+angle::Result Framebuffer11::discard(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments)
+{
+ return invalidateBase(context, count, attachments, true);
+}
+
+angle::Result Framebuffer11::invalidateBase(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments,
+ bool useEXTBehavior) const
+{
+ ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
+
+ if (!deviceContext1)
+ {
+ // DiscardView() is only supported on ID3D11DeviceContext1
+ return angle::Result::Continue;
+ }
+
+ bool foundDepth = false;
+ bool foundStencil = false;
+
+ for (size_t i = 0; i < count; ++i)
+ {
+ switch (attachments[i])
+ {
+ // Handle depth and stencil attachments. Defer discarding until later.
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ foundDepth = true;
+ foundStencil = true;
+ break;
+ case GL_DEPTH_EXT:
+ case GL_DEPTH_ATTACHMENT:
+ foundDepth = true;
+ break;
+ case GL_STENCIL_EXT:
+ case GL_STENCIL_ATTACHMENT:
+ foundStencil = true;
+ break;
+ default:
+ {
+ // Handle color attachments
+ ASSERT((attachments[i] >= GL_COLOR_ATTACHMENT0 &&
+ attachments[i] <= GL_COLOR_ATTACHMENT15) ||
+ (attachments[i] == GL_COLOR));
+
+ size_t colorIndex =
+ (attachments[i] == GL_COLOR ? 0u : (attachments[i] - GL_COLOR_ATTACHMENT0));
+ const gl::FramebufferAttachment *colorAttachment =
+ mState.getColorAttachment(colorIndex);
+ if (colorAttachment)
+ {
+ ANGLE_TRY(invalidateAttachment(context, colorAttachment));
+ }
+ break;
+ }
+ }
+ }
+
+ bool discardDepth = false;
+ bool discardStencil = false;
+
+ // The D3D11 renderer uses the same view for depth and stencil buffers, so we must be careful.
+ if (useEXTBehavior)
+ {
+ // In the extension, if the app discards only one of the depth and stencil attachments, but
+ // those are backed by the same packed_depth_stencil buffer, then both images become
+ // undefined.
+ discardDepth = foundDepth;
+
+ // Don't bother discarding the stencil buffer if the depth buffer will already do it
+ discardStencil = foundStencil && (!discardDepth || mState.getDepthAttachment() == nullptr);
+ }
+ else
+ {
+ // In ES 3.0.4, if a specified attachment has base internal format DEPTH_STENCIL but the
+ // attachments list does not include DEPTH_STENCIL_ATTACHMENT or both DEPTH_ATTACHMENT and
+ // STENCIL_ATTACHMENT, then only the specified portion of every pixel in the subregion of
+ // pixels of the DEPTH_STENCIL buffer may be invalidated, and the other portion must be
+ // preserved.
+ discardDepth = (foundDepth && foundStencil) ||
+ (foundDepth && (mState.getStencilAttachment() == nullptr));
+ discardStencil = (foundStencil && (mState.getDepthAttachment() == nullptr));
+ }
+
+ if (discardDepth && mState.getDepthAttachment())
+ {
+ ANGLE_TRY(invalidateAttachment(context, mState.getDepthAttachment()));
+ }
+
+ if (discardStencil && mState.getStencilAttachment())
+ {
+ ANGLE_TRY(invalidateAttachment(context, mState.getStencilAttachment()));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Framebuffer11::invalidateSub(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area)
+{
+ // A no-op implementation conforms to the spec, so don't call UNIMPLEMENTED()
+ return angle::Result::Continue;
+}
+
+angle::Result Framebuffer11::invalidateAttachment(const gl::Context *context,
+ const gl::FramebufferAttachment *attachment) const
+{
+ ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
+ ASSERT(deviceContext1);
+ ASSERT(attachment && attachment->isAttached());
+
+ RenderTarget11 *renderTarget = nullptr;
+ ANGLE_TRY(attachment->getRenderTarget(context, 0, &renderTarget));
+ const auto &rtv = renderTarget->getRenderTargetView();
+
+ if (rtv.valid())
+ {
+ deviceContext1->DiscardView(rtv.get());
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Framebuffer11::readPixelsImpl(const gl::Context *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ gl::Buffer *packBuffer,
+ uint8_t *pixels)
+{
+ const gl::FramebufferAttachment *readAttachment = mState.getReadPixelsAttachment(format);
+ ASSERT(readAttachment);
+
+ if (packBuffer != nullptr)
+ {
+ Buffer11 *packBufferStorage = GetImplAs<Buffer11>(packBuffer);
+ const angle::Format &angleFormat = GetFormatFromFormatType(format, type);
+ PackPixelsParams packParams(area, angleFormat, static_cast<GLuint>(outputPitch),
+ pack.reverseRowOrder, packBuffer,
+ reinterpret_cast<ptrdiff_t>(pixels));
+
+ return packBufferStorage->packPixels(context, *readAttachment, packParams);
+ }
+
+ return mRenderer->readFromAttachment(context, *readAttachment, area, format, type,
+ static_cast<GLuint>(outputPitch), pack, pixels);
+}
+
+angle::Result Framebuffer11::blitImpl(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ const gl::Rectangle *scissor,
+ bool blitRenderTarget,
+ bool blitDepth,
+ bool blitStencil,
+ GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer)
+{
+ if (blitRenderTarget)
+ {
+ const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getReadColorAttachment();
+ ASSERT(readBuffer);
+
+ RenderTargetD3D *readRenderTarget = nullptr;
+ ANGLE_TRY(readBuffer->getRenderTarget(context, 0, &readRenderTarget));
+ ASSERT(readRenderTarget);
+
+ const auto &colorAttachments = mState.getColorAttachments();
+ const auto &drawBufferStates = mState.getDrawBufferStates();
+ UINT readLayer = GetAttachmentLayer(readBuffer);
+
+ for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size();
+ colorAttachment++)
+ {
+ const gl::FramebufferAttachment &drawBuffer = colorAttachments[colorAttachment];
+
+ if (drawBuffer.isAttached() && drawBufferStates[colorAttachment] != GL_NONE)
+ {
+ RenderTargetD3D *drawRenderTarget = nullptr;
+ ANGLE_TRY(drawBuffer.getRenderTarget(
+ context, drawBuffer.getRenderToTextureSamples(), &drawRenderTarget));
+ ASSERT(drawRenderTarget);
+
+ const bool invertColorSource = UsePresentPathFast(mRenderer, readBuffer);
+ gl::Rectangle actualSourceArea = sourceArea;
+ if (invertColorSource)
+ {
+ RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget);
+ actualSourceArea.y = readRenderTarget11->getHeight() - sourceArea.y;
+ actualSourceArea.height = -sourceArea.height;
+ }
+
+ const bool invertColorDest = UsePresentPathFast(mRenderer, &drawBuffer);
+ gl::Rectangle actualDestArea = destArea;
+ UINT drawLayer = GetAttachmentLayer(&drawBuffer);
+
+ const auto &surfaceTextureOffset = mState.getSurfaceTextureOffset();
+ actualDestArea.x = actualDestArea.x + surfaceTextureOffset.x;
+ actualDestArea.y = actualDestArea.y + surfaceTextureOffset.y;
+
+ if (invertColorDest)
+ {
+ RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget);
+ actualDestArea.y = drawRenderTarget11->getHeight() - destArea.y;
+ actualDestArea.height = -destArea.height;
+ }
+
+ ANGLE_TRY(mRenderer->blitRenderbufferRect(context, actualSourceArea, actualDestArea,
+ readLayer, drawLayer, readRenderTarget,
+ drawRenderTarget, filter, scissor,
+ blitRenderTarget, false, false));
+ }
+ }
+ }
+
+ if (blitDepth || blitStencil)
+ {
+ const gl::FramebufferAttachment *readBuffer =
+ sourceFramebuffer->getDepthOrStencilAttachment();
+ ASSERT(readBuffer);
+ RenderTargetD3D *readRenderTarget = nullptr;
+ ANGLE_TRY(readBuffer->getRenderTarget(context, 0, &readRenderTarget));
+ ASSERT(readRenderTarget);
+
+ const bool invertSource = UsePresentPathFast(mRenderer, readBuffer);
+ gl::Rectangle actualSourceArea = sourceArea;
+ if (invertSource)
+ {
+ RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget);
+ actualSourceArea.y = readRenderTarget11->getHeight() - sourceArea.y;
+ actualSourceArea.height = -sourceArea.height;
+ }
+
+ const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment();
+ ASSERT(drawBuffer);
+ RenderTargetD3D *drawRenderTarget = nullptr;
+ ANGLE_TRY(drawBuffer->getRenderTarget(context, drawBuffer->getRenderToTextureSamples(),
+ &drawRenderTarget));
+ ASSERT(drawRenderTarget);
+
+ bool invertDest = UsePresentPathFast(mRenderer, drawBuffer);
+ gl::Rectangle actualDestArea = destArea;
+ if (invertDest)
+ {
+ RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget);
+ actualDestArea.y = drawRenderTarget11->getHeight() - destArea.y;
+ actualDestArea.height = -destArea.height;
+ }
+
+ ANGLE_TRY(mRenderer->blitRenderbufferRect(context, actualSourceArea, actualDestArea, 0, 0,
+ readRenderTarget, drawRenderTarget, filter,
+ scissor, false, blitDepth, blitStencil));
+ }
+
+ ANGLE_TRY(markAttachmentsDirty(context));
+ return angle::Result::Continue;
+}
+
+const gl::InternalFormat &Framebuffer11::getImplementationColorReadFormat(
+ const gl::Context *context) const
+{
+ Context11 *context11 = GetImplAs<Context11>(context);
+ const Renderer11DeviceCaps &caps = context11->getRenderer()->getRenderer11DeviceCaps();
+ GLenum sizedFormat = mState.getReadAttachment()->getFormat().info->sizedInternalFormat;
+ const angle::Format &angleFormat = d3d11::Format::Get(sizedFormat, caps).format();
+ return gl::GetSizedInternalFormatInfo(angleFormat.fboImplementationInternalFormat);
+}
+
+angle::Result Framebuffer11::syncState(const gl::Context *context,
+ GLenum binding,
+ const gl::Framebuffer::DirtyBits &dirtyBits,
+ gl::Command command)
+{
+ ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
+ ANGLE_TRY(FramebufferD3D::syncState(context, binding, dirtyBits, command));
+
+ // Call this last to allow the state manager to take advantage of the cached render targets.
+ mRenderer->getStateManager()->invalidateRenderTarget();
+
+ // Call this to syncViewport for framebuffer default parameters.
+ if (mState.getDefaultWidth() != 0 || mState.getDefaultHeight() != 0)
+ {
+ mRenderer->getStateManager()->invalidateViewport(context);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Framebuffer11::getSamplePosition(const gl::Context *context,
+ size_t index,
+ GLfloat *xy) const
+{
+ const gl::FramebufferAttachment *attachment = mState.getFirstNonNullAttachment();
+ ASSERT(attachment);
+ GLsizei sampleCount = attachment->getSamples();
+
+ rx::GetSamplePosition(sampleCount, index, xy);
+ return angle::Result::Continue;
+}
+
+RenderTarget11 *Framebuffer11::getFirstRenderTarget() const
+{
+ for (auto *renderTarget : mRenderTargetCache.getColors())
+ {
+ if (renderTarget)
+ {
+ return renderTarget;
+ }
+ }
+
+ return mRenderTargetCache.getDepthStencil();
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
new file mode 100644
index 0000000000..34cfdbd30e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
@@ -0,0 +1,100 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Framebuffer11.h: Defines the Framebuffer11 class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_
+
+#include "libANGLE/Observer.h"
+#include "libANGLE/renderer/RenderTargetCache.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+class Renderer11;
+
+class Framebuffer11 : public FramebufferD3D
+{
+ public:
+ Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer);
+ ~Framebuffer11() override;
+
+ angle::Result discard(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments) override;
+ angle::Result invalidate(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments) override;
+ angle::Result invalidateSub(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area) override;
+
+ // Invalidate the cached swizzles of all bound texture attachments.
+ angle::Result markAttachmentsDirty(const gl::Context *context) const;
+
+ angle::Result syncState(const gl::Context *context,
+ GLenum binding,
+ const gl::Framebuffer::DirtyBits &dirtyBits,
+ gl::Command command) override;
+
+ const gl::AttachmentArray<RenderTarget11 *> &getCachedColorRenderTargets() const
+ {
+ return mRenderTargetCache.getColors();
+ }
+ const RenderTarget11 *getCachedDepthStencilRenderTarget() const
+ {
+ return mRenderTargetCache.getDepthStencil();
+ }
+
+ RenderTarget11 *getFirstRenderTarget() const;
+
+ angle::Result getSamplePosition(const gl::Context *context,
+ size_t index,
+ GLfloat *xy) const override;
+
+ const gl::InternalFormat &getImplementationColorReadFormat(
+ const gl::Context *context) const override;
+
+ private:
+ angle::Result clearImpl(const gl::Context *context,
+ const ClearParameters &clearParams) override;
+
+ angle::Result readPixelsImpl(const gl::Context *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ gl::Buffer *packBuffer,
+ uint8_t *pixels) override;
+
+ angle::Result blitImpl(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ const gl::Rectangle *scissor,
+ bool blitRenderTarget,
+ bool blitDepth,
+ bool blitStencil,
+ GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer) override;
+
+ angle::Result invalidateBase(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments,
+ bool useEXTBehavior) const;
+ angle::Result invalidateAttachment(const gl::Context *context,
+ const gl::FramebufferAttachment *attachment) const;
+
+ Renderer11 *const mRenderer;
+ RenderTargetCache<RenderTarget11> mRenderTargetCache;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
new file mode 100644
index 0000000000..2e6558b304
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
@@ -0,0 +1,676 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image11.h: Implements the rx::Image11 class, which acts as the interface to
+// the actual underlying resources of a Texture
+
+#include "libANGLE/renderer/d3d/d3d11/Image11.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+namespace rx
+{
+
+Image11::Image11(Renderer11 *renderer)
+ : mRenderer(renderer),
+ mDXGIFormat(DXGI_FORMAT_UNKNOWN),
+ mStagingTexture(),
+ mStagingSubresource(0),
+ mRecoverFromStorage(false),
+ mAssociatedStorage(nullptr),
+ mAssociatedImageIndex(),
+ mRecoveredFromStorageCount(0)
+{}
+
+Image11::~Image11()
+{
+ disassociateStorage();
+ releaseStagingTexture();
+}
+
+// static
+angle::Result Image11::GenerateMipmap(const gl::Context *context,
+ Image11 *dest,
+ Image11 *src,
+ const Renderer11DeviceCaps &rendererCaps)
+{
+ ASSERT(src->getDXGIFormat() == dest->getDXGIFormat());
+ ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth());
+ ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight());
+
+ D3D11_MAPPED_SUBRESOURCE destMapped;
+ ANGLE_TRY(dest->map(context, D3D11_MAP_WRITE, &destMapped));
+ d3d11::ScopedUnmapper<Image11> destRAII(dest);
+
+ D3D11_MAPPED_SUBRESOURCE srcMapped;
+ ANGLE_TRY(src->map(context, D3D11_MAP_READ, &srcMapped));
+ d3d11::ScopedUnmapper<Image11> srcRAII(src);
+
+ const uint8_t *sourceData = static_cast<const uint8_t *>(srcMapped.pData);
+ uint8_t *destData = static_cast<uint8_t *>(destMapped.pData);
+
+ auto mipGenerationFunction =
+ d3d11::Format::Get(src->getInternalFormat(), rendererCaps).format().mipGenerationFunction;
+ mipGenerationFunction(src->getWidth(), src->getHeight(), src->getDepth(), sourceData,
+ srcMapped.RowPitch, srcMapped.DepthPitch, destData, destMapped.RowPitch,
+ destMapped.DepthPitch);
+
+ dest->markDirty();
+
+ return angle::Result::Continue;
+}
+
+// static
+angle::Result Image11::CopyImage(const gl::Context *context,
+ Image11 *dest,
+ Image11 *source,
+ const gl::Box &sourceBox,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const Renderer11DeviceCaps &rendererCaps)
+{
+ D3D11_MAPPED_SUBRESOURCE destMapped;
+ ANGLE_TRY(dest->map(context, D3D11_MAP_WRITE, &destMapped));
+ d3d11::ScopedUnmapper<Image11> destRAII(dest);
+
+ D3D11_MAPPED_SUBRESOURCE srcMapped;
+ ANGLE_TRY(source->map(context, D3D11_MAP_READ, &srcMapped));
+ d3d11::ScopedUnmapper<Image11> sourceRAII(source);
+
+ const auto &sourceFormat =
+ d3d11::Format::Get(source->getInternalFormat(), rendererCaps).format();
+ GLuint sourcePixelBytes =
+ gl::GetSizedInternalFormatInfo(sourceFormat.fboImplementationInternalFormat).pixelBytes;
+
+ GLenum destUnsizedFormat = gl::GetUnsizedFormat(dest->getInternalFormat());
+ const auto &destFormat = d3d11::Format::Get(dest->getInternalFormat(), rendererCaps).format();
+ const auto &destFormatInfo =
+ gl::GetSizedInternalFormatInfo(destFormat.fboImplementationInternalFormat);
+ GLuint destPixelBytes = destFormatInfo.pixelBytes;
+
+ const uint8_t *sourceData = static_cast<const uint8_t *>(srcMapped.pData) +
+ sourceBox.x * sourcePixelBytes + sourceBox.y * srcMapped.RowPitch +
+ sourceBox.z * srcMapped.DepthPitch;
+ uint8_t *destData = static_cast<uint8_t *>(destMapped.pData) + destOffset.x * destPixelBytes +
+ destOffset.y * destMapped.RowPitch + destOffset.z * destMapped.DepthPitch;
+
+ CopyImageCHROMIUM(sourceData, srcMapped.RowPitch, sourcePixelBytes, srcMapped.DepthPitch,
+ sourceFormat.pixelReadFunction, destData, destMapped.RowPitch, destPixelBytes,
+ destMapped.DepthPitch, destFormat.pixelWriteFunction, destUnsizedFormat,
+ destFormatInfo.componentType, sourceBox.width, sourceBox.height,
+ sourceBox.depth, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+
+ dest->markDirty();
+
+ return angle::Result::Continue;
+}
+
+bool Image11::isDirty() const
+{
+ // If mDirty is true AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be
+ // recovered from TextureStorage AND the texture doesn't require init data (i.e. a blank new
+ // texture will suffice) AND robust resource initialization is not enabled then isDirty should
+ // still return false.
+ if (mDirty && !mStagingTexture.valid() && !mRecoverFromStorage)
+ {
+ const Renderer11DeviceCaps &deviceCaps = mRenderer->getRenderer11DeviceCaps();
+ const auto &formatInfo = d3d11::Format::Get(mInternalFormat, deviceCaps);
+ if (formatInfo.dataInitializerFunction == nullptr)
+ {
+ return false;
+ }
+ }
+
+ return mDirty;
+}
+
+angle::Result Image11::copyToStorage(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::ImageIndex &index,
+ const gl::Box &region)
+{
+ TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);
+
+ // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage
+ // multiple times, then we should just keep the staging texture around to prevent the copying
+ // from impacting perf. We allow the Image11 to copy its data to/from TextureStorage once. This
+ // accounts for an app making a late call to glGenerateMipmap.
+ bool attemptToReleaseStagingTexture = (mRecoveredFromStorageCount < 2);
+
+ if (attemptToReleaseStagingTexture)
+ {
+ // If another image is relying on this Storage for its data, then we must let it recover its
+ // data before we overwrite it.
+ ANGLE_TRY(storage11->releaseAssociatedImage(context, index, this));
+ }
+
+ const TextureHelper11 *stagingTexture = nullptr;
+ unsigned int stagingSubresourceIndex = 0;
+ ANGLE_TRY(getStagingTexture(context, &stagingTexture, &stagingSubresourceIndex));
+ ANGLE_TRY(storage11->updateSubresourceLevel(context, *stagingTexture, stagingSubresourceIndex,
+ index, region));
+
+ // Once the image data has been copied into the Storage, we can release it locally.
+ if (attemptToReleaseStagingTexture)
+ {
+ storage11->associateImage(this, index);
+ releaseStagingTexture();
+ mRecoverFromStorage = true;
+ mAssociatedStorage = storage11;
+ mAssociatedImageIndex = index;
+ }
+
+ return angle::Result::Continue;
+}
+
+void Image11::verifyAssociatedStorageValid(TextureStorage11 *textureStorageEXT) const
+{
+ ASSERT(mAssociatedStorage == textureStorageEXT);
+}
+
+angle::Result Image11::recoverFromAssociatedStorage(const gl::Context *context)
+{
+ if (mRecoverFromStorage)
+ {
+ ANGLE_TRY(createStagingTexture(context));
+
+ mAssociatedStorage->verifyAssociatedImageValid(mAssociatedImageIndex, this);
+
+ // CopySubResource from the Storage to the Staging texture
+ gl::Box region(0, 0, 0, mWidth, mHeight, mDepth);
+ ANGLE_TRY(mAssociatedStorage->copySubresourceLevel(
+ context, mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region));
+ mRecoveredFromStorageCount += 1;
+
+ // Reset all the recovery parameters, even if the texture storage association is broken.
+ disassociateStorage();
+
+ markDirty();
+ }
+
+ return angle::Result::Continue;
+}
+
+void Image11::disassociateStorage()
+{
+ if (mRecoverFromStorage)
+ {
+ // Make the texturestorage release the Image11 too
+ mAssociatedStorage->disassociateImage(mAssociatedImageIndex, this);
+
+ mRecoverFromStorage = false;
+ mAssociatedStorage = nullptr;
+ mAssociatedImageIndex = gl::ImageIndex();
+ }
+}
+
+bool Image11::redefine(gl::TextureType type,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease)
+{
+ if (mWidth != size.width || mHeight != size.height || mDepth != size.depth ||
+ mInternalFormat != internalformat || forceRelease)
+ {
+ // End the association with the TextureStorage, since that data will be out of date.
+ // Also reset mRecoveredFromStorageCount since this Image is getting completely redefined.
+ disassociateStorage();
+ mRecoveredFromStorageCount = 0;
+
+ mWidth = size.width;
+ mHeight = size.height;
+ mDepth = size.depth;
+ mInternalFormat = internalformat;
+ mType = type;
+
+ // compute the d3d format that will be used
+ const d3d11::Format &formatInfo =
+ d3d11::Format::Get(internalformat, mRenderer->getRenderer11DeviceCaps());
+ mDXGIFormat = formatInfo.texFormat;
+ mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
+
+ releaseStagingTexture();
+ mDirty = (formatInfo.dataInitializerFunction != nullptr);
+
+ return true;
+ }
+
+ return false;
+}
+
+DXGI_FORMAT Image11::getDXGIFormat() const
+{
+ // this should only happen if the image hasn't been redefined first
+ // which would be a bug by the caller
+ ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN);
+
+ return mDXGIFormat;
+}
+
+// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as
+// format/type at input
+// into the target pixel rectangle.
+angle::Result Image11::loadData(const gl::Context *context,
+ const gl::Box &area,
+ const gl::PixelUnpackState &unpack,
+ GLenum type,
+ const void *input,
+ bool applySkipImages)
+{
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
+ GLuint inputRowPitch = 0;
+ ANGLE_CHECK_GL_MATH(context11, formatInfo.computeRowPitch(type, area.width, unpack.alignment,
+ unpack.rowLength, &inputRowPitch));
+ GLuint inputDepthPitch = 0;
+ ANGLE_CHECK_GL_MATH(context11, formatInfo.computeDepthPitch(area.height, unpack.imageHeight,
+ inputRowPitch, &inputDepthPitch));
+ GLuint inputSkipBytes = 0;
+ ANGLE_CHECK_GL_MATH(context11,
+ formatInfo.computeSkipBytes(type, inputRowPitch, inputDepthPitch, unpack,
+ applySkipImages, &inputSkipBytes));
+
+ const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat);
+ GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
+
+ const d3d11::Format &d3dFormatInfo =
+ d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
+ LoadImageFunction loadFunction = d3dFormatInfo.getLoadFunctions()(type).loadFunction;
+
+ D3D11_MAPPED_SUBRESOURCE mappedImage;
+ ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage));
+
+ uint8_t *offsetMappedData = (static_cast<uint8_t *>(mappedImage.pData) +
+ (area.y * mappedImage.RowPitch + area.x * outputPixelSize +
+ area.z * mappedImage.DepthPitch));
+ loadFunction(area.width, area.height, area.depth,
+ static_cast<const uint8_t *>(input) + inputSkipBytes, inputRowPitch,
+ inputDepthPitch, offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
+
+ unmap();
+
+ return angle::Result::Continue;
+}
+
+angle::Result Image11::loadCompressedData(const gl::Context *context,
+ const gl::Box &area,
+ const void *input)
+{
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
+ GLuint inputRowPitch = 0;
+ ANGLE_CHECK_GL_MATH(
+ context11, formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0, &inputRowPitch));
+ GLuint inputDepthPitch = 0;
+ ANGLE_CHECK_GL_MATH(
+ context11, formatInfo.computeDepthPitch(area.height, 0, inputRowPitch, &inputDepthPitch));
+
+ const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat);
+ GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
+ GLuint outputBlockWidth = dxgiFormatInfo.blockWidth;
+ GLuint outputBlockHeight = dxgiFormatInfo.blockHeight;
+
+ ASSERT(area.x % outputBlockWidth == 0);
+ ASSERT(area.y % outputBlockHeight == 0);
+
+ const d3d11::Format &d3dFormatInfo =
+ d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
+ LoadImageFunction loadFunction =
+ d3dFormatInfo.getLoadFunctions()(GL_UNSIGNED_BYTE).loadFunction;
+
+ D3D11_MAPPED_SUBRESOURCE mappedImage;
+ ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage));
+
+ uint8_t *offsetMappedData =
+ static_cast<uint8_t *>(mappedImage.pData) +
+ ((area.y / outputBlockHeight) * mappedImage.RowPitch +
+ (area.x / outputBlockWidth) * outputPixelSize + area.z * mappedImage.DepthPitch);
+
+ loadFunction(area.width, area.height, area.depth, static_cast<const uint8_t *>(input),
+ inputRowPitch, inputDepthPitch, offsetMappedData, mappedImage.RowPitch,
+ mappedImage.DepthPitch);
+
+ unmap();
+
+ return angle::Result::Continue;
+}
+
+angle::Result Image11::copyFromTexStorage(const gl::Context *context,
+ const gl::ImageIndex &imageIndex,
+ TextureStorage *source)
+{
+ TextureStorage11 *storage11 = GetAs<TextureStorage11>(source);
+
+ const TextureHelper11 *textureHelper = nullptr;
+ ANGLE_TRY(storage11->getResource(context, &textureHelper));
+
+ UINT subresourceIndex = 0;
+ ANGLE_TRY(storage11->getSubresourceIndex(context, imageIndex, &subresourceIndex));
+
+ gl::Box sourceBox(0, 0, 0, mWidth, mHeight, mDepth);
+ return copyWithoutConversion(context, gl::Offset(), sourceBox, *textureHelper,
+ subresourceIndex);
+}
+
+angle::Result Image11::copyFromFramebuffer(const gl::Context *context,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *sourceFBO)
+{
+ const gl::FramebufferAttachment *srcAttachment = sourceFBO->getReadColorAttachment();
+ ASSERT(srcAttachment);
+
+ GLenum sourceInternalFormat = srcAttachment->getFormat().info->sizedInternalFormat;
+ const auto &d3d11Format =
+ d3d11::Format::Get(sourceInternalFormat, mRenderer->getRenderer11DeviceCaps());
+
+ if (d3d11Format.texFormat == mDXGIFormat && sourceInternalFormat == mInternalFormat)
+ {
+ RenderTarget11 *rt11 = nullptr;
+ ANGLE_TRY(srcAttachment->getRenderTarget(context, 0, &rt11));
+ ASSERT(rt11->getTexture().get());
+
+ TextureHelper11 textureHelper = rt11->getTexture();
+ unsigned int sourceSubResource = rt11->getSubresourceIndex();
+
+ gl::Box sourceBox(sourceArea.x, sourceArea.y, 0, sourceArea.width, sourceArea.height, 1);
+ return copyWithoutConversion(context, destOffset, sourceBox, textureHelper,
+ sourceSubResource);
+ }
+
+ // This format requires conversion, so we must copy the texture to staging and manually convert
+ // via readPixels
+ D3D11_MAPPED_SUBRESOURCE mappedImage;
+ ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage));
+
+ // determine the offset coordinate into the destination buffer
+ const auto &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat);
+ GLsizei rowOffset = dxgiFormatInfo.pixelBytes * destOffset.x;
+
+ uint8_t *dataOffset = static_cast<uint8_t *>(mappedImage.pData) +
+ mappedImage.RowPitch * destOffset.y + rowOffset +
+ destOffset.z * mappedImage.DepthPitch;
+
+ const gl::InternalFormat &destFormatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
+ const auto &destD3D11Format =
+ d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
+
+ auto loadFunction = destD3D11Format.getLoadFunctions()(destFormatInfo.type);
+ angle::Result result = angle::Result::Continue;
+ if (loadFunction.requiresConversion)
+ {
+ size_t bufferSize = destFormatInfo.pixelBytes * sourceArea.width * sourceArea.height;
+ angle::MemoryBuffer *memoryBuffer = nullptr;
+ result = mRenderer->getScratchMemoryBuffer(GetImplAs<Context11>(context), bufferSize,
+ &memoryBuffer);
+
+ if (result == angle::Result::Continue)
+ {
+ GLuint memoryBufferRowPitch = destFormatInfo.pixelBytes * sourceArea.width;
+
+ result = mRenderer->readFromAttachment(
+ context, *srcAttachment, sourceArea, destFormatInfo.format, destFormatInfo.type,
+ memoryBufferRowPitch, gl::PixelPackState(), memoryBuffer->data());
+
+ loadFunction.loadFunction(sourceArea.width, sourceArea.height, 1, memoryBuffer->data(),
+ memoryBufferRowPitch, 0, dataOffset, mappedImage.RowPitch,
+ mappedImage.DepthPitch);
+ }
+ }
+ else
+ {
+ result = mRenderer->readFromAttachment(
+ context, *srcAttachment, sourceArea, destFormatInfo.format, destFormatInfo.type,
+ mappedImage.RowPitch, gl::PixelPackState(), dataOffset);
+ }
+
+ unmap();
+ mDirty = true;
+
+ return result;
+}
+
+angle::Result Image11::copyWithoutConversion(const gl::Context *context,
+ const gl::Offset &destOffset,
+ const gl::Box &sourceArea,
+ const TextureHelper11 &textureHelper,
+ UINT sourceSubResource)
+{
+ // No conversion needed-- use copyback fastpath
+ const TextureHelper11 *stagingTexture = nullptr;
+ unsigned int stagingSubresourceIndex = 0;
+ ANGLE_TRY(getStagingTexture(context, &stagingTexture, &stagingSubresourceIndex));
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ const gl::Extents &extents = textureHelper.getExtents();
+
+ D3D11_BOX srcBox;
+ srcBox.left = sourceArea.x;
+ srcBox.right = sourceArea.x + sourceArea.width;
+ srcBox.top = sourceArea.y;
+ srcBox.bottom = sourceArea.y + sourceArea.height;
+ srcBox.front = sourceArea.z;
+ srcBox.back = sourceArea.z + sourceArea.depth;
+
+ if (textureHelper.is2D() && textureHelper.getSampleCount() > 1)
+ {
+ D3D11_TEXTURE2D_DESC resolveDesc;
+ resolveDesc.Width = extents.width;
+ resolveDesc.Height = extents.height;
+ resolveDesc.MipLevels = 1;
+ resolveDesc.ArraySize = 1;
+ resolveDesc.Format = textureHelper.getFormat();
+ resolveDesc.SampleDesc.Count = 1;
+ resolveDesc.SampleDesc.Quality = 0;
+ resolveDesc.Usage = D3D11_USAGE_DEFAULT;
+ resolveDesc.BindFlags = 0;
+ resolveDesc.CPUAccessFlags = 0;
+ resolveDesc.MiscFlags = 0;
+
+ d3d11::Texture2D resolveTex;
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), resolveDesc, &resolveTex));
+
+ deviceContext->ResolveSubresource(resolveTex.get(), 0, textureHelper.get(),
+ sourceSubResource, textureHelper.getFormat());
+
+ deviceContext->CopySubresourceRegion(stagingTexture->get(), stagingSubresourceIndex,
+ destOffset.x, destOffset.y, destOffset.z,
+ resolveTex.get(), 0, &srcBox);
+ }
+ else
+ {
+ deviceContext->CopySubresourceRegion(stagingTexture->get(), stagingSubresourceIndex,
+ destOffset.x, destOffset.y, destOffset.z,
+ textureHelper.get(), sourceSubResource, &srcBox);
+ }
+
+ mDirty = true;
+ return angle::Result::Continue;
+}
+
+angle::Result Image11::getStagingTexture(const gl::Context *context,
+ const TextureHelper11 **outStagingTexture,
+ unsigned int *outSubresourceIndex)
+{
+ ANGLE_TRY(createStagingTexture(context));
+
+ *outStagingTexture = &mStagingTexture;
+ *outSubresourceIndex = mStagingSubresource;
+ return angle::Result::Continue;
+}
+
+void Image11::releaseStagingTexture()
+{
+ mStagingTexture.reset();
+ mStagingTextureSubresourceVerifier.reset();
+}
+
+angle::Result Image11::createStagingTexture(const gl::Context *context)
+{
+ if (mStagingTexture.valid())
+ {
+ return angle::Result::Continue;
+ }
+
+ ASSERT(mWidth > 0 && mHeight > 0 && mDepth > 0);
+
+ const DXGI_FORMAT dxgiFormat = getDXGIFormat();
+ const auto &formatInfo =
+ d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
+
+ int lodOffset = 1;
+ GLsizei width = mWidth;
+ GLsizei height = mHeight;
+
+ // adjust size if needed for compressed textures
+ d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset);
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ switch (mType)
+ {
+ case gl::TextureType::_3D:
+ {
+ D3D11_TEXTURE3D_DESC desc;
+ desc.Width = width;
+ desc.Height = height;
+ desc.Depth = mDepth;
+ desc.MipLevels = lodOffset + 1;
+ desc.Format = dxgiFormat;
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.BindFlags = 0;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+ desc.MiscFlags = 0;
+
+ if (formatInfo.dataInitializerFunction != nullptr)
+ {
+ gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> initialData;
+ ANGLE_TRY(d3d11::GenerateInitialTextureData(
+ context, mInternalFormat, mRenderer->getRenderer11DeviceCaps(), width, height,
+ mDepth, lodOffset + 1, &initialData));
+
+ ANGLE_TRY(mRenderer->allocateTexture(context11, desc, formatInfo,
+ initialData.data(), &mStagingTexture));
+ }
+ else
+ {
+ ANGLE_TRY(
+ mRenderer->allocateTexture(context11, desc, formatInfo, &mStagingTexture));
+ }
+
+ mStagingTexture.setInternalName("Image11::StagingTexture3D");
+ mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
+ mStagingTextureSubresourceVerifier.setDesc(desc);
+ }
+ break;
+
+ case gl::TextureType::_2D:
+ case gl::TextureType::_2DArray:
+ case gl::TextureType::CubeMap:
+ {
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = width;
+ desc.Height = height;
+ desc.MipLevels = lodOffset + 1;
+ desc.ArraySize = 1;
+ desc.Format = dxgiFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_STAGING;
+ desc.BindFlags = 0;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+ desc.MiscFlags = 0;
+
+ if (formatInfo.dataInitializerFunction != nullptr)
+ {
+ gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> initialData;
+ ANGLE_TRY(d3d11::GenerateInitialTextureData(
+ context, mInternalFormat, mRenderer->getRenderer11DeviceCaps(), width, height,
+ 1, lodOffset + 1, &initialData));
+
+ ANGLE_TRY(mRenderer->allocateTexture(context11, desc, formatInfo,
+ initialData.data(), &mStagingTexture));
+ }
+ else
+ {
+ ANGLE_TRY(
+ mRenderer->allocateTexture(context11, desc, formatInfo, &mStagingTexture));
+ }
+
+ mStagingTexture.setInternalName("Image11::StagingTexture2D");
+ mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1);
+ mStagingTextureSubresourceVerifier.setDesc(desc);
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+
+ mDirty = false;
+ return angle::Result::Continue;
+}
+
+angle::Result Image11::map(const gl::Context *context,
+ D3D11_MAP mapType,
+ D3D11_MAPPED_SUBRESOURCE *map)
+{
+ // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE.
+ ANGLE_TRY(recoverFromAssociatedStorage(context));
+
+ const TextureHelper11 *stagingTexture = nullptr;
+ unsigned int subresourceIndex = 0;
+ ANGLE_TRY(getStagingTexture(context, &stagingTexture, &subresourceIndex));
+
+ ASSERT(stagingTexture && stagingTexture->valid());
+
+ ANGLE_TRY(
+ mRenderer->mapResource(context, stagingTexture->get(), subresourceIndex, mapType, 0, map));
+
+ if (!mStagingTextureSubresourceVerifier.wrap(mapType, map))
+ {
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->Unmap(mStagingTexture.get(), mStagingSubresource);
+ Context11 *context11 = GetImplAs<Context11>(context);
+ context11->handleError(GL_OUT_OF_MEMORY,
+ "Failed to allocate staging texture mapping verifier buffer.",
+ __FILE__, ANGLE_FUNCTION, __LINE__);
+ return angle::Result::Stop;
+ }
+
+ mDirty = true;
+
+ return angle::Result::Continue;
+}
+
+void Image11::unmap()
+{
+ if (mStagingTexture.valid())
+ {
+ mStagingTextureSubresourceVerifier.unwrap();
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->Unmap(mStagingTexture.get(), mStagingSubresource);
+ }
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Image11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Image11.h
new file mode 100644
index 0000000000..661365240c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Image11.h
@@ -0,0 +1,128 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image11.h: Defines the rx::Image11 class, which acts as the interface to
+// the actual underlying resources of a Texture
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_
+
+#include "common/debug.h"
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/renderer/d3d/ImageD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/MappedSubresourceVerifier11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace d3d11
+{
+template <typename T>
+class ScopedUnmapper;
+} // namespace d3d11
+
+namespace rx
+{
+class Renderer11;
+class TextureHelper11;
+class TextureStorage11;
+struct Renderer11DeviceCaps;
+
+class Image11 : public ImageD3D
+{
+ public:
+ Image11(Renderer11 *renderer);
+ ~Image11() override;
+
+ static angle::Result GenerateMipmap(const gl::Context *context,
+ Image11 *dest,
+ Image11 *src,
+ const Renderer11DeviceCaps &rendererCaps);
+ static angle::Result CopyImage(const gl::Context *context,
+ Image11 *dest,
+ Image11 *source,
+ const gl::Box &sourceBox,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha,
+ const Renderer11DeviceCaps &rendererCaps);
+
+ bool isDirty() const override;
+
+ angle::Result copyToStorage(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::ImageIndex &index,
+ const gl::Box &region) override;
+
+ bool redefine(gl::TextureType type,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease) override;
+
+ DXGI_FORMAT getDXGIFormat() const;
+
+ angle::Result loadData(const gl::Context *context,
+ const gl::Box &area,
+ const gl::PixelUnpackState &unpack,
+ GLenum type,
+ const void *input,
+ bool applySkipImages) override;
+ angle::Result loadCompressedData(const gl::Context *context,
+ const gl::Box &area,
+ const void *input) override;
+
+ angle::Result copyFromTexStorage(const gl::Context *context,
+ const gl::ImageIndex &imageIndex,
+ TextureStorage *source) override;
+ angle::Result copyFromFramebuffer(const gl::Context *context,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ angle::Result recoverFromAssociatedStorage(const gl::Context *context);
+ void verifyAssociatedStorageValid(TextureStorage11 *textureStorageEXT) const;
+ void disassociateStorage();
+
+ angle::Result getStagingTexture(const gl::Context *context,
+ const TextureHelper11 **outStagingTexture,
+ unsigned int *outSubresourceIndex);
+
+ protected:
+ template <typename T>
+ friend class d3d11::ScopedUnmapper;
+ angle::Result map(const gl::Context *context, D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
+ void unmap();
+
+ private:
+ angle::Result copyWithoutConversion(const gl::Context *context,
+ const gl::Offset &destOffset,
+ const gl::Box &sourceArea,
+ const TextureHelper11 &textureHelper,
+ UINT sourceSubResource);
+
+ angle::Result createStagingTexture(const gl::Context *context);
+ void releaseStagingTexture();
+
+ Renderer11 *mRenderer;
+
+ DXGI_FORMAT mDXGIFormat;
+ TextureHelper11 mStagingTexture;
+ unsigned int mStagingSubresource;
+ MappedSubresourceVerifier11 mStagingTextureSubresourceVerifier;
+
+ bool mRecoverFromStorage;
+ TextureStorage11 *mAssociatedStorage;
+ gl::ImageIndex mAssociatedImageIndex;
+ unsigned int mRecoveredFromStorageCount;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp
new file mode 100644
index 0000000000..7630b341fa
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp
@@ -0,0 +1,160 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation.
+
+#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+
+IndexBuffer11::IndexBuffer11(Renderer11 *const renderer)
+ : mRenderer(renderer),
+ mBuffer(),
+ mBufferSize(0),
+ mIndexType(gl::DrawElementsType::InvalidEnum),
+ mDynamicUsage(false)
+{}
+
+IndexBuffer11::~IndexBuffer11() {}
+
+angle::Result IndexBuffer11::initialize(const gl::Context *context,
+ unsigned int bufferSize,
+ gl::DrawElementsType indexType,
+ bool dynamic)
+{
+ mBuffer.reset();
+
+ updateSerial();
+
+ if (bufferSize > 0)
+ {
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = bufferSize;
+ bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+ bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.StructureByteStride = 0;
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), bufferDesc, &mBuffer));
+
+ if (dynamic)
+ {
+ mBuffer.setInternalName("IndexBuffer11(dynamic)");
+ }
+ else
+ {
+ mBuffer.setInternalName("IndexBuffer11(static)");
+ }
+ }
+
+ mBufferSize = bufferSize;
+ mIndexType = indexType;
+ mDynamicUsage = dynamic;
+
+ return angle::Result::Continue;
+}
+
+angle::Result IndexBuffer11::mapBuffer(const gl::Context *context,
+ unsigned int offset,
+ unsigned int size,
+ void **outMappedMemory)
+{
+ Context11 *context11 = GetImplAs<Context11>(context);
+ ANGLE_CHECK_HR(context11, mBuffer.valid(), "Internal index buffer is not initialized.",
+ E_OUTOFMEMORY);
+
+ // Check for integer overflows and out-out-bounds map requests
+ bool outOfBounds = (offset + size < offset || offset + size > mBufferSize);
+ ANGLE_CHECK_HR(context11, !outOfBounds, "Index buffer map range is not inside the buffer.",
+ E_OUTOFMEMORY);
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ ANGLE_TRY(mRenderer->mapResource(context, mBuffer.get(), 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0,
+ &mappedResource));
+
+ *outMappedMemory = static_cast<char *>(mappedResource.pData) + offset;
+ return angle::Result::Continue;
+}
+
+angle::Result IndexBuffer11::unmapBuffer(const gl::Context *context)
+{
+ Context11 *context11 = GetImplAs<Context11>(context);
+ ANGLE_CHECK_HR(context11, mBuffer.valid(), "Internal index buffer is not initialized.",
+ E_OUTOFMEMORY);
+
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+ dxContext->Unmap(mBuffer.get(), 0);
+ return angle::Result::Continue;
+}
+
+gl::DrawElementsType IndexBuffer11::getIndexType() const
+{
+ return mIndexType;
+}
+
+unsigned int IndexBuffer11::getBufferSize() const
+{
+ return mBufferSize;
+}
+
+angle::Result IndexBuffer11::setSize(const gl::Context *context,
+ unsigned int bufferSize,
+ gl::DrawElementsType indexType)
+{
+ if (bufferSize > mBufferSize || indexType != mIndexType)
+ {
+ return initialize(context, bufferSize, indexType, mDynamicUsage);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result IndexBuffer11::discard(const gl::Context *context)
+{
+ Context11 *context11 = GetImplAs<Context11>(context);
+ ANGLE_CHECK_HR(context11, mBuffer.valid(), "Internal index buffer is not initialized.",
+ E_OUTOFMEMORY);
+
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ ANGLE_TRY(mRenderer->mapResource(context, mBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
+ &mappedResource));
+
+ dxContext->Unmap(mBuffer.get(), 0);
+
+ return angle::Result::Continue;
+}
+
+DXGI_FORMAT IndexBuffer11::getIndexFormat() const
+{
+ switch (mIndexType)
+ {
+ case gl::DrawElementsType::UnsignedByte:
+ return DXGI_FORMAT_R16_UINT;
+ case gl::DrawElementsType::UnsignedShort:
+ return DXGI_FORMAT_R16_UINT;
+ case gl::DrawElementsType::UnsignedInt:
+ return DXGI_FORMAT_R32_UINT;
+ default:
+ UNREACHABLE();
+ return DXGI_FORMAT_UNKNOWN;
+ }
+}
+
+const d3d11::Buffer &IndexBuffer11::getBuffer() const
+{
+ return mBuffer;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h
new file mode 100644
index 0000000000..53c736cf7a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h
@@ -0,0 +1,58 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// IndexBuffer11.h: Defines the D3D11 IndexBuffer implementation.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_
+
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+
+namespace rx
+{
+class Renderer11;
+
+class IndexBuffer11 : public IndexBuffer
+{
+ public:
+ explicit IndexBuffer11(Renderer11 *const renderer);
+ ~IndexBuffer11() override;
+
+ angle::Result initialize(const gl::Context *context,
+ unsigned int bufferSize,
+ gl::DrawElementsType indexType,
+ bool dynamic) override;
+
+ angle::Result mapBuffer(const gl::Context *context,
+ unsigned int offset,
+ unsigned int size,
+ void **outMappedMemory) override;
+ angle::Result unmapBuffer(const gl::Context *context) override;
+
+ gl::DrawElementsType getIndexType() const override;
+ unsigned int getBufferSize() const override;
+ angle::Result setSize(const gl::Context *context,
+ unsigned int bufferSize,
+ gl::DrawElementsType indexType) override;
+
+ angle::Result discard(const gl::Context *context) override;
+
+ DXGI_FORMAT getIndexFormat() const;
+ const d3d11::Buffer &getBuffer() const;
+
+ private:
+ Renderer11 *const mRenderer;
+
+ d3d11::Buffer mBuffer;
+ unsigned int mBufferSize;
+ gl::DrawElementsType mIndexType;
+ bool mDynamicUsage;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
new file mode 100644
index 0000000000..b5e12499b2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
@@ -0,0 +1,313 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches
+// D3D11 input layouts.
+
+#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h"
+
+#include "common/bitset_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+
+namespace rx
+{
+
+namespace
+{
+
+GLenum GetGLSLAttributeType(const std::vector<sh::ShaderVariable> &shaderAttributes, size_t index)
+{
+ // Count matrices differently
+ for (const sh::ShaderVariable &attrib : shaderAttributes)
+ {
+ if (attrib.location == -1)
+ {
+ continue;
+ }
+
+ GLenum transposedType = gl::TransposeMatrixType(attrib.type);
+ int rows = gl::VariableRowCount(transposedType);
+ int intIndex = static_cast<int>(index);
+
+ if (intIndex >= attrib.location && intIndex < attrib.location + rows)
+ {
+ return transposedType;
+ }
+ }
+
+ UNREACHABLE();
+ return GL_NONE;
+}
+
+struct PackedAttribute
+{
+ uint8_t attribType;
+ uint8_t semanticIndex;
+ uint8_t vertexFormatType;
+ uint8_t unusedPadding;
+ uint32_t divisor;
+};
+
+} // anonymous namespace
+
+PackedAttributeLayout::PackedAttributeLayout() : numAttributes(0), flags(0), attributeData({}) {}
+
+PackedAttributeLayout::PackedAttributeLayout(const PackedAttributeLayout &other) = default;
+
+void PackedAttributeLayout::addAttributeData(GLenum glType,
+ UINT semanticIndex,
+ angle::FormatID vertexFormatID,
+ unsigned int divisor)
+{
+ gl::AttributeType attribType = gl::GetAttributeType(glType);
+
+ PackedAttribute packedAttrib;
+ packedAttrib.attribType = static_cast<uint8_t>(attribType);
+ packedAttrib.semanticIndex = static_cast<uint8_t>(semanticIndex);
+ packedAttrib.vertexFormatType = static_cast<uint8_t>(vertexFormatID);
+ packedAttrib.unusedPadding = 0u;
+ packedAttrib.divisor = static_cast<uint32_t>(divisor);
+
+ ASSERT(static_cast<gl::AttributeType>(packedAttrib.attribType) == attribType);
+ ASSERT(static_cast<UINT>(packedAttrib.semanticIndex) == semanticIndex);
+ ASSERT(static_cast<angle::FormatID>(packedAttrib.vertexFormatType) == vertexFormatID);
+ ASSERT(static_cast<unsigned int>(packedAttrib.divisor) == divisor);
+
+ static_assert(sizeof(uint64_t) == sizeof(PackedAttribute),
+ "PackedAttributes must be 64-bits exactly.");
+
+ attributeData[numAttributes++] = gl::bitCast<uint64_t>(packedAttrib);
+}
+
+bool PackedAttributeLayout::operator==(const PackedAttributeLayout &other) const
+{
+ return (numAttributes == other.numAttributes) && (flags == other.flags) &&
+ (attributeData == other.attributeData);
+}
+
+InputLayoutCache::InputLayoutCache() : mLayoutCache(kDefaultCacheSize * 2) {}
+
+InputLayoutCache::~InputLayoutCache() {}
+
+void InputLayoutCache::clear()
+{
+ mLayoutCache.Clear();
+}
+
+angle::Result InputLayoutCache::getInputLayout(
+ Context11 *context11,
+ const gl::State &state,
+ const std::vector<const TranslatedAttribute *> &currentAttributes,
+ const AttribIndexArray &sortedSemanticIndices,
+ gl::PrimitiveMode mode,
+ GLsizei vertexCount,
+ GLsizei instances,
+ const d3d11::InputLayout **inputLayoutOut)
+{
+ gl::Program *program = state.getProgram();
+ const auto &shaderAttributes = program->getAttributes();
+ PackedAttributeLayout layout;
+
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+ bool programUsesInstancedPointSprites =
+ programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation();
+ bool instancedPointSpritesActive =
+ programUsesInstancedPointSprites && (mode == gl::PrimitiveMode::Points);
+
+ if (programUsesInstancedPointSprites)
+ {
+ layout.flags |= PackedAttributeLayout::FLAG_USES_INSTANCED_SPRITES;
+ }
+
+ if (instancedPointSpritesActive)
+ {
+ layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_SPRITES_ACTIVE;
+ }
+
+ if (instances > 0)
+ {
+ layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_RENDERING_ACTIVE;
+ }
+
+ const auto &attribs = state.getVertexArray()->getVertexAttributes();
+ const auto &bindings = state.getVertexArray()->getVertexBindings();
+ const auto &locationToSemantic = programD3D->getAttribLocationToD3DSemantics();
+ int divisorMultiplier = program->usesMultiview() ? program->getNumViews() : 1;
+
+ for (size_t attribIndex : state.getProgramExecutable()->getActiveAttribLocationsMask())
+ {
+ // Record the type of the associated vertex shader vector in our key
+ // This will prevent mismatched vertex shaders from using the same input layout
+ GLenum glslElementType = GetGLSLAttributeType(shaderAttributes, attribIndex);
+
+ const auto &attrib = attribs[attribIndex];
+ const auto &binding = bindings[attrib.bindingIndex];
+ int d3dSemantic = locationToSemantic[attribIndex];
+
+ const auto &currentValue =
+ state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex));
+ angle::FormatID vertexFormatID = gl::GetVertexFormatID(attrib, currentValue.Type);
+
+ layout.addAttributeData(glslElementType, d3dSemantic, vertexFormatID,
+ binding.getDivisor() * divisorMultiplier);
+ }
+
+ if (layout.numAttributes > 0 || layout.flags != 0)
+ {
+ auto it = mLayoutCache.Get(layout);
+ if (it != mLayoutCache.end())
+ {
+ *inputLayoutOut = &it->second;
+ }
+ else
+ {
+ angle::TrimCache(mLayoutCache.max_size() / 2, kGCLimit, "input layout", &mLayoutCache);
+
+ d3d11::InputLayout newInputLayout;
+ ANGLE_TRY(createInputLayout(context11, sortedSemanticIndices, currentAttributes, mode,
+ vertexCount, instances, &newInputLayout));
+
+ auto insertIt = mLayoutCache.Put(layout, std::move(newInputLayout));
+ *inputLayoutOut = &insertIt->second;
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result InputLayoutCache::createInputLayout(
+ Context11 *context11,
+ const AttribIndexArray &sortedSemanticIndices,
+ const std::vector<const TranslatedAttribute *> &currentAttributes,
+ gl::PrimitiveMode mode,
+ GLsizei vertexCount,
+ GLsizei instances,
+ d3d11::InputLayout *inputLayoutOut)
+{
+ Renderer11 *renderer = context11->getRenderer();
+ ProgramD3D *programD3D = renderer->getStateManager()->getProgramD3D();
+ D3D_FEATURE_LEVEL featureLevel = renderer->getRenderer11DeviceCaps().featureLevel;
+
+ bool programUsesInstancedPointSprites =
+ programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation();
+
+ unsigned int inputElementCount = 0;
+ gl::AttribArray<D3D11_INPUT_ELEMENT_DESC> inputElements;
+
+ for (size_t attribIndex = 0; attribIndex < currentAttributes.size(); ++attribIndex)
+ {
+ const auto &attrib = *currentAttributes[attribIndex];
+ const int sortedIndex = sortedSemanticIndices[attribIndex];
+
+ D3D11_INPUT_CLASSIFICATION inputClass =
+ attrib.divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
+
+ angle::FormatID vertexFormatID =
+ gl::GetVertexFormatID(*attrib.attribute, attrib.currentValueType);
+ const auto &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormatID, featureLevel);
+
+ auto *inputElement = &inputElements[inputElementCount];
+
+ inputElement->SemanticName = "TEXCOORD";
+ inputElement->SemanticIndex = sortedIndex;
+ inputElement->Format = vertexFormatInfo.nativeFormat;
+ inputElement->InputSlot = static_cast<UINT>(attribIndex);
+ inputElement->AlignedByteOffset = 0;
+ inputElement->InputSlotClass = inputClass;
+ inputElement->InstanceDataStepRate = attrib.divisor;
+
+ inputElementCount++;
+ }
+
+ // Instanced PointSprite emulation requires additional entries in the
+ // inputlayout to support the vertices that make up the pointsprite quad.
+ // We do this even if mode != GL_POINTS, since the shader signature has these inputs, and the
+ // input layout must match the shader
+ if (programUsesInstancedPointSprites)
+ {
+ // On 9_3, we must ensure that slot 0 contains non-instanced data.
+ // If slot 0 currently contains instanced data then we swap it with a non-instanced element.
+ // Note that instancing is only available on 9_3 via ANGLE_instanced_arrays, since 9_3
+ // doesn't support OpenGL ES 3.0.
+ // As per the spec for ANGLE_instanced_arrays, not all attributes can be instanced
+ // simultaneously, so a non-instanced element must exist.
+
+ UINT numIndicesPerInstance = 0;
+ if (instances > 0)
+ {
+ // This requires that the index range is resolved.
+ // Note: Vertex indexes can be arbitrarily large.
+ numIndicesPerInstance = gl::clampCast<UINT>(vertexCount);
+ }
+
+ for (size_t elementIndex = 0; elementIndex < inputElementCount; ++elementIndex)
+ {
+ // If rendering points and instanced pointsprite emulation is being used, the
+ // inputClass is required to be configured as per instance data
+ if (mode == gl::PrimitiveMode::Points)
+ {
+ inputElements[elementIndex].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA;
+ inputElements[elementIndex].InstanceDataStepRate = 1;
+ if (numIndicesPerInstance > 0 && currentAttributes[elementIndex]->divisor > 0)
+ {
+ inputElements[elementIndex].InstanceDataStepRate = numIndicesPerInstance;
+ }
+ }
+ inputElements[elementIndex].InputSlot++;
+ }
+
+ inputElements[inputElementCount].SemanticName = "SPRITEPOSITION";
+ inputElements[inputElementCount].SemanticIndex = 0;
+ inputElements[inputElementCount].Format = DXGI_FORMAT_R32G32B32_FLOAT;
+ inputElements[inputElementCount].InputSlot = 0;
+ inputElements[inputElementCount].AlignedByteOffset = 0;
+ inputElements[inputElementCount].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
+ inputElements[inputElementCount].InstanceDataStepRate = 0;
+ inputElementCount++;
+
+ inputElements[inputElementCount].SemanticName = "SPRITETEXCOORD";
+ inputElements[inputElementCount].SemanticIndex = 0;
+ inputElements[inputElementCount].Format = DXGI_FORMAT_R32G32_FLOAT;
+ inputElements[inputElementCount].InputSlot = 0;
+ inputElements[inputElementCount].AlignedByteOffset = sizeof(float) * 3;
+ inputElements[inputElementCount].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
+ inputElements[inputElementCount].InstanceDataStepRate = 0;
+ inputElementCount++;
+ }
+
+ ShaderExecutableD3D *shader = nullptr;
+ ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(context11, &shader, nullptr));
+
+ ShaderExecutableD3D *shader11 = GetAs<ShaderExecutable11>(shader);
+
+ InputElementArray inputElementArray(inputElements.data(), inputElementCount);
+ ShaderData vertexShaderData(shader11->getFunction(), shader11->getLength());
+
+ ANGLE_TRY(renderer->allocateResource(context11, inputElementArray, &vertexShaderData,
+ inputLayoutOut));
+ return angle::Result::Continue;
+}
+
+void InputLayoutCache::setCacheSize(size_t newCacheSize)
+{
+ // Forces a reset of the cache.
+ LayoutCache newCache(newCacheSize);
+ mLayoutCache.Swap(newCache);
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
new file mode 100644
index 0000000000..35d1b60607
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
@@ -0,0 +1,123 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// InputLayoutCache.h: Defines InputLayoutCache, a class that builds and caches
+// D3D11 input layouts.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_
+
+#include <GLES2/gl2.h>
+
+#include <cstddef>
+
+#include <array>
+#include <map>
+
+#include "common/angleutils.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/SizedMRUCache.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+
+namespace rx
+{
+struct PackedAttributeLayout
+{
+ PackedAttributeLayout();
+ PackedAttributeLayout(const PackedAttributeLayout &other);
+
+ void addAttributeData(GLenum glType,
+ UINT semanticIndex,
+ angle::FormatID vertexFormatID,
+ unsigned int divisor);
+
+ bool operator==(const PackedAttributeLayout &other) const;
+
+ enum Flags
+ {
+ FLAG_USES_INSTANCED_SPRITES = 0x1,
+ FLAG_INSTANCED_SPRITES_ACTIVE = 0x2,
+ FLAG_INSTANCED_RENDERING_ACTIVE = 0x4,
+ };
+
+ uint32_t numAttributes;
+ uint32_t flags;
+ gl::AttribArray<uint64_t> attributeData;
+};
+} // namespace rx
+
+namespace std
+{
+template <>
+struct hash<rx::PackedAttributeLayout>
+{
+ size_t operator()(const rx::PackedAttributeLayout &value) const
+ {
+ return angle::ComputeGenericHash(value);
+ }
+};
+} // namespace std
+
+namespace gl
+{
+class Program;
+} // namespace gl
+
+namespace rx
+{
+class Context11;
+struct TranslatedAttribute;
+struct TranslatedIndexData;
+struct SourceIndexData;
+class ProgramD3D;
+class Renderer11;
+
+class InputLayoutCache : angle::NonCopyable
+{
+ public:
+ InputLayoutCache();
+ ~InputLayoutCache();
+
+ void clear();
+
+ // Useful for testing
+ void setCacheSize(size_t newCacheSize);
+
+ angle::Result getInputLayout(Context11 *context,
+ const gl::State &state,
+ const std::vector<const TranslatedAttribute *> &currentAttributes,
+ const AttribIndexArray &sortedSemanticIndices,
+ gl::PrimitiveMode mode,
+ GLsizei vertexCount,
+ GLsizei instances,
+ const d3d11::InputLayout **inputLayoutOut);
+
+ private:
+ angle::Result createInputLayout(
+ Context11 *context11,
+ const AttribIndexArray &sortedSemanticIndices,
+ const std::vector<const TranslatedAttribute *> &currentAttributes,
+ gl::PrimitiveMode mode,
+ GLsizei vertexCount,
+ GLsizei instances,
+ d3d11::InputLayout *inputLayoutOut);
+
+ // Starting cache size.
+ static constexpr size_t kDefaultCacheSize = 1024;
+
+ // The cache tries to clean up this many states at once.
+ static constexpr size_t kGCLimit = 128;
+
+ using LayoutCache = angle::base::HashingMRUCache<PackedAttributeLayout, d3d11::InputLayout>;
+ LayoutCache mLayoutCache;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/MappedSubresourceVerifier11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/MappedSubresourceVerifier11.cpp
new file mode 100644
index 0000000000..d0f6906f1e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/MappedSubresourceVerifier11.cpp
@@ -0,0 +1,119 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// MappedSubresourceVerifier11.cpp: Implements the
+// rx::MappedSubresourceVerifier11 class, a simple wrapper to D3D11 Texture2D
+// mapped memory so that ASAN and MSAN can catch memory errors done with a
+// pointer to the mapped texture memory.
+
+#include "libANGLE/renderer/d3d/d3d11/MappedSubresourceVerifier11.h"
+
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+
+namespace rx
+{
+
+#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || defined(ANGLE_ENABLE_ASSERTS)
+
+namespace
+{
+
+# if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER)
+constexpr bool kUseWrap = true;
+# else
+constexpr bool kUseWrap = false;
+# endif
+
+size_t getPitchCount(const D3D11_TEXTURE2D_DESC &desc)
+{
+ const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(desc.Format);
+ ASSERT(desc.Height % dxgiFormatInfo.blockHeight == 0);
+ return desc.Height / dxgiFormatInfo.blockHeight;
+}
+
+} // namespace
+
+MappedSubresourceVerifier11::MappedSubresourceVerifier11() = default;
+
+MappedSubresourceVerifier11::~MappedSubresourceVerifier11()
+{
+ ASSERT(!mOrigData);
+ ASSERT(!mWrapData.size());
+}
+
+void MappedSubresourceVerifier11::setDesc(const D3D11_TEXTURE2D_DESC &desc)
+{
+ ASSERT(desc.CPUAccessFlags & (D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE));
+ ASSERT(desc.Width);
+ ASSERT(desc.Height);
+ ASSERT(!mOrigData);
+ ASSERT(!mWrapData.size());
+ ASSERT(!mPitchType);
+ ASSERT(!mPitchCount);
+ mPitchType = &D3D11_MAPPED_SUBRESOURCE::RowPitch;
+ mPitchCount = getPitchCount(desc);
+}
+
+void MappedSubresourceVerifier11::setDesc(const D3D11_TEXTURE3D_DESC &desc)
+{
+ ASSERT(desc.CPUAccessFlags & (D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE));
+ ASSERT(desc.Width);
+ ASSERT(desc.Height);
+ ASSERT(desc.Depth);
+ ASSERT(!mOrigData);
+ ASSERT(!mWrapData.size());
+ ASSERT(!mPitchType);
+ ASSERT(!mPitchCount);
+ mPitchType = &D3D11_MAPPED_SUBRESOURCE::DepthPitch;
+ mPitchCount = desc.Depth;
+}
+
+void MappedSubresourceVerifier11::reset()
+{
+ ASSERT(!mOrigData);
+ ASSERT(!mWrapData.size());
+ mPitchType = nullptr;
+ mPitchCount = 0;
+}
+
+bool MappedSubresourceVerifier11::wrap(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
+{
+ ASSERT(map && map->pData);
+ ASSERT(mapType == D3D11_MAP_READ || mapType == D3D11_MAP_WRITE ||
+ mapType == D3D11_MAP_READ_WRITE);
+ ASSERT(mPitchCount);
+
+ if (kUseWrap)
+ {
+ if (!mWrapData.resize(mPitchCount * map->*mPitchType))
+ return false;
+ }
+
+ mOrigData = reinterpret_cast<uint8_t *>(map->pData);
+
+ if (kUseWrap)
+ {
+ std::copy(mOrigData, mOrigData + mWrapData.size(), mWrapData.data());
+ map->pData = mWrapData.data();
+ }
+ return true;
+}
+
+void MappedSubresourceVerifier11::unwrap()
+{
+ ASSERT(mPitchCount);
+ ASSERT(mOrigData);
+ if (kUseWrap)
+ {
+ std::copy(mWrapData.data(), mWrapData.data() + mWrapData.size(), mOrigData);
+ mWrapData = angle::MemoryBuffer();
+ }
+ mOrigData = nullptr;
+}
+
+#endif
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/MappedSubresourceVerifier11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/MappedSubresourceVerifier11.h
new file mode 100644
index 0000000000..f0fc70eb85
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/MappedSubresourceVerifier11.h
@@ -0,0 +1,63 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// MappedSubresourceVerifier11.h: Defines the rx::MappedSubresourceVerifier11
+// class, a simple wrapper to D3D11 Texture2D mapped memory so that ASAN
+// MSAN can catch memory errors done with a pointer to the mapped texture
+// memory.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_MAPPED_SUBRESOURCE_VERIFIER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_MAPPED_SUBRESOURCE_VERIFIER11_H_
+
+#include "common/MemoryBuffer.h"
+#include "common/angleutils.h"
+
+namespace rx
+{
+
+class MappedSubresourceVerifier11 final : angle::NonCopyable
+{
+ public:
+ MappedSubresourceVerifier11();
+ ~MappedSubresourceVerifier11();
+
+ void setDesc(const D3D11_TEXTURE2D_DESC &desc);
+ void setDesc(const D3D11_TEXTURE3D_DESC &desc);
+ void reset();
+
+ bool wrap(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map);
+ void unwrap();
+
+ private:
+#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || defined(ANGLE_ENABLE_ASSERTS)
+ UINT D3D11_MAPPED_SUBRESOURCE::*mPitchType = nullptr;
+ size_t mPitchCount = 0;
+ angle::MemoryBuffer mWrapData;
+ uint8_t *mOrigData = nullptr;
+#endif
+};
+
+#if !(defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || defined(ANGLE_ENABLE_ASSERTS))
+
+inline MappedSubresourceVerifier11::MappedSubresourceVerifier11() = default;
+inline MappedSubresourceVerifier11::~MappedSubresourceVerifier11() = default;
+
+inline void MappedSubresourceVerifier11::setDesc(const D3D11_TEXTURE2D_DESC &desc) {}
+inline void MappedSubresourceVerifier11::setDesc(const D3D11_TEXTURE3D_DESC &desc) {}
+inline void MappedSubresourceVerifier11::reset() {}
+
+inline bool MappedSubresourceVerifier11::wrap(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map)
+{
+ return true;
+}
+
+inline void MappedSubresourceVerifier11::unwrap() {}
+
+#endif
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_MAPPED_SUBRESOURCE_VERIFIER11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h
new file mode 100644
index 0000000000..e11b19cace
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h
@@ -0,0 +1,38 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow11.h: Defines NativeWindow11, a class for managing and performing operations on an
+// EGLNativeWindowType for the D3D11 renderer.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_
+
+#include "common/debug.h"
+#include "common/platform.h"
+
+#include "libANGLE/Config.h"
+#include "libANGLE/renderer/d3d/NativeWindowD3D.h"
+
+namespace rx
+{
+
+class NativeWindow11 : public NativeWindowD3D
+{
+ public:
+ NativeWindow11(EGLNativeWindowType window) : NativeWindowD3D(window) {}
+
+ virtual HRESULT createSwapChain(ID3D11Device *device,
+ IDXGIFactory *factory,
+ DXGI_FORMAT format,
+ UINT width,
+ UINT height,
+ UINT samples,
+ IDXGISwapChain **swapChain) = 0;
+ virtual void commitChange() = 0;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
new file mode 100644
index 0000000000..9649a91dd3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
@@ -0,0 +1,271 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// PixelTransfer11.cpp:
+// Implementation for buffer-to-texture and texture-to-buffer copies.
+// Used to implement pixel transfers from unpack and to pack buffers.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/serial_utils.h"
+
+// Precompiled shaders
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h"
+
+namespace rx
+{
+
+PixelTransfer11::PixelTransfer11(Renderer11 *renderer)
+ : mRenderer(renderer),
+ mResourcesLoaded(false),
+ mBufferToTextureVS(),
+ mBufferToTextureGS(),
+ mParamsConstantBuffer(),
+ mCopyRasterizerState(),
+ mCopyDepthStencilState()
+{}
+
+PixelTransfer11::~PixelTransfer11() {}
+
+angle::Result PixelTransfer11::loadResources(const gl::Context *context)
+{
+ if (mResourcesLoaded)
+ {
+ return angle::Result::Continue;
+ }
+
+ D3D11_RASTERIZER_DESC rasterDesc;
+ rasterDesc.FillMode = D3D11_FILL_SOLID;
+ rasterDesc.CullMode = D3D11_CULL_NONE;
+ rasterDesc.FrontCounterClockwise = FALSE;
+ rasterDesc.DepthBias = 0;
+ rasterDesc.SlopeScaledDepthBias = 0.0f;
+ rasterDesc.DepthBiasClamp = 0.0f;
+ rasterDesc.DepthClipEnable = TRUE;
+ rasterDesc.ScissorEnable = FALSE;
+ rasterDesc.MultisampleEnable = FALSE;
+ rasterDesc.AntialiasedLineEnable = FALSE;
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, rasterDesc, &mCopyRasterizerState));
+
+ D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
+ depthStencilDesc.DepthEnable = true;
+ depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
+ depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
+ depthStencilDesc.StencilEnable = FALSE;
+ depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
+ depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
+ depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
+ depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
+ depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, depthStencilDesc, &mCopyDepthStencilState));
+
+ D3D11_BUFFER_DESC constantBufferDesc = {};
+ constantBufferDesc.ByteWidth = roundUpPow2<UINT>(sizeof(CopyShaderParams), 32u);
+ constantBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+ constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ constantBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ constantBufferDesc.MiscFlags = 0;
+ constantBufferDesc.StructureByteStride = 0;
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, constantBufferDesc, &mParamsConstantBuffer));
+ mParamsConstantBuffer.setInternalName("PixelTransfer11ConstantBuffer");
+
+ // init shaders
+ ANGLE_TRY(mRenderer->allocateResource(context11, ShaderData(g_VS_BufferToTexture),
+ &mBufferToTextureVS));
+ mBufferToTextureVS.setInternalName("BufferToTextureVS");
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, ShaderData(g_GS_BufferToTexture),
+ &mBufferToTextureGS));
+ mBufferToTextureGS.setInternalName("BufferToTextureGS");
+
+ ANGLE_TRY(buildShaderMap(context));
+
+ StructZero(&mParamsData);
+
+ mResourcesLoaded = true;
+
+ return angle::Result::Continue;
+}
+
+void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea,
+ const gl::Extents &destSize,
+ GLenum internalFormat,
+ const gl::PixelUnpackState &unpack,
+ unsigned int offset,
+ CopyShaderParams *parametersOut)
+{
+ StructZero(parametersOut);
+
+ float texelCenterX = 0.5f / static_cast<float>(destSize.width);
+ float texelCenterY = 0.5f / static_cast<float>(destSize.height);
+
+ unsigned int bytesPerPixel = gl::GetSizedInternalFormatInfo(internalFormat).pixelBytes;
+ unsigned int alignmentBytes = static_cast<unsigned int>(unpack.alignment);
+ unsigned int alignmentPixels =
+ (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel);
+
+ parametersOut->FirstPixelOffset = offset / bytesPerPixel;
+ parametersOut->PixelsPerRow =
+ static_cast<unsigned int>((unpack.rowLength > 0) ? unpack.rowLength : destArea.width);
+ parametersOut->RowStride = roundUp(parametersOut->PixelsPerRow, alignmentPixels);
+ parametersOut->RowsPerSlice = static_cast<unsigned int>(destArea.height);
+ parametersOut->PositionOffset[0] =
+ texelCenterX + (destArea.x / float(destSize.width)) * 2.0f - 1.0f;
+ parametersOut->PositionOffset[1] =
+ texelCenterY + ((destSize.height - destArea.y - 1) / float(destSize.height)) * 2.0f - 1.0f;
+ parametersOut->PositionScale[0] = 2.0f / static_cast<float>(destSize.width);
+ parametersOut->PositionScale[1] = -2.0f / static_cast<float>(destSize.height);
+ parametersOut->FirstSlice = destArea.z;
+}
+
+angle::Result PixelTransfer11::copyBufferToTexture(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea)
+{
+ ASSERT(unpackBuffer);
+
+ ANGLE_TRY(loadResources(context));
+
+ gl::Extents destSize = destRenderTarget->getExtents();
+
+ ASSERT(destArea.x >= 0 && destArea.x + destArea.width <= destSize.width && destArea.y >= 0 &&
+ destArea.y + destArea.height <= destSize.height && destArea.z >= 0 &&
+ destArea.z + destArea.depth <= destSize.depth);
+
+ ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat));
+
+ const d3d11::PixelShader *pixelShader = findBufferToTexturePS(destinationFormat);
+ ASSERT(pixelShader);
+
+ // The SRV must be in the proper read format, which may be different from the destination format
+ // EG: for half float data, we can load full precision floats with implicit conversion
+ GLenum unsizedFormat = gl::GetUnsizedFormat(destinationFormat);
+ const gl::InternalFormat &sourceglFormatInfo =
+ gl::GetInternalFormatInfo(unsizedFormat, sourcePixelsType);
+
+ const d3d11::Format &sourceFormatInfo = d3d11::Format::Get(
+ sourceglFormatInfo.sizedInternalFormat, mRenderer->getRenderer11DeviceCaps());
+ DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat;
+ ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN);
+ Buffer11 *bufferStorage11 = GetAs<Buffer11>(unpackBuffer->getImplementation());
+ const d3d11::ShaderResourceView *bufferSRV = nullptr;
+ ANGLE_TRY(bufferStorage11->getSRV(context, srvFormat, &bufferSRV));
+ ASSERT(bufferSRV != nullptr);
+
+ const d3d11::RenderTargetView &textureRTV =
+ GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
+ ASSERT(textureRTV.valid());
+
+ CopyShaderParams shaderParams;
+ setBufferToTextureCopyParams(destArea, destSize, sourceglFormatInfo.sizedInternalFormat, unpack,
+ offset, &shaderParams);
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ // Are we doing a 2D or 3D copy?
+ const auto *geometryShader = ((destSize.depth > 1) ? &mBufferToTextureGS : nullptr);
+ StateManager11 *stateManager = mRenderer->getStateManager();
+
+ stateManager->setDrawShaders(&mBufferToTextureVS, geometryShader, pixelShader);
+ stateManager->setShaderResource(gl::ShaderType::Fragment, 0, bufferSRV);
+ stateManager->setInputLayout(nullptr);
+ stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
+
+ stateManager->setSingleVertexBuffer(nullptr, 0, 0);
+ stateManager->setSimpleBlendState(nullptr);
+ stateManager->setDepthStencilState(&mCopyDepthStencilState, 0xFFFFFFFF);
+ stateManager->setRasterizerState(&mCopyRasterizerState);
+
+ stateManager->setRenderTarget(textureRTV.get(), nullptr);
+
+ if (!StructEquals(mParamsData, shaderParams))
+ {
+ d3d11::SetBufferData(deviceContext, mParamsConstantBuffer.get(), shaderParams);
+ mParamsData = shaderParams;
+ }
+
+ stateManager->setVertexConstantBuffer(0, &mParamsConstantBuffer);
+
+ // Set the viewport
+ stateManager->setSimpleViewport(destSize);
+
+ UINT numPixels = (shaderParams.PixelsPerRow * destArea.height * destArea.depth);
+ deviceContext->Draw(numPixels, 0);
+
+ return angle::Result::Continue;
+}
+
+angle::Result PixelTransfer11::buildShaderMap(const gl::Context *context)
+{
+ d3d11::PixelShader bufferToTextureFloat;
+ d3d11::PixelShader bufferToTextureInt;
+ d3d11::PixelShader bufferToTextureUint;
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, ShaderData(g_PS_BufferToTexture_4F),
+ &bufferToTextureFloat));
+ ANGLE_TRY(mRenderer->allocateResource(context11, ShaderData(g_PS_BufferToTexture_4I),
+ &bufferToTextureInt));
+ ANGLE_TRY(mRenderer->allocateResource(context11, ShaderData(g_PS_BufferToTexture_4UI),
+ &bufferToTextureUint));
+
+ bufferToTextureFloat.setInternalName("BufferToTextureRGBA.ps");
+ bufferToTextureInt.setInternalName("BufferToTextureRGBA-I.ps");
+ bufferToTextureUint.setInternalName("BufferToTextureRGBA-UI.ps");
+
+ mBufferToTexturePSMap[GL_FLOAT] = std::move(bufferToTextureFloat);
+ mBufferToTexturePSMap[GL_INT] = std::move(bufferToTextureInt);
+ mBufferToTexturePSMap[GL_UNSIGNED_INT] = std::move(bufferToTextureUint);
+
+ return angle::Result::Continue;
+}
+
+const d3d11::PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const
+{
+ GLenum componentType = gl::GetSizedInternalFormatInfo(internalFormat).componentType;
+ if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED)
+ {
+ componentType = GL_FLOAT;
+ }
+
+ auto shaderMapIt = mBufferToTexturePSMap.find(componentType);
+ return (shaderMapIt == mBufferToTexturePSMap.end() ? nullptr : &shaderMapIt->second);
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h
new file mode 100644
index 0000000000..bdb11b90ff
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h
@@ -0,0 +1,96 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// PixelTransfer11.h:
+// Buffer-to-Texture and Texture-to-Buffer data transfers.
+// Used to implement pixel unpack and pixel pack buffers in ES3.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_
+
+#include <GLES2/gl2.h>
+
+#include <map>
+
+#include "common/platform.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+
+namespace gl
+{
+class Buffer;
+class Context;
+struct Box;
+struct Extents;
+struct PixelUnpackState;
+} // namespace gl
+
+namespace rx
+{
+class Renderer11;
+class RenderTargetD3D;
+
+class PixelTransfer11
+{
+ public:
+ explicit PixelTransfer11(Renderer11 *renderer);
+ ~PixelTransfer11();
+
+ // unpack: the source buffer is stored in the unpack state, and buffer strides
+ // offset: the start of the data within the unpack buffer
+ // destRenderTarget: individual slice/layer of a target texture
+ // destinationFormat/sourcePixelsType: determines shaders + shader parameters
+ // destArea: the sub-section of destRenderTarget to copy to
+ angle::Result copyBufferToTexture(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea);
+
+ private:
+ struct CopyShaderParams
+ {
+ unsigned int FirstPixelOffset;
+ unsigned int PixelsPerRow;
+ unsigned int RowStride;
+ unsigned int RowsPerSlice;
+ float PositionOffset[2];
+ float PositionScale[2];
+ int TexLocationOffset[2];
+ int TexLocationScale[2];
+ unsigned int FirstSlice;
+ };
+
+ static void setBufferToTextureCopyParams(const gl::Box &destArea,
+ const gl::Extents &destSize,
+ GLenum internalFormat,
+ const gl::PixelUnpackState &unpack,
+ unsigned int offset,
+ CopyShaderParams *parametersOut);
+
+ angle::Result loadResources(const gl::Context *context);
+ angle::Result buildShaderMap(const gl::Context *context);
+ const d3d11::PixelShader *findBufferToTexturePS(GLenum internalFormat) const;
+
+ Renderer11 *mRenderer;
+
+ bool mResourcesLoaded;
+ std::map<GLenum, d3d11::PixelShader> mBufferToTexturePSMap;
+ d3d11::VertexShader mBufferToTextureVS;
+ d3d11::GeometryShader mBufferToTextureGS;
+ d3d11::Buffer mParamsConstantBuffer;
+ CopyShaderParams mParamsData;
+
+ d3d11::RasterizerState mCopyRasterizerState;
+ d3d11::DepthStencilState mCopyDepthStencilState;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Program11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Program11.cpp
new file mode 100644
index 0000000000..510065ccd6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Program11.cpp
@@ -0,0 +1,34 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Program11: D3D11 implementation of an OpenGL Program.
+
+#include "libANGLE/renderer/d3d/d3d11/Program11.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
+
+namespace rx
+{
+Program11::Program11(const gl::ProgramState &programState, Renderer11 *renderer)
+ : ProgramD3D(programState, renderer)
+{}
+
+Program11::~Program11() = default;
+
+angle::Result Program11::syncState(const gl::Context *context,
+ const gl::Program::DirtyBits &dirtyBits)
+{
+ Renderer11 *renderer11 = GetImplAs<Context11>(context)->getRenderer();
+ StateManager11 *stateManager = renderer11->getStateManager();
+
+ // This single flag should be replace by individual dirtyness.
+ stateManager->invalidateProgramUniformBuffers();
+
+ return angle::Result::Continue;
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Program11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Program11.h
new file mode 100644
index 0000000000..2bd6bc3710
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Program11.h
@@ -0,0 +1,28 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Program11: D3D11 implementation of an OpenGL Program.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_PROGRAM11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_PROGRAM11_H_
+
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+
+namespace rx
+{
+class Renderer11;
+
+class Program11 : public ProgramD3D
+{
+ public:
+ Program11(const gl::ProgramState &programState, Renderer11 *renderer11);
+ ~Program11() override;
+
+ angle::Result syncState(const gl::Context *context,
+ const gl::Program::DirtyBits &dirtyBits) override;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_PROGRAM11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp
new file mode 100644
index 0000000000..2790809dde
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp
@@ -0,0 +1,21 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ProgramPipelineNULL.cpp:
+// Implements the class methods for ProgramPipeline11.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h"
+
+namespace rx
+{
+
+ProgramPipeline11::ProgramPipeline11(const gl::ProgramPipelineState &state)
+ : ProgramPipelineImpl(state)
+{}
+
+ProgramPipeline11::~ProgramPipeline11() {}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h
new file mode 100644
index 0000000000..cf838eec05
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h
@@ -0,0 +1,27 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ProgramPipeline11.h:
+// Defines the class interface for ProgramPipeline11, implementing ProgramPipelineImpl.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_PROGRAMPIPELINE11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_PROGRAMPIPELINE11_H_
+
+#include "libANGLE/renderer/ProgramPipelineImpl.h"
+
+namespace rx
+{
+
+class ProgramPipeline11 : public ProgramPipelineImpl
+{
+ public:
+ ProgramPipeline11(const gl::ProgramPipelineState &state);
+ ~ProgramPipeline11() override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_PROGRAMPIPELINE11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Query11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
new file mode 100644
index 0000000000..f2368e9f8f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
@@ -0,0 +1,357 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl.
+
+#include "libANGLE/renderer/d3d/d3d11/Query11.h"
+
+#include <GLES2/gl2ext.h>
+
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace
+{
+
+GLuint64 MergeQueryResults(gl::QueryType type, GLuint64 currentResult, GLuint64 newResult)
+{
+ switch (type)
+ {
+ case gl::QueryType::AnySamples:
+ case gl::QueryType::AnySamplesConservative:
+ return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE;
+
+ case gl::QueryType::TransformFeedbackPrimitivesWritten:
+ return currentResult + newResult;
+
+ case gl::QueryType::TimeElapsed:
+ return currentResult + newResult;
+
+ case gl::QueryType::Timestamp:
+ return newResult;
+
+ case gl::QueryType::CommandsCompleted:
+ return newResult;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+} // anonymous namespace
+
+namespace rx
+{
+
+Query11::QueryState::QueryState()
+ : getDataAttemptCount(0), query(), beginTimestamp(), endTimestamp(), finished(false)
+{}
+
+Query11::QueryState::~QueryState() {}
+
+Query11::Query11(Renderer11 *renderer, gl::QueryType type)
+ : QueryImpl(type), mResult(0), mResultSum(0), mRenderer(renderer)
+{
+ mActiveQuery = std::unique_ptr<QueryState>(new QueryState());
+}
+
+Query11::~Query11()
+{
+ mRenderer->getStateManager()->onDeleteQueryObject(this);
+}
+
+angle::Result Query11::begin(const gl::Context *context)
+{
+ mResultSum = 0;
+ mRenderer->getStateManager()->onBeginQuery(this);
+ return resume(GetImplAs<Context11>(context));
+}
+
+angle::Result Query11::end(const gl::Context *context)
+{
+ return pause(GetImplAs<Context11>(context));
+}
+
+angle::Result Query11::queryCounter(const gl::Context *context)
+{
+ // This doesn't do anything for D3D11 as we don't support timestamps
+ ASSERT(getType() == gl::QueryType::Timestamp);
+ mResultSum = 0;
+ mPendingQueries.push_back(std::unique_ptr<QueryState>(new QueryState()));
+ return angle::Result::Continue;
+}
+
+template <typename T>
+angle::Result Query11::getResultBase(Context11 *context11, T *params)
+{
+ ASSERT(!mActiveQuery->query.valid());
+ ANGLE_TRY(flush(context11, true));
+ ASSERT(mPendingQueries.empty());
+ *params = static_cast<T>(mResultSum);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Query11::getResult(const gl::Context *context, GLint *params)
+{
+ return getResultBase(GetImplAs<Context11>(context), params);
+}
+
+angle::Result Query11::getResult(const gl::Context *context, GLuint *params)
+{
+ return getResultBase(GetImplAs<Context11>(context), params);
+}
+
+angle::Result Query11::getResult(const gl::Context *context, GLint64 *params)
+{
+ return getResultBase(GetImplAs<Context11>(context), params);
+}
+
+angle::Result Query11::getResult(const gl::Context *context, GLuint64 *params)
+{
+ return getResultBase(GetImplAs<Context11>(context), params);
+}
+
+angle::Result Query11::isResultAvailable(const gl::Context *context, bool *available)
+{
+ ANGLE_TRY(flush(GetImplAs<Context11>(context), false));
+
+ *available = mPendingQueries.empty();
+ return angle::Result::Continue;
+}
+
+angle::Result Query11::pause(Context11 *context11)
+{
+ if (mActiveQuery->query.valid())
+ {
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ gl::QueryType type = getType();
+
+ // If we are doing time elapsed query the end timestamp
+ if (type == gl::QueryType::TimeElapsed)
+ {
+ context->End(mActiveQuery->endTimestamp.get());
+ }
+
+ context->End(mActiveQuery->query.get());
+
+ mPendingQueries.push_back(std::move(mActiveQuery));
+ mActiveQuery = std::unique_ptr<QueryState>(new QueryState());
+ }
+
+ return flush(context11, false);
+}
+
+angle::Result Query11::resume(Context11 *context11)
+{
+ if (!mActiveQuery->query.valid())
+ {
+ ANGLE_TRY(flush(context11, false));
+
+ gl::QueryType type = getType();
+ D3D11_QUERY d3dQueryType = gl_d3d11::ConvertQueryType(type);
+
+ D3D11_QUERY_DESC queryDesc;
+ queryDesc.Query = d3dQueryType;
+ queryDesc.MiscFlags = 0;
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, queryDesc, &mActiveQuery->query));
+
+ // If we are doing time elapsed we also need a query to actually query the timestamp
+ if (type == gl::QueryType::TimeElapsed)
+ {
+ D3D11_QUERY_DESC desc;
+ desc.Query = D3D11_QUERY_TIMESTAMP;
+ desc.MiscFlags = 0;
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, desc, &mActiveQuery->beginTimestamp));
+ ANGLE_TRY(mRenderer->allocateResource(context11, desc, &mActiveQuery->endTimestamp));
+ }
+
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ if (d3dQueryType != D3D11_QUERY_EVENT)
+ {
+ context->Begin(mActiveQuery->query.get());
+ }
+
+ // If we are doing time elapsed, query the begin timestamp
+ if (type == gl::QueryType::TimeElapsed)
+ {
+ context->End(mActiveQuery->beginTimestamp.get());
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Query11::flush(Context11 *context11, bool force)
+{
+ while (!mPendingQueries.empty())
+ {
+ QueryState *query = mPendingQueries.front().get();
+
+ do
+ {
+ ANGLE_TRY(testQuery(context11, query));
+ if (!query->finished && !force)
+ {
+ return angle::Result::Continue;
+ }
+ } while (!query->finished);
+
+ mResultSum = MergeQueryResults(getType(), mResultSum, mResult);
+ mPendingQueries.pop_front();
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Query11::testQuery(Context11 *context11, QueryState *queryState)
+{
+ if (!queryState->finished)
+ {
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ switch (getType())
+ {
+ case gl::QueryType::AnySamples:
+ case gl::QueryType::AnySamplesConservative:
+ {
+ ASSERT(queryState->query.valid());
+ UINT64 numPixels = 0;
+ HRESULT result =
+ context->GetData(queryState->query.get(), &numPixels, sizeof(numPixels), 0);
+ ANGLE_TRY_HR(context11, result, "Failed to get the data of an internal query");
+
+ if (result == S_OK)
+ {
+ queryState->finished = true;
+ mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+ }
+ }
+ break;
+
+ case gl::QueryType::TransformFeedbackPrimitivesWritten:
+ {
+ ASSERT(queryState->query.valid());
+ D3D11_QUERY_DATA_SO_STATISTICS soStats = {};
+ HRESULT result =
+ context->GetData(queryState->query.get(), &soStats, sizeof(soStats), 0);
+ ANGLE_TRY_HR(context11, result, "Failed to get the data of an internal query");
+
+ if (result == S_OK)
+ {
+ queryState->finished = true;
+ mResult = static_cast<GLuint64>(soStats.NumPrimitivesWritten);
+ }
+ }
+ break;
+
+ case gl::QueryType::TimeElapsed:
+ {
+ ASSERT(queryState->query.valid());
+ ASSERT(queryState->beginTimestamp.valid());
+ ASSERT(queryState->endTimestamp.valid());
+ D3D11_QUERY_DATA_TIMESTAMP_DISJOINT timeStats = {};
+ HRESULT result =
+ context->GetData(queryState->query.get(), &timeStats, sizeof(timeStats), 0);
+ ANGLE_TRY_HR(context11, result, "Failed to get the data of an internal query");
+
+ if (result == S_OK)
+ {
+ UINT64 beginTime = 0;
+ HRESULT beginRes = context->GetData(queryState->beginTimestamp.get(),
+ &beginTime, sizeof(UINT64), 0);
+ ANGLE_TRY_HR(context11, beginRes,
+ "Failed to get the data of an internal query");
+
+ UINT64 endTime = 0;
+ HRESULT endRes = context->GetData(queryState->endTimestamp.get(), &endTime,
+ sizeof(UINT64), 0);
+ ANGLE_TRY_HR(context11, endRes, "Failed to get the data of an internal query");
+
+ if (beginRes == S_OK && endRes == S_OK)
+ {
+ queryState->finished = true;
+ if (timeStats.Disjoint)
+ {
+ mRenderer->setGPUDisjoint();
+ }
+ static_assert(sizeof(UINT64) == sizeof(unsigned long long),
+ "D3D UINT64 isn't 64 bits");
+
+ angle::CheckedNumeric<UINT64> checkedTime(endTime);
+ checkedTime -= beginTime;
+ checkedTime *= 1000000000ull;
+ checkedTime /= timeStats.Frequency;
+ if (checkedTime.IsValid())
+ {
+ mResult = checkedTime.ValueOrDie();
+ }
+ else
+ {
+ mResult = std::numeric_limits<GLuint64>::max() / timeStats.Frequency;
+ // If an overflow does somehow occur, there is no way the elapsed time
+ // is accurate, so we generate a disjoint event
+ mRenderer->setGPUDisjoint();
+ }
+ }
+ }
+ }
+ break;
+
+ case gl::QueryType::Timestamp:
+ {
+ // D3D11 doesn't support GL timestamp queries as D3D timestamps are not guaranteed
+ // to have any sort of continuity outside of a disjoint timestamp query block, which
+ // GL depends on
+ ASSERT(!queryState->query.valid());
+ mResult = 0;
+ queryState->finished = true;
+ }
+ break;
+
+ case gl::QueryType::CommandsCompleted:
+ {
+ ASSERT(queryState->query.valid());
+ BOOL completed = 0;
+ HRESULT result =
+ context->GetData(queryState->query.get(), &completed, sizeof(completed), 0);
+ ANGLE_TRY_HR(context11, result, "Failed to get the data of an internal query");
+
+ if (result == S_OK)
+ {
+ queryState->finished = true;
+ ASSERT(completed == TRUE);
+ mResult = (completed == TRUE) ? GL_TRUE : GL_FALSE;
+ }
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ queryState->getDataAttemptCount++;
+ bool checkDeviceLost =
+ (queryState->getDataAttemptCount % kPollingD3DDeviceLostCheckFrequency) == 0;
+ if (!queryState->finished && checkDeviceLost && mRenderer->testDeviceLost())
+ {
+ mRenderer->notifyDeviceLost();
+ ANGLE_TRY_HR(context11, E_OUTOFMEMORY,
+ "Failed to test get query result, device is lost.");
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Query11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Query11.h
new file mode 100644
index 0000000000..96ac59d742
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Query11.h
@@ -0,0 +1,71 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Query11.h: Defines the rx::Query11 class which implements rx::QueryImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_
+
+#include <deque>
+
+#include "libANGLE/renderer/QueryImpl.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+
+namespace rx
+{
+class Context11;
+class Renderer11;
+
+class Query11 : public QueryImpl
+{
+ public:
+ Query11(Renderer11 *renderer, gl::QueryType type);
+ ~Query11() override;
+
+ angle::Result begin(const gl::Context *context) override;
+ angle::Result end(const gl::Context *context) override;
+ angle::Result queryCounter(const gl::Context *context) override;
+ angle::Result getResult(const gl::Context *context, GLint *params) override;
+ angle::Result getResult(const gl::Context *context, GLuint *params) override;
+ angle::Result getResult(const gl::Context *context, GLint64 *params) override;
+ angle::Result getResult(const gl::Context *context, GLuint64 *params) override;
+ angle::Result isResultAvailable(const gl::Context *context, bool *available) override;
+
+ angle::Result pause(Context11 *context11);
+ angle::Result resume(Context11 *context11);
+
+ private:
+ struct QueryState final : private angle::NonCopyable
+ {
+ QueryState();
+ ~QueryState();
+
+ unsigned int getDataAttemptCount;
+
+ d3d11::Query query;
+ d3d11::Query beginTimestamp;
+ d3d11::Query endTimestamp;
+ bool finished;
+ };
+
+ angle::Result flush(Context11 *context11, bool force);
+ angle::Result testQuery(Context11 *context11, QueryState *queryState);
+
+ template <typename T>
+ angle::Result getResultBase(Context11 *context11, T *params);
+
+ GLuint64 mResult;
+ GLuint64 mResultSum;
+
+ Renderer11 *mRenderer;
+
+ std::unique_ptr<QueryState> mActiveQuery;
+ std::deque<std::unique_ptr<QueryState>> mPendingQueries;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
new file mode 100644
index 0000000000..964ac8c287
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
@@ -0,0 +1,323 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render
+// state objects.
+
+#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
+
+#include <float.h>
+
+#include "common/Color.h"
+#include "common/debug.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+using namespace gl_d3d11;
+
+RenderStateCache::RenderStateCache()
+ : mBlendStateCache(kMaxStates),
+ mRasterizerStateCache(kMaxStates),
+ mDepthStencilStateCache(kMaxStates),
+ mSamplerStateCache(kMaxStates)
+{}
+
+RenderStateCache::~RenderStateCache() {}
+
+void RenderStateCache::clear()
+{
+ mBlendStateCache.Clear();
+ mRasterizerStateCache.Clear();
+ mDepthStencilStateCache.Clear();
+ mSamplerStateCache.Clear();
+}
+
+// static
+d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Context *context,
+ Framebuffer11 *framebuffer11,
+ const gl::BlendStateExt &blendStateExt,
+ bool sampleAlphaToCoverage)
+{
+ d3d11::BlendStateKey key;
+ // All fields of the BlendStateExt inside the key should be initialized for the caching to
+ // work correctly. Due to mrt_perf_workaround, the actual indices of active draw buffers may be
+ // different, so both arrays should be tracked.
+ key.blendStateExt = gl::BlendStateExt(blendStateExt.getDrawBufferCount());
+ const gl::AttachmentList &colorbuffers = framebuffer11->getColorAttachmentsForRender(context);
+ const gl::DrawBufferMask colorAttachmentsForRenderMask =
+ framebuffer11->getLastColorAttachmentsForRenderMask();
+
+ ASSERT(blendStateExt.getDrawBufferCount() <= colorAttachmentsForRenderMask.size());
+ ASSERT(colorbuffers.size() == colorAttachmentsForRenderMask.count());
+
+ size_t keyBlendIndex = 0;
+
+ // With blending disabled, factors and equations are ignored when building
+ // D3D11_RENDER_TARGET_BLEND_DESC, so we can reduce the amount of unique keys by
+ // enforcing default values.
+ for (size_t sourceIndex : colorAttachmentsForRenderMask)
+ {
+ ASSERT(keyBlendIndex < colorbuffers.size());
+ const gl::FramebufferAttachment *attachment = colorbuffers[keyBlendIndex];
+
+ // Do not set blend state for null attachments that may be present when
+ // mrt_perf_workaround is disabled.
+ if (attachment == nullptr)
+ {
+ keyBlendIndex++;
+ continue;
+ }
+
+ const uint8_t colorMask = blendStateExt.getColorMaskIndexed(sourceIndex);
+
+ const gl::InternalFormat &internalFormat = *attachment->getFormat().info;
+
+ key.blendStateExt.setColorMaskIndexed(keyBlendIndex,
+ gl_d3d11::GetColorMask(internalFormat) & colorMask);
+ key.rtvMax = static_cast<uint16_t>(keyBlendIndex) + 1;
+
+ // Some D3D11 drivers produce unexpected results when blending is enabled for integer
+ // attachments. Per OpenGL ES spec, it must be ignored anyway. When blending is disabled,
+ // the state remains default to reduce the number of unique keys.
+ if (blendStateExt.getEnabledMask().test(sourceIndex) && !internalFormat.isInt())
+ {
+ key.blendStateExt.setEnabledIndexed(keyBlendIndex, true);
+ key.blendStateExt.setEquationsIndexed(keyBlendIndex, sourceIndex, blendStateExt);
+ key.blendStateExt.setFactorsIndexed(keyBlendIndex, sourceIndex, blendStateExt);
+ }
+ keyBlendIndex++;
+ }
+
+ key.sampleAlphaToCoverage = sampleAlphaToCoverage ? 1 : 0;
+ return key;
+}
+
+angle::Result RenderStateCache::getBlendState(const gl::Context *context,
+ Renderer11 *renderer,
+ const d3d11::BlendStateKey &key,
+ const d3d11::BlendState **outBlendState)
+{
+ auto keyIter = mBlendStateCache.Get(key);
+ if (keyIter != mBlendStateCache.end())
+ {
+ *outBlendState = &keyIter->second;
+ return angle::Result::Continue;
+ }
+
+ TrimCache(kMaxStates, kGCLimit, "blend state", &mBlendStateCache);
+
+ // Create a new blend state and insert it into the cache
+ D3D11_BLEND_DESC blendDesc = {}; // avoid undefined fields
+ const gl::BlendStateExt &blendStateExt = key.blendStateExt;
+
+ blendDesc.AlphaToCoverageEnable = key.sampleAlphaToCoverage != 0 ? TRUE : FALSE;
+ blendDesc.IndependentBlendEnable = key.rtvMax > 1 ? TRUE : FALSE;
+
+ // D3D11 API always accepts an array of blend states. Its validity depends on the hardware
+ // feature level. Given that we do not expose GL entrypoints that set per-buffer blend states on
+ // systems lower than FL10_1, this array will be always valid.
+
+ for (size_t i = 0; i < blendStateExt.getDrawBufferCount(); i++)
+ {
+ D3D11_RENDER_TARGET_BLEND_DESC &rtDesc = blendDesc.RenderTarget[i];
+
+ if (blendStateExt.getEnabledMask().test(i))
+ {
+ rtDesc.BlendEnable = true;
+ rtDesc.SrcBlend =
+ gl_d3d11::ConvertBlendFunc(blendStateExt.getSrcColorIndexed(i), false);
+ rtDesc.DestBlend =
+ gl_d3d11::ConvertBlendFunc(blendStateExt.getDstColorIndexed(i), false);
+ rtDesc.BlendOp = gl_d3d11::ConvertBlendOp(blendStateExt.getEquationColorIndexed(i));
+ rtDesc.SrcBlendAlpha =
+ gl_d3d11::ConvertBlendFunc(blendStateExt.getSrcAlphaIndexed(i), true);
+ rtDesc.DestBlendAlpha =
+ gl_d3d11::ConvertBlendFunc(blendStateExt.getDstAlphaIndexed(i), true);
+ rtDesc.BlendOpAlpha =
+ gl_d3d11::ConvertBlendOp(blendStateExt.getEquationAlphaIndexed(i));
+ }
+
+ // blendStateExt.colorMask follows the same packing scheme as
+ // D3D11_RENDER_TARGET_BLEND_DESC.RenderTargetWriteMask
+ rtDesc.RenderTargetWriteMask = blendStateExt.getColorMaskIndexed(i);
+ }
+
+ d3d11::BlendState d3dBlendState;
+ ANGLE_TRY(renderer->allocateResource(GetImplAs<Context11>(context), blendDesc, &d3dBlendState));
+ const auto &iter = mBlendStateCache.Put(key, std::move(d3dBlendState));
+
+ *outBlendState = &iter->second;
+
+ return angle::Result::Continue;
+}
+
+angle::Result RenderStateCache::getRasterizerState(const gl::Context *context,
+ Renderer11 *renderer,
+ const gl::RasterizerState &rasterState,
+ bool scissorEnabled,
+ ID3D11RasterizerState **outRasterizerState)
+{
+ d3d11::RasterizerStateKey key;
+ key.rasterizerState = rasterState;
+ key.scissorEnabled = scissorEnabled ? 1 : 0;
+
+ auto keyIter = mRasterizerStateCache.Get(key);
+ if (keyIter != mRasterizerStateCache.end())
+ {
+ *outRasterizerState = keyIter->second.get();
+ return angle::Result::Continue;
+ }
+
+ TrimCache(kMaxStates, kGCLimit, "rasterizer state", &mRasterizerStateCache);
+
+ D3D11_CULL_MODE cullMode =
+ gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode);
+
+ // Disable culling if drawing points
+ if (rasterState.pointDrawMode)
+ {
+ cullMode = D3D11_CULL_NONE;
+ }
+
+ D3D11_RASTERIZER_DESC rasterDesc;
+ rasterDesc.FillMode = D3D11_FILL_SOLID;
+ rasterDesc.CullMode = cullMode;
+ rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE : TRUE;
+ rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of
+ // zero will preform no clamping, must be tested though.
+ rasterDesc.DepthClipEnable = TRUE;
+ rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE;
+ rasterDesc.MultisampleEnable = rasterState.multiSample;
+ rasterDesc.AntialiasedLineEnable = FALSE;
+
+ if (rasterState.polygonOffsetFill)
+ {
+ rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor;
+ rasterDesc.DepthBias = (INT)rasterState.polygonOffsetUnits;
+ }
+ else
+ {
+ rasterDesc.SlopeScaledDepthBias = 0.0f;
+ rasterDesc.DepthBias = 0;
+ }
+
+ d3d11::RasterizerState dx11RasterizerState;
+ ANGLE_TRY(renderer->allocateResource(GetImplAs<Context11>(context), rasterDesc,
+ &dx11RasterizerState));
+ *outRasterizerState = dx11RasterizerState.get();
+ mRasterizerStateCache.Put(key, std::move(dx11RasterizerState));
+
+ return angle::Result::Continue;
+}
+
+angle::Result RenderStateCache::getDepthStencilState(const gl::Context *context,
+ Renderer11 *renderer,
+ const gl::DepthStencilState &glState,
+ const d3d11::DepthStencilState **outDSState)
+{
+ auto keyIter = mDepthStencilStateCache.Get(glState);
+ if (keyIter != mDepthStencilStateCache.end())
+ {
+ *outDSState = &keyIter->second;
+ return angle::Result::Continue;
+ }
+
+ TrimCache(kMaxStates, kGCLimit, "depth stencil state", &mDepthStencilStateCache);
+
+ D3D11_DEPTH_STENCIL_DESC dsDesc = {};
+ dsDesc.DepthEnable = glState.depthTest ? TRUE : FALSE;
+ dsDesc.DepthWriteMask = ConvertDepthMask(glState.depthMask);
+ dsDesc.DepthFunc = ConvertComparison(glState.depthFunc);
+ dsDesc.StencilEnable = glState.stencilTest ? TRUE : FALSE;
+ dsDesc.StencilReadMask = ConvertStencilMask(glState.stencilMask);
+ dsDesc.StencilWriteMask = ConvertStencilMask(glState.stencilWritemask);
+ dsDesc.FrontFace.StencilFailOp = ConvertStencilOp(glState.stencilFail);
+ dsDesc.FrontFace.StencilDepthFailOp = ConvertStencilOp(glState.stencilPassDepthFail);
+ dsDesc.FrontFace.StencilPassOp = ConvertStencilOp(glState.stencilPassDepthPass);
+ dsDesc.FrontFace.StencilFunc = ConvertComparison(glState.stencilFunc);
+ dsDesc.BackFace.StencilFailOp = ConvertStencilOp(glState.stencilBackFail);
+ dsDesc.BackFace.StencilDepthFailOp = ConvertStencilOp(glState.stencilBackPassDepthFail);
+ dsDesc.BackFace.StencilPassOp = ConvertStencilOp(glState.stencilBackPassDepthPass);
+ dsDesc.BackFace.StencilFunc = ConvertComparison(glState.stencilBackFunc);
+
+ d3d11::DepthStencilState dx11DepthStencilState;
+ ANGLE_TRY(
+ renderer->allocateResource(GetImplAs<Context11>(context), dsDesc, &dx11DepthStencilState));
+ const auto &iter = mDepthStencilStateCache.Put(glState, std::move(dx11DepthStencilState));
+
+ *outDSState = &iter->second;
+
+ return angle::Result::Continue;
+}
+
+angle::Result RenderStateCache::getSamplerState(const gl::Context *context,
+ Renderer11 *renderer,
+ const gl::SamplerState &samplerState,
+ ID3D11SamplerState **outSamplerState)
+{
+ auto keyIter = mSamplerStateCache.Get(samplerState);
+ if (keyIter != mSamplerStateCache.end())
+ {
+ *outSamplerState = keyIter->second.get();
+ return angle::Result::Continue;
+ }
+
+ TrimCache(kMaxStates, kGCLimit, "sampler state", &mSamplerStateCache);
+
+ const auto &featureLevel = renderer->getRenderer11DeviceCaps().featureLevel;
+
+ D3D11_SAMPLER_DESC samplerDesc;
+ samplerDesc.Filter =
+ gl_d3d11::ConvertFilter(samplerState.getMinFilter(), samplerState.getMagFilter(),
+ samplerState.getMaxAnisotropy(), samplerState.getCompareMode());
+ samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.getWrapS());
+ samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.getWrapT());
+ samplerDesc.AddressW = gl_d3d11::ConvertTextureWrap(samplerState.getWrapR());
+ samplerDesc.MipLODBias = 0;
+ samplerDesc.MaxAnisotropy =
+ gl_d3d11::ConvertMaxAnisotropy(samplerState.getMaxAnisotropy(), featureLevel);
+ samplerDesc.ComparisonFunc = gl_d3d11::ConvertComparison(samplerState.getCompareFunc());
+ angle::ColorF borderColor;
+ if (samplerState.getBorderColor().type == angle::ColorGeneric::Type::Float)
+ {
+ borderColor = samplerState.getBorderColor().colorF;
+ }
+ samplerDesc.BorderColor[0] = borderColor.red;
+ samplerDesc.BorderColor[1] = borderColor.green;
+ samplerDesc.BorderColor[2] = borderColor.blue;
+ samplerDesc.BorderColor[3] = borderColor.alpha;
+ samplerDesc.MinLOD = samplerState.getMinLod();
+ samplerDesc.MaxLOD = samplerState.getMaxLod();
+
+ if (featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ // Check that maxLOD is nearly FLT_MAX (1000.0f is the default), since 9_3 doesn't support
+ // anything other than FLT_MAX. Note that Feature Level 9_* only supports GL ES 2.0, so the
+ // consumer of ANGLE can't modify the Max LOD themselves.
+ ASSERT(samplerState.getMaxLod() >= 999.9f);
+
+ // Now just set MaxLOD to FLT_MAX. Other parts of the renderer (e.g. the non-zero max LOD
+ // workaround) should take account of this.
+ samplerDesc.MaxLOD = FLT_MAX;
+ }
+
+ d3d11::SamplerState dx11SamplerState;
+ ANGLE_TRY(
+ renderer->allocateResource(GetImplAs<Context11>(context), samplerDesc, &dx11SamplerState));
+ *outSamplerState = dx11SamplerState.get();
+ mSamplerStateCache.Put(samplerState, std::move(dx11SamplerState));
+
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h
new file mode 100644
index 0000000000..bd853fe86e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h
@@ -0,0 +1,124 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderStateCache.h: Defines rx::RenderStateCache, a cache of Direct3D render
+// state objects.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/SizedMRUCache.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#include <unordered_map>
+
+namespace std
+{
+template <>
+struct hash<rx::d3d11::BlendStateKey>
+{
+ size_t operator()(const rx::d3d11::BlendStateKey &key) const
+ {
+ return angle::ComputeGenericHash(key);
+ }
+};
+
+template <>
+struct hash<rx::d3d11::RasterizerStateKey>
+{
+ size_t operator()(const rx::d3d11::RasterizerStateKey &key) const
+ {
+ return angle::ComputeGenericHash(key);
+ }
+};
+
+template <>
+struct hash<gl::DepthStencilState>
+{
+ size_t operator()(const gl::DepthStencilState &key) const
+ {
+ return angle::ComputeGenericHash(key);
+ }
+};
+
+template <>
+struct hash<gl::SamplerState>
+{
+ size_t operator()(const gl::SamplerState &key) const { return angle::ComputeGenericHash(key); }
+};
+} // namespace std
+
+namespace rx
+{
+class Framebuffer11;
+class Renderer11;
+
+class RenderStateCache : angle::NonCopyable
+{
+ public:
+ RenderStateCache();
+ virtual ~RenderStateCache();
+
+ void clear();
+
+ static d3d11::BlendStateKey GetBlendStateKey(const gl::Context *context,
+ Framebuffer11 *framebuffer11,
+ const gl::BlendStateExt &blendStateExt,
+ bool sampleAlphaToCoverage);
+ angle::Result getBlendState(const gl::Context *context,
+ Renderer11 *renderer,
+ const d3d11::BlendStateKey &key,
+ const d3d11::BlendState **outBlendState);
+ angle::Result getRasterizerState(const gl::Context *context,
+ Renderer11 *renderer,
+ const gl::RasterizerState &rasterState,
+ bool scissorEnabled,
+ ID3D11RasterizerState **outRasterizerState);
+ angle::Result getDepthStencilState(const gl::Context *context,
+ Renderer11 *renderer,
+ const gl::DepthStencilState &dsState,
+ const d3d11::DepthStencilState **outDSState);
+ angle::Result getSamplerState(const gl::Context *context,
+ Renderer11 *renderer,
+ const gl::SamplerState &samplerState,
+ ID3D11SamplerState **outSamplerState);
+
+ private:
+ // MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState,
+ // ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum
+ // number of unique states of each type an application can create is 4096
+ // TODO(ShahmeerEsmail): Revisit the cache sizes to make sure they are appropriate for most
+ // scenarios.
+ static constexpr unsigned int kMaxStates = 4096;
+
+ // The cache tries to clean up this many states at once.
+ static constexpr unsigned int kGCLimit = 128;
+
+ // Blend state cache
+ using BlendStateMap = angle::base::HashingMRUCache<d3d11::BlendStateKey, d3d11::BlendState>;
+ BlendStateMap mBlendStateCache;
+
+ // Rasterizer state cache
+ using RasterizerStateMap =
+ angle::base::HashingMRUCache<d3d11::RasterizerStateKey, d3d11::RasterizerState>;
+ RasterizerStateMap mRasterizerStateCache;
+
+ // Depth stencil state cache
+ using DepthStencilStateMap =
+ angle::base::HashingMRUCache<gl::DepthStencilState, d3d11::DepthStencilState>;
+ DepthStencilStateMap mDepthStencilStateCache;
+
+ // Sample state cache
+ using SamplerStateMap = angle::base::HashingMRUCache<gl::SamplerState, d3d11::SamplerState>;
+ SamplerStateMap mSamplerStateCache;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp
new file mode 100644
index 0000000000..2f550b5a77
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp
@@ -0,0 +1,403 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers
+// retained by Renderbuffers.
+
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+namespace rx
+{
+
+namespace
+{
+bool GetTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples)
+{
+ ID3D11Texture1D *texture1D = d3d11::DynamicCastComObject<ID3D11Texture1D>(resource);
+ if (texture1D)
+ {
+ D3D11_TEXTURE1D_DESC texDesc;
+ texture1D->GetDesc(&texDesc);
+ SafeRelease(texture1D);
+
+ *mipLevels = texDesc.MipLevels;
+ *samples = 0;
+
+ return true;
+ }
+
+ ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource);
+ if (texture2D)
+ {
+ D3D11_TEXTURE2D_DESC texDesc;
+ texture2D->GetDesc(&texDesc);
+ SafeRelease(texture2D);
+
+ *mipLevels = texDesc.MipLevels;
+ *samples = texDesc.SampleDesc.Count > 1 ? texDesc.SampleDesc.Count : 0;
+
+ return true;
+ }
+
+ ID3D11Texture3D *texture3D = d3d11::DynamicCastComObject<ID3D11Texture3D>(resource);
+ if (texture3D)
+ {
+ D3D11_TEXTURE3D_DESC texDesc;
+ texture3D->GetDesc(&texDesc);
+ SafeRelease(texture3D);
+
+ *mipLevels = texDesc.MipLevels;
+ *samples = 0;
+
+ return true;
+ }
+
+ return false;
+}
+
+unsigned int GetRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view)
+{
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ view->GetDesc(&rtvDesc);
+
+ unsigned int mipSlice = 0;
+ unsigned int arraySlice = 0;
+
+ switch (rtvDesc.ViewDimension)
+ {
+ case D3D11_RTV_DIMENSION_TEXTURE1D:
+ mipSlice = rtvDesc.Texture1D.MipSlice;
+ arraySlice = 0;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
+ mipSlice = rtvDesc.Texture1DArray.MipSlice;
+ arraySlice = rtvDesc.Texture1DArray.FirstArraySlice;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2D:
+ mipSlice = rtvDesc.Texture2D.MipSlice;
+ arraySlice = 0;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
+ mipSlice = rtvDesc.Texture2DArray.MipSlice;
+ arraySlice = rtvDesc.Texture2DArray.FirstArraySlice;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DMS:
+ mipSlice = 0;
+ arraySlice = 0;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
+ mipSlice = 0;
+ arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice;
+ break;
+
+ case D3D11_RTV_DIMENSION_TEXTURE3D:
+ mipSlice = rtvDesc.Texture3D.MipSlice;
+ arraySlice = 0;
+ break;
+
+ case D3D11_RTV_DIMENSION_UNKNOWN:
+ case D3D11_RTV_DIMENSION_BUFFER:
+ UNIMPLEMENTED();
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ unsigned int mipLevels, samples;
+ GetTextureProperties(resource, &mipLevels, &samples);
+
+ return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
+}
+
+unsigned int GetDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view)
+{
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ view->GetDesc(&dsvDesc);
+
+ unsigned int mipSlice = 0;
+ unsigned int arraySlice = 0;
+
+ switch (dsvDesc.ViewDimension)
+ {
+ case D3D11_DSV_DIMENSION_TEXTURE1D:
+ mipSlice = dsvDesc.Texture1D.MipSlice;
+ arraySlice = 0;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
+ mipSlice = dsvDesc.Texture1DArray.MipSlice;
+ arraySlice = dsvDesc.Texture1DArray.FirstArraySlice;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2D:
+ mipSlice = dsvDesc.Texture2D.MipSlice;
+ arraySlice = 0;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
+ mipSlice = dsvDesc.Texture2DArray.MipSlice;
+ arraySlice = dsvDesc.Texture2DArray.FirstArraySlice;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2DMS:
+ mipSlice = 0;
+ arraySlice = 0;
+ break;
+
+ case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
+ mipSlice = 0;
+ arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice;
+ break;
+
+ case D3D11_DSV_DIMENSION_UNKNOWN:
+ UNIMPLEMENTED();
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ unsigned int mipLevels, samples;
+ GetTextureProperties(resource, &mipLevels, &samples);
+
+ return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
+}
+
+GLenum GetSurfaceRTFormat(bool depth, SwapChain11 *swapChain)
+{
+ return (depth ? swapChain->getDepthBufferInternalFormat()
+ : swapChain->getRenderTargetInternalFormat());
+}
+
+const d3d11::Format &GetSurfaceFormatSet(bool depth, SwapChain11 *swapChain, Renderer11 *renderer)
+{
+ return d3d11::Format::Get(GetSurfaceRTFormat(depth, swapChain),
+ renderer->getRenderer11DeviceCaps());
+}
+
+} // anonymous namespace
+
+RenderTarget11::RenderTarget11(const d3d11::Format &formatSet) : mFormatSet(formatSet) {}
+
+RenderTarget11::~RenderTarget11() {}
+
+TextureRenderTarget11::TextureRenderTarget11(d3d11::RenderTargetView &&rtv,
+ const TextureHelper11 &resource,
+ const d3d11::SharedSRV &srv,
+ const d3d11::SharedSRV &blitSRV,
+ GLenum internalFormat,
+ const d3d11::Format &formatSet,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei samples)
+ : RenderTarget11(formatSet),
+ mWidth(width),
+ mHeight(height),
+ mDepth(depth),
+ mInternalFormat(internalFormat),
+ mSamples(samples),
+ mSubresourceIndex(0),
+ mTexture(resource),
+ mRenderTarget(std::move(rtv)),
+ mDepthStencil(),
+ mShaderResource(srv.makeCopy()),
+ mBlitShaderResource(blitSRV.makeCopy())
+{
+ if (mRenderTarget.valid() && mTexture.valid())
+ {
+ mSubresourceIndex = GetRTVSubresourceIndex(mTexture.get(), mRenderTarget.get());
+ }
+ ASSERT(mFormatSet.formatID != angle::FormatID::NONE || mWidth == 0 || mHeight == 0);
+}
+
+TextureRenderTarget11::TextureRenderTarget11(d3d11::DepthStencilView &&dsv,
+ const TextureHelper11 &resource,
+ const d3d11::SharedSRV &srv,
+ GLenum internalFormat,
+ const d3d11::Format &formatSet,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei samples)
+ : RenderTarget11(formatSet),
+ mWidth(width),
+ mHeight(height),
+ mDepth(depth),
+ mInternalFormat(internalFormat),
+ mSamples(samples),
+ mSubresourceIndex(0),
+ mTexture(resource),
+ mRenderTarget(),
+ mDepthStencil(std::move(dsv)),
+ mShaderResource(srv.makeCopy()),
+ mBlitShaderResource()
+{
+ if (mDepthStencil.valid() && mTexture.valid())
+ {
+ mSubresourceIndex = GetDSVSubresourceIndex(mTexture.get(), mDepthStencil.get());
+ }
+ ASSERT(mFormatSet.formatID != angle::FormatID::NONE || mWidth == 0 || mHeight == 0);
+}
+
+TextureRenderTarget11::~TextureRenderTarget11() {}
+
+const TextureHelper11 &TextureRenderTarget11::getTexture() const
+{
+ return mTexture;
+}
+
+const d3d11::RenderTargetView &TextureRenderTarget11::getRenderTargetView() const
+{
+ return mRenderTarget;
+}
+
+const d3d11::DepthStencilView &TextureRenderTarget11::getDepthStencilView() const
+{
+ return mDepthStencil;
+}
+
+angle::Result TextureRenderTarget11::getShaderResourceView(const gl::Context *context,
+ const d3d11::SharedSRV **outSRV)
+{
+ *outSRV = &mShaderResource;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureRenderTarget11::getBlitShaderResourceView(const gl::Context *context,
+ const d3d11::SharedSRV **outSRV)
+{
+ *outSRV = &mBlitShaderResource;
+ return angle::Result::Continue;
+}
+
+GLsizei TextureRenderTarget11::getWidth() const
+{
+ return mWidth;
+}
+
+GLsizei TextureRenderTarget11::getHeight() const
+{
+ return mHeight;
+}
+
+GLsizei TextureRenderTarget11::getDepth() const
+{
+ return mDepth;
+}
+
+GLenum TextureRenderTarget11::getInternalFormat() const
+{
+ return mInternalFormat;
+}
+
+GLsizei TextureRenderTarget11::getSamples() const
+{
+ return mSamples;
+}
+
+unsigned int TextureRenderTarget11::getSubresourceIndex() const
+{
+ return mSubresourceIndex;
+}
+
+SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain,
+ Renderer11 *renderer,
+ bool depth)
+ : RenderTarget11(GetSurfaceFormatSet(depth, swapChain, renderer)),
+ mSwapChain(swapChain),
+ mDepth(depth)
+{
+ ASSERT(mSwapChain);
+}
+
+SurfaceRenderTarget11::~SurfaceRenderTarget11() {}
+
+GLsizei SurfaceRenderTarget11::getWidth() const
+{
+ return mSwapChain->getWidth();
+}
+
+GLsizei SurfaceRenderTarget11::getHeight() const
+{
+ return mSwapChain->getHeight();
+}
+
+GLsizei SurfaceRenderTarget11::getDepth() const
+{
+ return 1;
+}
+
+GLenum SurfaceRenderTarget11::getInternalFormat() const
+{
+ return GetSurfaceRTFormat(mDepth, mSwapChain);
+}
+
+GLsizei SurfaceRenderTarget11::getSamples() const
+{
+ return mSwapChain->getSamples();
+}
+
+const TextureHelper11 &SurfaceRenderTarget11::getTexture() const
+{
+ return (mDepth ? mSwapChain->getDepthStencilTexture() : mSwapChain->getOffscreenTexture());
+}
+
+const d3d11::RenderTargetView &SurfaceRenderTarget11::getRenderTargetView() const
+{
+ ASSERT(!mDepth);
+ return mSwapChain->getRenderTarget();
+}
+
+const d3d11::DepthStencilView &SurfaceRenderTarget11::getDepthStencilView() const
+{
+ ASSERT(mDepth);
+ return mSwapChain->getDepthStencil();
+}
+
+angle::Result SurfaceRenderTarget11::getShaderResourceView(const gl::Context *context,
+ const d3d11::SharedSRV **outSRV)
+{
+ if (mDepth)
+ {
+ *outSRV = &mSwapChain->getDepthStencilShaderResource();
+ }
+ else
+ {
+ ANGLE_TRY(mSwapChain->getRenderTargetShaderResource(GetImplAs<Context11>(context), outSRV));
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result SurfaceRenderTarget11::getBlitShaderResourceView(const gl::Context *context,
+ const d3d11::SharedSRV **outSRV)
+{
+ // The SurfaceRenderTargetView format should always be such that the normal SRV works for blits.
+ return getShaderResourceView(context, outSRV);
+}
+
+unsigned int SurfaceRenderTarget11::getSubresourceIndex() const
+{
+ return 0;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h
new file mode 100644
index 0000000000..8467831e3b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h
@@ -0,0 +1,133 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTarget11.h: Defines a DX11-specific wrapper for ID3D11View pointers
+// retained by Renderbuffers.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_
+
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+namespace rx
+{
+class SwapChain11;
+class Renderer11;
+
+class RenderTarget11 : public RenderTargetD3D
+{
+ public:
+ RenderTarget11(const d3d11::Format &formatSet);
+ ~RenderTarget11() override;
+
+ virtual const TextureHelper11 &getTexture() const = 0;
+ virtual const d3d11::RenderTargetView &getRenderTargetView() const = 0;
+ virtual const d3d11::DepthStencilView &getDepthStencilView() const = 0;
+ virtual angle::Result getShaderResourceView(const gl::Context *context,
+ const d3d11::SharedSRV **outSRV) = 0;
+ virtual angle::Result getBlitShaderResourceView(const gl::Context *context,
+ const d3d11::SharedSRV **outSRV) = 0;
+
+ virtual unsigned int getSubresourceIndex() const = 0;
+
+ const d3d11::Format &getFormatSet() const { return mFormatSet; }
+
+ protected:
+ const d3d11::Format &mFormatSet;
+};
+
+class TextureRenderTarget11 : public RenderTarget11
+{
+ public:
+ // TextureRenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them
+ TextureRenderTarget11(d3d11::RenderTargetView &&rtv,
+ const TextureHelper11 &resource,
+ const d3d11::SharedSRV &srv,
+ const d3d11::SharedSRV &blitSRV,
+ GLenum internalFormat,
+ const d3d11::Format &formatSet,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei samples);
+ TextureRenderTarget11(d3d11::DepthStencilView &&dsv,
+ const TextureHelper11 &resource,
+ const d3d11::SharedSRV &srv,
+ GLenum internalFormat,
+ const d3d11::Format &formatSet,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei samples);
+ ~TextureRenderTarget11() override;
+
+ GLsizei getWidth() const override;
+ GLsizei getHeight() const override;
+ GLsizei getDepth() const override;
+ GLenum getInternalFormat() const override;
+ GLsizei getSamples() const override;
+
+ const TextureHelper11 &getTexture() const override;
+ const d3d11::RenderTargetView &getRenderTargetView() const override;
+ const d3d11::DepthStencilView &getDepthStencilView() const override;
+ angle::Result getShaderResourceView(const gl::Context *context,
+ const d3d11::SharedSRV **outSRV) override;
+ angle::Result getBlitShaderResourceView(const gl::Context *context,
+ const d3d11::SharedSRV **outSRV) override;
+
+ unsigned int getSubresourceIndex() const override;
+
+ private:
+ GLsizei mWidth;
+ GLsizei mHeight;
+ GLsizei mDepth;
+ GLenum mInternalFormat;
+ GLsizei mSamples;
+
+ unsigned int mSubresourceIndex;
+ TextureHelper11 mTexture;
+ d3d11::RenderTargetView mRenderTarget;
+ d3d11::DepthStencilView mDepthStencil;
+ d3d11::SharedSRV mShaderResource;
+
+ // Shader resource view to use with internal blit shaders. Not set for depth/stencil render
+ // targets.
+ d3d11::SharedSRV mBlitShaderResource;
+};
+
+class SurfaceRenderTarget11 : public RenderTarget11
+{
+ public:
+ SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth);
+ ~SurfaceRenderTarget11() override;
+
+ GLsizei getWidth() const override;
+ GLsizei getHeight() const override;
+ GLsizei getDepth() const override;
+ GLenum getInternalFormat() const override;
+ GLsizei getSamples() const override;
+
+ const TextureHelper11 &getTexture() const override;
+ const d3d11::RenderTargetView &getRenderTargetView() const override;
+ const d3d11::DepthStencilView &getDepthStencilView() const override;
+ angle::Result getShaderResourceView(const gl::Context *context,
+ const d3d11::SharedSRV **outSRV) override;
+ angle::Result getBlitShaderResourceView(const gl::Context *context,
+ const d3d11::SharedSRV **outSRV) override;
+
+ unsigned int getSubresourceIndex() const override;
+
+ private:
+ SwapChain11 *mSwapChain;
+ bool mDepth;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
new file mode 100644
index 0000000000..fdd264e92b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -0,0 +1,4454 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
+
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+#include <EGL/eglext.h>
+#include <versionhelpers.h>
+#include <sstream>
+
+#include "anglebase/no_destructor.h"
+#include "common/tls.h"
+#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/histogram_macros.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
+#include "libANGLE/renderer/d3d/DisplayD3D.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.h"
+#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
+#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Image11.h"
+#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Program11.h"
+#include "libANGLE/renderer/d3d/d3d11/Query11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.h"
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
+#include "libANGLE/renderer/d3d/d3d11/Trim11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/d3d/driver_utils_d3d.h"
+#include "libANGLE/renderer/driver_utils.h"
+#include "libANGLE/renderer/dxgi_support_table.h"
+#include "libANGLE/renderer/renderer_utils.h"
+#include "libANGLE/trace.h"
+
+#ifdef ANGLE_ENABLE_WINDOWS_UWP
+# include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h"
+#else
+# include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h"
+#endif
+
+#ifdef ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW
+# include "libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h"
+#endif
+
+// Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process
+// HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed.
+#ifndef ANGLE_SKIP_DXGI_1_2_CHECK
+# define ANGLE_SKIP_DXGI_1_2_CHECK 0
+#endif
+
+namespace rx
+{
+
+namespace
+{
+
+enum
+{
+ MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16
+};
+
+enum ANGLEFeatureLevel
+{
+ ANGLE_FEATURE_LEVEL_INVALID,
+ ANGLE_FEATURE_LEVEL_9_3,
+ ANGLE_FEATURE_LEVEL_10_0,
+ ANGLE_FEATURE_LEVEL_10_1,
+ ANGLE_FEATURE_LEVEL_11_0,
+ ANGLE_FEATURE_LEVEL_11_1,
+ NUM_ANGLE_FEATURE_LEVELS
+};
+
+ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel)
+{
+ switch (d3dFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_9_3:
+ return ANGLE_FEATURE_LEVEL_9_3;
+ case D3D_FEATURE_LEVEL_10_0:
+ return ANGLE_FEATURE_LEVEL_10_0;
+ case D3D_FEATURE_LEVEL_10_1:
+ return ANGLE_FEATURE_LEVEL_10_1;
+ case D3D_FEATURE_LEVEL_11_0:
+ return ANGLE_FEATURE_LEVEL_11_0;
+ case D3D_FEATURE_LEVEL_11_1:
+ return ANGLE_FEATURE_LEVEL_11_1;
+ default:
+ return ANGLE_FEATURE_LEVEL_INVALID;
+ }
+}
+
+void SetLineLoopIndices(GLuint *dest, size_t count)
+{
+ for (size_t i = 0; i < count; i++)
+ {
+ dest[i] = static_cast<GLuint>(i);
+ }
+ dest[count] = 0;
+}
+
+template <typename T>
+void CopyLineLoopIndices(const void *indices, GLuint *dest, size_t count)
+{
+ const T *srcPtr = static_cast<const T *>(indices);
+ for (size_t i = 0; i < count; ++i)
+ {
+ dest[i] = static_cast<GLuint>(srcPtr[i]);
+ }
+ dest[count] = static_cast<GLuint>(srcPtr[0]);
+}
+
+void SetTriangleFanIndices(GLuint *destPtr, size_t numTris)
+{
+ for (size_t i = 0; i < numTris; i++)
+ {
+ destPtr[i * 3 + 0] = 0;
+ destPtr[i * 3 + 1] = static_cast<GLuint>(i) + 1;
+ destPtr[i * 3 + 2] = static_cast<GLuint>(i) + 2;
+ }
+}
+
+void GetLineLoopIndices(const void *indices,
+ gl::DrawElementsType indexType,
+ GLuint count,
+ bool usePrimitiveRestartFixedIndex,
+ std::vector<GLuint> *bufferOut)
+{
+ if (indexType != gl::DrawElementsType::InvalidEnum && usePrimitiveRestartFixedIndex)
+ {
+ size_t indexCount = GetLineLoopWithRestartIndexCount(indexType, count,
+ static_cast<const uint8_t *>(indices));
+ bufferOut->resize(indexCount);
+ switch (indexType)
+ {
+ case gl::DrawElementsType::UnsignedByte:
+ CopyLineLoopIndicesWithRestart<GLubyte, GLuint>(
+ count, static_cast<const uint8_t *>(indices),
+ reinterpret_cast<uint8_t *>(bufferOut->data()));
+ break;
+ case gl::DrawElementsType::UnsignedShort:
+ CopyLineLoopIndicesWithRestart<GLushort, GLuint>(
+ count, static_cast<const uint8_t *>(indices),
+ reinterpret_cast<uint8_t *>(bufferOut->data()));
+ break;
+ case gl::DrawElementsType::UnsignedInt:
+ CopyLineLoopIndicesWithRestart<GLuint, GLuint>(
+ count, static_cast<const uint8_t *>(indices),
+ reinterpret_cast<uint8_t *>(bufferOut->data()));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ }
+
+ // For non-primitive-restart draws, the index count is static.
+ bufferOut->resize(static_cast<size_t>(count) + 1);
+
+ switch (indexType)
+ {
+ // Non-indexed draw
+ case gl::DrawElementsType::InvalidEnum:
+ SetLineLoopIndices(&(*bufferOut)[0], count);
+ break;
+ case gl::DrawElementsType::UnsignedByte:
+ CopyLineLoopIndices<GLubyte>(indices, &(*bufferOut)[0], count);
+ break;
+ case gl::DrawElementsType::UnsignedShort:
+ CopyLineLoopIndices<GLushort>(indices, &(*bufferOut)[0], count);
+ break;
+ case gl::DrawElementsType::UnsignedInt:
+ CopyLineLoopIndices<GLuint>(indices, &(*bufferOut)[0], count);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+template <typename T>
+void CopyTriangleFanIndices(const void *indices, GLuint *destPtr, size_t numTris)
+{
+ const T *srcPtr = static_cast<const T *>(indices);
+
+ for (size_t i = 0; i < numTris; i++)
+ {
+ destPtr[i * 3 + 0] = static_cast<GLuint>(srcPtr[0]);
+ destPtr[i * 3 + 1] = static_cast<GLuint>(srcPtr[i + 1]);
+ destPtr[i * 3 + 2] = static_cast<GLuint>(srcPtr[i + 2]);
+ }
+}
+
+template <typename T>
+void CopyTriangleFanIndicesWithRestart(const void *indices,
+ GLuint indexCount,
+ gl::DrawElementsType indexType,
+ std::vector<GLuint> *bufferOut)
+{
+ GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType);
+ GLuint d3dRestartIndex = gl::GetPrimitiveRestartIndex(gl::DrawElementsType::UnsignedInt);
+ const T *srcPtr = static_cast<const T *>(indices);
+ Optional<GLuint> vertexA;
+ Optional<GLuint> vertexB;
+
+ bufferOut->clear();
+
+ for (size_t indexIdx = 0; indexIdx < indexCount; ++indexIdx)
+ {
+ GLuint value = static_cast<GLuint>(srcPtr[indexIdx]);
+
+ if (value == restartIndex)
+ {
+ bufferOut->push_back(d3dRestartIndex);
+ vertexA.reset();
+ vertexB.reset();
+ }
+ else
+ {
+ if (!vertexA.valid())
+ {
+ vertexA = value;
+ }
+ else if (!vertexB.valid())
+ {
+ vertexB = value;
+ }
+ else
+ {
+ bufferOut->push_back(vertexA.value());
+ bufferOut->push_back(vertexB.value());
+ bufferOut->push_back(value);
+ vertexB = value;
+ }
+ }
+ }
+}
+
+void GetTriFanIndices(const void *indices,
+ gl::DrawElementsType indexType,
+ GLuint count,
+ bool usePrimitiveRestartFixedIndex,
+ std::vector<GLuint> *bufferOut)
+{
+ if (indexType != gl::DrawElementsType::InvalidEnum && usePrimitiveRestartFixedIndex)
+ {
+ switch (indexType)
+ {
+ case gl::DrawElementsType::UnsignedByte:
+ CopyTriangleFanIndicesWithRestart<GLubyte>(indices, count, indexType, bufferOut);
+ break;
+ case gl::DrawElementsType::UnsignedShort:
+ CopyTriangleFanIndicesWithRestart<GLushort>(indices, count, indexType, bufferOut);
+ break;
+ case gl::DrawElementsType::UnsignedInt:
+ CopyTriangleFanIndicesWithRestart<GLuint>(indices, count, indexType, bufferOut);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ }
+
+ // For non-primitive-restart draws, the index count is static.
+ GLuint numTris = count - 2;
+ bufferOut->resize(numTris * 3);
+
+ switch (indexType)
+ {
+ // Non-indexed draw
+ case gl::DrawElementsType::InvalidEnum:
+ SetTriangleFanIndices(&(*bufferOut)[0], numTris);
+ break;
+ case gl::DrawElementsType::UnsignedByte:
+ CopyTriangleFanIndices<GLubyte>(indices, &(*bufferOut)[0], numTris);
+ break;
+ case gl::DrawElementsType::UnsignedShort:
+ CopyTriangleFanIndices<GLushort>(indices, &(*bufferOut)[0], numTris);
+ break;
+ case gl::DrawElementsType::UnsignedInt:
+ CopyTriangleFanIndices<GLuint>(indices, &(*bufferOut)[0], numTris);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+bool IsArrayRTV(ID3D11RenderTargetView *rtv)
+{
+ D3D11_RENDER_TARGET_VIEW_DESC desc;
+ rtv->GetDesc(&desc);
+ if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE1DARRAY &&
+ desc.Texture1DArray.ArraySize > 1)
+ return true;
+ if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DARRAY &&
+ desc.Texture2DArray.ArraySize > 1)
+ return true;
+ if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY &&
+ desc.Texture2DMSArray.ArraySize > 1)
+ return true;
+ return false;
+}
+
+GLsizei GetAdjustedInstanceCount(const ProgramD3D *program, GLsizei instanceCount)
+{
+ if (!program->getState().usesMultiview())
+ {
+ return instanceCount;
+ }
+ if (instanceCount == 0)
+ {
+ return program->getState().getNumViews();
+ }
+ return program->getState().getNumViews() * instanceCount;
+}
+
+const uint32_t ScratchMemoryBufferLifetime = 1000;
+
+void PopulateFormatDeviceCaps(ID3D11Device *device,
+ DXGI_FORMAT format,
+ UINT *outSupport,
+ UINT *outMaxSamples)
+{
+ if (FAILED(device->CheckFormatSupport(format, outSupport)))
+ {
+ *outSupport = 0;
+ }
+
+ *outMaxSamples = 0;
+ for (UINT sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount *= 2)
+ {
+ UINT qualityCount = 0;
+ if (FAILED(device->CheckMultisampleQualityLevels(format, sampleCount, &qualityCount)) ||
+ qualityCount == 0)
+ {
+ break;
+ }
+
+ *outMaxSamples = sampleCount;
+ }
+}
+
+angle::Result GetTextureD3DResourceFromStorageOrImage(const gl::Context *context,
+ TextureD3D *texture,
+ const gl::ImageIndex &index,
+ const TextureHelper11 **outResource,
+ UINT *outSubresource)
+{
+ // If the storage exists, use it. Otherwise, copy directly from the images to avoid
+ // allocating a new storage.
+ if (texture->hasStorage())
+ {
+ TextureStorage *storage = nullptr;
+ ANGLE_TRY(texture->getNativeTexture(context, &storage));
+
+ TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);
+ ANGLE_TRY(storage11->getResource(context, outResource));
+ ANGLE_TRY(storage11->getSubresourceIndex(context, index, outSubresource));
+ }
+ else
+ {
+ ImageD3D *image = texture->getImage(index);
+ Image11 *image11 = GetAs<Image11>(image);
+ ANGLE_TRY(image11->getStagingTexture(context, outResource, outSubresource));
+ }
+
+ return angle::Result::Continue;
+}
+
+} // anonymous namespace
+
+Renderer11DeviceCaps::Renderer11DeviceCaps() = default;
+
+Renderer11::Renderer11(egl::Display *display)
+ : RendererD3D(display),
+ mCreateDebugDevice(false),
+ mStateCache(),
+ mStateManager(this),
+ mLastHistogramUpdateTime(
+ ANGLEPlatformCurrent()->monotonicallyIncreasingTime(ANGLEPlatformCurrent())),
+ mDebug(nullptr),
+ mScratchMemoryBuffer(ScratchMemoryBufferLifetime)
+{
+ mLineLoopIB = nullptr;
+ mTriangleFanIB = nullptr;
+
+ mBlit = nullptr;
+ mPixelTransfer = nullptr;
+
+ mClear = nullptr;
+
+ mTrim = nullptr;
+
+ mRenderer11DeviceCaps.supportsClearView = false;
+ mRenderer11DeviceCaps.supportsConstantBufferOffsets = false;
+ mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader = false;
+ mRenderer11DeviceCaps.supportsDXGI1_2 = false;
+ mRenderer11DeviceCaps.allowES3OnFL10_0 = false;
+ mRenderer11DeviceCaps.supportsTypedUAVLoadAdditionalFormats = false;
+ mRenderer11DeviceCaps.supportsRasterizerOrderViews = false;
+ mRenderer11DeviceCaps.B5G6R5support = 0;
+ mRenderer11DeviceCaps.B4G4R4A4support = 0;
+ mRenderer11DeviceCaps.B5G5R5A1support = 0;
+
+ mD3d11Module = nullptr;
+ mD3d12Module = nullptr;
+ mDxgiModule = nullptr;
+ mDCompModule = nullptr;
+ mCreatedWithDeviceEXT = false;
+
+ mDevice = nullptr;
+ mDevice1 = nullptr;
+ mDeviceContext = nullptr;
+ mDeviceContext1 = nullptr;
+ mDeviceContext3 = nullptr;
+ mDxgiAdapter = nullptr;
+ mDxgiFactory = nullptr;
+
+ ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription));
+
+ const auto &attributes = mDisplay->getAttributeMap();
+
+ if (mDisplay->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
+ {
+ EGLint requestedMajorVersion = static_cast<EGLint>(
+ attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE));
+ EGLint requestedMinorVersion = static_cast<EGLint>(
+ attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE));
+
+ if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11)
+ {
+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
+ {
+ // This could potentially lead to failed context creation if done on a system
+ // without the platform update which installs DXGI 1.2. Currently, for Chrome users
+ // D3D11 contexts are only created if the platform update is available, so this
+ // should not cause any issues.
+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_1);
+ }
+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
+ {
+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0);
+ }
+ }
+
+ if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10)
+ {
+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
+ {
+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1);
+ }
+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0)
+ {
+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0);
+ }
+ }
+
+ if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
+ {
+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
+ }
+
+ EGLint requestedDeviceType = static_cast<EGLint>(attributes.get(
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE));
+ switch (requestedDeviceType)
+ {
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
+ mRequestedDriverType = D3D_DRIVER_TYPE_HARDWARE;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE:
+ mRequestedDriverType = D3D_DRIVER_TYPE_WARP;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
+ mRequestedDriverType = D3D_DRIVER_TYPE_REFERENCE;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+ mRequestedDriverType = D3D_DRIVER_TYPE_NULL;
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+
+ mCreateDebugDevice = ShouldUseDebugLayers(attributes);
+ }
+ else if (mDisplay->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
+ {
+ ASSERT(mDisplay->getDevice() != nullptr);
+ mCreatedWithDeviceEXT = true;
+
+ // Also set EGL_PLATFORM_ANGLE_ANGLE variables, in case they're used elsewhere in ANGLE
+ // mAvailableFeatureLevels defaults to empty
+ mRequestedDriverType = D3D_DRIVER_TYPE_UNKNOWN;
+ }
+
+ const EGLenum presentPath = static_cast<EGLenum>(attributes.get(
+ EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE));
+ mPresentPathFastEnabled = (presentPath == EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE);
+}
+
+Renderer11::~Renderer11()
+{
+ release();
+}
+
+#ifndef __d3d11_1_h__
+# define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081)
+#endif
+
+egl::Error Renderer11::initialize()
+{
+ HRESULT result = S_OK;
+
+ ANGLE_TRY(initializeD3DDevice());
+
+#if !defined(ANGLE_ENABLE_WINDOWS_UWP)
+# if !ANGLE_SKIP_DXGI_1_2_CHECK
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initialize (DXGICheck)");
+ // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is
+ // required.
+ // The easiest way to check is to query for a IDXGIDevice2.
+ bool requireDXGI1_2 = false;
+ HWND hwnd = WindowFromDC(mDisplay->getNativeDisplayId());
+ if (hwnd)
+ {
+ DWORD currentProcessId = GetCurrentProcessId();
+ DWORD wndProcessId;
+ GetWindowThreadProcessId(hwnd, &wndProcessId);
+ requireDXGI1_2 = (currentProcessId != wndProcessId);
+ }
+ else
+ {
+ requireDXGI1_2 = true;
+ }
+
+ if (requireDXGI1_2)
+ {
+ IDXGIDevice2 *dxgiDevice2 = nullptr;
+ result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void **)&dxgiDevice2);
+ if (FAILED(result))
+ {
+ return egl::EglNotInitialized(D3D11_INIT_INCOMPATIBLE_DXGI)
+ << "DXGI 1.2 required to present to HWNDs owned by another process.";
+ }
+ SafeRelease(dxgiDevice2);
+ }
+ }
+# endif
+#endif
+
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initialize (ComQueries)");
+ // Cast the DeviceContext to a DeviceContext1 and DeviceContext3.
+ // This could fail on Windows 7 without the Platform Update.
+ // Don't error in this case- just don't use mDeviceContext1 or mDeviceContext3.
+ mDeviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(mDeviceContext);
+ mDeviceContext3 = d3d11::DynamicCastComObject<ID3D11DeviceContext3>(mDeviceContext);
+
+ IDXGIDevice *dxgiDevice = nullptr;
+ result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
+
+ if (FAILED(result))
+ {
+ return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) << "Could not query DXGI device.";
+ }
+
+ result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&mDxgiAdapter);
+
+ if (FAILED(result))
+ {
+ return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
+ << "Could not retrieve DXGI adapter";
+ }
+
+ SafeRelease(dxgiDevice);
+
+ IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
+
+ // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the
+ // description string.
+ // If DXGI1.2 is available then IDXGIAdapter2::GetDesc2 can be used to get the actual
+ // hardware values.
+ if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != nullptr)
+ {
+ DXGI_ADAPTER_DESC2 adapterDesc2 = {};
+ result = dxgiAdapter2->GetDesc2(&adapterDesc2);
+ if (SUCCEEDED(result))
+ {
+ // Copy the contents of the DXGI_ADAPTER_DESC2 into mAdapterDescription (a
+ // DXGI_ADAPTER_DESC).
+ memcpy(mAdapterDescription.Description, adapterDesc2.Description,
+ sizeof(mAdapterDescription.Description));
+ mAdapterDescription.VendorId = adapterDesc2.VendorId;
+ mAdapterDescription.DeviceId = adapterDesc2.DeviceId;
+ mAdapterDescription.SubSysId = adapterDesc2.SubSysId;
+ mAdapterDescription.Revision = adapterDesc2.Revision;
+ mAdapterDescription.DedicatedVideoMemory = adapterDesc2.DedicatedVideoMemory;
+ mAdapterDescription.DedicatedSystemMemory = adapterDesc2.DedicatedSystemMemory;
+ mAdapterDescription.SharedSystemMemory = adapterDesc2.SharedSystemMemory;
+ mAdapterDescription.AdapterLuid = adapterDesc2.AdapterLuid;
+ }
+ }
+ else
+ {
+ result = mDxgiAdapter->GetDesc(&mAdapterDescription);
+ }
+
+ SafeRelease(dxgiAdapter2);
+
+ if (FAILED(result))
+ {
+ return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
+ << "Could not read DXGI adaptor description.";
+ }
+
+ memset(mDescription, 0, sizeof(mDescription));
+ wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
+
+ result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&mDxgiFactory);
+
+ if (!mDxgiFactory || FAILED(result))
+ {
+ return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR)
+ << "Could not create DXGI factory.";
+ }
+ }
+
+ // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
+ if (mCreateDebugDevice)
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initialize (HideWarnings)");
+ ID3D11InfoQueue *infoQueue;
+ result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue);
+
+ if (SUCCEEDED(result))
+ {
+ D3D11_MESSAGE_ID hideMessages[] = {
+ D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET,
+
+ // Robust access behaviour makes out of bounds messages safe
+ D3D11_MESSAGE_ID_DEVICE_DRAW_VERTEX_BUFFER_TOO_SMALL,
+ };
+
+ D3D11_INFO_QUEUE_FILTER filter = {};
+ filter.DenyList.NumIDs = static_cast<unsigned int>(ArraySize(hideMessages));
+ filter.DenyList.pIDList = hideMessages;
+
+ infoQueue->AddStorageFilterEntries(&filter);
+ SafeRelease(infoQueue);
+ }
+ }
+
+#if !defined(NDEBUG)
+ mDebug = d3d11::DynamicCastComObject<ID3D11Debug>(mDevice);
+#endif
+
+ ANGLE_TRY(initializeDevice());
+
+ return egl::NoError();
+}
+
+HRESULT Renderer11::callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, bool debug)
+{
+ angle::ComPtr<IDXGIAdapter> adapter;
+
+ const egl::AttributeMap &attributes = mDisplay->getAttributeMap();
+ // Check EGL_ANGLE_platform_angle_d3d_luid
+ long high = static_cast<long>(attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 0));
+ unsigned long low =
+ static_cast<unsigned long>(attributes.get(EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE, 0));
+ // Check EGL_ANGLE_platform_angle_device_id
+ if (high == 0 && low == 0)
+ {
+ high = static_cast<long>(attributes.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0));
+ low = static_cast<unsigned long>(attributes.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0));
+ }
+ if (high != 0 || low != 0)
+ {
+ angle::ComPtr<IDXGIFactory1> factory;
+ if (SUCCEEDED(CreateDXGIFactory1(IID_PPV_ARGS(&factory))))
+ {
+ angle::ComPtr<IDXGIAdapter> temp;
+ for (UINT i = 0; SUCCEEDED(factory->EnumAdapters(i, &temp)); i++)
+ {
+ DXGI_ADAPTER_DESC desc;
+ if (SUCCEEDED(temp->GetDesc(&desc)))
+ {
+ // EGL_ANGLE_platform_angle_d3d_luid
+ if (desc.AdapterLuid.HighPart == high && desc.AdapterLuid.LowPart == low)
+ {
+ adapter = temp;
+ break;
+ }
+
+ // EGL_ANGLE_platform_angle_device_id
+ // NOTE: If there are multiple GPUs with the same PCI
+ // vendor and device IDs, this will arbitrarily choose one
+ // of them. To select a specific GPU, use the LUID instead.
+ if ((high == 0 || desc.VendorId == static_cast<UINT>(high)) &&
+ (low == 0 || desc.DeviceId == static_cast<UINT>(low)))
+ {
+ adapter = temp;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // If adapter is not nullptr, the driver type must be D3D_DRIVER_TYPE_UNKNOWN or
+ // D3D11CreateDevice will return E_INVALIDARG.
+ return createDevice(
+ adapter.Get(), adapter ? D3D_DRIVER_TYPE_UNKNOWN : mRequestedDriverType, nullptr,
+ debug ? D3D11_CREATE_DEVICE_DEBUG : 0, mAvailableFeatureLevels.data(),
+ static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &mDevice,
+ &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext);
+}
+
+HRESULT Renderer11::callD3D11On12CreateDevice(PFN_D3D12_CREATE_DEVICE createDevice12,
+ PFN_D3D11ON12_CREATE_DEVICE createDevice11on12,
+ bool debug)
+{
+ angle::ComPtr<IDXGIFactory4> factory;
+ HRESULT result = CreateDXGIFactory1(IID_PPV_ARGS(&factory));
+ if (FAILED(result))
+ {
+ return result;
+ }
+
+ if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP)
+ {
+ angle::ComPtr<IDXGIAdapter> warpAdapter;
+ result = factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter));
+ if (SUCCEEDED(result))
+ {
+ result = createDevice12(warpAdapter.Get(), mAvailableFeatureLevels[0],
+ IID_PPV_ARGS(&mDevice12));
+ }
+ }
+ else
+ {
+ // Passing nullptr into pAdapter chooses the default adapter which will be the hardware
+ // adapter if it exists.
+ result = createDevice12(nullptr, mAvailableFeatureLevels[0], IID_PPV_ARGS(&mDevice12));
+ }
+
+ if (SUCCEEDED(result))
+ {
+ D3D12_COMMAND_QUEUE_DESC queueDesc = {};
+ queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
+ queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
+ result = mDevice12->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&mCommandQueue));
+ }
+
+ if (SUCCEEDED(result))
+ {
+ result = createDevice11on12(
+ mDevice12.Get(), debug ? D3D11_CREATE_DEVICE_DEBUG : 0, mAvailableFeatureLevels.data(),
+ static_cast<unsigned int>(mAvailableFeatureLevels.size()),
+ reinterpret_cast<IUnknown **>(mCommandQueue.GetAddressOf()), 1 /* NumQueues */,
+ 0 /* NodeMask */, &mDevice, &mDeviceContext, &(mRenderer11DeviceCaps.featureLevel));
+ }
+
+ return result;
+}
+
+egl::Error Renderer11::initializeD3DDevice()
+{
+ HRESULT result = S_OK;
+ bool createD3D11on12Device = false;
+
+ if (!mCreatedWithDeviceEXT)
+ {
+#if !defined(ANGLE_ENABLE_WINDOWS_UWP)
+ PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr;
+ PFN_D3D12_CREATE_DEVICE D3D12CreateDevice = nullptr;
+ PFN_D3D11ON12_CREATE_DEVICE D3D11On12CreateDevice = nullptr;
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)");
+ mDxgiModule = LoadLibrary(TEXT("dxgi.dll"));
+ mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
+ mDCompModule = LoadLibrary(TEXT("dcomp.dll"));
+
+ // create the D3D11 device
+ ASSERT(mDevice == nullptr);
+
+ const egl::AttributeMap &attributes = mDisplay->getAttributeMap();
+ createD3D11on12Device =
+ attributes.get(EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE, EGL_FALSE) == EGL_TRUE;
+
+ if (createD3D11on12Device)
+ {
+ mD3d12Module = LoadLibrary(TEXT("d3d12.dll"));
+ if (mD3d12Module == nullptr)
+ {
+ return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
+ << "Could not load D3D12 library.";
+ }
+
+ D3D12CreateDevice = reinterpret_cast<PFN_D3D12_CREATE_DEVICE>(
+ GetProcAddress(mD3d12Module, "D3D12CreateDevice"));
+ if (D3D12CreateDevice == nullptr)
+ {
+ return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
+ << "Could not retrieve D3D12CreateDevice address.";
+ }
+
+ D3D11On12CreateDevice = reinterpret_cast<PFN_D3D11ON12_CREATE_DEVICE>(
+ GetProcAddress(mD3d11Module, "D3D11On12CreateDevice"));
+ if (D3D11On12CreateDevice == nullptr)
+ {
+ return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
+ << "Could not retrieve D3D11On12CreateDevice address.";
+ }
+ }
+ else
+ {
+ if (mD3d11Module == nullptr || mDxgiModule == nullptr)
+ {
+ return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
+ << "Could not load D3D11 or DXGI library.";
+ }
+
+ D3D11CreateDevice = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
+ GetProcAddress(mD3d11Module, "D3D11CreateDevice"));
+
+ if (D3D11CreateDevice == nullptr)
+ {
+ return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP)
+ << "Could not retrieve D3D11CreateDevice address.";
+ }
+ }
+ }
+#endif
+
+ if (mCreateDebugDevice)
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)");
+ if (createD3D11on12Device)
+ {
+ result = callD3D11On12CreateDevice(D3D12CreateDevice, D3D11On12CreateDevice, true);
+ }
+ else
+ {
+ result = callD3D11CreateDevice(D3D11CreateDevice, true);
+ }
+
+ if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u &&
+ mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1)
+ {
+ // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG.
+ // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature
+ // levels to fall back on.
+ mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin());
+ if (createD3D11on12Device)
+ {
+ result =
+ callD3D11On12CreateDevice(D3D12CreateDevice, D3D11On12CreateDevice, true);
+ }
+ else
+ {
+ result = callD3D11CreateDevice(D3D11CreateDevice, true);
+ }
+ }
+
+ if (!mDevice || FAILED(result))
+ {
+ WARN() << "Failed creating Debug D3D11 device - falling back to release runtime.";
+ }
+ }
+
+ if (!mDevice || FAILED(result))
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "D3D11CreateDevice");
+ if (createD3D11on12Device)
+ {
+ result = callD3D11On12CreateDevice(D3D12CreateDevice, D3D11On12CreateDevice, false);
+ }
+ else
+ {
+ result = callD3D11CreateDevice(D3D11CreateDevice, false);
+ }
+
+ if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u &&
+ mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1)
+ {
+ // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG.
+ // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature
+ // levels to fall back on.
+ mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin());
+ if (createD3D11on12Device)
+ {
+ result =
+ callD3D11On12CreateDevice(D3D12CreateDevice, D3D11On12CreateDevice, false);
+ }
+ else
+ {
+ result = callD3D11CreateDevice(D3D11CreateDevice, false);
+ }
+ }
+
+ // Cleanup done by destructor
+ if (!mDevice || FAILED(result))
+ {
+ ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError",
+ static_cast<int>(result));
+ return egl::EglNotInitialized(D3D11_INIT_CREATEDEVICE_ERROR)
+ << "Could not create D3D11 device.";
+ }
+ }
+ }
+ else
+ {
+ DeviceD3D *deviceD3D = GetImplAs<DeviceD3D>(mDisplay->getDevice());
+ ASSERT(deviceD3D != nullptr);
+
+ // We should use the inputted D3D11 device instead
+ void *device = nullptr;
+ ANGLE_TRY(deviceD3D->getAttribute(mDisplay, EGL_D3D11_DEVICE_ANGLE, &device));
+
+ ID3D11Device *d3dDevice = static_cast<ID3D11Device *>(device);
+ if (FAILED(d3dDevice->GetDeviceRemovedReason()))
+ {
+ return egl::EglNotInitialized() << "Inputted D3D11 device has been lost.";
+ }
+
+ if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3)
+ {
+ return egl::EglNotInitialized()
+ << "Inputted D3D11 device must be Feature Level 9_3 or greater.";
+ }
+
+ // The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does.
+ mDevice = d3dDevice;
+ mDevice->AddRef();
+ mDevice->GetImmediateContext(&mDeviceContext);
+ mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel();
+ }
+
+ mResourceManager11.setAllocationsInitialized(mCreateDebugDevice);
+
+ d3d11::SetDebugName(mDeviceContext, "DeviceContext", nullptr);
+
+ mAnnotatorContext.initialize(mDeviceContext);
+
+ mDevice->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast<void **>(&mDevice1));
+
+ return egl::NoError();
+}
+
+void Renderer11::setGlobalDebugAnnotator()
+{
+ static angle::base::NoDestructor<std::mutex> gMutex;
+ static angle::base::NoDestructor<DebugAnnotator11> gGlobalAnnotator;
+
+ std::lock_guard<std::mutex> lg(*gMutex);
+ gl::InitializeDebugAnnotations(gGlobalAnnotator.get());
+}
+
+// do any one-time device initialization
+// NOTE: this is also needed after a device lost/reset
+// to reset the scene status and ensure the default states are reset.
+egl::Error Renderer11::initializeDevice()
+{
+ ANGLE_TRACE_EVENT0("gpu.angle", "Renderer11::initializeDevice");
+
+ populateRenderer11DeviceCaps();
+
+ mStateCache.clear();
+
+ ASSERT(!mBlit);
+ mBlit = new Blit11(this);
+
+ ASSERT(!mClear);
+ mClear = new Clear11(this);
+
+ const auto &attributes = mDisplay->getAttributeMap();
+ // If automatic trim is enabled, DXGIDevice3::Trim( ) is called for the application
+ // automatically when an application is suspended by the OS. This feature is currently
+ // only supported for Windows Store applications.
+ EGLint enableAutoTrim = static_cast<EGLint>(
+ attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE));
+
+ if (enableAutoTrim == EGL_TRUE)
+ {
+ ASSERT(!mTrim);
+ mTrim = new Trim11(this);
+ }
+
+ ASSERT(!mPixelTransfer);
+ mPixelTransfer = new PixelTransfer11(this);
+
+ // Gather stats on DXGI and D3D feature level
+ ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.SupportsDXGI1_2", mRenderer11DeviceCaps.supportsDXGI1_2);
+
+ ANGLEFeatureLevel angleFeatureLevel = GetANGLEFeatureLevel(mRenderer11DeviceCaps.featureLevel);
+
+ // We don't actually request a 11_1 device, because of complications with the platform
+ // update. Instead we check if the mDeviceContext1 pointer cast succeeded.
+ // Note: we should support D3D11_0 always, but we aren't guaranteed to be at FL11_0
+ // because the app can specify a lower version (such as 9_3) on Display creation.
+ if (mDeviceContext1 != nullptr)
+ {
+ angleFeatureLevel = ANGLE_FEATURE_LEVEL_11_1;
+ }
+
+ ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel", angleFeatureLevel,
+ NUM_ANGLE_FEATURE_LEVELS);
+
+ return egl::NoError();
+}
+
+void Renderer11::populateRenderer11DeviceCaps()
+{
+ HRESULT hr = S_OK;
+
+ LARGE_INTEGER version;
+ hr = mDxgiAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version);
+ if (FAILED(hr))
+ {
+ mRenderer11DeviceCaps.driverVersion.reset();
+ ERR() << "Error querying driver version from DXGI Adapter.";
+ }
+ else
+ {
+ mRenderer11DeviceCaps.driverVersion = version;
+ }
+
+ if (mDeviceContext1)
+ {
+ D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options;
+ HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options,
+ sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS));
+ if (SUCCEEDED(result))
+ {
+ mRenderer11DeviceCaps.supportsClearView = (d3d11Options.ClearView != FALSE);
+ mRenderer11DeviceCaps.supportsConstantBufferOffsets =
+ (d3d11Options.ConstantBufferOffsetting != FALSE);
+ }
+ }
+
+ if (mDeviceContext3)
+ {
+ D3D11_FEATURE_DATA_D3D11_OPTIONS3 d3d11Options3;
+ HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &d3d11Options3,
+ sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS3));
+ if (SUCCEEDED(result))
+ {
+ mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader =
+ (d3d11Options3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer == TRUE);
+ }
+ D3D11_FEATURE_DATA_D3D11_OPTIONS2 d3d11Options2;
+ result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS2, &d3d11Options2,
+ sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS2));
+ if (SUCCEEDED(result))
+ {
+ mRenderer11DeviceCaps.supportsTypedUAVLoadAdditionalFormats =
+ d3d11Options2.TypedUAVLoadAdditionalFormats;
+ if (!getFeatures().disableRasterizerOrderViews.enabled)
+ {
+ mRenderer11DeviceCaps.supportsRasterizerOrderViews = d3d11Options2.ROVsSupported;
+ }
+ }
+ }
+
+ mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs =
+ mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_10_0;
+
+ if (getFeatures().disableB5G6R5Support.enabled)
+ {
+ mRenderer11DeviceCaps.B5G6R5support = 0;
+ mRenderer11DeviceCaps.B5G6R5maxSamples = 0;
+ }
+ else
+ {
+ PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G6R5_UNORM,
+ &mRenderer11DeviceCaps.B5G6R5support,
+ &mRenderer11DeviceCaps.B5G6R5maxSamples);
+ }
+
+ if (getFeatures().allowES3OnFL100.enabled)
+ {
+ mRenderer11DeviceCaps.allowES3OnFL10_0 = true;
+ }
+
+ PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B4G4R4A4_UNORM,
+ &mRenderer11DeviceCaps.B4G4R4A4support,
+ &mRenderer11DeviceCaps.B4G4R4A4maxSamples);
+ PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G5R5A1_UNORM,
+ &mRenderer11DeviceCaps.B5G5R5A1support,
+ &mRenderer11DeviceCaps.B5G5R5A1maxSamples);
+
+ IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
+ mRenderer11DeviceCaps.supportsDXGI1_2 = (dxgiAdapter2 != nullptr);
+ SafeRelease(dxgiAdapter2);
+}
+
+gl::SupportedSampleSet Renderer11::generateSampleSetForEGLConfig(
+ const gl::TextureCaps &colorBufferFormatCaps,
+ const gl::TextureCaps &depthStencilBufferFormatCaps) const
+{
+ gl::SupportedSampleSet sampleCounts;
+
+ // Generate a new set from the set intersection of sample counts between the color and depth
+ // format caps.
+ std::set_intersection(colorBufferFormatCaps.sampleCounts.begin(),
+ colorBufferFormatCaps.sampleCounts.end(),
+ depthStencilBufferFormatCaps.sampleCounts.begin(),
+ depthStencilBufferFormatCaps.sampleCounts.end(),
+ std::inserter(sampleCounts, sampleCounts.begin()));
+
+ // Format of GL_NONE results in no supported sample counts.
+ // Add back the color sample counts to the supported sample set.
+ if (depthStencilBufferFormatCaps.sampleCounts.empty())
+ {
+ sampleCounts = colorBufferFormatCaps.sampleCounts;
+ }
+ else if (colorBufferFormatCaps.sampleCounts.empty())
+ {
+ // Likewise, add back the depth sample counts to the supported sample set.
+ sampleCounts = depthStencilBufferFormatCaps.sampleCounts;
+ }
+
+ // Always support 0 samples
+ sampleCounts.insert(0);
+
+ return sampleCounts;
+}
+
+egl::ConfigSet Renderer11::generateConfigs()
+{
+ std::vector<GLenum> colorBufferFormats;
+
+ // 32-bit supported formats
+ colorBufferFormats.push_back(GL_BGRA8_EXT);
+ colorBufferFormats.push_back(GL_RGBA8_OES);
+
+ // 24-bit supported formats
+ colorBufferFormats.push_back(GL_RGB8_OES);
+
+ if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
+ {
+ // Additional high bit depth formats added in D3D 10.0
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/bb173064.aspx
+ colorBufferFormats.push_back(GL_RGBA16F);
+ colorBufferFormats.push_back(GL_RGB10_A2);
+ }
+
+ if (!mPresentPathFastEnabled)
+ {
+ // 16-bit supported formats
+ // These aren't valid D3D11 swapchain formats, so don't expose them as configs
+ // if present path fast is active
+ colorBufferFormats.push_back(GL_RGBA4);
+ colorBufferFormats.push_back(GL_RGB5_A1);
+ colorBufferFormats.push_back(GL_RGB565);
+ }
+
+ static const GLenum depthStencilBufferFormats[] = {
+ GL_NONE, GL_DEPTH24_STENCIL8_OES, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16,
+ GL_STENCIL_INDEX8,
+ };
+
+ const gl::Caps &rendererCaps = getNativeCaps();
+ const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps();
+
+ const EGLint optimalSurfaceOrientation =
+ mPresentPathFastEnabled ? 0 : EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE;
+
+ egl::ConfigSet configs;
+ for (GLenum colorBufferInternalFormat : colorBufferFormats)
+ {
+ const gl::TextureCaps &colorBufferFormatCaps =
+ rendererTextureCaps.get(colorBufferInternalFormat);
+ if (!colorBufferFormatCaps.renderbuffer)
+ {
+ ASSERT(!colorBufferFormatCaps.textureAttachment);
+ continue;
+ }
+
+ for (GLenum depthStencilBufferInternalFormat : depthStencilBufferFormats)
+ {
+ const gl::TextureCaps &depthStencilBufferFormatCaps =
+ rendererTextureCaps.get(depthStencilBufferInternalFormat);
+ if (!depthStencilBufferFormatCaps.renderbuffer &&
+ depthStencilBufferInternalFormat != GL_NONE)
+ {
+ ASSERT(!depthStencilBufferFormatCaps.textureAttachment);
+ continue;
+ }
+
+ const gl::InternalFormat &colorBufferFormatInfo =
+ gl::GetSizedInternalFormatInfo(colorBufferInternalFormat);
+ const gl::InternalFormat &depthStencilBufferFormatInfo =
+ gl::GetSizedInternalFormatInfo(depthStencilBufferInternalFormat);
+ const gl::Version &maxVersion = getMaxSupportedESVersion();
+
+ const gl::SupportedSampleSet sampleCounts =
+ generateSampleSetForEGLConfig(colorBufferFormatCaps, depthStencilBufferFormatCaps);
+
+ for (GLuint sampleCount : sampleCounts)
+ {
+ egl::Config config;
+ config.renderTargetFormat = colorBufferInternalFormat;
+ config.depthStencilFormat = depthStencilBufferInternalFormat;
+ config.bufferSize = colorBufferFormatInfo.pixelBytes * 8;
+ config.redSize = colorBufferFormatInfo.redBits;
+ config.greenSize = colorBufferFormatInfo.greenBits;
+ config.blueSize = colorBufferFormatInfo.blueBits;
+ config.luminanceSize = colorBufferFormatInfo.luminanceBits;
+ config.alphaSize = colorBufferFormatInfo.alphaBits;
+ config.alphaMaskSize = 0;
+ config.bindToTextureRGB =
+ ((colorBufferFormatInfo.format == GL_RGB) && (sampleCount <= 1));
+ config.bindToTextureRGBA = (((colorBufferFormatInfo.format == GL_RGBA) ||
+ (colorBufferFormatInfo.format == GL_BGRA_EXT)) &&
+ (sampleCount <= 1));
+ config.colorBufferType = EGL_RGB_BUFFER;
+ config.configCaveat = EGL_NONE;
+ config.configID = static_cast<EGLint>(configs.size() + 1);
+
+ // PresentPathFast may not be conformant
+ config.conformant = 0;
+ if (!mPresentPathFastEnabled)
+ {
+ // Can only support a conformant ES2 with feature level greater than 10.0.
+ if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0)
+ {
+ config.conformant |= EGL_OPENGL_ES2_BIT;
+ }
+
+ // We can only support conformant ES3 on FL 10.1+
+ if (maxVersion.major >= 3)
+ {
+ config.conformant |= EGL_OPENGL_ES3_BIT_KHR;
+ }
+ }
+
+ config.depthSize = depthStencilBufferFormatInfo.depthBits;
+ config.level = 0;
+ config.matchNativePixmap = EGL_NONE;
+ config.maxPBufferWidth = rendererCaps.max2DTextureSize;
+ config.maxPBufferHeight = rendererCaps.max2DTextureSize;
+ config.maxPBufferPixels =
+ rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
+ config.maxSwapInterval = 4;
+ config.minSwapInterval = 0;
+ config.nativeRenderable = EGL_FALSE;
+ config.nativeVisualID = 0;
+ config.nativeVisualType = EGL_NONE;
+
+ // Can't support ES3 at all without feature level 10.1
+ config.renderableType = EGL_OPENGL_ES2_BIT;
+ if (maxVersion.major >= 3)
+ {
+ config.renderableType |= EGL_OPENGL_ES3_BIT_KHR;
+ }
+
+ config.sampleBuffers = (sampleCount == 0) ? 0 : 1;
+ config.samples = sampleCount;
+ config.stencilSize = depthStencilBufferFormatInfo.stencilBits;
+ config.surfaceType =
+ EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+ config.transparentType = EGL_NONE;
+ config.transparentRedValue = 0;
+ config.transparentGreenValue = 0;
+ config.transparentBlueValue = 0;
+ config.optimalOrientation = optimalSurfaceOrientation;
+ config.colorComponentType = gl_egl::GLComponentTypeToEGLColorComponentType(
+ colorBufferFormatInfo.componentType);
+
+ configs.add(config);
+ }
+ }
+ }
+
+ ASSERT(configs.size() > 0);
+ return configs;
+}
+
+void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const
+{
+ outExtensions->createContextRobustness = true;
+
+ if (getShareHandleSupport())
+ {
+ outExtensions->d3dShareHandleClientBuffer = true;
+ outExtensions->surfaceD3DTexture2DShareHandle = true;
+ }
+ outExtensions->d3dTextureClientBuffer = true;
+ outExtensions->imageD3D11Texture = true;
+
+ outExtensions->keyedMutex = true;
+ outExtensions->querySurfacePointer = true;
+ outExtensions->windowFixedSize = true;
+
+ // If present path fast is active then the surface orientation extension isn't supported
+ outExtensions->surfaceOrientation = !mPresentPathFastEnabled;
+
+ // D3D11 does not support present with dirty rectangles until DXGI 1.2.
+ outExtensions->postSubBuffer = mRenderer11DeviceCaps.supportsDXGI1_2;
+
+ outExtensions->image = true;
+ outExtensions->imageBase = true;
+ outExtensions->glTexture2DImage = true;
+ outExtensions->glTextureCubemapImage = true;
+ outExtensions->glRenderbufferImage = true;
+
+ outExtensions->stream = true;
+ outExtensions->streamConsumerGLTexture = true;
+ outExtensions->streamConsumerGLTextureYUV = true;
+ outExtensions->streamProducerD3DTexture = true;
+
+ outExtensions->noConfigContext = true;
+ outExtensions->directComposition = !!mDCompModule;
+
+ // Contexts are virtualized so textures and semaphores can be shared globally
+ outExtensions->displayTextureShareGroup = true;
+ outExtensions->displaySemaphoreShareGroup = true;
+
+ // syncControlCHROMIUM requires direct composition.
+ outExtensions->syncControlCHROMIUM = outExtensions->directComposition;
+
+ // D3D11 can be used without a swap chain
+ outExtensions->surfacelessContext = true;
+
+ // All D3D feature levels support robust resource init
+ outExtensions->robustResourceInitializationANGLE = true;
+
+#ifdef ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW
+ // Compositor Native Window capabilies require WinVer >= 1803
+ if (CompositorNativeWindow11::IsSupportedWinRelease())
+ {
+ outExtensions->windowsUIComposition = true;
+ }
+#endif
+}
+
+angle::Result Renderer11::flush(Context11 *context11)
+{
+ mDeviceContext->Flush();
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::finish(Context11 *context11)
+{
+ if (!mSyncQuery.valid())
+ {
+ D3D11_QUERY_DESC queryDesc;
+ queryDesc.Query = D3D11_QUERY_EVENT;
+ queryDesc.MiscFlags = 0;
+
+ ANGLE_TRY(allocateResource(context11, queryDesc, &mSyncQuery));
+ }
+
+ mDeviceContext->End(mSyncQuery.get());
+
+ HRESULT result = S_OK;
+ unsigned int attempt = 0;
+ do
+ {
+ unsigned int flushFrequency = 100;
+ UINT flags = (attempt % flushFrequency == 0) ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH;
+ attempt++;
+
+ result = mDeviceContext->GetData(mSyncQuery.get(), nullptr, 0, flags);
+ ANGLE_TRY_HR(context11, result, "Failed to get event query data");
+
+ if (result == S_FALSE)
+ {
+ // Keep polling, but allow other threads to do something useful first
+ ScheduleYield();
+ }
+
+ // Attempt is incremented before checking if we should test for device loss so that device
+ // loss is not checked on the first iteration
+ bool checkDeviceLost = (attempt % kPollingD3DDeviceLostCheckFrequency) == 0;
+ if (checkDeviceLost && testDeviceLost())
+ {
+ mDisplay->notifyDeviceLost();
+ ANGLE_CHECK(context11, false, "Device was lost while waiting for sync.",
+ GL_OUT_OF_MEMORY);
+ }
+ } while (result == S_FALSE);
+
+ return angle::Result::Continue;
+}
+
+bool Renderer11::isValidNativeWindow(EGLNativeWindowType window) const
+{
+#if defined(ANGLE_ENABLE_WINDOWS_UWP)
+ if (NativeWindow11WinRT::IsValidNativeWindow(window))
+ {
+ return true;
+ }
+#else
+ if (NativeWindow11Win32::IsValidNativeWindow(window))
+ {
+ return true;
+ }
+#endif
+
+#ifdef ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW
+ static_assert(sizeof(ABI::Windows::UI::Composition::SpriteVisual *) == sizeof(HWND),
+ "Pointer size must match Window Handle size");
+ if (CompositorNativeWindow11::IsValidNativeWindow(window))
+ {
+ return true;
+ }
+#endif
+
+ return false;
+}
+
+NativeWindowD3D *Renderer11::createNativeWindow(EGLNativeWindowType window,
+ const egl::Config *config,
+ const egl::AttributeMap &attribs) const
+{
+#if defined(ANGLE_ENABLE_WINDOWS_UWP)
+ if (window == nullptr || NativeWindow11WinRT::IsValidNativeWindow(window))
+ {
+ return new NativeWindow11WinRT(window, config->alphaSize > 0);
+ }
+#else
+ if (window == nullptr || NativeWindow11Win32::IsValidNativeWindow(window))
+ {
+ return new NativeWindow11Win32(
+ window, config->alphaSize > 0,
+ attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE);
+ }
+#endif
+
+#ifdef ANGLE_ENABLE_D3D11_COMPOSITOR_NATIVE_WINDOW
+ if (CompositorNativeWindow11::IsValidNativeWindow(window))
+ {
+ return new CompositorNativeWindow11(window, config->alphaSize > 0);
+ }
+#endif
+
+ UNREACHABLE();
+ return nullptr;
+}
+
+egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
+ IUnknown *texture,
+ const egl::AttributeMap &attribs,
+ EGLint *width,
+ EGLint *height,
+ GLsizei *samples,
+ gl::Format *glFormat,
+ const angle::Format **angleFormat,
+ UINT *arraySlice) const
+{
+ angle::ComPtr<ID3D11Texture2D> d3dTexture =
+ d3d11::DynamicCastComObjectToComPtr<ID3D11Texture2D>(texture);
+ if (d3dTexture == nullptr)
+ {
+ return egl::EglBadParameter() << "client buffer is not a ID3D11Texture2D";
+ }
+
+ angle::ComPtr<ID3D11Device> textureDevice;
+ d3dTexture->GetDevice(&textureDevice);
+ if (textureDevice.Get() != mDevice)
+ {
+ return egl::EglBadParameter() << "Texture's device does not match.";
+ }
+
+ D3D11_TEXTURE2D_DESC desc = {};
+ d3dTexture->GetDesc(&desc);
+
+ EGLint imageWidth = static_cast<EGLint>(desc.Width);
+ EGLint imageHeight = static_cast<EGLint>(desc.Height);
+
+ GLsizei sampleCount = static_cast<GLsizei>(desc.SampleDesc.Count);
+ if (configuration && (configuration->samples != sampleCount))
+ {
+ // Both the texture and EGL config sample count may not be the same when multi-sampling
+ // is disabled. The EGL sample count can be 0 but a D3D texture is always 1. Therefore,
+ // we must only check for a invalid match when the EGL config is non-zero or the texture is
+ // not one.
+ if (configuration->samples != 0 || sampleCount != 1)
+ {
+ return egl::EglBadParameter() << "Texture's sample count does not match.";
+ }
+ }
+
+ const angle::Format *textureAngleFormat = nullptr;
+ GLenum sizedInternalFormat = GL_NONE;
+
+ // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
+ if (desc.Format == DXGI_FORMAT_NV12 || desc.Format == DXGI_FORMAT_P010 ||
+ desc.Format == DXGI_FORMAT_P016)
+ {
+ if (!attribs.contains(EGL_D3D11_TEXTURE_PLANE_ANGLE))
+ {
+ return egl::EglBadParameter()
+ << "EGL_D3D11_TEXTURE_PLANE_ANGLE must be specified for YUV textures.";
+ }
+
+ EGLint plane = attribs.getAsInt(EGL_D3D11_TEXTURE_PLANE_ANGLE);
+
+ // P010 and P016 have the same memory layout, SRV/RTV format, etc.
+ const bool isNV12 = (desc.Format == DXGI_FORMAT_NV12);
+ if (plane == 0)
+ {
+ textureAngleFormat = isNV12 ? &angle::Format::Get(angle::FormatID::R8_UNORM)
+ : &angle::Format::Get(angle::FormatID::R16_UNORM);
+ }
+ else if (plane == 1)
+ {
+ textureAngleFormat = isNV12 ? &angle::Format::Get(angle::FormatID::R8G8_UNORM)
+ : &angle::Format::Get(angle::FormatID::R16G16_UNORM);
+ imageWidth /= 2;
+ imageHeight /= 2;
+ }
+ else
+ {
+ return egl::EglBadParameter() << "Invalid client buffer texture plane: " << plane;
+ }
+
+ ASSERT(textureAngleFormat);
+ sizedInternalFormat = textureAngleFormat->glInternalFormat;
+ }
+ else
+ {
+ switch (desc.Format)
+ {
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R8_UNORM:
+ case DXGI_FORMAT_R8G8_UNORM:
+ case DXGI_FORMAT_R16_UNORM:
+ case DXGI_FORMAT_R16G16_UNORM:
+ break;
+
+ default:
+ return egl::EglBadParameter()
+ << "Invalid client buffer texture format: " << desc.Format;
+ }
+
+ textureAngleFormat = &d3d11_angle::GetFormat(desc.Format);
+ ASSERT(textureAngleFormat);
+
+ sizedInternalFormat = textureAngleFormat->glInternalFormat;
+
+ if (attribs.contains(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE))
+ {
+ const GLenum internalFormat =
+ static_cast<GLenum>(attribs.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE));
+ switch (internalFormat)
+ {
+ case GL_RGBA:
+ case GL_BGRA_EXT:
+ case GL_RGB:
+ case GL_RED_EXT:
+ case GL_RG_EXT:
+ case GL_RGB10_A2_EXT:
+ case GL_R16_EXT:
+ case GL_RG16_EXT:
+ break;
+ default:
+ return egl::EglBadParameter()
+ << "Invalid client buffer texture internal format: " << std::hex
+ << internalFormat;
+ }
+
+ const GLenum type = gl::GetSizedInternalFormatInfo(sizedInternalFormat).type;
+
+ const auto format = gl::Format(internalFormat, type);
+ if (!format.valid())
+ {
+ return egl::EglBadParameter()
+ << "Invalid client buffer texture internal format: " << std::hex
+ << internalFormat;
+ }
+
+ sizedInternalFormat = format.info->sizedInternalFormat;
+ }
+ }
+
+ UINT textureArraySlice =
+ static_cast<UINT>(attribs.getAsInt(EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE, 0));
+ if (textureArraySlice >= desc.ArraySize)
+ {
+ return egl::EglBadParameter()
+ << "Invalid client buffer texture array slice: " << textureArraySlice;
+ }
+
+ if (width)
+ {
+ *width = imageWidth;
+ }
+ if (height)
+ {
+ *height = imageHeight;
+ }
+
+ if (samples)
+ {
+ // EGL samples 0 corresponds to D3D11 sample count 1.
+ *samples = sampleCount != 1 ? sampleCount : 0;
+ }
+
+ if (glFormat)
+ {
+ *glFormat = gl::Format(sizedInternalFormat);
+ }
+
+ if (angleFormat)
+ {
+ *angleFormat = textureAngleFormat;
+ }
+
+ if (arraySlice)
+ {
+ *arraySlice = textureArraySlice;
+ }
+
+ return egl::NoError();
+}
+
+egl::Error Renderer11::validateShareHandle(const egl::Config *config,
+ HANDLE shareHandle,
+ const egl::AttributeMap &attribs) const
+{
+ if (shareHandle == nullptr)
+ {
+ return egl::EglBadParameter() << "NULL share handle.";
+ }
+
+ ID3D11Resource *tempResource11 = nullptr;
+ HRESULT result = mDevice->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource),
+ (void **)&tempResource11);
+ if (FAILED(result) && mDevice1)
+ {
+ result = mDevice1->OpenSharedResource1(shareHandle, __uuidof(ID3D11Resource),
+ (void **)&tempResource11);
+ }
+
+ if (FAILED(result))
+ {
+ return egl::EglBadParameter() << "Failed to open share handle, " << gl::FmtHR(result);
+ }
+
+ ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11);
+ SafeRelease(tempResource11);
+
+ if (texture2D == nullptr)
+ {
+ return egl::EglBadParameter()
+ << "Failed to query ID3D11Texture2D object from share handle.";
+ }
+
+ D3D11_TEXTURE2D_DESC desc = {};
+ texture2D->GetDesc(&desc);
+ SafeRelease(texture2D);
+
+ EGLint width = attribs.getAsInt(EGL_WIDTH, 0);
+ EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
+ ASSERT(width != 0 && height != 0);
+
+ const d3d11::Format &backbufferFormatInfo =
+ d3d11::Format::Get(config->renderTargetFormat, getRenderer11DeviceCaps());
+
+ if (desc.Width != static_cast<UINT>(width) || desc.Height != static_cast<UINT>(height) ||
+ desc.Format != backbufferFormatInfo.texFormat || desc.MipLevels != 1 || desc.ArraySize != 1)
+ {
+ return egl::EglBadParameter() << "Invalid texture parameters in share handle texture.";
+ }
+
+ return egl::NoError();
+}
+
+SwapChainD3D *Renderer11::createSwapChain(NativeWindowD3D *nativeWindow,
+ HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation,
+ EGLint samples)
+{
+ return new SwapChain11(this, GetAs<NativeWindow11>(nativeWindow), shareHandle, d3dTexture,
+ backBufferFormat, depthBufferFormat, orientation, samples);
+}
+
+void *Renderer11::getD3DDevice()
+{
+ return mDevice;
+}
+
+angle::Result Renderer11::drawWithGeometryShaderAndTransformFeedback(Context11 *context11,
+ gl::PrimitiveMode mode,
+ UINT instanceCount,
+ UINT vertexCount)
+{
+ const gl::State &glState = context11->getState();
+ ProgramD3D *programD3D = mStateManager.getProgramD3D();
+
+ // Since we use a geometry if-and-only-if we rewrite vertex streams, transform feedback
+ // won't get the correct output. To work around this, draw with *only* the stream out
+ // first (no pixel shader) to feed the stream out buffers and then draw again with the
+ // geometry shader + pixel shader to rasterize the primitives.
+ mStateManager.setPixelShader(nullptr);
+
+ if (instanceCount > 0)
+ {
+ mDeviceContext->DrawInstanced(vertexCount, instanceCount, 0, 0);
+ }
+ else
+ {
+ mDeviceContext->Draw(vertexCount, 0);
+ }
+
+ rx::ShaderExecutableD3D *pixelExe = nullptr;
+ ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(context11, &pixelExe, nullptr));
+
+ // Skip the draw call if rasterizer discard is enabled (or no fragment shader).
+ if (!pixelExe || glState.getRasterizerState().rasterizerDiscard)
+ {
+ return angle::Result::Continue;
+ }
+
+ mStateManager.setPixelShader(&GetAs<ShaderExecutable11>(pixelExe)->getPixelShader());
+
+ // Retrieve the geometry shader.
+ rx::ShaderExecutableD3D *geometryExe = nullptr;
+ ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context11, glState, mode,
+ &geometryExe, nullptr));
+
+ mStateManager.setGeometryShader(&GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader());
+
+ if (instanceCount > 0)
+ {
+ mDeviceContext->DrawInstanced(vertexCount, instanceCount, 0, 0);
+ }
+ else
+ {
+ mDeviceContext->Draw(vertexCount, 0);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::drawArrays(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint firstVertex,
+ GLsizei vertexCount,
+ GLsizei instanceCount,
+ GLuint baseInstance,
+ bool isInstancedDraw)
+{
+ if (mStateManager.getCullEverything())
+ {
+ return angle::Result::Continue;
+ }
+
+ ANGLE_TRY(markRawBufferUsage(context));
+
+ ProgramD3D *programD3D = mStateManager.getProgramD3D();
+ GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(programD3D, instanceCount);
+
+ // Note: vertex indexes can be arbitrarily large.
+ UINT clampedVertexCount = gl::GetClampedVertexCount<UINT>(vertexCount);
+
+ const auto &glState = context->getState();
+ if (glState.getCurrentTransformFeedback() && glState.isTransformFeedbackActiveUnpaused())
+ {
+ ANGLE_TRY(markTransformFeedbackUsage(context));
+
+ if (programD3D->usesGeometryShader(glState, mode))
+ {
+ return drawWithGeometryShaderAndTransformFeedback(
+ GetImplAs<Context11>(context), mode, adjustedInstanceCount, clampedVertexCount);
+ }
+ }
+
+ switch (mode)
+ {
+ case gl::PrimitiveMode::LineLoop:
+ return drawLineLoop(context, clampedVertexCount, gl::DrawElementsType::InvalidEnum,
+ nullptr, 0, adjustedInstanceCount);
+ case gl::PrimitiveMode::TriangleFan:
+ return drawTriangleFan(context, clampedVertexCount, gl::DrawElementsType::InvalidEnum,
+ nullptr, 0, adjustedInstanceCount);
+ case gl::PrimitiveMode::Points:
+ if (getFeatures().useInstancedPointSpriteEmulation.enabled)
+ {
+ // This code should not be reachable by multi-view programs.
+ ASSERT(programD3D->getState().usesMultiview() == false);
+
+ // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
+ // Emulating instanced point sprites for FL9_3 requires the topology to be
+ // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
+ if (adjustedInstanceCount == 0)
+ {
+ mDeviceContext->DrawIndexedInstanced(6, clampedVertexCount, 0, 0, baseInstance);
+ return angle::Result::Continue;
+ }
+
+ // If pointsprite emulation is used with glDrawArraysInstanced then we need to take
+ // a less efficent code path. Instanced rendering of emulated pointsprites requires
+ // a loop to draw each batch of points. An offset into the instanced data buffer is
+ // calculated and applied on each iteration to ensure all instances are rendered
+ // correctly. Each instance being rendered requires the inputlayout cache to reapply
+ // buffers and offsets.
+ for (GLsizei i = 0; i < instanceCount; i++)
+ {
+ ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation(
+ context, firstVertex, i));
+ mDeviceContext->DrawIndexedInstanced(6, clampedVertexCount, 0, 0, baseInstance);
+ }
+
+ // This required by updateVertexOffsets... above but is outside of the loop for
+ // speed.
+ mStateManager.invalidateVertexBuffer();
+ return angle::Result::Continue;
+ }
+ break;
+ default:
+ break;
+ }
+
+ // "Normal" draw case.
+ if (!isInstancedDraw && adjustedInstanceCount == 0)
+ {
+ mDeviceContext->Draw(clampedVertexCount, 0);
+ }
+ else
+ {
+ mDeviceContext->DrawInstanced(clampedVertexCount, adjustedInstanceCount, 0, baseInstance);
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::drawElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint startVertex,
+ GLsizei indexCount,
+ gl::DrawElementsType indexType,
+ const void *indices,
+ GLsizei instanceCount,
+ GLint baseVertex,
+ GLuint baseInstance,
+ bool isInstancedDraw)
+{
+ if (mStateManager.getCullEverything())
+ {
+ return angle::Result::Continue;
+ }
+
+ ANGLE_TRY(markRawBufferUsage(context));
+
+ // Transform feedback is not allowed for DrawElements, this error should have been caught at the
+ // API validation layer.
+ const gl::State &glState = context->getState();
+ ASSERT(!glState.isTransformFeedbackActiveUnpaused());
+
+ // If this draw call is coming from an indirect call, offset by the indirect call's base vertex.
+ GLint baseVertexAdjusted = baseVertex - startVertex;
+
+ const ProgramD3D *programD3D = mStateManager.getProgramD3D();
+ GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(programD3D, instanceCount);
+
+ if (mode == gl::PrimitiveMode::LineLoop)
+ {
+ return drawLineLoop(context, indexCount, indexType, indices, baseVertexAdjusted,
+ adjustedInstanceCount);
+ }
+
+ if (mode == gl::PrimitiveMode::TriangleFan)
+ {
+ return drawTriangleFan(context, indexCount, indexType, indices, baseVertexAdjusted,
+ adjustedInstanceCount);
+ }
+
+ if (mode != gl::PrimitiveMode::Points || !programD3D->usesInstancedPointSpriteEmulation())
+ {
+ if (!isInstancedDraw && adjustedInstanceCount == 0)
+ {
+ mDeviceContext->DrawIndexed(indexCount, 0, baseVertexAdjusted);
+ }
+ else
+ {
+ mDeviceContext->DrawIndexedInstanced(indexCount, adjustedInstanceCount, 0,
+ baseVertexAdjusted, baseInstance);
+ }
+ return angle::Result::Continue;
+ }
+
+ // This code should not be reachable by multi-view programs.
+ ASSERT(programD3D->getState().usesMultiview() == false);
+
+ // If the shader is writing to gl_PointSize, then pointsprites are being rendered.
+ // Emulating instanced point sprites for FL9_3 requires the topology to be
+ // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead.
+ //
+ // The count parameter passed to drawElements represents the total number of instances to be
+ // rendered. Each instance is referenced by the bound index buffer from the the caller.
+ //
+ // Indexed pointsprite emulation replicates data for duplicate entries found in the index
+ // buffer. This is not an efficent rendering mechanism and is only used on downlevel renderers
+ // that do not support geometry shaders.
+ if (instanceCount == 0)
+ {
+ mDeviceContext->DrawIndexedInstanced(6, indexCount, 0, baseVertexAdjusted, baseInstance);
+ return angle::Result::Continue;
+ }
+
+ // If pointsprite emulation is used with glDrawElementsInstanced then we need to take a less
+ // efficent code path. Instanced rendering of emulated pointsprites requires a loop to draw each
+ // batch of points. An offset into the instanced data buffer is calculated and applied on each
+ // iteration to ensure all instances are rendered correctly.
+ gl::IndexRange indexRange;
+ ANGLE_TRY(glState.getVertexArray()->getIndexRange(context, indexType, indexCount, indices,
+ &indexRange));
+
+ UINT clampedVertexCount = gl::clampCast<UINT>(indexRange.vertexCount());
+
+ // Each instance being rendered requires the inputlayout cache to reapply buffers and offsets.
+ for (GLsizei i = 0; i < instanceCount; i++)
+ {
+ ANGLE_TRY(
+ mStateManager.updateVertexOffsetsForPointSpritesEmulation(context, startVertex, i));
+ mDeviceContext->DrawIndexedInstanced(6, clampedVertexCount, 0, baseVertexAdjusted,
+ baseInstance);
+ }
+ mStateManager.invalidateVertexBuffer();
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::drawArraysIndirect(const gl::Context *context, const void *indirect)
+{
+ if (mStateManager.getCullEverything())
+ {
+ return angle::Result::Continue;
+ }
+
+ ANGLE_TRY(markRawBufferUsage(context));
+
+ const gl::State &glState = context->getState();
+ ASSERT(!glState.isTransformFeedbackActiveUnpaused());
+
+ gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
+ ASSERT(drawIndirectBuffer);
+ Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
+
+ uintptr_t offset = reinterpret_cast<uintptr_t>(indirect);
+
+ ID3D11Buffer *buffer = nullptr;
+ ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer));
+ mDeviceContext->DrawInstancedIndirect(buffer, static_cast<unsigned int>(offset));
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::drawElementsIndirect(const gl::Context *context, const void *indirect)
+{
+ if (mStateManager.getCullEverything())
+ {
+ return angle::Result::Continue;
+ }
+
+ ANGLE_TRY(markRawBufferUsage(context));
+
+ const gl::State &glState = context->getState();
+ ASSERT(!glState.isTransformFeedbackActiveUnpaused());
+
+ gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
+ ASSERT(drawIndirectBuffer);
+ Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
+ uintptr_t offset = reinterpret_cast<uintptr_t>(indirect);
+
+ ID3D11Buffer *buffer = nullptr;
+ ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer));
+ mDeviceContext->DrawIndexedInstancedIndirect(buffer, static_cast<unsigned int>(offset));
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::drawLineLoop(const gl::Context *context,
+ GLuint count,
+ gl::DrawElementsType type,
+ const void *indexPointer,
+ int baseVertex,
+ int instances)
+{
+ const gl::State &glState = context->getState();
+ gl::VertexArray *vao = glState.getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
+
+ const void *indices = indexPointer;
+
+ // Get the raw indices for an indexed draw
+ if (type != gl::DrawElementsType::InvalidEnum && elementArrayBuffer)
+ {
+ BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+
+ const uint8_t *bufferData = nullptr;
+ ANGLE_TRY(storage->getData(context, &bufferData));
+
+ indices = bufferData + offset;
+ }
+
+ if (!mLineLoopIB)
+ {
+ mLineLoopIB = new StreamingIndexBufferInterface(this);
+ ANGLE_TRY(mLineLoopIB->reserveBufferSpace(context, INITIAL_INDEX_BUFFER_SIZE,
+ gl::DrawElementsType::UnsignedInt));
+ }
+
+ // Checked by Renderer11::applyPrimitiveType
+ bool indexCheck = static_cast<unsigned int>(count) + 1 >
+ (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int));
+ ANGLE_CHECK(GetImplAs<Context11>(context), !indexCheck,
+ "Failed to create a 32-bit looping index buffer for "
+ "GL_LINE_LOOP, too many indices required.",
+ GL_OUT_OF_MEMORY);
+
+ GetLineLoopIndices(indices, type, static_cast<GLuint>(count),
+ glState.isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer);
+
+ unsigned int spaceNeeded =
+ static_cast<unsigned int>(sizeof(GLuint) * mScratchIndexDataBuffer.size());
+ ANGLE_TRY(
+ mLineLoopIB->reserveBufferSpace(context, spaceNeeded, gl::DrawElementsType::UnsignedInt));
+
+ void *mappedMemory = nullptr;
+ unsigned int offset;
+ ANGLE_TRY(mLineLoopIB->mapBuffer(context, spaceNeeded, &mappedMemory, &offset));
+
+ // Copy over the converted index data.
+ memcpy(mappedMemory, &mScratchIndexDataBuffer[0],
+ sizeof(GLuint) * mScratchIndexDataBuffer.size());
+
+ ANGLE_TRY(mLineLoopIB->unmapBuffer(context));
+
+ IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mLineLoopIB->getIndexBuffer());
+ const d3d11::Buffer &d3dIndexBuffer = indexBuffer->getBuffer();
+ DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
+
+ mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, offset);
+
+ UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
+
+ if (instances > 0)
+ {
+ mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0);
+ }
+ else
+ {
+ mDeviceContext->DrawIndexed(indexCount, 0, baseVertex);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::drawTriangleFan(const gl::Context *context,
+ GLuint count,
+ gl::DrawElementsType type,
+ const void *indices,
+ int baseVertex,
+ int instances)
+{
+ const gl::State &glState = context->getState();
+ gl::VertexArray *vao = glState.getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
+
+ const void *indexPointer = indices;
+
+ // Get the raw indices for an indexed draw
+ if (type != gl::DrawElementsType::InvalidEnum && elementArrayBuffer)
+ {
+ BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+
+ const uint8_t *bufferData = nullptr;
+ ANGLE_TRY(storage->getData(context, &bufferData));
+
+ indexPointer = bufferData + offset;
+ }
+
+ if (!mTriangleFanIB)
+ {
+ mTriangleFanIB = new StreamingIndexBufferInterface(this);
+ ANGLE_TRY(mTriangleFanIB->reserveBufferSpace(context, INITIAL_INDEX_BUFFER_SIZE,
+ gl::DrawElementsType::UnsignedInt));
+ }
+
+ // Checked by Renderer11::applyPrimitiveType
+ ASSERT(count >= 3);
+
+ const GLuint numTris = count - 2;
+
+ bool indexCheck =
+ (numTris > std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3));
+ ANGLE_CHECK(GetImplAs<Context11>(context), !indexCheck,
+ "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, "
+ "too many indices required.",
+ GL_OUT_OF_MEMORY);
+
+ GetTriFanIndices(indexPointer, type, count, glState.isPrimitiveRestartEnabled(),
+ &mScratchIndexDataBuffer);
+
+ const unsigned int spaceNeeded =
+ static_cast<unsigned int>(mScratchIndexDataBuffer.size() * sizeof(unsigned int));
+ ANGLE_TRY(mTriangleFanIB->reserveBufferSpace(context, spaceNeeded,
+ gl::DrawElementsType::UnsignedInt));
+
+ void *mappedMemory = nullptr;
+ unsigned int offset;
+ ANGLE_TRY(mTriangleFanIB->mapBuffer(context, spaceNeeded, &mappedMemory, &offset));
+
+ memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded);
+
+ ANGLE_TRY(mTriangleFanIB->unmapBuffer(context));
+
+ IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(mTriangleFanIB->getIndexBuffer());
+ const d3d11::Buffer &d3dIndexBuffer = indexBuffer->getBuffer();
+ DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat();
+
+ mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, offset);
+
+ UINT indexCount = static_cast<UINT>(mScratchIndexDataBuffer.size());
+
+ if (instances > 0)
+ {
+ mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0);
+ }
+ else
+ {
+ mDeviceContext->DrawIndexed(indexCount, 0, baseVertex);
+ }
+
+ return angle::Result::Continue;
+}
+
+void Renderer11::releaseDeviceResources()
+{
+ mStateManager.deinitialize();
+ mStateCache.clear();
+
+ SafeDelete(mLineLoopIB);
+ SafeDelete(mTriangleFanIB);
+ SafeDelete(mBlit);
+ SafeDelete(mClear);
+ SafeDelete(mTrim);
+ SafeDelete(mPixelTransfer);
+
+ mSyncQuery.reset();
+
+ mCachedResolveTexture.reset();
+}
+
+// set notify to true to broadcast a message to all contexts of the device loss
+bool Renderer11::testDeviceLost()
+{
+ if (!mDevice)
+ {
+ return true;
+ }
+
+ // GetRemovedReason is used to test if the device is removed
+ HRESULT result = mDevice->GetDeviceRemovedReason();
+ bool isLost = FAILED(result);
+
+ if (isLost)
+ {
+ ERR() << "The D3D11 device was removed, " << gl::FmtHR(result);
+ }
+
+ return isLost;
+}
+
+bool Renderer11::testDeviceResettable()
+{
+ // determine if the device is resettable by creating a mock device
+ PFN_D3D11_CREATE_DEVICE D3D11CreateDevice =
+ (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
+
+ if (D3D11CreateDevice == nullptr)
+ {
+ return false;
+ }
+
+ ID3D11Device *mockDevice;
+ D3D_FEATURE_LEVEL mockFeatureLevel;
+ ID3D11DeviceContext *mockContext;
+ UINT flags = (mCreateDebugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0);
+
+ ASSERT(mRequestedDriverType != D3D_DRIVER_TYPE_UNKNOWN);
+ HRESULT result = D3D11CreateDevice(
+ nullptr, mRequestedDriverType, nullptr, flags, mAvailableFeatureLevels.data(),
+ static_cast<unsigned int>(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &mockDevice,
+ &mockFeatureLevel, &mockContext);
+
+ if (!mDevice || FAILED(result))
+ {
+ return false;
+ }
+
+ SafeRelease(mockContext);
+ SafeRelease(mockDevice);
+
+ return true;
+}
+
+void Renderer11::release()
+{
+ mScratchMemoryBuffer.clear();
+
+ mAnnotatorContext.release();
+ gl::UninitializeDebugAnnotations();
+
+ releaseDeviceResources();
+
+ SafeRelease(mDxgiFactory);
+ SafeRelease(mDxgiAdapter);
+
+ SafeRelease(mDeviceContext3);
+ SafeRelease(mDeviceContext1);
+
+ if (mDeviceContext)
+ {
+ mDeviceContext->ClearState();
+ mDeviceContext->Flush();
+ SafeRelease(mDeviceContext);
+ }
+
+ SafeRelease(mDevice);
+ SafeRelease(mDevice1);
+ SafeRelease(mDebug);
+
+ if (mD3d11Module)
+ {
+ FreeLibrary(mD3d11Module);
+ mD3d11Module = nullptr;
+ }
+
+ if (mDxgiModule)
+ {
+ FreeLibrary(mDxgiModule);
+ mDxgiModule = nullptr;
+ }
+
+ if (mDCompModule)
+ {
+ FreeLibrary(mDCompModule);
+ mDCompModule = nullptr;
+ }
+
+ mDevice12.Reset();
+ mCommandQueue.Reset();
+
+ if (mD3d12Module)
+ {
+ FreeLibrary(mD3d12Module);
+ mD3d12Module = nullptr;
+ }
+
+ mCompiler.release();
+
+ mSupportsShareHandles.reset();
+}
+
+bool Renderer11::resetDevice()
+{
+ // recreate everything
+ release();
+ egl::Error result = initialize();
+
+ if (result.isError())
+ {
+ ERR() << "Could not reinitialize D3D11 device: " << result;
+ return false;
+ }
+
+ return true;
+}
+
+std::string Renderer11::getRendererDescription() const
+{
+ std::ostringstream rendererString;
+
+ rendererString << mDescription;
+ rendererString << " Direct3D11";
+
+ rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel()
+ << getShaderModelSuffix();
+ rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel()
+ << getShaderModelSuffix();
+
+ return rendererString.str();
+}
+
+DeviceIdentifier Renderer11::getAdapterIdentifier() const
+{
+ // Don't use the AdapterLuid here, since that doesn't persist across reboot.
+ DeviceIdentifier deviceIdentifier = {};
+ deviceIdentifier.VendorId = mAdapterDescription.VendorId;
+ deviceIdentifier.DeviceId = mAdapterDescription.DeviceId;
+ deviceIdentifier.SubSysId = mAdapterDescription.SubSysId;
+ deviceIdentifier.Revision = mAdapterDescription.Revision;
+ deviceIdentifier.FeatureLevel = static_cast<UINT>(mRenderer11DeviceCaps.featureLevel);
+
+ return deviceIdentifier;
+}
+
+unsigned int Renderer11::getReservedVertexUniformVectors() const
+{
+ // Driver uniforms are stored in a separate constant buffer
+ return d3d11_gl::GetReservedVertexUniformVectors(mRenderer11DeviceCaps.featureLevel);
+}
+
+unsigned int Renderer11::getReservedFragmentUniformVectors() const
+{
+ // Driver uniforms are stored in a separate constant buffer
+ return d3d11_gl::GetReservedFragmentUniformVectors(mRenderer11DeviceCaps.featureLevel);
+}
+
+gl::ShaderMap<unsigned int> Renderer11::getReservedShaderUniformBuffers() const
+{
+ gl::ShaderMap<unsigned int> shaderReservedUniformBuffers = {};
+
+ // we reserve one buffer for the application uniforms, and one for driver uniforms
+ shaderReservedUniformBuffers[gl::ShaderType::Vertex] = 2;
+ shaderReservedUniformBuffers[gl::ShaderType::Fragment] = 2;
+
+ return shaderReservedUniformBuffers;
+}
+
+d3d11::ANGLED3D11DeviceType Renderer11::getDeviceType() const
+{
+ if (mCreatedWithDeviceEXT)
+ {
+ return d3d11::GetDeviceType(mDevice);
+ }
+
+ if ((mRequestedDriverType == D3D_DRIVER_TYPE_SOFTWARE) ||
+ (mRequestedDriverType == D3D_DRIVER_TYPE_REFERENCE) ||
+ (mRequestedDriverType == D3D_DRIVER_TYPE_NULL))
+ {
+ return d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL;
+ }
+
+ if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP)
+ {
+ return d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP;
+ }
+
+ return d3d11::ANGLE_D3D11_DEVICE_TYPE_HARDWARE;
+}
+
+bool Renderer11::getShareHandleSupport() const
+{
+ if (mSupportsShareHandles.valid())
+ {
+ return mSupportsShareHandles.value();
+ }
+
+ // We only currently support share handles with BGRA surfaces, because
+ // chrome needs BGRA. Once chrome fixes this, we should always support them.
+ if (!getNativeExtensions().textureFormatBGRA8888EXT)
+ {
+ mSupportsShareHandles = false;
+ return false;
+ }
+
+ // PIX doesn't seem to support using share handles, so disable them.
+ if (mAnnotatorContext.getStatus())
+ {
+ mSupportsShareHandles = false;
+ return false;
+ }
+
+ // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on
+ // RGBA8 textures/swapchains.
+ if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ mSupportsShareHandles = false;
+ return false;
+ }
+
+ // Find out which type of D3D11 device the Renderer11 is using
+ d3d11::ANGLED3D11DeviceType deviceType = getDeviceType();
+ if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_UNKNOWN)
+ {
+ mSupportsShareHandles = false;
+ return false;
+ }
+
+ if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL)
+ {
+ // Software/Reference/NULL devices don't support share handles
+ mSupportsShareHandles = false;
+ return false;
+ }
+
+ if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP)
+ {
+#if !defined(ANGLE_ENABLE_WINDOWS_UWP)
+ if (!IsWindows8OrGreater())
+ {
+ // WARP on Windows 7 doesn't support shared handles
+ mSupportsShareHandles = false;
+ return false;
+ }
+#endif // !defined(ANGLE_ENABLE_WINDOWS_UWP)
+
+ // WARP on Windows 8.0+ supports shared handles when shared with another WARP device
+ // TODO: allow applications to query for HARDWARE or WARP-specific share handles,
+ // to prevent them trying to use a WARP share handle with an a HW device (or
+ // vice-versa)
+ // e.g. by creating EGL_D3D11_[HARDWARE/WARP]_DEVICE_SHARE_HANDLE_ANGLE
+ mSupportsShareHandles = true;
+ return true;
+ }
+
+ ASSERT(mCreatedWithDeviceEXT || mRequestedDriverType == D3D_DRIVER_TYPE_HARDWARE);
+ mSupportsShareHandles = true;
+ return true;
+}
+
+int Renderer11::getMajorShaderModel() const
+{
+ switch (mRenderer11DeviceCaps.featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_SHADER_MAJOR_VERSION; // 5
+ case D3D_FEATURE_LEVEL_10_1:
+ return D3D10_1_SHADER_MAJOR_VERSION; // 4
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_SHADER_MAJOR_VERSION; // 4
+ case D3D_FEATURE_LEVEL_9_3:
+ return D3D10_SHADER_MAJOR_VERSION; // 4
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int Renderer11::getMinorShaderModel() const
+{
+ switch (mRenderer11DeviceCaps.featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_SHADER_MINOR_VERSION; // 0
+ case D3D_FEATURE_LEVEL_10_1:
+ return D3D10_1_SHADER_MINOR_VERSION; // 1
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_SHADER_MINOR_VERSION; // 0
+ case D3D_FEATURE_LEVEL_9_3:
+ return D3D10_SHADER_MINOR_VERSION; // 0
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+std::string Renderer11::getShaderModelSuffix() const
+{
+ switch (mRenderer11DeviceCaps.featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return "";
+ case D3D_FEATURE_LEVEL_10_1:
+ return "";
+ case D3D_FEATURE_LEVEL_10_0:
+ return "";
+ case D3D_FEATURE_LEVEL_9_3:
+ return "_level_9_3";
+ default:
+ UNREACHABLE();
+ return "";
+ }
+}
+
+angle::Result Renderer11::copyImageInternal(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ RenderTargetD3D *destRenderTarget)
+{
+ const gl::FramebufferAttachment *colorAttachment = framebuffer->getReadColorAttachment();
+ ASSERT(colorAttachment);
+
+ RenderTarget11 *sourceRenderTarget = nullptr;
+ ANGLE_TRY(colorAttachment->getRenderTarget(context, 0, &sourceRenderTarget));
+ ASSERT(sourceRenderTarget);
+
+ const d3d11::RenderTargetView &dest =
+ GetAs<RenderTarget11>(destRenderTarget)->getRenderTargetView();
+ ASSERT(dest.valid());
+
+ gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1);
+ gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1);
+
+ const bool invertSource = UsePresentPathFast(this, colorAttachment);
+ if (invertSource)
+ {
+ sourceArea.y = sourceSize.height - sourceRect.y;
+ sourceArea.height = -sourceArea.height;
+ }
+
+ gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
+ gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
+
+ // Use nearest filtering because source and destination are the same size for the direct copy.
+ // Convert to the unsized format before calling copyTexture.
+ GLenum sourceFormat = colorAttachment->getFormat().info->format;
+ if (sourceRenderTarget->getTexture().is2D() && sourceRenderTarget->isMultisampled())
+ {
+ TextureHelper11 tex;
+ ANGLE_TRY(resolveMultisampledTexture(context, sourceRenderTarget,
+ colorAttachment->getDepthSize() > 0,
+ colorAttachment->getStencilSize() > 0, &tex));
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
+ viewDesc.Format = sourceRenderTarget->getFormatSet().srvFormat;
+ viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ viewDesc.Texture2D.MipLevels = 1;
+ viewDesc.Texture2D.MostDetailedMip = 0;
+
+ d3d11::SharedSRV readSRV;
+ ANGLE_TRY(allocateResource(GetImplAs<Context11>(context), viewDesc, tex.get(), &readSRV));
+ ASSERT(readSRV.valid());
+
+ ANGLE_TRY(mBlit->copyTexture(context, readSRV, sourceArea, sourceSize, sourceFormat, dest,
+ destArea, destSize, nullptr, gl::GetUnsizedFormat(destFormat),
+ GL_NONE, GL_NEAREST, false, false, false));
+
+ return angle::Result::Continue;
+ }
+
+ ASSERT(!sourceRenderTarget->isMultisampled());
+
+ const d3d11::SharedSRV *source;
+ ANGLE_TRY(sourceRenderTarget->getBlitShaderResourceView(context, &source));
+ ASSERT(source->valid());
+
+ ANGLE_TRY(mBlit->copyTexture(context, *source, sourceArea, sourceSize, sourceFormat, dest,
+ destArea, destSize, nullptr, gl::GetUnsizedFormat(destFormat),
+ GL_NONE, GL_NEAREST, false, false, false));
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::copyImage2D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level)
+{
+ TextureStorage11_2D *storage11 = GetAs<TextureStorage11_2D>(storage);
+ ASSERT(storage11);
+
+ gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+ RenderTargetD3D *destRenderTarget = nullptr;
+ ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(),
+ &destRenderTarget));
+ ASSERT(destRenderTarget);
+
+ ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
+ destRenderTarget));
+
+ storage11->markLevelDirty(level);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::copyImageCube(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ gl::TextureTarget target,
+ GLint level)
+{
+ TextureStorage11_Cube *storage11 = GetAs<TextureStorage11_Cube>(storage);
+ ASSERT(storage11);
+
+ gl::ImageIndex index = gl::ImageIndex::MakeCubeMapFace(target, level);
+ RenderTargetD3D *destRenderTarget = nullptr;
+ ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(),
+ &destRenderTarget));
+ ASSERT(destRenderTarget);
+
+ ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
+ destRenderTarget));
+
+ storage11->markLevelDirty(level);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::copyImage3D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level)
+{
+ TextureStorage11_3D *storage11 = GetAs<TextureStorage11_3D>(storage);
+ ASSERT(storage11);
+
+ gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z);
+ RenderTargetD3D *destRenderTarget = nullptr;
+ ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(),
+ &destRenderTarget));
+ ASSERT(destRenderTarget);
+
+ ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
+ destRenderTarget));
+
+ storage11->markLevelDirty(level);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::copyImage2DArray(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level)
+{
+ TextureStorage11_2DArray *storage11 = GetAs<TextureStorage11_2DArray>(storage);
+ ASSERT(storage11);
+
+ gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z);
+ RenderTargetD3D *destRenderTarget = nullptr;
+ ANGLE_TRY(storage11->getRenderTarget(context, index, storage11->getRenderToTextureSamples(),
+ &destRenderTarget));
+ ASSERT(destRenderTarget);
+
+ ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset,
+ destRenderTarget));
+ storage11->markLevelDirty(level);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::copyTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ gl::TextureTarget srcTarget,
+ const gl::Box &sourceBox,
+ GLenum destFormat,
+ GLenum destType,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ gl::TextureTarget destTarget,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+ const gl::ImageDesc &sourceImageDesc = source->getTextureState().getImageDesc(
+ NonCubeTextureTypeToTarget(source->getType()), sourceLevel);
+
+ TextureStorage11 *destStorage11 = GetAs<TextureStorage11>(storage);
+ ASSERT(destStorage11);
+
+ // Check for fast path where a CopySubresourceRegion can be used.
+ if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !unpackFlipY &&
+ sourceImageDesc.format.info->sizedInternalFormat ==
+ destStorage11->getFormatSet().internalFormat)
+ {
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(destStorage11->getResource(context, &destResource));
+
+ if (srcTarget == gl::TextureTarget::_2D || srcTarget == gl::TextureTarget::_3D)
+ {
+ gl::ImageIndex sourceIndex = gl::ImageIndex::MakeFromTarget(srcTarget, sourceLevel, 1);
+ const TextureHelper11 *sourceResource = nullptr;
+ UINT sourceSubresource = 0;
+ ANGLE_TRY(GetTextureD3DResourceFromStorageOrImage(context, sourceD3D, sourceIndex,
+ &sourceResource, &sourceSubresource));
+
+ gl::ImageIndex destIndex = gl::ImageIndex::MakeFromTarget(destTarget, destLevel, 1);
+
+ UINT destSubresource = 0;
+ ANGLE_TRY(destStorage11->getSubresourceIndex(context, destIndex, &destSubresource));
+
+ D3D11_BOX d3dBox{static_cast<UINT>(sourceBox.x),
+ static_cast<UINT>(sourceBox.y),
+ static_cast<UINT>(sourceBox.z),
+ static_cast<UINT>(sourceBox.x + sourceBox.width),
+ static_cast<UINT>(sourceBox.y + sourceBox.height),
+ static_cast<UINT>(sourceBox.z + sourceBox.depth)};
+
+ mDeviceContext->CopySubresourceRegion(
+ destResource->get(), destSubresource, destOffset.x, destOffset.y, destOffset.z,
+ sourceResource->get(), sourceSubresource, &d3dBox);
+ }
+ else if (srcTarget == gl::TextureTarget::_2DArray)
+ {
+ D3D11_BOX d3dBox{static_cast<UINT>(sourceBox.x),
+ static_cast<UINT>(sourceBox.y),
+ 0,
+ static_cast<UINT>(sourceBox.x + sourceBox.width),
+ static_cast<UINT>(sourceBox.y + sourceBox.height),
+ 1u};
+
+ for (int i = 0; i < sourceBox.depth; i++)
+ {
+ gl::ImageIndex sourceIndex =
+ gl::ImageIndex::Make2DArray(sourceLevel, i + sourceBox.z);
+ const TextureHelper11 *sourceResource = nullptr;
+ UINT sourceSubresource = 0;
+ ANGLE_TRY(GetTextureD3DResourceFromStorageOrImage(
+ context, sourceD3D, sourceIndex, &sourceResource, &sourceSubresource));
+
+ gl::ImageIndex dIndex = gl::ImageIndex::Make2DArray(destLevel, i + destOffset.z);
+ UINT destSubresource = 0;
+ ANGLE_TRY(destStorage11->getSubresourceIndex(context, dIndex, &destSubresource));
+
+ mDeviceContext->CopySubresourceRegion(
+ destResource->get(), destSubresource, destOffset.x, destOffset.y, 0,
+ sourceResource->get(), sourceSubresource, &d3dBox);
+ }
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ TextureStorage *sourceStorage = nullptr;
+ ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage));
+
+ TextureStorage11 *sourceStorage11 = GetAs<TextureStorage11>(sourceStorage);
+ ASSERT(sourceStorage11);
+
+ const d3d11::SharedSRV *sourceSRV = nullptr;
+ ANGLE_TRY(sourceStorage11->getSRVLevels(context, sourceLevel, sourceLevel, &sourceSRV));
+
+ gl::ImageIndex destIndex;
+ if (destTarget == gl::TextureTarget::_2D || destTarget == gl::TextureTarget::_3D ||
+ gl::IsCubeMapFaceTarget(destTarget))
+ {
+ destIndex = gl::ImageIndex::MakeFromTarget(destTarget, destLevel, 1);
+ }
+ else if (destTarget == gl::TextureTarget::_2DArray)
+ {
+ destIndex = gl::ImageIndex::Make2DArrayRange(destLevel, 0, sourceImageDesc.size.depth);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ RenderTargetD3D *destRenderTargetD3D = nullptr;
+ ANGLE_TRY(destStorage11->getRenderTarget(
+ context, destIndex, destStorage11->getRenderToTextureSamples(), &destRenderTargetD3D));
+
+ RenderTarget11 *destRenderTarget11 = GetAs<RenderTarget11>(destRenderTargetD3D);
+
+ const d3d11::RenderTargetView &destRTV = destRenderTarget11->getRenderTargetView();
+ ASSERT(destRTV.valid());
+
+ gl::Box sourceArea(sourceBox.x, sourceBox.y, sourceBox.z, sourceBox.width, sourceBox.height,
+ sourceBox.depth);
+
+ if (unpackFlipY)
+ {
+ sourceArea.y += sourceArea.height;
+ sourceArea.height = -sourceArea.height;
+ }
+
+ gl::Box destArea(destOffset.x, destOffset.y, destOffset.z, sourceBox.width,
+ sourceBox.height, sourceBox.depth);
+
+ gl::Extents destSize(destRenderTarget11->getWidth(), destRenderTarget11->getHeight(),
+ sourceBox.depth);
+
+ // Use nearest filtering because source and destination are the same size for the direct
+ // copy
+ GLenum sourceFormat = source->getFormat(srcTarget, sourceLevel).info->format;
+ ANGLE_TRY(mBlit->copyTexture(context, *sourceSRV, sourceArea, sourceImageDesc.size,
+ sourceFormat, destRTV, destArea, destSize, nullptr, destFormat,
+ destType, GL_NEAREST, false, unpackPremultiplyAlpha,
+ unpackUnmultiplyAlpha));
+ }
+
+ destStorage11->markLevelDirty(destLevel);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ TextureStorage *storage,
+ GLint destLevel)
+{
+ TextureStorage11_2D *destStorage11 = GetAs<TextureStorage11_2D>(storage);
+ ASSERT(destStorage11);
+
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(destStorage11->getResource(context, &destResource));
+
+ gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
+ UINT destSubresource = 0;
+ ANGLE_TRY(destStorage11->getSubresourceIndex(context, destIndex, &destSubresource));
+
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+ ASSERT(sourceD3D);
+
+ TextureStorage *sourceStorage = nullptr;
+ ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage));
+
+ TextureStorage11_2D *sourceStorage11 = GetAs<TextureStorage11_2D>(sourceStorage);
+ ASSERT(sourceStorage11);
+
+ const TextureHelper11 *sourceResource = nullptr;
+ ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource));
+
+ gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
+ UINT sourceSubresource = 0;
+ ANGLE_TRY(sourceStorage11->getSubresourceIndex(context, sourceIndex, &sourceSubresource));
+
+ mDeviceContext->CopySubresourceRegion(destResource->get(), destSubresource, 0, 0, 0,
+ sourceResource->get(), sourceSubresource, nullptr);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::createRenderTarget(const gl::Context *context,
+ int width,
+ int height,
+ GLenum format,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ const d3d11::Format &formatInfo = d3d11::Format::Get(format, mRenderer11DeviceCaps);
+
+ const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format);
+ GLuint supportedSamples = textureCaps.getNearestSamples(samples);
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ if (width > 0 && height > 0)
+ {
+ // Create texture resource
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = width;
+ desc.Height = height;
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = formatInfo.texFormat;
+ desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
+ desc.SampleDesc.Quality = getSampleDescQuality(supportedSamples);
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ // If a rendertarget or depthstencil format exists for this texture format,
+ // we'll flag it to allow binding that way. Shader resource views are a little
+ // more complicated.
+ bool bindRTV = false, bindDSV = false, bindSRV = false;
+ bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
+ bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
+ bindSRV = (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN);
+
+ bool isMultisampledDepthStencil = bindDSV && desc.SampleDesc.Count > 1;
+ if (isMultisampledDepthStencil &&
+ !mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs)
+ {
+ bindSRV = false;
+ }
+
+ desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) |
+ (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) |
+ (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0);
+
+ // The format must be either an RTV or a DSV
+ ASSERT(bindRTV != bindDSV);
+
+ TextureHelper11 texture;
+ ANGLE_TRY(allocateTexture(context11, desc, formatInfo, &texture));
+ texture.setInternalName("createRenderTarget.Texture");
+
+ d3d11::SharedSRV srv;
+ d3d11::SharedSRV blitSRV;
+ if (bindSRV)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = formatInfo.srvFormat;
+ srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D
+ : D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ srvDesc.Texture2D.MostDetailedMip = 0;
+ srvDesc.Texture2D.MipLevels = 1;
+
+ ANGLE_TRY(allocateResource(context11, srvDesc, texture.get(), &srv));
+ srv.setInternalName("createRenderTarget.SRV");
+
+ if (formatInfo.blitSRVFormat != formatInfo.srvFormat)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC blitSRVDesc;
+ blitSRVDesc.Format = formatInfo.blitSRVFormat;
+ blitSRVDesc.ViewDimension = (supportedSamples == 0)
+ ? D3D11_SRV_DIMENSION_TEXTURE2D
+ : D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ blitSRVDesc.Texture2D.MostDetailedMip = 0;
+ blitSRVDesc.Texture2D.MipLevels = 1;
+
+ ANGLE_TRY(allocateResource(context11, blitSRVDesc, texture.get(), &blitSRV));
+ blitSRV.setInternalName("createRenderTarget.BlitSRV");
+ }
+ else
+ {
+ blitSRV = srv.makeCopy();
+ }
+ }
+
+ if (bindDSV)
+ {
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Format = formatInfo.dsvFormat;
+ dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D
+ : D3D11_DSV_DIMENSION_TEXTURE2DMS;
+ dsvDesc.Texture2D.MipSlice = 0;
+ dsvDesc.Flags = 0;
+
+ d3d11::DepthStencilView dsv;
+ ANGLE_TRY(allocateResource(context11, dsvDesc, texture.get(), &dsv));
+ dsv.setInternalName("createRenderTarget.DSV");
+
+ *outRT = new TextureRenderTarget11(std::move(dsv), texture, srv, format, formatInfo,
+ width, height, 1, supportedSamples);
+ }
+ else if (bindRTV)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = formatInfo.rtvFormat;
+ rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D
+ : D3D11_RTV_DIMENSION_TEXTURE2DMS;
+ rtvDesc.Texture2D.MipSlice = 0;
+
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(allocateResource(context11, rtvDesc, texture.get(), &rtv));
+ rtv.setInternalName("createRenderTarget.RTV");
+
+ if (formatInfo.dataInitializerFunction != nullptr)
+ {
+ const float clearValues[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ mDeviceContext->ClearRenderTargetView(rtv.get(), clearValues);
+ }
+
+ *outRT = new TextureRenderTarget11(std::move(rtv), texture, srv, blitSRV, format,
+ formatInfo, width, height, 1, supportedSamples);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ *outRT = new TextureRenderTarget11(d3d11::RenderTargetView(), TextureHelper11(),
+ d3d11::SharedSRV(), d3d11::SharedSRV(), format,
+ d3d11::Format::Get(GL_NONE, mRenderer11DeviceCaps),
+ width, height, 1, supportedSamples);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::createRenderTargetCopy(const gl::Context *context,
+ RenderTargetD3D *source,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(source != nullptr);
+
+ RenderTargetD3D *newRT = nullptr;
+ ANGLE_TRY(createRenderTarget(context, source->getWidth(), source->getHeight(),
+ source->getInternalFormat(), source->getSamples(), &newRT));
+
+ RenderTarget11 *source11 = GetAs<RenderTarget11>(source);
+ RenderTarget11 *dest11 = GetAs<RenderTarget11>(newRT);
+
+ mDeviceContext->CopySubresourceRegion(dest11->getTexture().get(), dest11->getSubresourceIndex(),
+ 0, 0, 0, source11->getTexture().get(),
+ source11->getSubresourceIndex(), nullptr);
+ *outRT = newRT;
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::loadExecutable(d3d::Context *context,
+ const uint8_t *function,
+ size_t length,
+ gl::ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ ShaderExecutableD3D **outExecutable)
+{
+ ShaderData shaderData(function, length);
+
+ switch (type)
+ {
+ case gl::ShaderType::Vertex:
+ {
+ d3d11::VertexShader vertexShader;
+ d3d11::GeometryShader streamOutShader;
+ ANGLE_TRY(allocateResource(context, shaderData, &vertexShader));
+
+ if (!streamOutVaryings.empty())
+ {
+ std::vector<D3D11_SO_DECLARATION_ENTRY> soDeclaration;
+ soDeclaration.reserve(streamOutVaryings.size());
+
+ for (const auto &streamOutVarying : streamOutVaryings)
+ {
+ D3D11_SO_DECLARATION_ENTRY entry = {};
+ entry.Stream = 0;
+ entry.SemanticName = streamOutVarying.semanticName.c_str();
+ entry.SemanticIndex = streamOutVarying.semanticIndex;
+ entry.StartComponent = 0;
+ entry.ComponentCount = static_cast<BYTE>(streamOutVarying.componentCount);
+ entry.OutputSlot = static_cast<BYTE>(
+ (separatedOutputBuffers ? streamOutVarying.outputSlot : 0));
+ soDeclaration.push_back(entry);
+ }
+
+ ANGLE_TRY(allocateResource(context, shaderData, &soDeclaration, &streamOutShader));
+ }
+
+ *outExecutable = new ShaderExecutable11(function, length, std::move(vertexShader),
+ std::move(streamOutShader));
+ }
+ break;
+ case gl::ShaderType::Fragment:
+ {
+ d3d11::PixelShader pixelShader;
+ ANGLE_TRY(allocateResource(context, shaderData, &pixelShader));
+ *outExecutable = new ShaderExecutable11(function, length, std::move(pixelShader));
+ }
+ break;
+ case gl::ShaderType::Geometry:
+ {
+ d3d11::GeometryShader geometryShader;
+ ANGLE_TRY(allocateResource(context, shaderData, &geometryShader));
+ *outExecutable = new ShaderExecutable11(function, length, std::move(geometryShader));
+ }
+ break;
+ case gl::ShaderType::Compute:
+ {
+ d3d11::ComputeShader computeShader;
+ ANGLE_TRY(allocateResource(context, shaderData, &computeShader));
+ *outExecutable = new ShaderExecutable11(function, length, std::move(computeShader));
+ }
+ break;
+ default:
+ ANGLE_HR_UNREACHABLE(context);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::compileToExecutable(d3d::Context *context,
+ gl::InfoLog &infoLog,
+ const std::string &shaderHLSL,
+ gl::ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ const CompilerWorkaroundsD3D &workarounds,
+ ShaderExecutableD3D **outExectuable)
+{
+ std::stringstream profileStream;
+
+ switch (type)
+ {
+ case gl::ShaderType::Vertex:
+ profileStream << "vs";
+ break;
+ case gl::ShaderType::Fragment:
+ profileStream << "ps";
+ break;
+ case gl::ShaderType::Geometry:
+ profileStream << "gs";
+ break;
+ case gl::ShaderType::Compute:
+ profileStream << "cs";
+ break;
+ default:
+ ANGLE_HR_UNREACHABLE(context);
+ }
+
+ profileStream << "_" << getMajorShaderModel() << "_" << getMinorShaderModel()
+ << getShaderModelSuffix();
+ std::string profile = profileStream.str();
+
+ UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2;
+
+#if defined(ANGLE_ENABLE_DEBUG_TRACE)
+# ifndef NDEBUG
+ flags = D3DCOMPILE_SKIP_OPTIMIZATION;
+# endif // NDEBUG
+ flags |= D3DCOMPILE_DEBUG;
+#endif // defined(ANGLE_ENABLE_DEBUG_TRACE)
+
+ if (workarounds.enableIEEEStrictness)
+ flags |= D3DCOMPILE_IEEE_STRICTNESS;
+
+ // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders
+ // when it would otherwise pass with alternative options.
+ // Try the default flags first and if compilation fails, try some alternatives.
+ std::vector<CompileConfig> configs;
+ configs.push_back(CompileConfig(flags, "default"));
+ configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation"));
+ configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization"));
+
+ if (getMajorShaderModel() == 4 && getShaderModelSuffix() != "")
+ {
+ // Some shaders might cause a "blob content mismatch between level9 and d3d10 shader".
+ // e.g. dEQP-GLES2.functional.shaders.struct.local.loop_nested_struct_array_*.
+ // Using the [unroll] directive works around this, as does this D3DCompile flag.
+ configs.push_back(
+ CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control"));
+ }
+
+ D3D_SHADER_MACRO loopMacros[] = {{"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0}};
+
+ // TODO(jmadill): Use ComPtr?
+ ID3DBlob *binary = nullptr;
+ std::string debugInfo;
+ ANGLE_TRY(mCompiler.compileToBinary(context, infoLog, shaderHLSL, profile, configs, loopMacros,
+ &binary, &debugInfo));
+
+ // It's possible that binary is NULL if the compiler failed in all configurations. Set the
+ // executable to NULL and return GL_NO_ERROR to signify that there was a link error but the
+ // internal state is still OK.
+ if (!binary)
+ {
+ *outExectuable = nullptr;
+ return angle::Result::Continue;
+ }
+
+ angle::Result error = loadExecutable(
+ context, static_cast<const uint8_t *>(binary->GetBufferPointer()), binary->GetBufferSize(),
+ type, streamOutVaryings, separatedOutputBuffers, outExectuable);
+
+ SafeRelease(binary);
+ if (error == angle::Result::Stop)
+ {
+ return error;
+ }
+
+ if (!debugInfo.empty())
+ {
+ (*outExectuable)->appendDebugInfo(debugInfo);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::ensureHLSLCompilerInitialized(d3d::Context *context)
+{
+ return mCompiler.ensureInitialized(context);
+}
+
+UniformStorageD3D *Renderer11::createUniformStorage(size_t storageSize)
+{
+ return new UniformStorage11(storageSize);
+}
+
+VertexBuffer *Renderer11::createVertexBuffer()
+{
+ return new VertexBuffer11(this);
+}
+
+IndexBuffer *Renderer11::createIndexBuffer()
+{
+ return new IndexBuffer11(this);
+}
+
+StreamProducerImpl *Renderer11::createStreamProducerD3DTexture(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs)
+{
+ return new StreamProducerD3DTexture(this);
+}
+
+bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
+{
+ ASSERT(getNativeExtensions().pixelBufferObjectNV);
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
+ const d3d11::Format &d3d11FormatInfo =
+ d3d11::Format::Get(internalFormat, mRenderer11DeviceCaps);
+
+ // sRGB formats do not work with D3D11 buffer SRVs
+ if (internalFormatInfo.colorEncoding == GL_SRGB)
+ {
+ return false;
+ }
+
+ // We cannot support direct copies to non-color-renderable formats
+ if (d3d11FormatInfo.rtvFormat == DXGI_FORMAT_UNKNOWN)
+ {
+ return false;
+ }
+
+ // We skip all 3-channel formats since sometimes format support is missing
+ if (internalFormatInfo.componentCount == 3)
+ {
+ return false;
+ }
+
+ // We don't support formats which we can't represent without conversion
+ if (d3d11FormatInfo.format().glInternalFormat != internalFormat)
+ {
+ return false;
+ }
+
+ // Buffer SRV creation for this format was not working on Windows 10.
+ if (d3d11FormatInfo.texFormat == DXGI_FORMAT_B5G5R5A1_UNORM)
+ {
+ return false;
+ }
+
+ // This format is not supported as a buffer SRV.
+ if (d3d11FormatInfo.texFormat == DXGI_FORMAT_A8_UNORM)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+angle::Result Renderer11::fastCopyBufferToTexture(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea)
+{
+ ASSERT(supportsFastCopyBufferToTexture(destinationFormat));
+ return mPixelTransfer->copyBufferToTexture(context, unpack, unpackBuffer, offset,
+ destRenderTarget, destinationFormat,
+ sourcePixelsType, destArea);
+}
+
+ImageD3D *Renderer11::createImage()
+{
+ return new Image11(this);
+}
+
+ExternalImageSiblingImpl *Renderer11::createExternalImageSibling(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs)
+{
+ switch (target)
+ {
+ case EGL_D3D11_TEXTURE_ANGLE:
+ return new ExternalImageSiblingImpl11(this, buffer, attribs);
+
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+
+angle::Result Renderer11::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src)
+{
+ Image11 *dest11 = GetAs<Image11>(dest);
+ Image11 *src11 = GetAs<Image11>(src);
+ return Image11::GenerateMipmap(context, dest11, src11, mRenderer11DeviceCaps);
+}
+
+angle::Result Renderer11::generateMipmapUsingD3D(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::TextureState &textureState)
+{
+ TextureStorage11 *storage11 = GetAs<TextureStorage11>(storage);
+
+ ASSERT(storage11->isRenderTarget());
+ ASSERT(storage11->supportsNativeMipmapFunction());
+
+ const d3d11::SharedSRV *srv = nullptr;
+ ANGLE_TRY(storage11->getSRVLevels(context, textureState.getEffectiveBaseLevel(),
+ textureState.getEffectiveMaxLevel(), &srv));
+
+ mDeviceContext->GenerateMips(srv->get());
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::copyImage(const gl::Context *context,
+ ImageD3D *dest,
+ ImageD3D *source,
+ const gl::Box &sourceBox,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+ Image11 *dest11 = GetAs<Image11>(dest);
+ Image11 *src11 = GetAs<Image11>(source);
+ return Image11::CopyImage(context, dest11, src11, sourceBox, destOffset, unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha, mRenderer11DeviceCaps);
+}
+
+TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain,
+ const std::string &label)
+{
+ SwapChain11 *swapChain11 = GetAs<SwapChain11>(swapChain);
+ return new TextureStorage11_2D(this, swapChain11, label);
+}
+
+TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage,
+ RenderTargetD3D *renderTargetD3D,
+ const std::string &label)
+{
+ return new TextureStorage11_EGLImage(this, eglImage, GetAs<RenderTarget11>(renderTargetD3D),
+ label);
+}
+
+TextureStorage *Renderer11::createTextureStorageExternal(
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc,
+ const std::string &label)
+{
+ return new TextureStorage11_External(this, stream, desc, label);
+}
+
+TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ const std::string &label,
+ bool hintLevelZeroOnly)
+{
+ return new TextureStorage11_2D(this, internalformat, bindFlags, width, height, levels, label,
+ hintLevelZeroOnly);
+}
+
+TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat,
+ BindFlags bindFlags,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly,
+ const std::string &label)
+{
+ return new TextureStorage11_Cube(this, internalformat, bindFlags, size, levels,
+ hintLevelZeroOnly, label);
+}
+
+TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ const std::string &label)
+{
+ return new TextureStorage11_3D(this, internalformat, bindFlags, width, height, depth, levels,
+ label);
+}
+
+TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ const std::string &label)
+{
+ return new TextureStorage11_2DArray(this, internalformat, bindFlags, width, height, depth,
+ levels, label);
+}
+
+TextureStorage *Renderer11::createTextureStorage2DMultisample(GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ int samples,
+ bool fixedSampleLocations,
+ const std::string &label)
+{
+ return new TextureStorage11_2DMultisample(this, internalformat, width, height, levels, samples,
+ fixedSampleLocations, label);
+}
+
+TextureStorage *Renderer11::createTextureStorageBuffer(
+ const gl::OffsetBindingPointer<gl::Buffer> &buffer,
+ GLenum internalFormat,
+ const std::string &label)
+{
+ return new TextureStorage11_Buffer(this, buffer, internalFormat, label);
+}
+
+TextureStorage *Renderer11::createTextureStorage2DMultisampleArray(GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ int samples,
+ bool fixedSampleLocations,
+ const std::string &label)
+{
+ return new TextureStorage11_2DMultisampleArray(this, internalformat, width, height, depth,
+ levels, samples, fixedSampleLocations, label);
+}
+
+angle::Result Renderer11::readFromAttachment(const gl::Context *context,
+ const gl::FramebufferAttachment &srcAttachment,
+ const gl::Rectangle &sourceArea,
+ GLenum format,
+ GLenum type,
+ GLuint outputPitch,
+ const gl::PixelPackState &pack,
+ uint8_t *pixelsOut)
+{
+ ASSERT(sourceArea.width >= 0);
+ ASSERT(sourceArea.height >= 0);
+
+ const bool invertTexture = UsePresentPathFast(this, &srcAttachment);
+
+ RenderTarget11 *rt11 = nullptr;
+ ANGLE_TRY(srcAttachment.getRenderTarget(context, 0, &rt11));
+ ASSERT(rt11->getTexture().valid());
+
+ const TextureHelper11 &textureHelper = rt11->getTexture();
+ unsigned int sourceSubResource = rt11->getSubresourceIndex();
+
+ const gl::Extents &texSize = textureHelper.getExtents();
+
+ gl::Rectangle actualArea = sourceArea;
+ bool reverseRowOrder = pack.reverseRowOrder;
+ if (invertTexture)
+ {
+ actualArea.y = texSize.height - actualArea.y - actualArea.height;
+ reverseRowOrder = !reverseRowOrder;
+ }
+
+ // Clamp read region to the defined texture boundaries, preventing out of bounds reads
+ // and reads of uninitialized data.
+ gl::Rectangle safeArea;
+ safeArea.x = gl::clamp(actualArea.x, 0, texSize.width);
+ safeArea.y = gl::clamp(actualArea.y, 0, texSize.height);
+ safeArea.width =
+ gl::clamp(actualArea.width + std::min(actualArea.x, 0), 0, texSize.width - safeArea.x);
+ safeArea.height =
+ gl::clamp(actualArea.height + std::min(actualArea.y, 0), 0, texSize.height - safeArea.y);
+
+ ASSERT(safeArea.x >= 0 && safeArea.y >= 0);
+ ASSERT(safeArea.x + safeArea.width <= texSize.width);
+ ASSERT(safeArea.y + safeArea.height <= texSize.height);
+
+ if (safeArea.width == 0 || safeArea.height == 0)
+ {
+ // no work to do
+ return angle::Result::Continue;
+ }
+
+ gl::Extents safeSize(safeArea.width, safeArea.height, 1);
+ TextureHelper11 stagingHelper;
+ ANGLE_TRY(createStagingTexture(context, textureHelper.getTextureType(),
+ textureHelper.getFormatSet(), safeSize, StagingAccess::READ,
+ &stagingHelper));
+ stagingHelper.setInternalName("readFromAttachment::stagingHelper");
+
+ TextureHelper11 resolvedTextureHelper;
+
+ // "srcTexture" usually points to the source texture.
+ // For 2D multisampled textures, it points to the multisampled resolve texture.
+ const TextureHelper11 *srcTexture = &textureHelper;
+
+ if (textureHelper.is2D() && textureHelper.getSampleCount() > 1)
+ {
+ D3D11_TEXTURE2D_DESC resolveDesc;
+ resolveDesc.Width = static_cast<UINT>(texSize.width);
+ resolveDesc.Height = static_cast<UINT>(texSize.height);
+ resolveDesc.MipLevels = 1;
+ resolveDesc.ArraySize = 1;
+ resolveDesc.Format = textureHelper.getFormat();
+ resolveDesc.SampleDesc.Count = 1;
+ resolveDesc.SampleDesc.Quality = 0;
+ resolveDesc.Usage = D3D11_USAGE_DEFAULT;
+ resolveDesc.BindFlags = 0;
+ resolveDesc.CPUAccessFlags = 0;
+ resolveDesc.MiscFlags = 0;
+
+ ANGLE_TRY(allocateTexture(GetImplAs<Context11>(context), resolveDesc,
+ textureHelper.getFormatSet(), &resolvedTextureHelper));
+ resolvedTextureHelper.setInternalName("readFromAttachment::resolvedTextureHelper");
+
+ mDeviceContext->ResolveSubresource(resolvedTextureHelper.get(), 0, textureHelper.get(),
+ sourceSubResource, textureHelper.getFormat());
+
+ sourceSubResource = 0;
+ srcTexture = &resolvedTextureHelper;
+ }
+
+ D3D11_BOX srcBox;
+ srcBox.left = static_cast<UINT>(safeArea.x);
+ srcBox.right = static_cast<UINT>(safeArea.x + safeArea.width);
+ srcBox.top = static_cast<UINT>(safeArea.y);
+ srcBox.bottom = static_cast<UINT>(safeArea.y + safeArea.height);
+
+ // Select the correct layer from a 3D attachment
+ srcBox.front = 0;
+ if (textureHelper.is3D())
+ {
+ srcBox.front = static_cast<UINT>(srcAttachment.layer());
+ }
+ srcBox.back = srcBox.front + 1;
+
+ mDeviceContext->CopySubresourceRegion(stagingHelper.get(), 0, 0, 0, 0, srcTexture->get(),
+ sourceSubResource, &srcBox);
+
+ const angle::Format &angleFormat = GetFormatFromFormatType(format, type);
+ gl::Buffer *packBuffer = context->getState().getTargetBuffer(gl::BufferBinding::PixelPack);
+
+ PackPixelsParams packParams(safeArea, angleFormat, outputPitch, reverseRowOrder, packBuffer, 0);
+ return packPixels(context, stagingHelper, packParams, pixelsOut);
+}
+
+angle::Result Renderer11::packPixels(const gl::Context *context,
+ const TextureHelper11 &textureHelper,
+ const PackPixelsParams &params,
+ uint8_t *pixelsOut)
+{
+ ID3D11Resource *readResource = textureHelper.get();
+
+ D3D11_MAPPED_SUBRESOURCE mapping;
+ ANGLE_TRY(mapResource(context, readResource, 0, D3D11_MAP_READ, 0, &mapping));
+
+ uint8_t *source = static_cast<uint8_t *>(mapping.pData);
+ int inputPitch = static_cast<int>(mapping.RowPitch);
+
+ const auto &formatInfo = textureHelper.getFormatSet();
+ ASSERT(formatInfo.format().glInternalFormat != GL_NONE);
+
+ PackPixels(params, formatInfo.format(), inputPitch, source, pixelsOut);
+
+ mDeviceContext->Unmap(readResource, 0);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::blitRenderbufferRect(const gl::Context *context,
+ const gl::Rectangle &readRectIn,
+ const gl::Rectangle &drawRectIn,
+ UINT readLayer,
+ UINT drawLayer,
+ RenderTargetD3D *readRenderTarget,
+ RenderTargetD3D *drawRenderTarget,
+ GLenum filter,
+ const gl::Rectangle *scissor,
+ bool colorBlit,
+ bool depthBlit,
+ bool stencilBlit)
+{
+ // Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
+ // it should never be the case that both color and depth/stencil need to be blitted at
+ // at the same time.
+ ASSERT(colorBlit != (depthBlit || stencilBlit));
+
+ RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget);
+ ASSERT(drawRenderTarget11);
+
+ const TextureHelper11 &drawTexture = drawRenderTarget11->getTexture();
+ unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex();
+
+ RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget);
+ ASSERT(readRenderTarget11);
+
+ const gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
+ const gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
+
+ // From the spec:
+ // "The actual region taken from the read framebuffer is limited to the intersection of the
+ // source buffers being transferred, which may include the color buffer selected by the read
+ // buffer, the depth buffer, and / or the stencil buffer depending on mask."
+ // This means negative x and y are out of bounds, and not to be read from. We handle this here
+ // by internally scaling the read and draw rectangles.
+
+ // Remove reversal from readRect to simplify further operations.
+ gl::Rectangle readRect = readRectIn;
+ gl::Rectangle drawRect = drawRectIn;
+ if (readRect.isReversedX())
+ {
+ readRect.x = readRect.x + readRect.width;
+ readRect.width = -readRect.width;
+ drawRect.x = drawRect.x + drawRect.width;
+ drawRect.width = -drawRect.width;
+ }
+ if (readRect.isReversedY())
+ {
+ readRect.y = readRect.y + readRect.height;
+ readRect.height = -readRect.height;
+ drawRect.y = drawRect.y + drawRect.height;
+ drawRect.height = -drawRect.height;
+ }
+
+ gl::Rectangle readBounds(0, 0, readSize.width, readSize.height);
+ gl::Rectangle inBoundsReadRect;
+ if (!gl::ClipRectangle(readRect, readBounds, &inBoundsReadRect))
+ {
+ return angle::Result::Continue;
+ }
+
+ {
+ // Calculate the drawRect that corresponds to inBoundsReadRect.
+ auto readToDrawX = [&drawRect, &readRect](int readOffset) {
+ double readToDrawScale =
+ static_cast<double>(drawRect.width) / static_cast<double>(readRect.width);
+ return static_cast<int>(
+ round(static_cast<double>(readOffset - readRect.x) * readToDrawScale) + drawRect.x);
+ };
+ auto readToDrawY = [&drawRect, &readRect](int readOffset) {
+ double readToDrawScale =
+ static_cast<double>(drawRect.height) / static_cast<double>(readRect.height);
+ return static_cast<int>(
+ round(static_cast<double>(readOffset - readRect.y) * readToDrawScale) + drawRect.y);
+ };
+
+ gl::Rectangle drawRectMatchingInBoundsReadRect;
+ drawRectMatchingInBoundsReadRect.x = readToDrawX(inBoundsReadRect.x);
+ drawRectMatchingInBoundsReadRect.y = readToDrawY(inBoundsReadRect.y);
+ drawRectMatchingInBoundsReadRect.width =
+ readToDrawX(inBoundsReadRect.x1()) - drawRectMatchingInBoundsReadRect.x;
+ drawRectMatchingInBoundsReadRect.height =
+ readToDrawY(inBoundsReadRect.y1()) - drawRectMatchingInBoundsReadRect.y;
+ drawRect = drawRectMatchingInBoundsReadRect;
+ readRect = inBoundsReadRect;
+ }
+
+ bool scissorNeeded = false;
+ if (scissor)
+ {
+ gl::Rectangle scissoredDrawRect;
+ if (!gl::ClipRectangle(drawRect, *scissor, &scissoredDrawRect))
+ {
+ return angle::Result::Continue;
+ }
+ scissorNeeded = scissoredDrawRect != drawRect;
+ }
+
+ const auto &destFormatInfo =
+ gl::GetSizedInternalFormatInfo(drawRenderTarget->getInternalFormat());
+ const auto &srcFormatInfo =
+ gl::GetSizedInternalFormatInfo(readRenderTarget->getInternalFormat());
+ const auto &formatSet = drawRenderTarget11->getFormatSet();
+ const auto &nativeFormat = formatSet.format();
+
+ // Some blits require masking off emulated texture channels. eg: from RGBA8 to RGB8, we
+ // emulate RGB8 with RGBA8, so we need to mask off the alpha channel when we copy.
+
+ gl::Color<bool> colorMask;
+ colorMask.red =
+ (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) && (nativeFormat.redBits > 0);
+ colorMask.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) &&
+ (nativeFormat.greenBits > 0);
+ colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) &&
+ (nativeFormat.blueBits > 0);
+ colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) &&
+ (nativeFormat.alphaBits > 0);
+
+ // We only currently support masking off the alpha channel.
+ bool colorMaskingNeeded = colorMask.alpha;
+ ASSERT(!colorMask.red && !colorMask.green && !colorMask.blue);
+
+ bool wholeBufferCopy = !scissorNeeded && !colorMaskingNeeded && readRect.x == 0 &&
+ readRect.width == readSize.width && readRect.y == 0 &&
+ readRect.height == readSize.height && drawRect.x == 0 &&
+ drawRect.width == drawSize.width && drawRect.y == 0 &&
+ drawRect.height == drawSize.height;
+
+ bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height;
+
+ ASSERT(!readRect.isReversedX() && !readRect.isReversedY());
+ bool reversalRequired = drawRect.isReversedX() || drawRect.isReversedY();
+
+ bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width ||
+ readRect.y < 0 || readRect.y + readRect.height > readSize.height ||
+ drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width ||
+ drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height;
+
+ bool partialDSBlit =
+ (nativeFormat.depthBits > 0 && depthBlit) != (nativeFormat.stencilBits > 0 && stencilBlit);
+
+ const bool canCopySubresource =
+ drawRenderTarget->getSamples() == readRenderTarget->getSamples() &&
+ readRenderTarget11->getFormatSet().formatID ==
+ drawRenderTarget11->getFormatSet().formatID &&
+ !stretchRequired && !outOfBounds && !reversalRequired && !partialDSBlit &&
+ !colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy);
+
+ TextureHelper11 readTexture;
+ unsigned int readSubresource = 0;
+ d3d11::SharedSRV readSRV;
+
+ if (readRenderTarget->isMultisampled())
+ {
+ ANGLE_TRY(resolveMultisampledTexture(context, readRenderTarget11, depthBlit, stencilBlit,
+ &readTexture));
+
+ if (!stencilBlit && !canCopySubresource)
+ {
+ const auto &readFormatSet = readTexture.getFormatSet();
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc;
+ viewDesc.Format = readFormatSet.srvFormat;
+ viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ viewDesc.Texture2D.MipLevels = 1;
+ viewDesc.Texture2D.MostDetailedMip = 0;
+
+ ANGLE_TRY(allocateResource(GetImplAs<Context11>(context), viewDesc, readTexture.get(),
+ &readSRV));
+ }
+ }
+ else
+ {
+ ASSERT(readRenderTarget11);
+ readTexture = readRenderTarget11->getTexture();
+ readSubresource = readRenderTarget11->getSubresourceIndex();
+ if (!canCopySubresource)
+ {
+ const d3d11::SharedSRV *blitSRV;
+ ANGLE_TRY(readRenderTarget11->getBlitShaderResourceView(context, &blitSRV));
+ readSRV = blitSRV->makeCopy();
+ if (!readSRV.valid())
+ {
+ ASSERT(depthBlit || stencilBlit);
+ const d3d11::SharedSRV *srv;
+ ANGLE_TRY(readRenderTarget11->getShaderResourceView(context, &srv));
+ readSRV = srv->makeCopy();
+ }
+ ASSERT(readSRV.valid());
+ }
+ }
+
+ if (canCopySubresource)
+ {
+ UINT dstX = drawRect.x;
+ UINT dstY = drawRect.y;
+ UINT dstZ = drawLayer;
+
+ D3D11_BOX readBox;
+ readBox.left = readRect.x;
+ readBox.right = readRect.x + readRect.width;
+ readBox.top = readRect.y;
+ readBox.bottom = readRect.y + readRect.height;
+ readBox.front = readLayer;
+ readBox.back = readLayer + 1;
+
+ if (scissorNeeded)
+ {
+ // drawRect is guaranteed to have positive width and height because stretchRequired is
+ // false.
+ ASSERT(drawRect.width >= 0 || drawRect.height >= 0);
+
+ if (drawRect.x < scissor->x)
+ {
+ dstX = scissor->x;
+ readBox.left += (scissor->x - drawRect.x);
+ }
+ if (drawRect.y < scissor->y)
+ {
+ dstY = scissor->y;
+ readBox.top += (scissor->y - drawRect.y);
+ }
+ if (drawRect.x + drawRect.width > scissor->x + scissor->width)
+ {
+ readBox.right -= ((drawRect.x + drawRect.width) - (scissor->x + scissor->width));
+ }
+ if (drawRect.y + drawRect.height > scissor->y + scissor->height)
+ {
+ readBox.bottom -= ((drawRect.y + drawRect.height) - (scissor->y + scissor->height));
+ }
+ }
+
+ // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox
+ // We also require complete framebuffer copies for depth-stencil blit.
+ D3D11_BOX *pSrcBox = wholeBufferCopy && readLayer == 0 ? nullptr : &readBox;
+
+ mDeviceContext->CopySubresourceRegion(drawTexture.get(), drawSubresource, dstX, dstY, dstZ,
+ readTexture.get(), readSubresource, pSrcBox);
+ }
+ else
+ {
+ gl::Box readArea(readRect.x, readRect.y, 0, readRect.width, readRect.height, 1);
+ gl::Box drawArea(drawRect.x, drawRect.y, 0, drawRect.width, drawRect.height, 1);
+
+ if (depthBlit && stencilBlit)
+ {
+ ANGLE_TRY(mBlit->copyDepthStencil(context, readTexture, readSubresource, readArea,
+ readSize, drawTexture, drawSubresource, drawArea,
+ drawSize, scissor));
+ }
+ else if (depthBlit)
+ {
+ const d3d11::DepthStencilView &drawDSV = drawRenderTarget11->getDepthStencilView();
+ ASSERT(readSRV.valid());
+ ANGLE_TRY(mBlit->copyDepth(context, readSRV, readArea, readSize, drawDSV, drawArea,
+ drawSize, scissor));
+ }
+ else if (stencilBlit)
+ {
+ ANGLE_TRY(mBlit->copyStencil(context, readTexture, readSubresource, readArea, readSize,
+ drawTexture, drawSubresource, drawArea, drawSize,
+ scissor));
+ }
+ else
+ {
+ const d3d11::RenderTargetView &drawRTV = drawRenderTarget11->getRenderTargetView();
+
+ // We don't currently support masking off any other channel than alpha
+ bool maskOffAlpha = colorMaskingNeeded && colorMask.alpha;
+ ASSERT(readSRV.valid());
+ ANGLE_TRY(mBlit->copyTexture(context, readSRV, readArea, readSize, srcFormatInfo.format,
+ drawRTV, drawArea, drawSize, scissor,
+ destFormatInfo.format, GL_NONE, filter, maskOffAlpha,
+ false, false));
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+bool Renderer11::isES3Capable() const
+{
+ return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps).major > 2);
+}
+
+RendererClass Renderer11::getRendererClass() const
+{
+ return RENDERER_D3D11;
+}
+
+void Renderer11::onSwap()
+{
+ // Send histogram updates every half hour
+ const double kHistogramUpdateInterval = 30 * 60;
+
+ auto *platform = ANGLEPlatformCurrent();
+ const double currentTime = platform->monotonicallyIncreasingTime(platform);
+ const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime;
+
+ if (timeSinceLastUpdate > kHistogramUpdateInterval)
+ {
+ updateHistograms();
+ mLastHistogramUpdateTime = currentTime;
+ }
+}
+
+void Renderer11::updateHistograms()
+{
+ // Update the buffer CPU memory histogram
+ {
+ size_t sizeSum = 0;
+ for (const Buffer11 *buffer : mAliveBuffers)
+ {
+ sizeSum += buffer->getTotalCPUBufferMemoryBytes();
+ }
+ const int kOneMegaByte = 1024 * 1024;
+ ANGLE_HISTOGRAM_MEMORY_MB("GPU.ANGLE.Buffer11CPUMemoryMB",
+ static_cast<int>(sizeSum) / kOneMegaByte);
+ }
+}
+
+void Renderer11::onBufferCreate(const Buffer11 *created)
+{
+ mAliveBuffers.insert(created);
+}
+
+void Renderer11::onBufferDelete(const Buffer11 *deleted)
+{
+ mAliveBuffers.erase(deleted);
+}
+
+angle::Result Renderer11::resolveMultisampledTexture(const gl::Context *context,
+ RenderTarget11 *renderTarget,
+ bool depth,
+ bool stencil,
+ TextureHelper11 *textureOut)
+{
+ if (depth && !stencil)
+ {
+ return mBlit->resolveDepth(context, renderTarget, textureOut);
+ }
+
+ if (stencil)
+ {
+ return mBlit->resolveStencil(context, renderTarget, depth, textureOut);
+ }
+
+ const auto &formatSet = renderTarget->getFormatSet();
+
+ ASSERT(renderTarget->isMultisampled());
+ const d3d11::SharedSRV *sourceSRV;
+ ANGLE_TRY(renderTarget->getShaderResourceView(context, &sourceSRV));
+ D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
+ sourceSRV->get()->GetDesc(&sourceSRVDesc);
+ ASSERT(sourceSRVDesc.ViewDimension == D3D_SRV_DIMENSION_TEXTURE2DMS ||
+ sourceSRVDesc.ViewDimension == D3D_SRV_DIMENSION_TEXTURE2DMSARRAY);
+
+ if (!mCachedResolveTexture.valid() ||
+ mCachedResolveTexture.getExtents().width != renderTarget->getWidth() ||
+ mCachedResolveTexture.getExtents().height != renderTarget->getHeight() ||
+ mCachedResolveTexture.getFormat() != formatSet.texFormat)
+ {
+ D3D11_TEXTURE2D_DESC resolveDesc;
+ resolveDesc.Width = renderTarget->getWidth();
+ resolveDesc.Height = renderTarget->getHeight();
+ resolveDesc.MipLevels = 1;
+ resolveDesc.ArraySize = 1;
+ resolveDesc.Format = formatSet.texFormat;
+ resolveDesc.SampleDesc.Count = 1;
+ resolveDesc.SampleDesc.Quality = 0;
+ resolveDesc.Usage = D3D11_USAGE_DEFAULT;
+ resolveDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ resolveDesc.CPUAccessFlags = 0;
+ resolveDesc.MiscFlags = 0;
+
+ ANGLE_TRY(allocateTexture(GetImplAs<Context11>(context), resolveDesc, formatSet,
+ &mCachedResolveTexture));
+ }
+
+ mDeviceContext->ResolveSubresource(mCachedResolveTexture.get(), 0,
+ renderTarget->getTexture().get(),
+ renderTarget->getSubresourceIndex(), formatSet.texFormat);
+ *textureOut = mCachedResolveTexture;
+ return angle::Result::Continue;
+}
+
+bool Renderer11::getLUID(LUID *adapterLuid) const
+{
+ adapterLuid->HighPart = 0;
+ adapterLuid->LowPart = 0;
+
+ if (!mDxgiAdapter)
+ {
+ return false;
+ }
+
+ DXGI_ADAPTER_DESC adapterDesc;
+ if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc)))
+ {
+ return false;
+ }
+
+ *adapterLuid = adapterDesc.AdapterLuid;
+ return true;
+}
+
+VertexConversionType Renderer11::getVertexConversionType(angle::FormatID vertexFormatID) const
+{
+ return d3d11::GetVertexFormatInfo(vertexFormatID, mRenderer11DeviceCaps.featureLevel)
+ .conversionType;
+}
+
+GLenum Renderer11::getVertexComponentType(angle::FormatID vertexFormatID) const
+{
+ const auto &format =
+ d3d11::GetVertexFormatInfo(vertexFormatID, mRenderer11DeviceCaps.featureLevel);
+ return d3d11::GetComponentType(format.nativeFormat);
+}
+
+angle::Result Renderer11::getVertexSpaceRequired(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance,
+ unsigned int *bytesRequiredOut) const
+{
+ if (!attrib.enabled)
+ {
+ *bytesRequiredOut = 16u;
+ return angle::Result::Continue;
+ }
+
+ unsigned int elementCount = 0;
+ const unsigned int divisor = binding.getDivisor();
+ if (instances == 0 || divisor == 0)
+ {
+ // This could be a clipped cast.
+ elementCount = gl::clampCast<unsigned int>(count);
+ }
+ else
+ {
+ // Round up to divisor, if possible
+ elementCount =
+ UnsignedCeilDivide(static_cast<unsigned int>(instances + baseInstance), divisor);
+ }
+
+ ASSERT(elementCount > 0);
+
+ const D3D_FEATURE_LEVEL featureLevel = mRenderer11DeviceCaps.featureLevel;
+ const d3d11::VertexFormat &vertexFormatInfo =
+ d3d11::GetVertexFormatInfo(attrib.format->id, featureLevel);
+ const d3d11::DXGIFormatSize &dxgiFormatInfo =
+ d3d11::GetDXGIFormatSizeInfo(vertexFormatInfo.nativeFormat);
+ unsigned int elementSize = dxgiFormatInfo.pixelBytes;
+ bool check = (elementSize > std::numeric_limits<unsigned int>::max() / elementCount);
+ ANGLE_CHECK(GetImplAs<Context11>(context), !check,
+ "New vertex buffer size would result in an overflow.", GL_OUT_OF_MEMORY);
+
+ *bytesRequiredOut = elementSize * elementCount;
+ return angle::Result::Continue;
+}
+
+void Renderer11::generateCaps(gl::Caps *outCaps,
+ gl::TextureCapsMap *outTextureCaps,
+ gl::Extensions *outExtensions,
+ gl::Limitations *outLimitations) const
+{
+ d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, getFeatures(),
+ mDescription, outCaps, outTextureCaps, outExtensions, outLimitations);
+}
+
+void Renderer11::initializeFeatures(angle::FeaturesD3D *features) const
+{
+ if (!mDisplay->getState().featuresAllDisabled)
+ {
+ d3d11::InitializeFeatures(mRenderer11DeviceCaps, mAdapterDescription, features);
+ }
+ ApplyFeatureOverrides(features, mDisplay->getState());
+}
+
+void Renderer11::initializeFrontendFeatures(angle::FrontendFeatures *features) const
+{
+ if (!mDisplay->getState().featuresAllDisabled)
+ {
+ d3d11::InitializeFrontendFeatures(mAdapterDescription, features);
+ }
+ ApplyFeatureOverrides(features, mDisplay->getState());
+}
+
+DeviceImpl *Renderer11::createEGLDevice()
+{
+ return new DeviceD3D(EGL_D3D11_DEVICE_ANGLE, mDevice);
+}
+
+ContextImpl *Renderer11::createContext(const gl::State &state, gl::ErrorSet *errorSet)
+{
+ return new Context11(state, errorSet, this);
+}
+
+FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+ return new Framebuffer11(state, this);
+}
+
+angle::Result Renderer11::getScratchMemoryBuffer(Context11 *context11,
+ size_t requestedSize,
+ angle::MemoryBuffer **bufferOut)
+{
+ ANGLE_CHECK_GL_ALLOC(context11, mScratchMemoryBuffer.get(requestedSize, bufferOut));
+ return angle::Result::Continue;
+}
+
+gl::Version Renderer11::getMaxSupportedESVersion() const
+{
+ return d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps);
+}
+
+gl::Version Renderer11::getMaxConformantESVersion() const
+{
+ // 3.1 support is in progress.
+ return std::min(getMaxSupportedESVersion(), gl::Version(3, 0));
+}
+
+DebugAnnotatorContext11 *Renderer11::getDebugAnnotatorContext()
+{
+ return &mAnnotatorContext;
+}
+
+angle::Result Renderer11::dispatchCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ)
+{
+ const gl::State &glState = context->getState();
+ const gl::Program *program = glState.getProgram();
+ if (program->getActiveShaderStorageBlockCount() > 0 ||
+ program->getActiveAtomicCounterBufferCount() > 0)
+ {
+ ANGLE_TRY(markRawBufferUsage(context));
+ }
+ ANGLE_TRY(markTypedBufferUsage(context));
+ ANGLE_TRY(mStateManager.updateStateForCompute(context, numGroupsX, numGroupsY, numGroupsZ));
+ mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ);
+
+ return angle::Result::Continue;
+}
+angle::Result Renderer11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
+{
+ const auto &glState = context->getState();
+ const gl::Program *program = glState.getProgram();
+ if (program->getActiveShaderStorageBlockCount() > 0 ||
+ program->getActiveAtomicCounterBufferCount() > 0)
+ {
+ ANGLE_TRY(markRawBufferUsage(context));
+ }
+
+ auto *dispatchIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DispatchIndirect);
+ ASSERT(dispatchIndirectBuffer);
+
+ Buffer11 *storage = GetImplAs<Buffer11>(dispatchIndirectBuffer);
+ const uint8_t *bufferData = nullptr;
+ // TODO(jie.a.chen@intel.com): num_groups_x,y,z have to be written into the driver constant
+ // buffer for the built-in variable gl_NumWorkGroups. There is an opportunity for optimization
+ // to use GPU->GPU copy instead.
+ // http://anglebug.com/2807
+ ANGLE_TRY(storage->getData(context, &bufferData));
+ const GLuint *groups = reinterpret_cast<const GLuint *>(bufferData + indirect);
+ ANGLE_TRY(mStateManager.updateStateForCompute(context, groups[0], groups[1], groups[2]));
+
+ ID3D11Buffer *buffer = nullptr;
+ ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDIRECT, &buffer));
+
+ mDeviceContext->DispatchIndirect(buffer, static_cast<UINT>(indirect));
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::createStagingTexture(const gl::Context *context,
+ ResourceType textureType,
+ const d3d11::Format &formatSet,
+ const gl::Extents &size,
+ StagingAccess readAndWriteAccess,
+ TextureHelper11 *textureOut)
+{
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ if (textureType == ResourceType::Texture2D)
+ {
+ D3D11_TEXTURE2D_DESC stagingDesc;
+ stagingDesc.Width = size.width;
+ stagingDesc.Height = size.height;
+ stagingDesc.MipLevels = 1;
+ stagingDesc.ArraySize = 1;
+ stagingDesc.Format = formatSet.texFormat;
+ stagingDesc.SampleDesc.Count = 1;
+ stagingDesc.SampleDesc.Quality = 0;
+ stagingDesc.Usage = D3D11_USAGE_STAGING;
+ stagingDesc.BindFlags = 0;
+ stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ stagingDesc.MiscFlags = 0;
+
+ if (readAndWriteAccess == StagingAccess::READ_WRITE)
+ {
+ stagingDesc.CPUAccessFlags |= D3D11_CPU_ACCESS_WRITE;
+ }
+
+ ANGLE_TRY(allocateTexture(context11, stagingDesc, formatSet, textureOut));
+ return angle::Result::Continue;
+ }
+ ASSERT(textureType == ResourceType::Texture3D);
+
+ D3D11_TEXTURE3D_DESC stagingDesc;
+ stagingDesc.Width = size.width;
+ stagingDesc.Height = size.height;
+ stagingDesc.Depth = 1;
+ stagingDesc.MipLevels = 1;
+ stagingDesc.Format = formatSet.texFormat;
+ stagingDesc.Usage = D3D11_USAGE_STAGING;
+ stagingDesc.BindFlags = 0;
+ stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
+ stagingDesc.MiscFlags = 0;
+
+ ANGLE_TRY(allocateTexture(context11, stagingDesc, formatSet, textureOut));
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::allocateTexture(d3d::Context *context,
+ const D3D11_TEXTURE2D_DESC &desc,
+ const d3d11::Format &format,
+ const D3D11_SUBRESOURCE_DATA *initData,
+ TextureHelper11 *textureOut)
+{
+ d3d11::Texture2D texture;
+ ANGLE_TRY(mResourceManager11.allocate(context, this, &desc, initData, &texture));
+ textureOut->init(std::move(texture), desc, format);
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::allocateTexture(d3d::Context *context,
+ const D3D11_TEXTURE3D_DESC &desc,
+ const d3d11::Format &format,
+ const D3D11_SUBRESOURCE_DATA *initData,
+ TextureHelper11 *textureOut)
+{
+ d3d11::Texture3D texture;
+ ANGLE_TRY(mResourceManager11.allocate(context, this, &desc, initData, &texture));
+ textureOut->init(std::move(texture), desc, format);
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::getBlendState(const gl::Context *context,
+ const d3d11::BlendStateKey &key,
+ const d3d11::BlendState **outBlendState)
+{
+ return mStateCache.getBlendState(context, this, key, outBlendState);
+}
+
+angle::Result Renderer11::getRasterizerState(const gl::Context *context,
+ const gl::RasterizerState &rasterState,
+ bool scissorEnabled,
+ ID3D11RasterizerState **outRasterizerState)
+{
+ return mStateCache.getRasterizerState(context, this, rasterState, scissorEnabled,
+ outRasterizerState);
+}
+
+angle::Result Renderer11::getDepthStencilState(const gl::Context *context,
+ const gl::DepthStencilState &dsState,
+ const d3d11::DepthStencilState **outDSState)
+{
+ return mStateCache.getDepthStencilState(context, this, dsState, outDSState);
+}
+
+angle::Result Renderer11::getSamplerState(const gl::Context *context,
+ const gl::SamplerState &samplerState,
+ ID3D11SamplerState **outSamplerState)
+{
+ return mStateCache.getSamplerState(context, this, samplerState, outSamplerState);
+}
+
+UINT Renderer11::getSampleDescQuality(GLuint supportedSamples) const
+{
+ // Per the documentation on
+ // https://docs.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_standard_multisample_quality_levels
+ // applications can only request the standard multisample pattern on
+ // feature levels 10_1 and above.
+ if (supportedSamples > 0 && mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_1)
+ {
+ return D3D11_STANDARD_MULTISAMPLE_PATTERN;
+ }
+ return 0;
+}
+
+angle::Result Renderer11::clearRenderTarget(const gl::Context *context,
+ RenderTargetD3D *renderTarget,
+ const gl::ColorF &clearColorValue,
+ const float clearDepthValue,
+ const unsigned int clearStencilValue)
+{
+ RenderTarget11 *rt11 = GetAs<RenderTarget11>(renderTarget);
+
+ if (rt11->getFormatSet().dsvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ ASSERT(rt11->getDepthStencilView().valid());
+
+ const auto &format = rt11->getFormatSet();
+ const UINT clearFlags = (format.format().depthBits > 0 ? D3D11_CLEAR_DEPTH : 0) |
+ (format.format().stencilBits ? D3D11_CLEAR_STENCIL : 0);
+ mDeviceContext->ClearDepthStencilView(rt11->getDepthStencilView().get(), clearFlags,
+ clearDepthValue,
+ static_cast<UINT8>(clearStencilValue));
+ return angle::Result::Continue;
+ }
+
+ ASSERT(rt11->getRenderTargetView().valid());
+ ID3D11RenderTargetView *rtv = rt11->getRenderTargetView().get();
+
+ // There are complications with some types of RTV and FL 9_3 with ClearRenderTargetView.
+ // See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476388(v=vs.85).aspx
+ ASSERT(mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_9_3 || !IsArrayRTV(rtv));
+
+ const auto &d3d11Format = rt11->getFormatSet();
+ const auto &glFormat = gl::GetSizedInternalFormatInfo(renderTarget->getInternalFormat());
+
+ gl::ColorF safeClearColor = clearColorValue;
+
+ if (d3d11Format.format().alphaBits > 0 && glFormat.alphaBits == 0)
+ {
+ safeClearColor.alpha = 1.0f;
+ }
+
+ mDeviceContext->ClearRenderTargetView(rtv, &safeClearColor.red);
+ return angle::Result::Continue;
+}
+
+bool Renderer11::canSelectViewInVertexShader() const
+{
+ return !getFeatures().selectViewInGeometryShader.enabled &&
+ getRenderer11DeviceCaps().supportsVpRtIndexWriteFromVertexShader;
+}
+
+angle::Result Renderer11::mapResource(const gl::Context *context,
+ ID3D11Resource *resource,
+ UINT subResource,
+ D3D11_MAP mapType,
+ UINT mapFlags,
+ D3D11_MAPPED_SUBRESOURCE *mappedResource)
+{
+ HRESULT hr = mDeviceContext->Map(resource, subResource, mapType, mapFlags, mappedResource);
+ ANGLE_TRY_HR(GetImplAs<Context11>(context), hr, "Failed to map D3D11 resource.");
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::markTypedBufferUsage(const gl::Context *context)
+{
+ const gl::State &glState = context->getState();
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+ gl::RangeUI imageRange = programD3D->getUsedImageRange(gl::ShaderType::Compute, false);
+ for (unsigned int imageIndex = imageRange.low(); imageIndex < imageRange.high(); imageIndex++)
+ {
+ GLint imageUnitIndex = programD3D->getImageMapping(gl::ShaderType::Compute, imageIndex,
+ false, context->getCaps());
+ ASSERT(imageUnitIndex != -1);
+ const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
+ if (imageUnit.texture.get()->getType() == gl::TextureType::Buffer)
+ {
+ Buffer11 *buffer11 = GetImplAs<Buffer11>(imageUnit.texture.get()->getBuffer().get());
+ ANGLE_TRY(buffer11->markTypedBufferUsage(context));
+ }
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::markRawBufferUsage(const gl::Context *context)
+{
+ const gl::State &glState = context->getState();
+ const gl::Program *program = glState.getProgram();
+ for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount();
+ blockIndex++)
+ {
+ GLuint binding = program->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex));
+ const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding);
+ if (shaderStorageBuffer.get() != nullptr)
+ {
+ Buffer11 *bufferStorage = GetImplAs<Buffer11>(shaderStorageBuffer.get());
+ ANGLE_TRY(bufferStorage->markRawBufferUsage(context));
+ }
+ }
+
+ for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
+ {
+ GLuint binding = atomicCounterBuffer.binding;
+ const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);
+
+ if (buffer.get() != nullptr)
+ {
+ Buffer11 *bufferStorage = GetImplAs<Buffer11>(buffer.get());
+ ANGLE_TRY(bufferStorage->markRawBufferUsage(context));
+ }
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::markTransformFeedbackUsage(const gl::Context *context)
+{
+ const gl::State &glState = context->getState();
+ const gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
+ for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
+ {
+ const gl::OffsetBindingPointer<gl::Buffer> &binding =
+ transformFeedback->getIndexedBuffer(i);
+ if (binding.get() != nullptr)
+ {
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(binding.get());
+ ANGLE_TRY(bufferD3D->markTransformFeedbackUsage(context));
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer11::getIncompleteTexture(const gl::Context *context,
+ gl::TextureType type,
+ gl::Texture **textureOut)
+{
+ return GetImplAs<Context11>(context)->getIncompleteTexture(context, type, textureOut);
+}
+
+std::string Renderer11::getVendorString() const
+{
+ return GetVendorString(mAdapterDescription.VendorId);
+}
+
+std::string Renderer11::getVersionString(bool includeFullVersion) const
+{
+ std::ostringstream versionString;
+ versionString << "D3D11";
+ if (includeFullVersion && mRenderer11DeviceCaps.driverVersion.valid())
+ {
+ versionString << "-" << GetDriverVersionString(mRenderer11DeviceCaps.driverVersion.value());
+ }
+ return versionString.str();
+}
+
+RendererD3D *CreateRenderer11(egl::Display *display)
+{
+ return new Renderer11(display);
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
new file mode 100644
index 0000000000..6d4cb214af
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
@@ -0,0 +1,632 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Renderer11.h: Defines a back-end specific class for the D3D11 renderer.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_
+
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/HLSLCompiler.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+class ImageIndex;
+} // namespace gl
+
+namespace rx
+{
+class Blit11;
+class Buffer11;
+class Clear11;
+class Context11;
+class IndexDataManager;
+struct PackPixelsParams;
+class PixelTransfer11;
+class RenderTarget11;
+class StreamingIndexBufferInterface;
+class Trim11;
+class VertexDataManager;
+
+struct Renderer11DeviceCaps
+{
+ Renderer11DeviceCaps();
+
+ D3D_FEATURE_LEVEL featureLevel;
+ bool supportsDXGI1_2; // Support for DXGI 1.2
+ bool supportsClearView; // Support for ID3D11DeviceContext1::ClearView
+ bool supportsConstantBufferOffsets; // Support for Constant buffer offset
+ bool supportsVpRtIndexWriteFromVertexShader; // VP/RT can be selected in the Vertex Shader
+ // stage.
+ bool supportsMultisampledDepthStencilSRVs; // D3D feature level 10.0 no longer allows creation
+ // of textures with both the bind SRV and DSV flags
+ // when multisampled. Textures will need to be
+ // resolved before reading. crbug.com/656989
+ bool supportsTypedUAVLoadAdditionalFormats; //
+ bool supportsRasterizerOrderViews;
+ bool allowES3OnFL10_0;
+ UINT B5G6R5support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G6R5_UNORM
+ UINT B5G6R5maxSamples; // Maximum number of samples supported by DXGI_FORMAT_B5G6R5_UNORM
+ UINT B4G4R4A4support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B4G4R4A4_UNORM
+ UINT B4G4R4A4maxSamples; // Maximum number of samples supported by DXGI_FORMAT_B4G4R4A4_UNORM
+ UINT B5G5R5A1support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G5R5A1_UNORM
+ UINT B5G5R5A1maxSamples; // Maximum number of samples supported by DXGI_FORMAT_B5G5R5A1_UNORM
+ Optional<LARGE_INTEGER> driverVersion; // Four-part driver version number.
+};
+
+enum
+{
+ MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024,
+ MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024
+};
+
+class Renderer11 : public RendererD3D
+{
+ public:
+ explicit Renderer11(egl::Display *display);
+ ~Renderer11() override;
+
+ egl::Error initialize() override;
+ bool resetDevice() override;
+
+ egl::ConfigSet generateConfigs() override;
+ void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const override;
+
+ ContextImpl *createContext(const gl::State &state, gl::ErrorSet *errorSet) override;
+
+ angle::Result flush(Context11 *context11);
+ angle::Result finish(Context11 *context11);
+
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+ NativeWindowD3D *createNativeWindow(EGLNativeWindowType window,
+ const egl::Config *config,
+ const egl::AttributeMap &attribs) const override;
+
+ SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow,
+ HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation,
+ EGLint samples) override;
+ egl::Error getD3DTextureInfo(const egl::Config *configuration,
+ IUnknown *d3dTexture,
+ const egl::AttributeMap &attribs,
+ EGLint *width,
+ EGLint *height,
+ GLsizei *samples,
+ gl::Format *glFormat,
+ const angle::Format **angleFormat,
+ UINT *arraySlice) const override;
+ egl::Error validateShareHandle(const egl::Config *config,
+ HANDLE shareHandle,
+ const egl::AttributeMap &attribs) const override;
+
+ // lost device
+ bool testDeviceLost() override;
+ bool testDeviceResettable() override;
+
+ DeviceIdentifier getAdapterIdentifier() const override;
+
+ unsigned int getReservedVertexUniformVectors() const;
+ unsigned int getReservedFragmentUniformVectors() const;
+ gl::ShaderMap<unsigned int> getReservedShaderUniformBuffers() const;
+
+ bool getShareHandleSupport() const;
+
+ int getMajorShaderModel() const override;
+ int getMinorShaderModel() const override;
+ std::string getShaderModelSuffix() const override;
+
+ // Pixel operations
+ angle::Result copyImage2D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+ angle::Result copyImageCube(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ gl::TextureTarget target,
+ GLint level) override;
+ angle::Result copyImage3D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+ angle::Result copyImage2DArray(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+
+ angle::Result copyTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ gl::TextureTarget srcTarget,
+ const gl::Box &sourceBox,
+ GLenum destFormat,
+ GLenum destType,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ gl::TextureTarget destTarget,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha) override;
+ angle::Result copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ TextureStorage *storage,
+ GLint destLevel) override;
+
+ // RenderTarget creation
+ angle::Result createRenderTarget(const gl::Context *context,
+ int width,
+ int height,
+ GLenum format,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+ angle::Result createRenderTargetCopy(const gl::Context *context,
+ RenderTargetD3D *source,
+ RenderTargetD3D **outRT) override;
+
+ // Shader operations
+ angle::Result loadExecutable(d3d::Context *context,
+ const uint8_t *function,
+ size_t length,
+ gl::ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ ShaderExecutableD3D **outExecutable) override;
+ angle::Result compileToExecutable(d3d::Context *context,
+ gl::InfoLog &infoLog,
+ const std::string &shaderHLSL,
+ gl::ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ const CompilerWorkaroundsD3D &workarounds,
+ ShaderExecutableD3D **outExectuable) override;
+ angle::Result ensureHLSLCompilerInitialized(d3d::Context *context) override;
+
+ UniformStorageD3D *createUniformStorage(size_t storageSize) override;
+
+ // Image operations
+ ImageD3D *createImage() override;
+ ExternalImageSiblingImpl *createExternalImageSibling(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs) override;
+ angle::Result generateMipmap(const gl::Context *context,
+ ImageD3D *dest,
+ ImageD3D *source) override;
+ angle::Result generateMipmapUsingD3D(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::TextureState &textureState) override;
+ angle::Result copyImage(const gl::Context *context,
+ ImageD3D *dest,
+ ImageD3D *source,
+ const gl::Box &sourceBox,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha) override;
+
+ TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain,
+ const std::string &label) override;
+ TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage,
+ RenderTargetD3D *renderTargetD3D,
+ const std::string &label) override;
+ TextureStorage *createTextureStorageExternal(egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc,
+ const std::string &label) override;
+ TextureStorage *createTextureStorage2D(GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ const std::string &label,
+ bool hintLevelZeroOnly) override;
+ TextureStorage *createTextureStorageCube(GLenum internalformat,
+ BindFlags bindFlags,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly,
+ const std::string &label) override;
+ TextureStorage *createTextureStorage3D(GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ const std::string &label) override;
+ TextureStorage *createTextureStorage2DArray(GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ const std::string &label) override;
+ TextureStorage *createTextureStorage2DMultisample(GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ int samples,
+ bool fixedSampleLocations,
+ const std::string &label) override;
+
+ TextureStorage *createTextureStorageBuffer(const gl::OffsetBindingPointer<gl::Buffer> &buffer,
+ GLenum internalFormat,
+ const std::string &label) override;
+ TextureStorage *createTextureStorage2DMultisampleArray(GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ int samples,
+ bool fixedSampleLocations,
+ const std::string &label) override;
+
+ VertexBuffer *createVertexBuffer() override;
+ IndexBuffer *createIndexBuffer() override;
+
+ // Stream Creation
+ StreamProducerImpl *createStreamProducerD3DTexture(egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) override;
+
+ // D3D11-renderer specific methods
+ ID3D11Device *getDevice() { return mDevice; }
+ ID3D11Device1 *getDevice1() { return mDevice1; }
+ void *getD3DDevice() override;
+ ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }
+ ID3D11DeviceContext1 *getDeviceContext1IfSupported() { return mDeviceContext1; }
+ IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }
+
+ angle::Result getBlendState(const gl::Context *context,
+ const d3d11::BlendStateKey &key,
+ const d3d11::BlendState **outBlendState);
+ angle::Result getRasterizerState(const gl::Context *context,
+ const gl::RasterizerState &rasterState,
+ bool scissorEnabled,
+ ID3D11RasterizerState **outRasterizerState);
+ angle::Result getDepthStencilState(const gl::Context *context,
+ const gl::DepthStencilState &dsState,
+ const d3d11::DepthStencilState **outDSState);
+ angle::Result getSamplerState(const gl::Context *context,
+ const gl::SamplerState &samplerState,
+ ID3D11SamplerState **outSamplerState);
+ UINT getSampleDescQuality(GLuint supportedSamples) const;
+
+ Blit11 *getBlitter() { return mBlit; }
+ Clear11 *getClearer() { return mClear; }
+ DebugAnnotatorContext11 *getDebugAnnotatorContext();
+
+ // Buffer-to-texture and Texture-to-buffer copies
+ bool supportsFastCopyBufferToTexture(GLenum internalFormat) const override;
+ angle::Result fastCopyBufferToTexture(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea) override;
+
+ angle::Result packPixels(const gl::Context *context,
+ const TextureHelper11 &textureHelper,
+ const PackPixelsParams &params,
+ uint8_t *pixelsOut);
+
+ bool getLUID(LUID *adapterLuid) const override;
+ VertexConversionType getVertexConversionType(angle::FormatID vertexFormatID) const override;
+ GLenum getVertexComponentType(angle::FormatID vertexFormatID) const override;
+
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+ // function.
+ angle::Result getVertexSpaceRequired(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance,
+ unsigned int *bytesRequiredOut) const override;
+
+ angle::Result readFromAttachment(const gl::Context *context,
+ const gl::FramebufferAttachment &srcAttachment,
+ const gl::Rectangle &sourceArea,
+ GLenum format,
+ GLenum type,
+ GLuint outputPitch,
+ const gl::PixelPackState &pack,
+ uint8_t *pixels);
+
+ angle::Result blitRenderbufferRect(const gl::Context *context,
+ const gl::Rectangle &readRect,
+ const gl::Rectangle &drawRect,
+ UINT readLayer,
+ UINT drawLayer,
+ RenderTargetD3D *readRenderTarget,
+ RenderTargetD3D *drawRenderTarget,
+ GLenum filter,
+ const gl::Rectangle *scissor,
+ bool colorBlit,
+ bool depthBlit,
+ bool stencilBlit);
+
+ bool isES3Capable() const;
+ const Renderer11DeviceCaps &getRenderer11DeviceCaps() const { return mRenderer11DeviceCaps; }
+
+ RendererClass getRendererClass() const override;
+ StateManager11 *getStateManager() { return &mStateManager; }
+
+ void onSwap();
+ void onBufferCreate(const Buffer11 *created);
+ void onBufferDelete(const Buffer11 *deleted);
+
+ DeviceImpl *createEGLDevice() override;
+
+ angle::Result drawArrays(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint firstVertex,
+ GLsizei vertexCount,
+ GLsizei instanceCount,
+ GLuint baseInstance,
+ bool isInstancedDraw);
+ angle::Result drawElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint startVertex,
+ GLsizei indexCount,
+ gl::DrawElementsType indexType,
+ const void *indices,
+ GLsizei instanceCount,
+ GLint baseVertex,
+ GLuint baseInstance,
+ bool isInstancedDraw);
+ angle::Result drawArraysIndirect(const gl::Context *context, const void *indirect);
+ angle::Result drawElementsIndirect(const gl::Context *context, const void *indirect);
+
+ // Necessary hack for default framebuffers in D3D.
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+ angle::Result getScratchMemoryBuffer(Context11 *context11,
+ size_t requestedSize,
+ angle::MemoryBuffer **bufferOut);
+
+ gl::Version getMaxSupportedESVersion() const override;
+ gl::Version getMaxConformantESVersion() const override;
+
+ angle::Result dispatchCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ);
+ angle::Result dispatchComputeIndirect(const gl::Context *context, GLintptr indirect);
+
+ angle::Result createStagingTexture(const gl::Context *context,
+ ResourceType textureType,
+ const d3d11::Format &formatSet,
+ const gl::Extents &size,
+ StagingAccess readAndWriteAccess,
+ TextureHelper11 *textureOut);
+
+ template <typename DescT, typename ResourceT>
+ angle::Result allocateResource(d3d::Context *context, const DescT &desc, ResourceT *resourceOut)
+ {
+ return mResourceManager11.allocate(context, this, &desc, nullptr, resourceOut);
+ }
+
+ template <typename DescT, typename InitDataT, typename ResourceT>
+ angle::Result allocateResource(d3d::Context *context,
+ const DescT &desc,
+ InitDataT *initData,
+ ResourceT *resourceOut)
+ {
+ return mResourceManager11.allocate(context, this, &desc, initData, resourceOut);
+ }
+
+ template <typename InitDataT, typename ResourceT>
+ angle::Result allocateResourceNoDesc(d3d::Context *context,
+ InitDataT *initData,
+ ResourceT *resourceOut)
+ {
+ return mResourceManager11.allocate(context, this, nullptr, initData, resourceOut);
+ }
+
+ template <typename DescT>
+ angle::Result allocateTexture(d3d::Context *context,
+ const DescT &desc,
+ const d3d11::Format &format,
+ TextureHelper11 *textureOut)
+ {
+ return allocateTexture(context, desc, format, nullptr, textureOut);
+ }
+
+ angle::Result allocateTexture(d3d::Context *context,
+ const D3D11_TEXTURE2D_DESC &desc,
+ const d3d11::Format &format,
+ const D3D11_SUBRESOURCE_DATA *initData,
+ TextureHelper11 *textureOut);
+
+ angle::Result allocateTexture(d3d::Context *context,
+ const D3D11_TEXTURE3D_DESC &desc,
+ const d3d11::Format &format,
+ const D3D11_SUBRESOURCE_DATA *initData,
+ TextureHelper11 *textureOut);
+
+ angle::Result clearRenderTarget(const gl::Context *context,
+ RenderTargetD3D *renderTarget,
+ const gl::ColorF &clearColorValue,
+ const float clearDepthValue,
+ const unsigned int clearStencilValue) override;
+
+ bool canSelectViewInVertexShader() const override;
+
+ angle::Result mapResource(const gl::Context *context,
+ ID3D11Resource *resource,
+ UINT subResource,
+ D3D11_MAP mapType,
+ UINT mapFlags,
+ D3D11_MAPPED_SUBRESOURCE *mappedResource);
+
+ angle::Result getIncompleteTexture(const gl::Context *context,
+ gl::TextureType type,
+ gl::Texture **textureOut) override;
+
+ void setGlobalDebugAnnotator() override;
+
+ std::string getRendererDescription() const override;
+ std::string getVendorString() const override;
+ std::string getVersionString(bool includeFullVersion) const override;
+
+ private:
+ void generateCaps(gl::Caps *outCaps,
+ gl::TextureCapsMap *outTextureCaps,
+ gl::Extensions *outExtensions,
+ gl::Limitations *outLimitations) const override;
+
+ void initializeFeatures(angle::FeaturesD3D *features) const override;
+
+ void initializeFrontendFeatures(angle::FrontendFeatures *features) const override;
+
+ angle::Result drawLineLoop(const gl::Context *context,
+ GLuint count,
+ gl::DrawElementsType type,
+ const void *indices,
+ int baseVertex,
+ int instances);
+ angle::Result drawTriangleFan(const gl::Context *context,
+ GLuint count,
+ gl::DrawElementsType type,
+ const void *indices,
+ int baseVertex,
+ int instances);
+
+ angle::Result resolveMultisampledTexture(const gl::Context *context,
+ RenderTarget11 *renderTarget,
+ bool depth,
+ bool stencil,
+ TextureHelper11 *textureOut);
+
+ void populateRenderer11DeviceCaps();
+
+ void updateHistograms();
+
+ angle::Result copyImageInternal(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ RenderTargetD3D *destRenderTarget);
+
+ gl::SupportedSampleSet generateSampleSetForEGLConfig(
+ const gl::TextureCaps &colorBufferFormatCaps,
+ const gl::TextureCaps &depthStencilBufferFormatCaps) const;
+
+ HRESULT callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, bool debug);
+ HRESULT callD3D11On12CreateDevice(PFN_D3D12_CREATE_DEVICE createDevice12,
+ PFN_D3D11ON12_CREATE_DEVICE createDevice11on12,
+ bool debug);
+ egl::Error initializeD3DDevice();
+ egl::Error initializeDevice();
+ void releaseDeviceResources();
+ void release();
+
+ d3d11::ANGLED3D11DeviceType getDeviceType() const;
+
+ // Make sure that the raw buffer is the latest buffer.
+ angle::Result markRawBufferUsage(const gl::Context *context);
+ angle::Result markTypedBufferUsage(const gl::Context *context);
+ angle::Result markTransformFeedbackUsage(const gl::Context *context);
+ angle::Result drawWithGeometryShaderAndTransformFeedback(Context11 *context11,
+ gl::PrimitiveMode mode,
+ UINT instanceCount,
+ UINT vertexCount);
+
+ HMODULE mD3d11Module;
+ HMODULE mD3d12Module;
+ HMODULE mDxgiModule;
+ HMODULE mDCompModule;
+ std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels;
+ D3D_DRIVER_TYPE mRequestedDriverType;
+ bool mCreateDebugDevice;
+ bool mCreatedWithDeviceEXT;
+
+ HLSLCompiler mCompiler;
+
+ RenderStateCache mStateCache;
+
+ StateManager11 mStateManager;
+
+ StreamingIndexBufferInterface *mLineLoopIB;
+ StreamingIndexBufferInterface *mTriangleFanIB;
+
+ // Texture copy resources
+ Blit11 *mBlit;
+ PixelTransfer11 *mPixelTransfer;
+
+ // Masked clear resources
+ Clear11 *mClear;
+
+ // Perform trim for D3D resources
+ Trim11 *mTrim;
+
+ // Sync query
+ d3d11::Query mSyncQuery;
+
+ // Created objects state tracking
+ std::set<const Buffer11 *> mAliveBuffers;
+
+ double mLastHistogramUpdateTime;
+
+ angle::ComPtr<ID3D12Device> mDevice12;
+ angle::ComPtr<ID3D12CommandQueue> mCommandQueue;
+
+ ID3D11Device *mDevice;
+ ID3D11Device1 *mDevice1;
+ Renderer11DeviceCaps mRenderer11DeviceCaps;
+ ID3D11DeviceContext *mDeviceContext;
+ ID3D11DeviceContext1 *mDeviceContext1;
+ ID3D11DeviceContext3 *mDeviceContext3;
+ IDXGIAdapter *mDxgiAdapter;
+ DXGI_ADAPTER_DESC mAdapterDescription;
+ char mDescription[128];
+ IDXGIFactory *mDxgiFactory;
+ ID3D11Debug *mDebug;
+
+ std::vector<GLuint> mScratchIndexDataBuffer;
+
+ angle::ScratchBuffer mScratchMemoryBuffer;
+
+ DebugAnnotatorContext11 mAnnotatorContext;
+
+ mutable Optional<bool> mSupportsShareHandles;
+ ResourceManager11 mResourceManager11;
+
+ TextureHelper11 mCachedResolveTexture;
+};
+
+} // namespace rx
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp
new file mode 100644
index 0000000000..ebf2db497f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp
@@ -0,0 +1,560 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ResourceManager11:
+// Centralized point of allocation for all D3D11 Resources.
+
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+
+namespace rx
+{
+
+namespace
+{
+
+constexpr uint8_t kDebugInitTextureDataValue = 0x48;
+constexpr FLOAT kDebugColorInitClearValue[4] = {0.3f, 0.5f, 0.7f, 0.5f};
+constexpr FLOAT kDebugDepthInitValue = 0.2f;
+constexpr UINT8 kDebugStencilInitValue = 3;
+
+// A hard limit on buffer size. This works around a problem in the NVIDIA drivers where buffer sizes
+// close to MAX_UINT would give undefined results. The limit of MAX_UINT/2 should be generous enough
+// for almost any demanding application.
+constexpr UINT kMaximumBufferSizeHardLimit = std::numeric_limits<UINT>::max() >> 1;
+
+uint64_t ComputeMippedMemoryUsage(unsigned int width,
+ unsigned int height,
+ unsigned int depth,
+ uint64_t pixelSize,
+ unsigned int mipLevels)
+{
+ uint64_t sizeSum = 0;
+
+ for (unsigned int level = 0; level < mipLevels; ++level)
+ {
+ unsigned int mipWidth = std::max(width >> level, 1u);
+ unsigned int mipHeight = std::max(height >> level, 1u);
+ unsigned int mipDepth = std::max(depth >> level, 1u);
+ sizeSum += static_cast<uint64_t>(mipWidth * mipHeight * mipDepth) * pixelSize;
+ }
+
+ return sizeSum;
+}
+
+uint64_t ComputeMemoryUsage(const D3D11_TEXTURE2D_DESC *desc)
+{
+ ASSERT(desc);
+ uint64_t pixelBytes =
+ static_cast<uint64_t>(d3d11::GetDXGIFormatSizeInfo(desc->Format).pixelBytes);
+ return ComputeMippedMemoryUsage(desc->Width, desc->Height, 1, pixelBytes, desc->MipLevels);
+}
+
+uint64_t ComputeMemoryUsage(const D3D11_TEXTURE3D_DESC *desc)
+{
+ ASSERT(desc);
+ uint64_t pixelBytes =
+ static_cast<uint64_t>(d3d11::GetDXGIFormatSizeInfo(desc->Format).pixelBytes);
+ return ComputeMippedMemoryUsage(desc->Width, desc->Height, desc->Depth, pixelBytes,
+ desc->MipLevels);
+}
+
+uint64_t ComputeMemoryUsage(const D3D11_BUFFER_DESC *desc)
+{
+ ASSERT(desc);
+ return static_cast<uint64_t>(desc->ByteWidth);
+}
+
+template <typename T>
+uint64_t ComputeMemoryUsage(const T *desc)
+{
+ return 0;
+}
+
+template <ResourceType ResourceT>
+uint64_t ComputeGenericMemoryUsage(ID3D11DeviceChild *genericResource)
+{
+ auto *typedResource = static_cast<GetD3D11Type<ResourceT> *>(genericResource);
+ GetDescType<ResourceT> desc;
+ typedResource->GetDesc(&desc);
+ return ComputeMemoryUsage(&desc);
+}
+
+uint64_t ComputeGenericMemoryUsage(ResourceType resourceType, ID3D11DeviceChild *resource)
+{
+ switch (resourceType)
+ {
+ case ResourceType::Texture2D:
+ return ComputeGenericMemoryUsage<ResourceType::Texture2D>(resource);
+ case ResourceType::Texture3D:
+ return ComputeGenericMemoryUsage<ResourceType::Texture3D>(resource);
+ case ResourceType::Buffer:
+ return ComputeGenericMemoryUsage<ResourceType::Buffer>(resource);
+
+ default:
+ return 0;
+ }
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_BLEND_DESC *desc,
+ void * /*initData*/,
+ ID3D11BlendState **blendState)
+{
+ return device->CreateBlendState(desc, blendState);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_BUFFER_DESC *desc,
+ const D3D11_SUBRESOURCE_DATA *initData,
+ ID3D11Buffer **buffer)
+{
+ // Force buffers to be limited to a fixed max size.
+ if (desc->ByteWidth > kMaximumBufferSizeHardLimit)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ return device->CreateBuffer(desc, initData, buffer);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const ShaderData *desc,
+ void * /*initData*/,
+ ID3D11ComputeShader **resourceOut)
+{
+ return device->CreateComputeShader(desc->get(), desc->size(), nullptr, resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_DEPTH_STENCIL_DESC *desc,
+ void * /*initData*/,
+ ID3D11DepthStencilState **resourceOut)
+{
+ return device->CreateDepthStencilState(desc, resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_DEPTH_STENCIL_VIEW_DESC *desc,
+ ID3D11Resource *resource,
+ ID3D11DepthStencilView **resourceOut)
+{
+ return device->CreateDepthStencilView(resource, desc, resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const ShaderData *desc,
+ const std::vector<D3D11_SO_DECLARATION_ENTRY> *initData,
+ ID3D11GeometryShader **resourceOut)
+{
+ if (initData)
+ {
+ return device->CreateGeometryShaderWithStreamOutput(
+ desc->get(), desc->size(), initData->data(), static_cast<UINT>(initData->size()),
+ nullptr, 0, 0, nullptr, resourceOut);
+ }
+ else
+ {
+ return device->CreateGeometryShader(desc->get(), desc->size(), nullptr, resourceOut);
+ }
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const InputElementArray *desc,
+ const ShaderData *initData,
+ ID3D11InputLayout **resourceOut)
+{
+ return device->CreateInputLayout(desc->get(), static_cast<UINT>(desc->size()), initData->get(),
+ initData->size(), resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const ShaderData *desc,
+ void * /*initData*/,
+ ID3D11PixelShader **resourceOut)
+{
+ return device->CreatePixelShader(desc->get(), desc->size(), nullptr, resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_QUERY_DESC *desc,
+ void * /*initData*/,
+ ID3D11Query **resourceOut)
+{
+ return device->CreateQuery(desc, resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_RASTERIZER_DESC *desc,
+ void * /*initData*/,
+ ID3D11RasterizerState **rasterizerState)
+{
+ return device->CreateRasterizerState(desc, rasterizerState);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_RENDER_TARGET_VIEW_DESC *desc,
+ ID3D11Resource *resource,
+ ID3D11RenderTargetView **renderTargetView)
+{
+ return device->CreateRenderTargetView(resource, desc, renderTargetView);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_SAMPLER_DESC *desc,
+ void * /*initData*/,
+ ID3D11SamplerState **resourceOut)
+{
+ return device->CreateSamplerState(desc, resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_SHADER_RESOURCE_VIEW_DESC *desc,
+ ID3D11Resource *resource,
+ ID3D11ShaderResourceView **resourceOut)
+{
+ return device->CreateShaderResourceView(resource, desc, resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_UNORDERED_ACCESS_VIEW_DESC *desc,
+ ID3D11Resource *resource,
+ ID3D11UnorderedAccessView **resourceOut)
+{
+ return device->CreateUnorderedAccessView(resource, desc, resourceOut);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_TEXTURE2D_DESC *desc,
+ const D3D11_SUBRESOURCE_DATA *initData,
+ ID3D11Texture2D **texture)
+{
+ return device->CreateTexture2D(desc, initData, texture);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const D3D11_TEXTURE3D_DESC *desc,
+ const D3D11_SUBRESOURCE_DATA *initData,
+ ID3D11Texture3D **texture)
+{
+ return device->CreateTexture3D(desc, initData, texture);
+}
+
+HRESULT CreateResource(ID3D11Device *device,
+ const ShaderData *desc,
+ void * /*initData*/,
+ ID3D11VertexShader **resourceOut)
+{
+ return device->CreateVertexShader(desc->get(), desc->size(), nullptr, resourceOut);
+}
+
+DXGI_FORMAT GetTypedDepthStencilFormat(DXGI_FORMAT dxgiFormat)
+{
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_R16_TYPELESS:
+ return DXGI_FORMAT_D16_UNORM;
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ return DXGI_FORMAT_D24_UNORM_S8_UINT;
+ case DXGI_FORMAT_R32_TYPELESS:
+ return DXGI_FORMAT_D32_FLOAT;
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ return DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
+ default:
+ return dxgiFormat;
+ }
+}
+
+template <typename DescT, typename ResourceT>
+angle::Result ClearResource(d3d::Context *context,
+ Renderer11 *renderer,
+ const DescT *desc,
+ ResourceT *texture)
+{
+ // No-op.
+ return angle::Result::Continue;
+}
+
+template <>
+angle::Result ClearResource(d3d::Context *context,
+ Renderer11 *renderer,
+ const D3D11_TEXTURE2D_DESC *desc,
+ ID3D11Texture2D *texture)
+{
+ ID3D11DeviceContext *deviceContext = renderer->getDeviceContext();
+
+ if ((desc->BindFlags & D3D11_BIND_DEPTH_STENCIL) != 0)
+ {
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Flags = 0;
+ dsvDesc.Format = GetTypedDepthStencilFormat(desc->Format);
+
+ const auto &format = d3d11_angle::GetFormat(dsvDesc.Format);
+ UINT clearFlags = (format.depthBits > 0 ? D3D11_CLEAR_DEPTH : 0) |
+ (format.stencilBits > 0 ? D3D11_CLEAR_STENCIL : 0);
+
+ // Must process each mip level individually.
+ for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
+ {
+ if (desc->SampleDesc.Count == 0)
+ {
+ dsvDesc.Texture2D.MipSlice = mipLevel;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ }
+ else
+ {
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
+ }
+
+ d3d11::DepthStencilView dsv;
+ ANGLE_TRY(renderer->allocateResource(context, dsvDesc, texture, &dsv));
+
+ deviceContext->ClearDepthStencilView(dsv.get(), clearFlags, kDebugDepthInitValue,
+ kDebugStencilInitValue);
+ }
+ }
+ else
+ {
+ ASSERT((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0);
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(renderer->allocateResourceNoDesc(context, texture, &rtv));
+
+ deviceContext->ClearRenderTargetView(rtv.get(), kDebugColorInitClearValue);
+ }
+
+ return angle::Result::Continue;
+}
+
+template <>
+angle::Result ClearResource(d3d::Context *context,
+ Renderer11 *renderer,
+ const D3D11_TEXTURE3D_DESC *desc,
+ ID3D11Texture3D *texture)
+{
+ ID3D11DeviceContext *deviceContext = renderer->getDeviceContext();
+
+ ASSERT((desc->BindFlags & D3D11_BIND_DEPTH_STENCIL) == 0);
+ ASSERT((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0);
+
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(renderer->allocateResourceNoDesc(context, texture, &rtv));
+
+ deviceContext->ClearRenderTargetView(rtv.get(), kDebugColorInitClearValue);
+ return angle::Result::Continue;
+}
+
+#define ANGLE_RESOURCE_STRINGIFY_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+ "Error allocating " #RESTYPE,
+
+constexpr std::array<const char *, NumResourceTypes> kResourceTypeErrors = {
+ {ANGLE_RESOURCE_TYPE_OP(Stringify, ANGLE_RESOURCE_STRINGIFY_OP)}};
+static_assert(kResourceTypeErrors[NumResourceTypes - 1] != nullptr,
+ "All members must be initialized.");
+
+} // anonymous namespace
+
+// ResourceManager11 Implementation.
+ResourceManager11::ResourceManager11() : mInitializeAllocations(false)
+{
+ for (auto &count : mAllocatedResourceCounts)
+ {
+ count = 0;
+ }
+ for (auto &memorySize : mAllocatedResourceDeviceMemory)
+ {
+ memorySize = 0;
+ }
+}
+
+ResourceManager11::~ResourceManager11()
+{
+ for (size_t count : mAllocatedResourceCounts)
+ {
+ ASSERT(count == 0);
+ }
+
+ for (uint64_t memorySize : mAllocatedResourceDeviceMemory)
+ {
+ ASSERT(memorySize == 0);
+ }
+}
+
+template <typename T>
+angle::Result ResourceManager11::allocate(d3d::Context *context,
+ Renderer11 *renderer,
+ const GetDescFromD3D11<T> *desc,
+ GetInitDataFromD3D11<T> *initData,
+ Resource11<T> *resourceOut)
+{
+ ID3D11Device *device = renderer->getDevice();
+ T *resource = nullptr;
+
+ GetInitDataFromD3D11<T> *shadowInitData = initData;
+ if (!shadowInitData && mInitializeAllocations)
+ {
+ shadowInitData = createInitDataIfNeeded<T>(desc);
+ }
+
+ HRESULT hr = CreateResource(device, desc, shadowInitData, &resource);
+ ANGLE_TRY_HR(context, hr, kResourceTypeErrors[ResourceTypeIndex<T>()]);
+
+ if (!shadowInitData && mInitializeAllocations)
+ {
+ ANGLE_TRY(ClearResource(context, renderer, desc, resource));
+ }
+
+ ASSERT(resource);
+ incrResource(GetResourceTypeFromD3D11<T>(), ComputeMemoryUsage(desc));
+ *resourceOut = std::move(Resource11<T>(resource, this));
+ return angle::Result::Continue;
+}
+
+void ResourceManager11::incrResource(ResourceType resourceType, uint64_t memorySize)
+{
+ size_t typeIndex = ResourceTypeIndex(resourceType);
+
+ mAllocatedResourceCounts[typeIndex]++;
+ mAllocatedResourceDeviceMemory[typeIndex] += memorySize;
+
+ // This checks for integer overflow.
+ ASSERT(mAllocatedResourceCounts[typeIndex] > 0);
+ ASSERT(mAllocatedResourceDeviceMemory[typeIndex] >= memorySize);
+}
+
+void ResourceManager11::decrResource(ResourceType resourceType, uint64_t memorySize)
+{
+ size_t typeIndex = ResourceTypeIndex(resourceType);
+
+ ASSERT(mAllocatedResourceCounts[typeIndex] > 0);
+ mAllocatedResourceCounts[typeIndex]--;
+ ASSERT(mAllocatedResourceDeviceMemory[typeIndex] >= memorySize);
+ mAllocatedResourceDeviceMemory[typeIndex] -= memorySize;
+}
+
+void ResourceManager11::onReleaseGeneric(ResourceType resourceType, ID3D11DeviceChild *resource)
+{
+ ASSERT(resource);
+ decrResource(resourceType, ComputeGenericMemoryUsage(resourceType, resource));
+}
+
+template <>
+const D3D11_SUBRESOURCE_DATA *ResourceManager11::createInitDataIfNeeded<ID3D11Texture2D>(
+ const D3D11_TEXTURE2D_DESC *desc)
+{
+ ASSERT(desc);
+
+ if ((desc->BindFlags & (D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_RENDER_TARGET)) != 0)
+ {
+ // This will be done using ClearView methods.
+ return nullptr;
+ }
+
+ size_t requiredSize = static_cast<size_t>(ComputeMemoryUsage(desc));
+ if (mZeroMemory.size() < requiredSize)
+ {
+ if (!mZeroMemory.resize(requiredSize))
+ {
+ ERR() << "Failed to allocate D3D texture initialization data.";
+ return nullptr;
+ }
+ mZeroMemory.fill(kDebugInitTextureDataValue);
+ }
+
+ const auto &formatSizeInfo = d3d11::GetDXGIFormatSizeInfo(desc->Format);
+
+ UINT subresourceCount = desc->MipLevels * desc->ArraySize;
+ if (mShadowInitData.size() < subresourceCount)
+ {
+ mShadowInitData.resize(subresourceCount);
+ }
+
+ for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
+ {
+ for (UINT arrayIndex = 0; arrayIndex < desc->ArraySize; ++arrayIndex)
+ {
+ UINT subresourceIndex = D3D11CalcSubresource(mipLevel, arrayIndex, desc->MipLevels);
+ D3D11_SUBRESOURCE_DATA *data = &mShadowInitData[subresourceIndex];
+
+ UINT levelWidth = std::max(desc->Width >> mipLevel, 1u);
+ UINT levelHeight = std::max(desc->Height >> mipLevel, 1u);
+
+ data->SysMemPitch = levelWidth * formatSizeInfo.pixelBytes;
+ data->SysMemSlicePitch = data->SysMemPitch * levelHeight;
+ data->pSysMem = mZeroMemory.data();
+ }
+ }
+
+ return mShadowInitData.data();
+}
+
+template <>
+const D3D11_SUBRESOURCE_DATA *ResourceManager11::createInitDataIfNeeded<ID3D11Texture3D>(
+ const D3D11_TEXTURE3D_DESC *desc)
+{
+ ASSERT(desc);
+
+ if ((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0)
+ {
+ // This will be done using ClearView methods.
+ return nullptr;
+ }
+
+ size_t requiredSize = static_cast<size_t>(ComputeMemoryUsage(desc));
+ if (mZeroMemory.size() < requiredSize)
+ {
+ if (!mZeroMemory.resize(requiredSize))
+ {
+ ERR() << "Failed to allocate D3D texture initialization data.";
+ return nullptr;
+ }
+ mZeroMemory.fill(kDebugInitTextureDataValue);
+ }
+
+ const auto &formatSizeInfo = d3d11::GetDXGIFormatSizeInfo(desc->Format);
+
+ UINT subresourceCount = desc->MipLevels;
+ if (mShadowInitData.size() < subresourceCount)
+ {
+ mShadowInitData.resize(subresourceCount);
+ }
+
+ for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel)
+ {
+ UINT subresourceIndex = D3D11CalcSubresource(mipLevel, 0, desc->MipLevels);
+ D3D11_SUBRESOURCE_DATA *data = &mShadowInitData[subresourceIndex];
+
+ UINT levelWidth = std::max(desc->Width >> mipLevel, 1u);
+ UINT levelHeight = std::max(desc->Height >> mipLevel, 1u);
+
+ data->SysMemPitch = levelWidth * formatSizeInfo.pixelBytes;
+ data->SysMemSlicePitch = data->SysMemPitch * levelHeight;
+ data->pSysMem = mZeroMemory.data();
+ }
+
+ return mShadowInitData.data();
+}
+
+template <typename T>
+GetInitDataFromD3D11<T> *ResourceManager11::createInitDataIfNeeded(const GetDescFromD3D11<T> *desc)
+{
+ // No-op.
+ return nullptr;
+}
+
+void ResourceManager11::setAllocationsInitialized(bool initialize)
+{
+ mInitializeAllocations = initialize;
+}
+
+#define ANGLE_INSTANTIATE_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+ \
+ template angle::Result ResourceManager11::allocate( \
+ d3d::Context *, Renderer11 *, const DESCTYPE *, INITDATATYPE *, Resource11<D3D11TYPE> *);
+
+ANGLE_RESOURCE_TYPE_OP(Instantitate, ANGLE_INSTANTIATE_OP)
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h
new file mode 100644
index 0000000000..b013ab8358
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h
@@ -0,0 +1,411 @@
+//
+// Copyright 2017 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ResourceManager11:
+// Centralized point of allocation for all D3D11 Resources.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_
+
+#include <array>
+#include <atomic>
+#include <memory>
+
+#include "common/MemoryBuffer.h"
+#include "common/angleutils.h"
+#include "common/debug.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/serial_utils.h"
+
+namespace rx
+{
+// These two methods are declared here to prevent circular includes.
+namespace d3d11
+{
+HRESULT SetDebugName(ID3D11DeviceChild *resource,
+ const char *internalName,
+ const std::string *khrDebugName);
+
+template <typename T>
+HRESULT SetDebugName(angle::ComPtr<T> &resource,
+ const char *internalName,
+ const std::string *khrDebugName)
+{
+ return SetDebugName(resource.Get(), internalName, khrDebugName);
+}
+} // namespace d3d11
+
+namespace d3d
+{
+class Context;
+} // namespace d3d
+
+class Renderer11;
+class ResourceManager11;
+template <typename T>
+class SharedResource11;
+class TextureHelper11;
+
+using InputElementArray = WrappedArray<D3D11_INPUT_ELEMENT_DESC>;
+using ShaderData = WrappedArray<uint8_t>;
+
+// Format: ResourceType, D3D11 type, DESC type, init data type.
+#define ANGLE_RESOURCE_TYPE_OP(NAME, OP) \
+ OP(NAME, BlendState, ID3D11BlendState, D3D11_BLEND_DESC, void) \
+ OP(NAME, Buffer, ID3D11Buffer, D3D11_BUFFER_DESC, const D3D11_SUBRESOURCE_DATA) \
+ OP(NAME, ComputeShader, ID3D11ComputeShader, ShaderData, void) \
+ OP(NAME, DepthStencilState, ID3D11DepthStencilState, D3D11_DEPTH_STENCIL_DESC, void) \
+ OP(NAME, DepthStencilView, ID3D11DepthStencilView, D3D11_DEPTH_STENCIL_VIEW_DESC, \
+ ID3D11Resource) \
+ OP(NAME, GeometryShader, ID3D11GeometryShader, ShaderData, \
+ const std::vector<D3D11_SO_DECLARATION_ENTRY>) \
+ OP(NAME, InputLayout, ID3D11InputLayout, InputElementArray, const ShaderData) \
+ OP(NAME, PixelShader, ID3D11PixelShader, ShaderData, void) \
+ OP(NAME, Query, ID3D11Query, D3D11_QUERY_DESC, void) \
+ OP(NAME, RasterizerState, ID3D11RasterizerState, D3D11_RASTERIZER_DESC, void) \
+ OP(NAME, RenderTargetView, ID3D11RenderTargetView, D3D11_RENDER_TARGET_VIEW_DESC, \
+ ID3D11Resource) \
+ OP(NAME, SamplerState, ID3D11SamplerState, D3D11_SAMPLER_DESC, void) \
+ OP(NAME, ShaderResourceView, ID3D11ShaderResourceView, D3D11_SHADER_RESOURCE_VIEW_DESC, \
+ ID3D11Resource) \
+ OP(NAME, UnorderedAccessView, ID3D11UnorderedAccessView, D3D11_UNORDERED_ACCESS_VIEW_DESC, \
+ ID3D11Resource) \
+ OP(NAME, Texture2D, ID3D11Texture2D, D3D11_TEXTURE2D_DESC, const D3D11_SUBRESOURCE_DATA) \
+ OP(NAME, Texture3D, ID3D11Texture3D, D3D11_TEXTURE3D_DESC, const D3D11_SUBRESOURCE_DATA) \
+ OP(NAME, VertexShader, ID3D11VertexShader, ShaderData, void)
+
+#define ANGLE_RESOURCE_TYPE_LIST(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) RESTYPE,
+
+enum class ResourceType
+{
+ ANGLE_RESOURCE_TYPE_OP(List, ANGLE_RESOURCE_TYPE_LIST) Last
+};
+
+#undef ANGLE_RESOURCE_TYPE_LIST
+
+constexpr size_t ResourceTypeIndex(ResourceType resourceType)
+{
+ return static_cast<size_t>(resourceType);
+}
+
+constexpr size_t NumResourceTypes = ResourceTypeIndex(ResourceType::Last);
+
+#define ANGLE_RESOURCE_TYPE_TO_D3D11(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+ \
+ template <> \
+ struct NAME<ResourceType::RESTYPE> \
+ { \
+ using Value = D3D11TYPE; \
+ };
+
+#define ANGLE_RESOURCE_TYPE_TO_DESC(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+ \
+ template <> \
+ struct NAME<ResourceType::RESTYPE> \
+ { \
+ using Value = DESCTYPE; \
+ };
+
+#define ANGLE_RESOURCE_TYPE_TO_INIT_DATA(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+ \
+ template <> \
+ struct NAME<ResourceType::RESTYPE> \
+ { \
+ using Value = INITDATATYPE; \
+ };
+
+#define ANGLE_RESOURCE_TYPE_TO_TYPE(NAME, OP) \
+ template <ResourceType Param> \
+ struct NAME; \
+ ANGLE_RESOURCE_TYPE_OP(NAME, OP) \
+ \
+ template <ResourceType Param> \
+ struct NAME \
+ {}; \
+ \
+ template <ResourceType Param> \
+ using Get##NAME = typename NAME<Param>::Value;
+
+ANGLE_RESOURCE_TYPE_TO_TYPE(D3D11Type, ANGLE_RESOURCE_TYPE_TO_D3D11)
+ANGLE_RESOURCE_TYPE_TO_TYPE(DescType, ANGLE_RESOURCE_TYPE_TO_DESC)
+ANGLE_RESOURCE_TYPE_TO_TYPE(InitDataType, ANGLE_RESOURCE_TYPE_TO_INIT_DATA)
+
+#undef ANGLE_RESOURCE_TYPE_TO_D3D11
+#undef ANGLE_RESOURCE_TYPE_TO_DESC
+#undef ANGLE_RESOURCE_TYPE_TO_INIT_DATA
+#undef ANGLE_RESOURCE_TYPE_TO_TYPE
+
+#define ANGLE_TYPE_TO_RESOURCE_TYPE(NAME, OP) \
+ template <typename Param> \
+ struct NAME; \
+ ANGLE_RESOURCE_TYPE_OP(NAME, OP) \
+ \
+ template <typename Param> \
+ struct NAME \
+ {}; \
+ \
+ template <typename Param> \
+ constexpr ResourceType Get##NAME() \
+ { \
+ return NAME<Param>::Value; \
+ }
+
+#define ANGLE_D3D11_TO_RESOURCE_TYPE(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+ \
+ template <> \
+ struct NAME<D3D11TYPE> \
+ { \
+ static constexpr ResourceType Value = ResourceType::RESTYPE; \
+ };
+
+ANGLE_TYPE_TO_RESOURCE_TYPE(ResourceTypeFromD3D11, ANGLE_D3D11_TO_RESOURCE_TYPE)
+
+#undef ANGLE_D3D11_TO_RESOURCE_TYPE
+#undef ANGLE_TYPE_TO_RESOURCE_TYPE
+
+template <typename T>
+using GetDescFromD3D11 = GetDescType<ResourceTypeFromD3D11<T>::Value>;
+
+template <typename T>
+using GetInitDataFromD3D11 = GetInitDataType<ResourceTypeFromD3D11<T>::Value>;
+
+template <typename T>
+constexpr size_t ResourceTypeIndex()
+{
+ return static_cast<size_t>(GetResourceTypeFromD3D11<T>());
+}
+
+template <typename T>
+struct TypedData
+{
+ TypedData() {}
+ ~TypedData();
+
+ T *object = nullptr;
+ ResourceManager11 *manager = nullptr;
+};
+
+// Smart pointer type. Wraps the resource and a factory for safe deletion.
+template <typename T, template <class> class Pointer, typename DataT>
+class Resource11Base : angle::NonCopyable
+{
+ public:
+ T *get() const { return mData->object; }
+ T *const *getPointer() const { return &mData->object; }
+
+ void setInternalName(const char *name)
+ {
+ mInternalDebugName = name;
+ UpdateDebugNameWithD3D();
+ }
+
+ void setKHRDebugLabel(const std::string *label)
+ {
+ mKhrDebugName = label;
+ UpdateDebugNameWithD3D();
+ }
+
+ void setLabels(const char *name, const std::string *label)
+ {
+ mInternalDebugName = name;
+ mKhrDebugName = label;
+ UpdateDebugNameWithD3D();
+ }
+
+ void set(T *object)
+ {
+ ASSERT(!valid());
+ mData->object = object;
+ }
+
+ bool valid() const { return (mData->object != nullptr); }
+
+ void reset()
+ {
+ if (valid())
+ mData.reset(new DataT());
+ }
+
+ ResourceSerial getSerial() const
+ {
+ return ResourceSerial(reinterpret_cast<uintptr_t>(mData->object));
+ }
+
+ protected:
+ friend class TextureHelper11;
+
+ Resource11Base() : mData(new DataT()) {}
+
+ Resource11Base(Resource11Base &&movedObj) : mData(new DataT())
+ {
+ std::swap(mData, movedObj.mData);
+ }
+
+ virtual ~Resource11Base() { mData.reset(); }
+
+ Resource11Base &operator=(Resource11Base &&movedObj)
+ {
+ std::swap(mData, movedObj.mData);
+ return *this;
+ }
+
+ Pointer<DataT> mData;
+
+ private:
+ void UpdateDebugNameWithD3D()
+ {
+ d3d11::SetDebugName(mData->object, mInternalDebugName, mKhrDebugName);
+ }
+
+ const std::string *mKhrDebugName = nullptr;
+ const char *mInternalDebugName = nullptr;
+};
+
+template <typename T>
+using UniquePtr = typename std::unique_ptr<T, std::default_delete<T>>;
+
+template <typename ResourceT>
+class Resource11 : public Resource11Base<ResourceT, UniquePtr, TypedData<ResourceT>>
+{
+ public:
+ Resource11() {}
+ Resource11(Resource11 &&other)
+ : Resource11Base<ResourceT, UniquePtr, TypedData<ResourceT>>(std::move(other))
+ {}
+ Resource11 &operator=(Resource11 &&other)
+ {
+ std::swap(this->mData, other.mData);
+ return *this;
+ }
+
+ private:
+ template <typename T>
+ friend class SharedResource11;
+ friend class ResourceManager11;
+
+ Resource11(ResourceT *object, ResourceManager11 *manager)
+ {
+ this->mData->object = object;
+ this->mData->manager = manager;
+ }
+};
+
+template <typename T>
+class SharedResource11 : public Resource11Base<T, std::shared_ptr, TypedData<T>>
+{
+ public:
+ SharedResource11() {}
+ SharedResource11(SharedResource11 &&movedObj)
+ : Resource11Base<T, std::shared_ptr, TypedData<T>>(std::move(movedObj))
+ {}
+
+ SharedResource11 &operator=(SharedResource11 &&other)
+ {
+ std::swap(this->mData, other.mData);
+ return *this;
+ }
+
+ SharedResource11 makeCopy() const
+ {
+ SharedResource11 copy;
+ copy.mData = this->mData;
+ return std::move(copy);
+ }
+
+ private:
+ friend class ResourceManager11;
+ SharedResource11(Resource11<T> &&obj) : Resource11Base<T, std::shared_ptr, TypedData<T>>()
+ {
+ std::swap(this->mData->manager, obj.mData->manager);
+
+ // Can't use std::swap because of ID3D11Resource.
+ auto temp = this->mData->object;
+ this->mData->object = obj.mData->object;
+ obj.mData->object = static_cast<T *>(temp);
+ }
+};
+
+class ResourceManager11 final : angle::NonCopyable
+{
+ public:
+ ResourceManager11();
+ ~ResourceManager11();
+
+ template <typename T>
+ angle::Result allocate(d3d::Context *context,
+ Renderer11 *renderer,
+ const GetDescFromD3D11<T> *desc,
+ GetInitDataFromD3D11<T> *initData,
+ Resource11<T> *resourceOut);
+
+ template <typename T>
+ angle::Result allocate(d3d::Context *context,
+ Renderer11 *renderer,
+ const GetDescFromD3D11<T> *desc,
+ GetInitDataFromD3D11<T> *initData,
+ SharedResource11<T> *sharedRes)
+ {
+ Resource11<T> res;
+ ANGLE_TRY(allocate(context, renderer, desc, initData, &res));
+ *sharedRes = std::move(res);
+ return angle::Result::Continue;
+ }
+
+ template <typename T>
+ void onRelease(T *resource)
+ {
+ onReleaseGeneric(GetResourceTypeFromD3D11<T>(), resource);
+ }
+
+ void onReleaseGeneric(ResourceType resourceType, ID3D11DeviceChild *resource);
+
+ void setAllocationsInitialized(bool initialize);
+
+ private:
+ void incrResource(ResourceType resourceType, uint64_t memorySize);
+ void decrResource(ResourceType resourceType, uint64_t memorySize);
+
+ template <typename T>
+ GetInitDataFromD3D11<T> *createInitDataIfNeeded(const GetDescFromD3D11<T> *desc);
+
+ bool mInitializeAllocations;
+
+ std::array<std::atomic_size_t, NumResourceTypes> mAllocatedResourceCounts;
+ std::array<std::atomic_uint64_t, NumResourceTypes> mAllocatedResourceDeviceMemory;
+ angle::MemoryBuffer mZeroMemory;
+
+ std::vector<D3D11_SUBRESOURCE_DATA> mShadowInitData;
+};
+
+template <typename ResourceT>
+TypedData<ResourceT>::~TypedData()
+{
+ if (object)
+ {
+ // We can have a nullptr factory when holding passed-in resources.
+ if (manager)
+ {
+ manager->onRelease(object);
+ }
+ object->Release();
+ }
+}
+
+#define ANGLE_RESOURCE_TYPE_CLASS(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \
+ using RESTYPE = Resource11<D3D11TYPE>;
+
+namespace d3d11
+{
+ANGLE_RESOURCE_TYPE_OP(ClassList, ANGLE_RESOURCE_TYPE_CLASS)
+
+using SharedSRV = SharedResource11<ID3D11ShaderResourceView>;
+using SharedUAV = SharedResource11<ID3D11UnorderedAccessView>;
+} // namespace d3d11
+
+#undef ANGLE_RESOURCE_TYPE_CLASS
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp
new file mode 100644
index 0000000000..a30ca417c1
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp
@@ -0,0 +1,116 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader
+// executable implementation details.
+
+#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+ShaderExecutable11::ShaderExecutable11(const void *function,
+ size_t length,
+ d3d11::PixelShader &&executable)
+ : ShaderExecutableD3D(function, length),
+ mPixelExecutable(std::move(executable)),
+ mVertexExecutable(),
+ mGeometryExecutable(),
+ mStreamOutExecutable(),
+ mComputeExecutable()
+{}
+
+ShaderExecutable11::ShaderExecutable11(const void *function,
+ size_t length,
+ d3d11::VertexShader &&executable,
+ d3d11::GeometryShader &&streamOut)
+ : ShaderExecutableD3D(function, length),
+ mPixelExecutable(),
+ mVertexExecutable(std::move(executable)),
+ mGeometryExecutable(),
+ mStreamOutExecutable(std::move(streamOut)),
+ mComputeExecutable()
+{}
+
+ShaderExecutable11::ShaderExecutable11(const void *function,
+ size_t length,
+ d3d11::GeometryShader &&executable)
+ : ShaderExecutableD3D(function, length),
+ mPixelExecutable(),
+ mVertexExecutable(),
+ mGeometryExecutable(std::move(executable)),
+ mStreamOutExecutable(),
+ mComputeExecutable()
+{}
+
+ShaderExecutable11::ShaderExecutable11(const void *function,
+ size_t length,
+ d3d11::ComputeShader &&executable)
+ : ShaderExecutableD3D(function, length),
+ mPixelExecutable(),
+ mVertexExecutable(),
+ mGeometryExecutable(),
+ mStreamOutExecutable(),
+ mComputeExecutable(std::move(executable))
+{}
+
+ShaderExecutable11::~ShaderExecutable11() {}
+
+const d3d11::VertexShader &ShaderExecutable11::getVertexShader() const
+{
+ return mVertexExecutable;
+}
+
+const d3d11::PixelShader &ShaderExecutable11::getPixelShader() const
+{
+ return mPixelExecutable;
+}
+
+const d3d11::GeometryShader &ShaderExecutable11::getGeometryShader() const
+{
+ return mGeometryExecutable;
+}
+
+const d3d11::GeometryShader &ShaderExecutable11::getStreamOutShader() const
+{
+ return mStreamOutExecutable;
+}
+
+const d3d11::ComputeShader &ShaderExecutable11::getComputeShader() const
+{
+ return mComputeExecutable;
+}
+
+UniformStorage11::UniformStorage11(size_t initialSize)
+ : UniformStorageD3D(initialSize), mConstantBuffer()
+{}
+
+UniformStorage11::~UniformStorage11() {}
+
+angle::Result UniformStorage11::getConstantBuffer(const gl::Context *context,
+ Renderer11 *renderer,
+ const d3d11::Buffer **bufferOut)
+{
+ if (size() > 0 && !mConstantBuffer.valid())
+ {
+ D3D11_BUFFER_DESC desc = {};
+ desc.ByteWidth = static_cast<unsigned int>(size());
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+
+ ANGLE_TRY(
+ renderer->allocateResource(GetImplAs<Context11>(context), desc, &mConstantBuffer));
+ }
+
+ *bufferOut = &mConstantBuffer;
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h
new file mode 100644
index 0000000000..75c71b3238
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h
@@ -0,0 +1,69 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderExecutable11.h: Defines a D3D11-specific class to contain shader
+// executable implementation details.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_
+
+#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+
+namespace gl
+{
+class Context;
+} // namespace gl
+
+namespace rx
+{
+class Renderer11;
+class UniformStorage11;
+
+class ShaderExecutable11 : public ShaderExecutableD3D
+{
+ public:
+ ShaderExecutable11(const void *function, size_t length, d3d11::PixelShader &&executable);
+ ShaderExecutable11(const void *function,
+ size_t length,
+ d3d11::VertexShader &&executable,
+ d3d11::GeometryShader &&streamOut);
+ ShaderExecutable11(const void *function, size_t length, d3d11::GeometryShader &&executable);
+ ShaderExecutable11(const void *function, size_t length, d3d11::ComputeShader &&executable);
+
+ ~ShaderExecutable11() override;
+
+ const d3d11::PixelShader &getPixelShader() const;
+ const d3d11::VertexShader &getVertexShader() const;
+ const d3d11::GeometryShader &getGeometryShader() const;
+ const d3d11::GeometryShader &getStreamOutShader() const;
+ const d3d11::ComputeShader &getComputeShader() const;
+
+ private:
+ d3d11::PixelShader mPixelExecutable;
+ d3d11::VertexShader mVertexExecutable;
+ d3d11::GeometryShader mGeometryExecutable;
+ d3d11::GeometryShader mStreamOutExecutable;
+ d3d11::ComputeShader mComputeExecutable;
+};
+
+class UniformStorage11 : public UniformStorageD3D
+{
+ public:
+ UniformStorage11(size_t initialSize);
+ ~UniformStorage11() override;
+
+ angle::Result getConstantBuffer(const gl::Context *context,
+ Renderer11 *renderer,
+ const d3d11::Buffer **bufferOut);
+
+ private:
+ d3d11::Buffer mConstantBuffer;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
new file mode 100644
index 0000000000..194c89d1c7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
@@ -0,0 +1,4004 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StateManager11.cpp: Defines a class for caching D3D11 state
+
+#include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
+
+#include "common/angleutils.h"
+#include "common/bitset_utils.h"
+#include "common/mathutil.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/renderer/d3d/DisplayD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
+
+namespace rx
+{
+
+namespace
+{
+bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOURCE_VIEW_DESC desc)
+{
+ unsigned mipLevel = index.getLevelIndex();
+ gl::TextureType textureType = index.getType();
+
+ switch (desc.ViewDimension)
+ {
+ case D3D11_SRV_DIMENSION_TEXTURE2D:
+ {
+ bool allLevels = (desc.Texture2D.MipLevels == std::numeric_limits<UINT>::max());
+ unsigned int maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip;
+ maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
+
+ unsigned mipMin = index.getLevelIndex();
+ unsigned mipMax = INT_MAX;
+
+ return textureType == gl::TextureType::_2D &&
+ gl::RangeUI(mipMin, mipMax)
+ .intersects(gl::RangeUI(desc.Texture2D.MostDetailedMip, maxSrvMip));
+ }
+
+ case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
+ {
+ GLint layerIndex = index.getLayerIndex();
+
+ bool allLevels = (desc.Texture2DArray.MipLevels == std::numeric_limits<UINT>::max());
+ unsigned int maxSrvMip =
+ desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip;
+ maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
+
+ unsigned maxSlice = desc.Texture2DArray.FirstArraySlice + desc.Texture2DArray.ArraySize;
+
+ // Cube maps can be mapped to Texture2DArray SRVs
+ return (textureType == gl::TextureType::_2DArray ||
+ textureType == gl::TextureType::CubeMap) &&
+ desc.Texture2DArray.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip &&
+ desc.Texture2DArray.FirstArraySlice <= static_cast<UINT>(layerIndex) &&
+ static_cast<UINT>(layerIndex) < maxSlice;
+ }
+
+ case D3D11_SRV_DIMENSION_TEXTURECUBE:
+ {
+ bool allLevels = (desc.TextureCube.MipLevels == std::numeric_limits<UINT>::max());
+ unsigned int maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip;
+ maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
+
+ return textureType == gl::TextureType::CubeMap &&
+ desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
+ }
+
+ case D3D11_SRV_DIMENSION_TEXTURE3D:
+ {
+ bool allLevels = (desc.Texture3D.MipLevels == std::numeric_limits<UINT>::max());
+ unsigned int maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip;
+ maxSrvMip = allLevels ? INT_MAX : maxSrvMip;
+
+ return textureType == gl::TextureType::_3D &&
+ desc.Texture3D.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
+ }
+ default:
+ // We only handle the cases corresponding to valid image indexes
+ UNIMPLEMENTED();
+ }
+
+ return false;
+}
+
+bool ImageIndexConflictsWithUAV(const gl::ImageIndex &index, D3D11_UNORDERED_ACCESS_VIEW_DESC desc)
+{
+ unsigned mipLevel = index.getLevelIndex();
+ gl::TextureType textureType = index.getType();
+
+ switch (desc.ViewDimension)
+ {
+ case D3D11_UAV_DIMENSION_TEXTURE2D:
+ {
+ return textureType == gl::TextureType::_2D && mipLevel == desc.Texture2D.MipSlice;
+ }
+
+ case D3D11_UAV_DIMENSION_TEXTURE2DARRAY:
+ {
+ GLint layerIndex = index.getLayerIndex();
+ unsigned mipSlice = desc.Texture2DArray.MipSlice;
+ unsigned firstArraySlice = desc.Texture2DArray.FirstArraySlice;
+ unsigned lastArraySlice = firstArraySlice + desc.Texture2DArray.ArraySize;
+
+ return (textureType == gl::TextureType::_2DArray ||
+ textureType == gl::TextureType::CubeMap) &&
+ (mipLevel == mipSlice && gl::RangeUI(firstArraySlice, lastArraySlice)
+ .contains(static_cast<UINT>(layerIndex)));
+ }
+
+ case D3D11_UAV_DIMENSION_TEXTURE3D:
+ {
+ GLint layerIndex = index.getLayerIndex();
+ unsigned mipSlice = desc.Texture3D.MipSlice;
+ unsigned firstWSlice = desc.Texture3D.FirstWSlice;
+ unsigned lastWSlice = firstWSlice + desc.Texture3D.WSize;
+
+ return textureType == gl::TextureType::_3D &&
+ (mipLevel == mipSlice &&
+ gl::RangeUI(firstWSlice, lastWSlice).contains(static_cast<UINT>(layerIndex)));
+ }
+ default:
+ return false;
+ }
+}
+
+// Does *not* increment the resource ref count!!
+ID3D11Resource *GetViewResource(ID3D11View *view)
+{
+ ID3D11Resource *resource = nullptr;
+ ASSERT(view);
+ view->GetResource(&resource);
+ resource->Release();
+ return resource;
+}
+
+int GetWrapBits(GLenum wrap)
+{
+ switch (wrap)
+ {
+ case GL_CLAMP_TO_EDGE:
+ return 0x0;
+ case GL_REPEAT:
+ return 0x1;
+ case GL_MIRRORED_REPEAT:
+ return 0x2;
+ case GL_CLAMP_TO_BORDER:
+ return 0x3;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+Optional<size_t> FindFirstNonInstanced(
+ const std::vector<const TranslatedAttribute *> &currentAttributes)
+{
+ for (size_t index = 0; index < currentAttributes.size(); ++index)
+ {
+ if (currentAttributes[index]->divisor == 0)
+ {
+ return Optional<size_t>(index);
+ }
+ }
+
+ return Optional<size_t>::Invalid();
+}
+
+void SortAttributesByLayout(const ProgramD3D &programD3D,
+ const std::vector<TranslatedAttribute> &vertexArrayAttribs,
+ const std::vector<TranslatedAttribute> &currentValueAttribs,
+ AttribIndexArray *sortedD3DSemanticsOut,
+ std::vector<const TranslatedAttribute *> *sortedAttributesOut)
+{
+ sortedAttributesOut->clear();
+
+ const AttribIndexArray &locationToSemantic = programD3D.getAttribLocationToD3DSemantics();
+ const gl::ProgramExecutable &executable = programD3D.getState().getExecutable();
+
+ for (auto locationIndex : executable.getActiveAttribLocationsMask())
+ {
+ int d3dSemantic = locationToSemantic[locationIndex];
+ if (sortedAttributesOut->size() <= static_cast<size_t>(d3dSemantic))
+ {
+ sortedAttributesOut->resize(d3dSemantic + 1);
+ }
+
+ (*sortedD3DSemanticsOut)[d3dSemantic] = d3dSemantic;
+
+ const auto *arrayAttrib = &vertexArrayAttribs[locationIndex];
+ if (arrayAttrib->attribute && arrayAttrib->attribute->enabled)
+ {
+ (*sortedAttributesOut)[d3dSemantic] = arrayAttrib;
+ }
+ else
+ {
+ ASSERT(currentValueAttribs[locationIndex].attribute);
+ (*sortedAttributesOut)[d3dSemantic] = &currentValueAttribs[locationIndex];
+ }
+ }
+}
+
+void UpdateUniformBuffer(ID3D11DeviceContext *deviceContext,
+ UniformStorage11 *storage,
+ const d3d11::Buffer *buffer)
+{
+ deviceContext->UpdateSubresource(buffer->get(), 0, nullptr, storage->getDataPointer(0, 0), 0,
+ 0);
+}
+
+size_t GetReservedBufferCount(bool usesPointSpriteEmulation)
+{
+ return usesPointSpriteEmulation ? 1 : 0;
+}
+
+bool CullsEverything(const gl::State &glState)
+{
+ return (glState.getRasterizerState().cullFace &&
+ glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack);
+}
+} // anonymous namespace
+
+// StateManager11::ViewCache Implementation.
+template <typename ViewType, typename DescType>
+StateManager11::ViewCache<ViewType, DescType>::ViewCache() : mHighestUsedView(0)
+{}
+
+template <typename ViewType, typename DescType>
+StateManager11::ViewCache<ViewType, DescType>::~ViewCache()
+{}
+
+template <typename ViewType, typename DescType>
+void StateManager11::ViewCache<ViewType, DescType>::update(size_t resourceIndex, ViewType *view)
+{
+ ASSERT(resourceIndex < mCurrentViews.size());
+ ViewRecord<DescType> *record = &mCurrentViews[resourceIndex];
+
+ record->view = reinterpret_cast<uintptr_t>(view);
+ if (view)
+ {
+ record->resource = reinterpret_cast<uintptr_t>(GetViewResource(view));
+ view->GetDesc(&record->desc);
+ mHighestUsedView = std::max(resourceIndex + 1, mHighestUsedView);
+ }
+ else
+ {
+ record->resource = 0;
+
+ if (resourceIndex + 1 == mHighestUsedView)
+ {
+ do
+ {
+ --mHighestUsedView;
+ } while (mHighestUsedView > 0 && mCurrentViews[mHighestUsedView].view == 0);
+ }
+ }
+}
+
+template <typename ViewType, typename DescType>
+void StateManager11::ViewCache<ViewType, DescType>::clear()
+{
+ if (mCurrentViews.empty())
+ {
+ return;
+ }
+
+ memset(&mCurrentViews[0], 0, sizeof(ViewRecord<DescType>) * mCurrentViews.size());
+ mHighestUsedView = 0;
+}
+
+StateManager11::SRVCache *StateManager11::getSRVCache(gl::ShaderType shaderType)
+{
+ ASSERT(shaderType != gl::ShaderType::InvalidEnum);
+ return &mCurShaderSRVs[shaderType];
+}
+
+// ShaderConstants11 implementation
+ShaderConstants11::ShaderConstants11() : mNumActiveShaderSamplers({})
+{
+ mShaderConstantsDirty.set();
+}
+
+ShaderConstants11::~ShaderConstants11() {}
+
+void ShaderConstants11::init(const gl::Caps &caps)
+{
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ mShaderSamplerMetadata[shaderType].resize(caps.maxShaderTextureImageUnits[shaderType]);
+ mShaderReadonlyImageMetadata[shaderType].resize(caps.maxShaderImageUniforms[shaderType]);
+ mShaderImageMetadata[shaderType].resize(caps.maxShaderImageUniforms[shaderType]);
+ }
+}
+
+size_t ShaderConstants11::GetShaderConstantsStructSize(gl::ShaderType shaderType)
+{
+ switch (shaderType)
+ {
+ case gl::ShaderType::Vertex:
+ return sizeof(Vertex);
+ case gl::ShaderType::Fragment:
+ return sizeof(Pixel);
+ case gl::ShaderType::Compute:
+ return sizeof(Compute);
+
+ // TODO(jiawei.shao@intel.com): return geometry shader constant struct size
+ case gl::ShaderType::Geometry:
+ return 0u;
+
+ default:
+ UNREACHABLE();
+ return 0u;
+ }
+}
+
+size_t ShaderConstants11::getRequiredBufferSize(gl::ShaderType shaderType) const
+{
+ ASSERT(shaderType != gl::ShaderType::InvalidEnum);
+ return GetShaderConstantsStructSize(shaderType) +
+ mShaderSamplerMetadata[shaderType].size() * sizeof(SamplerMetadata) +
+ mShaderImageMetadata[shaderType].size() * sizeof(ImageMetadata) +
+ mShaderReadonlyImageMetadata[shaderType].size() * sizeof(ImageMetadata);
+}
+
+void ShaderConstants11::markDirty()
+{
+ mShaderConstantsDirty.set();
+ mNumActiveShaderSamplers.fill(0);
+}
+
+bool ShaderConstants11::updateSamplerMetadata(SamplerMetadata *data,
+ const gl::Texture &texture,
+ const gl::SamplerState &samplerState)
+{
+ bool dirty = false;
+ unsigned int baseLevel = texture.getTextureState().getEffectiveBaseLevel();
+ gl::TextureTarget target = (texture.getType() == gl::TextureType::CubeMap)
+ ? gl::kCubeMapTextureTargetMin
+ : gl::NonCubeTextureTypeToTarget(texture.getType());
+ GLenum sizedFormat = texture.getFormat(target, baseLevel).info->sizedInternalFormat;
+ if (data->baseLevel != static_cast<int>(baseLevel))
+ {
+ data->baseLevel = static_cast<int>(baseLevel);
+ dirty = true;
+ }
+
+ // Some metadata is needed only for integer textures. We avoid updating the constant buffer
+ // unnecessarily by changing the data only in case the texture is an integer texture and
+ // the values have changed.
+ bool needIntegerTextureMetadata = false;
+ // internalFormatBits == 0 means a 32-bit texture in the case of integer textures.
+ int internalFormatBits = 0;
+ switch (sizedFormat)
+ {
+ case GL_RGBA32I:
+ case GL_RGBA32UI:
+ case GL_RGB32I:
+ case GL_RGB32UI:
+ case GL_RG32I:
+ case GL_RG32UI:
+ case GL_R32I:
+ case GL_R32UI:
+ needIntegerTextureMetadata = true;
+ break;
+ case GL_RGBA16I:
+ case GL_RGBA16UI:
+ case GL_RGB16I:
+ case GL_RGB16UI:
+ case GL_RG16I:
+ case GL_RG16UI:
+ case GL_R16I:
+ case GL_R16UI:
+ needIntegerTextureMetadata = true;
+ internalFormatBits = 16;
+ break;
+ case GL_RGBA8I:
+ case GL_RGBA8UI:
+ case GL_RGB8I:
+ case GL_RGB8UI:
+ case GL_RG8I:
+ case GL_RG8UI:
+ case GL_R8I:
+ case GL_R8UI:
+ needIntegerTextureMetadata = true;
+ internalFormatBits = 8;
+ break;
+ case GL_RGB10_A2UI:
+ needIntegerTextureMetadata = true;
+ internalFormatBits = 10;
+ break;
+ default:
+ break;
+ }
+ if (needIntegerTextureMetadata)
+ {
+ if (data->internalFormatBits != internalFormatBits)
+ {
+ data->internalFormatBits = internalFormatBits;
+ dirty = true;
+ }
+ // Pack the wrap values into one integer so we can fit all the metadata in two 4-integer
+ // vectors.
+ GLenum wrapS = samplerState.getWrapS();
+ GLenum wrapT = samplerState.getWrapT();
+ GLenum wrapR = samplerState.getWrapR();
+ int wrapModes = GetWrapBits(wrapS) | (GetWrapBits(wrapT) << 2) | (GetWrapBits(wrapR) << 4);
+ if (data->wrapModes != wrapModes)
+ {
+ data->wrapModes = wrapModes;
+ dirty = true;
+ }
+
+ const angle::ColorGeneric &borderColor(samplerState.getBorderColor());
+ constexpr int kBlack[4] = {};
+ const void *const intBorderColor = (borderColor.type == angle::ColorGeneric::Type::Float)
+ ? kBlack
+ : borderColor.colorI.data();
+ ASSERT(static_cast<const void *>(borderColor.colorI.data()) ==
+ static_cast<const void *>(borderColor.colorUI.data()));
+ if (memcmp(data->intBorderColor, intBorderColor, sizeof(data->intBorderColor)) != 0)
+ {
+ memcpy(data->intBorderColor, intBorderColor, sizeof(data->intBorderColor));
+ dirty = true;
+ }
+ }
+
+ return dirty;
+}
+
+bool ShaderConstants11::updateImageMetadata(ImageMetadata *data, const gl::ImageUnit &imageUnit)
+{
+ bool dirty = false;
+
+ if (data->layer != static_cast<int>(imageUnit.layer))
+ {
+ data->layer = static_cast<int>(imageUnit.layer);
+ dirty = true;
+ }
+
+ if (data->level != static_cast<unsigned int>(imageUnit.level))
+ {
+ data->level = static_cast<unsigned int>(imageUnit.level);
+ dirty = true;
+ }
+
+ return dirty;
+}
+
+void ShaderConstants11::setComputeWorkGroups(GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ)
+{
+ mCompute.numWorkGroups[0] = numGroupsX;
+ mCompute.numWorkGroups[1] = numGroupsY;
+ mCompute.numWorkGroups[2] = numGroupsZ;
+ mShaderConstantsDirty.set(gl::ShaderType::Compute);
+}
+
+void ShaderConstants11::setMultiviewWriteToViewportIndex(GLfloat index)
+{
+ mVertex.multiviewWriteToViewportIndex = index;
+ mPixel.multiviewWriteToViewportIndex = index;
+ mShaderConstantsDirty.set(gl::ShaderType::Vertex);
+ mShaderConstantsDirty.set(gl::ShaderType::Fragment);
+}
+
+void ShaderConstants11::onViewportChange(const gl::Rectangle &glViewport,
+ const D3D11_VIEWPORT &dxViewport,
+ const gl::Offset &glFragCoordOffset,
+ bool is9_3,
+ bool presentPathFast)
+{
+ mShaderConstantsDirty.set(gl::ShaderType::Vertex);
+ mShaderConstantsDirty.set(gl::ShaderType::Fragment);
+
+ // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders
+ // using viewAdjust (like the D3D9 renderer).
+ if (is9_3)
+ {
+ mVertex.viewAdjust[0] = static_cast<float>((glViewport.width - dxViewport.Width) +
+ 2 * (glViewport.x - dxViewport.TopLeftX)) /
+ dxViewport.Width;
+ mVertex.viewAdjust[1] = static_cast<float>((glViewport.height - dxViewport.Height) +
+ 2 * (glViewport.y - dxViewport.TopLeftY)) /
+ dxViewport.Height;
+ mVertex.viewAdjust[2] = static_cast<float>(glViewport.width) / dxViewport.Width;
+ mVertex.viewAdjust[3] = static_cast<float>(glViewport.height) / dxViewport.Height;
+ }
+
+ mPixel.viewCoords[0] = glViewport.width * 0.5f;
+ mPixel.viewCoords[1] = glViewport.height * 0.5f;
+ mPixel.viewCoords[2] = glViewport.x + (glViewport.width * 0.5f);
+ mPixel.viewCoords[3] = glViewport.y + (glViewport.height * 0.5f);
+
+ // Instanced pointsprite emulation requires ViewCoords to be defined in the
+ // the vertex shader.
+ mVertex.viewCoords[0] = mPixel.viewCoords[0];
+ mVertex.viewCoords[1] = mPixel.viewCoords[1];
+ mVertex.viewCoords[2] = mPixel.viewCoords[2];
+ mVertex.viewCoords[3] = mPixel.viewCoords[3];
+
+ const float zNear = dxViewport.MinDepth;
+ const float zFar = dxViewport.MaxDepth;
+
+ mPixel.depthFront[0] = (zFar - zNear) * 0.5f;
+ mPixel.depthFront[1] = (zNear + zFar) * 0.5f;
+
+ mVertex.depthRange[0] = zNear;
+ mVertex.depthRange[1] = zFar;
+ mVertex.depthRange[2] = zFar - zNear;
+
+ mPixel.depthRange[0] = zNear;
+ mPixel.depthRange[1] = zFar;
+ mPixel.depthRange[2] = zFar - zNear;
+
+ mPixel.viewScale[0] = 1.0f;
+ mPixel.viewScale[1] = presentPathFast ? 1.0f : -1.0f;
+ // Updates to the multiviewWriteToViewportIndex member are to be handled whenever the draw
+ // framebuffer's layout is changed.
+
+ mVertex.viewScale[0] = mPixel.viewScale[0];
+ mVertex.viewScale[1] = mPixel.viewScale[1];
+
+ mPixel.fragCoordOffset[0] = static_cast<float>(glFragCoordOffset.x);
+ mPixel.fragCoordOffset[1] = static_cast<float>(glFragCoordOffset.y);
+}
+
+// Update the ShaderConstants with a new first vertex and return whether the update dirties them.
+ANGLE_INLINE bool ShaderConstants11::onFirstVertexChange(GLint firstVertex)
+{
+ // firstVertex should already include baseVertex, if any.
+ uint32_t newFirstVertex = static_cast<uint32_t>(firstVertex);
+
+ bool firstVertexDirty = (mVertex.firstVertex != newFirstVertex);
+ if (firstVertexDirty)
+ {
+ mVertex.firstVertex = newFirstVertex;
+ mShaderConstantsDirty.set(gl::ShaderType::Vertex);
+ }
+ return firstVertexDirty;
+}
+
+void ShaderConstants11::onSamplerChange(gl::ShaderType shaderType,
+ unsigned int samplerIndex,
+ const gl::Texture &texture,
+ const gl::SamplerState &samplerState)
+{
+ ASSERT(shaderType != gl::ShaderType::InvalidEnum);
+ if (updateSamplerMetadata(&mShaderSamplerMetadata[shaderType][samplerIndex], texture,
+ samplerState))
+ {
+ mNumActiveShaderSamplers[shaderType] = 0;
+ }
+}
+
+bool ShaderConstants11::onImageChange(gl::ShaderType shaderType,
+ unsigned int imageIndex,
+ const gl::ImageUnit &imageUnit)
+{
+ ASSERT(shaderType != gl::ShaderType::InvalidEnum);
+ bool dirty = false;
+ if (imageUnit.access == GL_READ_ONLY)
+ {
+ if (updateImageMetadata(&mShaderReadonlyImageMetadata[shaderType][imageIndex], imageUnit))
+ {
+ mNumActiveShaderReadonlyImages[shaderType] = 0;
+ dirty = true;
+ }
+ }
+ else
+ {
+ if (updateImageMetadata(&mShaderImageMetadata[shaderType][imageIndex], imageUnit))
+ {
+ mNumActiveShaderImages[shaderType] = 0;
+ dirty = true;
+ }
+ }
+ return dirty;
+}
+
+void ShaderConstants11::onClipControlChange(bool lowerLeft, bool zeroToOne)
+{
+ mVertex.clipControlOrigin = lowerLeft ? -1.0f : 1.0f;
+ mVertex.clipControlZeroToOne = zeroToOne ? 1.0f : 0.0f;
+ mShaderConstantsDirty.set(gl::ShaderType::Vertex);
+}
+
+angle::Result ShaderConstants11::updateBuffer(const gl::Context *context,
+ Renderer11 *renderer,
+ gl::ShaderType shaderType,
+ const ProgramD3D &programD3D,
+ const d3d11::Buffer &driverConstantBuffer)
+{
+ // Re-upload the sampler meta-data if the current program uses more samplers
+ // than we previously uploaded.
+ const int numSamplers = programD3D.getUsedSamplerRange(shaderType).length();
+ const int numReadonlyImages = programD3D.getUsedImageRange(shaderType, true).length();
+ const int numImages = programD3D.getUsedImageRange(shaderType, false).length();
+
+ const bool dirty = mShaderConstantsDirty[shaderType] ||
+ (mNumActiveShaderSamplers[shaderType] < numSamplers) ||
+ (mNumActiveShaderReadonlyImages[shaderType] < numReadonlyImages) ||
+ (mNumActiveShaderImages[shaderType] < numImages);
+
+ const size_t dataSize = GetShaderConstantsStructSize(shaderType);
+ const uint8_t *samplerData =
+ reinterpret_cast<const uint8_t *>(mShaderSamplerMetadata[shaderType].data());
+ const size_t samplerDataSize = sizeof(SamplerMetadata) * numSamplers;
+ const uint8_t *readonlyImageData =
+ reinterpret_cast<const uint8_t *>(mShaderReadonlyImageMetadata[shaderType].data());
+ const size_t readonlyImageDataSize = sizeof(ImageMetadata) * numReadonlyImages;
+ const uint8_t *imageData =
+ reinterpret_cast<const uint8_t *>(mShaderImageMetadata[shaderType].data());
+ const size_t imageDataSize = sizeof(ImageMetadata) * numImages;
+
+ mNumActiveShaderSamplers[shaderType] = numSamplers;
+ mNumActiveShaderReadonlyImages[shaderType] = numReadonlyImages;
+ mNumActiveShaderImages[shaderType] = numImages;
+ mShaderConstantsDirty.set(shaderType, false);
+
+ const uint8_t *data = nullptr;
+ switch (shaderType)
+ {
+ case gl::ShaderType::Vertex:
+ data = reinterpret_cast<const uint8_t *>(&mVertex);
+ break;
+ case gl::ShaderType::Fragment:
+ data = reinterpret_cast<const uint8_t *>(&mPixel);
+ break;
+ case gl::ShaderType::Compute:
+ data = reinterpret_cast<const uint8_t *>(&mCompute);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ ASSERT(driverConstantBuffer.valid());
+
+ if (!dirty)
+ {
+ return angle::Result::Continue;
+ }
+
+ // Previous buffer contents are discarded, so we need to refresh the whole buffer.
+ D3D11_MAPPED_SUBRESOURCE mapping = {};
+ ANGLE_TRY(renderer->mapResource(context, driverConstantBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD,
+ 0, &mapping));
+
+ memcpy(mapping.pData, data, dataSize);
+ memcpy(static_cast<uint8_t *>(mapping.pData) + dataSize, samplerData,
+ sizeof(SamplerMetadata) * numSamplers);
+
+ memcpy(static_cast<uint8_t *>(mapping.pData) + dataSize + samplerDataSize, readonlyImageData,
+ readonlyImageDataSize);
+ memcpy(
+ static_cast<uint8_t *>(mapping.pData) + dataSize + samplerDataSize + readonlyImageDataSize,
+ imageData, imageDataSize);
+ renderer->getDeviceContext()->Unmap(driverConstantBuffer.get(), 0);
+
+ return angle::Result::Continue;
+}
+
+StateManager11::StateManager11(Renderer11 *renderer)
+ : mRenderer(renderer),
+ mInternalDirtyBits(),
+ mCurSampleAlphaToCoverage(false),
+ mCurBlendStateExt(),
+ mCurBlendColor(0, 0, 0, 0),
+ mCurSampleMask(0),
+ mCurStencilRef(0),
+ mCurStencilBackRef(0),
+ mCurStencilSize(0),
+ mCurScissorEnabled(false),
+ mCurScissorRect(),
+ mCurViewport(),
+ mCurNear(0.0f),
+ mCurFar(0.0f),
+ mViewportBounds(),
+ mRenderTargetIsDirty(true),
+ mCurPresentPathFastEnabled(false),
+ mCurPresentPathFastColorBufferHeight(0),
+ mDirtyCurrentValueAttribs(),
+ mCurrentValueAttribs(),
+ mCurrentInputLayout(),
+ mDirtyVertexBufferRange(gl::MAX_VERTEX_ATTRIBS, 0),
+ mCurrentPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_UNDEFINED),
+ mLastAppliedDrawMode(gl::PrimitiveMode::InvalidEnum),
+ mCullEverything(false),
+ mDirtySwizzles(false),
+ mAppliedIB(nullptr),
+ mAppliedIBFormat(DXGI_FORMAT_UNKNOWN),
+ mAppliedIBOffset(0),
+ mIndexBufferIsDirty(false),
+ mVertexDataManager(renderer),
+ mIndexDataManager(renderer),
+ mIsMultiviewEnabled(false),
+ mIndependentBlendStates(false),
+ mEmptySerial(mRenderer->generateSerial()),
+ mProgramD3D(nullptr),
+ mVertexArray11(nullptr),
+ mFramebuffer11(nullptr)
+{
+ mCurDepthStencilState.depthTest = false;
+ mCurDepthStencilState.depthFunc = GL_LESS;
+ mCurDepthStencilState.depthMask = true;
+ mCurDepthStencilState.stencilTest = false;
+ mCurDepthStencilState.stencilMask = true;
+ mCurDepthStencilState.stencilFail = GL_KEEP;
+ mCurDepthStencilState.stencilPassDepthFail = GL_KEEP;
+ mCurDepthStencilState.stencilPassDepthPass = GL_KEEP;
+ mCurDepthStencilState.stencilWritemask = static_cast<GLuint>(-1);
+ mCurDepthStencilState.stencilBackFunc = GL_ALWAYS;
+ mCurDepthStencilState.stencilBackMask = static_cast<GLuint>(-1);
+ mCurDepthStencilState.stencilBackFail = GL_KEEP;
+ mCurDepthStencilState.stencilBackPassDepthFail = GL_KEEP;
+ mCurDepthStencilState.stencilBackPassDepthPass = GL_KEEP;
+ mCurDepthStencilState.stencilBackWritemask = static_cast<GLuint>(-1);
+
+ mCurRasterState.rasterizerDiscard = false;
+ mCurRasterState.cullFace = false;
+ mCurRasterState.cullMode = gl::CullFaceMode::Back;
+ mCurRasterState.frontFace = GL_CCW;
+ mCurRasterState.polygonOffsetFill = false;
+ mCurRasterState.polygonOffsetFactor = 0.0f;
+ mCurRasterState.polygonOffsetUnits = 0.0f;
+ mCurRasterState.pointDrawMode = false;
+ mCurRasterState.multiSample = false;
+ mCurRasterState.dither = false;
+
+ // Start with all internal dirty bits set except the SRV and UAV bits.
+ mInternalDirtyBits.set();
+ mInternalDirtyBits.reset(DIRTY_BIT_GRAPHICS_SRV_STATE);
+ mInternalDirtyBits.reset(DIRTY_BIT_GRAPHICS_UAV_STATE);
+ mInternalDirtyBits.reset(DIRTY_BIT_COMPUTE_SRV_STATE);
+ mInternalDirtyBits.reset(DIRTY_BIT_COMPUTE_UAV_STATE);
+
+ mGraphicsDirtyBitsMask.set();
+ mGraphicsDirtyBitsMask.reset(DIRTY_BIT_COMPUTE_SRV_STATE);
+ mGraphicsDirtyBitsMask.reset(DIRTY_BIT_COMPUTE_UAV_STATE);
+ mComputeDirtyBitsMask.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
+ mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_UNIFORMS);
+ mComputeDirtyBitsMask.set(DIRTY_BIT_DRIVER_UNIFORMS);
+ mComputeDirtyBitsMask.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS);
+ mComputeDirtyBitsMask.set(DIRTY_BIT_SHADERS);
+ mComputeDirtyBitsMask.set(DIRTY_BIT_COMPUTE_SRV_STATE);
+ mComputeDirtyBitsMask.set(DIRTY_BIT_COMPUTE_UAV_STATE);
+
+ // Initially all current value attributes must be updated on first use.
+ mDirtyCurrentValueAttribs.set();
+
+ mCurrentVertexBuffers.fill(nullptr);
+ mCurrentVertexStrides.fill(std::numeric_limits<UINT>::max());
+ mCurrentVertexOffsets.fill(std::numeric_limits<UINT>::max());
+}
+
+StateManager11::~StateManager11() {}
+
+template <typename SRVType>
+void StateManager11::setShaderResourceInternal(gl::ShaderType shaderType,
+ UINT resourceSlot,
+ const SRVType *srv)
+{
+ auto *currentSRVs = getSRVCache(shaderType);
+ ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs->size());
+ const ViewRecord<D3D11_SHADER_RESOURCE_VIEW_DESC> &record = (*currentSRVs)[resourceSlot];
+
+ if (record.view != reinterpret_cast<uintptr_t>(srv))
+ {
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ ID3D11ShaderResourceView *srvPtr = srv ? srv->get() : nullptr;
+ if (srvPtr)
+ {
+ uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(srvPtr));
+ unsetConflictingUAVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute,
+ resource, nullptr);
+ }
+
+ switch (shaderType)
+ {
+ case gl::ShaderType::Vertex:
+ deviceContext->VSSetShaderResources(resourceSlot, 1, &srvPtr);
+ break;
+ case gl::ShaderType::Fragment:
+ deviceContext->PSSetShaderResources(resourceSlot, 1, &srvPtr);
+ break;
+ case gl::ShaderType::Compute:
+ {
+ if (srvPtr)
+ {
+ uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(srvPtr));
+ unsetConflictingRTVs(resource);
+ }
+ deviceContext->CSSetShaderResources(resourceSlot, 1, &srvPtr);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+
+ currentSRVs->update(resourceSlot, srvPtr);
+ }
+}
+
+template <typename UAVType>
+void StateManager11::setUnorderedAccessViewInternal(UINT resourceSlot,
+ const UAVType *uav,
+ UAVList *uavList)
+{
+ ASSERT(static_cast<size_t>(resourceSlot) < mCurComputeUAVs.size());
+ const ViewRecord<D3D11_UNORDERED_ACCESS_VIEW_DESC> &record = mCurComputeUAVs[resourceSlot];
+
+ if (record.view != reinterpret_cast<uintptr_t>(uav))
+ {
+ ID3D11UnorderedAccessView *uavPtr = uav ? uav->get() : nullptr;
+ // We need to make sure that resource being set to UnorderedAccessView slot |resourceSlot|
+ // is not bound on SRV.
+ if (uavPtr)
+ {
+ uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(uavPtr));
+ unsetConflictingSRVs(gl::PipelineType::ComputePipeline, gl::ShaderType::Vertex,
+ resource, nullptr, false);
+ unsetConflictingSRVs(gl::PipelineType::ComputePipeline, gl::ShaderType::Fragment,
+ resource, nullptr, false);
+ unsetConflictingSRVs(gl::PipelineType::ComputePipeline, gl::ShaderType::Compute,
+ resource, nullptr, false);
+ }
+ uavList->data[resourceSlot] = uavPtr;
+ if (static_cast<int>(resourceSlot) > uavList->highestUsed)
+ {
+ uavList->highestUsed = resourceSlot;
+ }
+
+ mCurComputeUAVs.update(resourceSlot, uavPtr);
+ }
+}
+
+void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized,
+ unsigned int stencilSize)
+{
+ if (!depthStencilInitialized || stencilSize != mCurStencilSize)
+ {
+ mCurStencilSize = stencilSize;
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
+ }
+}
+
+void StateManager11::checkPresentPath(const gl::Context *context)
+{
+ const auto *framebuffer = context->getState().getDrawFramebuffer();
+ const auto *firstColorAttachment = framebuffer->getFirstColorAttachment();
+ const bool clipSpaceOriginUpperLeft =
+ context->getState().getClipSpaceOrigin() == gl::ClipSpaceOrigin::UpperLeft;
+ const bool presentPathFastActive =
+ UsePresentPathFast(mRenderer, firstColorAttachment) || clipSpaceOriginUpperLeft;
+
+ const int colorBufferHeight = firstColorAttachment ? firstColorAttachment->getSize().height : 0;
+
+ if ((mCurPresentPathFastEnabled != presentPathFastActive) ||
+ (presentPathFastActive && (colorBufferHeight != mCurPresentPathFastColorBufferHeight)))
+ {
+ mCurPresentPathFastEnabled = presentPathFastActive;
+ mCurPresentPathFastColorBufferHeight = colorBufferHeight;
+
+ // Scissor rect may need to be vertically inverted
+ mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
+
+ // Cull Mode may need to be inverted
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+
+ // Viewport may need to be vertically inverted
+ invalidateViewport(context);
+ }
+}
+
+angle::Result StateManager11::updateStateForCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ)
+{
+ mShaderConstants.setComputeWorkGroups(numGroupsX, numGroupsY, numGroupsZ);
+
+ if (mProgramD3D->updateSamplerMapping() == ProgramD3D::SamplerMapping::WasDirty)
+ {
+ invalidateTexturesAndSamplers();
+ }
+
+ if (mDirtySwizzles)
+ {
+ ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Compute));
+ mDirtySwizzles = false;
+ }
+
+ if (mProgramD3D->anyShaderUniformsDirty())
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
+ }
+
+ auto dirtyBitsCopy = mInternalDirtyBits & mComputeDirtyBitsMask;
+ mInternalDirtyBits &= ~mComputeDirtyBitsMask;
+
+ for (auto iter = dirtyBitsCopy.begin(), end = dirtyBitsCopy.end(); iter != end; ++iter)
+ {
+ switch (*iter)
+ {
+ case DIRTY_BIT_COMPUTE_SRV_STATE:
+ // Avoid to call syncTexturesForCompute function two times.
+ iter.resetLaterBit(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
+ ANGLE_TRY(syncTexturesForCompute(context));
+ break;
+ case DIRTY_BIT_COMPUTE_UAV_STATE:
+ ANGLE_TRY(syncUAVsForCompute(context));
+ break;
+ case DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE:
+ ANGLE_TRY(syncTexturesForCompute(context));
+ break;
+ case DIRTY_BIT_PROGRAM_UNIFORMS:
+ case DIRTY_BIT_DRIVER_UNIFORMS:
+ ANGLE_TRY(applyComputeUniforms(context, mProgramD3D));
+ break;
+ case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS:
+ ANGLE_TRY(syncUniformBuffers(context));
+ break;
+ case DIRTY_BIT_SHADERS:
+ ANGLE_TRY(syncProgramForCompute(context));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+void StateManager11::syncState(const gl::Context *context,
+ const gl::State::DirtyBits &dirtyBits,
+ gl::Command command)
+{
+ if (!dirtyBits.any())
+ {
+ return;
+ }
+
+ const gl::State &state = context->getState();
+
+ for (size_t dirtyBit : dirtyBits)
+ {
+ switch (dirtyBit)
+ {
+ case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
+ {
+ const gl::BlendStateExt &blendStateExt = state.getBlendStateExt();
+ ASSERT(mCurBlendStateExt.getDrawBufferCount() ==
+ blendStateExt.getDrawBufferCount());
+ // Compare blend equations only for buffers with blending enabled because
+ // subsequent sync stages enforce default values for buffers with blending disabled.
+ if ((blendStateExt.getEnabledMask() &
+ mCurBlendStateExt.compareEquations(blendStateExt))
+ .any())
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_BLEND_FUNCS:
+ {
+ const gl::BlendStateExt &blendStateExt = state.getBlendStateExt();
+ ASSERT(mCurBlendStateExt.getDrawBufferCount() ==
+ blendStateExt.getDrawBufferCount());
+ // Compare blend factors only for buffers with blending enabled because
+ // subsequent sync stages enforce default values for buffers with blending disabled.
+ if ((blendStateExt.getEnabledMask() &
+ mCurBlendStateExt.compareFactors(blendStateExt))
+ .any())
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_BLEND_ENABLED:
+ {
+ if (state.getBlendStateExt().getEnabledMask() != mCurBlendStateExt.getEnabledMask())
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
+ if (state.isSampleAlphaToCoverageEnabled() != mCurSampleAlphaToCoverage)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
+ }
+ break;
+ case gl::State::DIRTY_BIT_DITHER_ENABLED:
+ if (state.getRasterizerState().dither != mCurRasterState.dither)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+ }
+ break;
+ case gl::State::DIRTY_BIT_COLOR_MASK:
+ {
+ if (state.getBlendStateExt().getColorMaskBits() !=
+ mCurBlendStateExt.getColorMaskBits())
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_BLEND_COLOR:
+ if (state.getBlendColor() != mCurBlendColor)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
+ }
+ break;
+ // Depth and stencil redundant state changes are guarded in the
+ // frontend so for related cases here just set the dirty bit.
+ case gl::State::DIRTY_BIT_DEPTH_MASK:
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_FUNC:
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
+ break;
+
+ case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
+ if (state.getRasterizerState().cullFace != mCurRasterState.cullFace)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+ mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
+ }
+ break;
+ case gl::State::DIRTY_BIT_CULL_FACE:
+ if (state.getRasterizerState().cullMode != mCurRasterState.cullMode)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+ mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
+ }
+ break;
+ case gl::State::DIRTY_BIT_FRONT_FACE:
+ if (state.getRasterizerState().frontFace != mCurRasterState.frontFace)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+ mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
+ }
+ break;
+ case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
+ if (state.getRasterizerState().polygonOffsetFill !=
+ mCurRasterState.polygonOffsetFill)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+ }
+ break;
+ case gl::State::DIRTY_BIT_POLYGON_OFFSET:
+ {
+ const gl::RasterizerState &rasterState = state.getRasterizerState();
+ if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor ||
+ rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED:
+ if (state.getRasterizerState().rasterizerDiscard !=
+ mCurRasterState.rasterizerDiscard)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+
+ // Enabling/disabling rasterizer discard affects the pixel shader.
+ invalidateShaders();
+ }
+ break;
+ case gl::State::DIRTY_BIT_SCISSOR:
+ if (state.getScissor() != mCurScissorRect)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
+ }
+ break;
+ case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
+ if (state.isScissorTestEnabled() != mCurScissorEnabled)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
+ // Rasterizer state update needs mCurScissorsEnabled and updates when it changes
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+ }
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_RANGE:
+ invalidateViewport(context);
+ break;
+ case gl::State::DIRTY_BIT_VIEWPORT:
+ if (state.getViewport() != mCurViewport)
+ {
+ invalidateViewport(context);
+ }
+ break;
+ case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
+ invalidateRenderTarget();
+ if (mIsMultiviewEnabled)
+ {
+ handleMultiviewDrawFramebufferChange(context);
+ }
+ mFramebuffer11 = GetImplAs<Framebuffer11>(state.getDrawFramebuffer());
+ break;
+ case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING:
+ invalidateVertexBuffer();
+ // Force invalidate the current value attributes, since the VertexArray11 keeps an
+ // internal cache of TranslatedAttributes, and they CurrentValue attributes are
+ // owned by the StateManager11/Context.
+ mDirtyCurrentValueAttribs.set();
+ // Invalidate the cached index buffer.
+ invalidateIndexBuffer();
+ mVertexArray11 = GetImplAs<VertexArray11>(state.getVertexArray());
+ break;
+ case gl::State::DIRTY_BIT_UNIFORM_BUFFER_BINDINGS:
+ invalidateProgramUniformBuffers();
+ break;
+ case gl::State::DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING:
+ invalidateProgramAtomicCounterBuffers();
+ break;
+ case gl::State::DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING:
+ invalidateProgramShaderStorageBuffers();
+ break;
+ case gl::State::DIRTY_BIT_TEXTURE_BINDINGS:
+ invalidateTexturesAndSamplers();
+ break;
+ case gl::State::DIRTY_BIT_SAMPLER_BINDINGS:
+ invalidateTexturesAndSamplers();
+ break;
+ case gl::State::DIRTY_BIT_IMAGE_BINDINGS:
+ invalidateImageBindings();
+ break;
+ case gl::State::DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING:
+ invalidateTransformFeedback();
+ break;
+ case gl::State::DIRTY_BIT_PROGRAM_BINDING:
+ mProgramD3D = GetImplAs<ProgramD3D>(state.getProgram());
+ break;
+ case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE:
+ {
+ invalidateShaders();
+ invalidateTexturesAndSamplers();
+ invalidateProgramUniforms();
+ invalidateProgramUniformBuffers();
+ invalidateProgramAtomicCounterBuffers();
+ invalidateProgramShaderStorageBuffers();
+ invalidateDriverUniforms();
+ const gl::ProgramExecutable *executable = state.getProgramExecutable();
+ if (!executable || command != gl::Command::Dispatch)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
+ invalidateVertexBuffer();
+ invalidateRenderTarget();
+ // If OVR_multiview2 is enabled, the attribute divisor has to be updated for
+ // each binding. When using compute, there could be no vertex array.
+ if (mIsMultiviewEnabled && mVertexArray11)
+ {
+ ASSERT(mProgramD3D);
+ ASSERT(mVertexArray11 == GetImplAs<VertexArray11>(state.getVertexArray()));
+ const gl::ProgramState &programState = mProgramD3D->getState();
+ int numViews =
+ programState.usesMultiview() ? programState.getNumViews() : 1;
+ mVertexArray11->markAllAttributeDivisorsForAdjustment(numViews);
+ }
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_CURRENT_VALUES:
+ {
+ for (auto attribIndex : state.getAndResetDirtyCurrentValues())
+ {
+ invalidateCurrentValueAttrib(attribIndex);
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_PROVOKING_VERTEX:
+ invalidateShaders();
+ break;
+ case gl::State::DIRTY_BIT_EXTENDED:
+ {
+ gl::State::ExtendedDirtyBits extendedDirtyBits =
+ state.getAndResetExtendedDirtyBits();
+
+ for (size_t extendedDirtyBit : extendedDirtyBits)
+ {
+ switch (extendedDirtyBit)
+ {
+ case gl::State::EXTENDED_DIRTY_BIT_CLIP_CONTROL:
+ checkPresentPath(context);
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ // TODO(jmadill): Input layout and vertex buffer state.
+}
+
+void StateManager11::handleMultiviewDrawFramebufferChange(const gl::Context *context)
+{
+ const auto &glState = context->getState();
+ const gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
+ ASSERT(drawFramebuffer != nullptr);
+
+ if (drawFramebuffer->isMultiview())
+ {
+ // Because the base view index is applied as an offset to the 2D texture array when the
+ // RTV is created, we just have to pass a boolean to select which code path is to be
+ // used.
+ mShaderConstants.setMultiviewWriteToViewportIndex(0.0f);
+ }
+}
+
+angle::Result StateManager11::syncBlendState(const gl::Context *context,
+ const gl::BlendStateExt &blendStateExt,
+ const gl::ColorF &blendColor,
+ unsigned int sampleMask,
+ bool sampleAlphaToCoverage,
+ bool emulateConstantAlpha)
+{
+ const d3d11::BlendState *dxBlendState = nullptr;
+ const d3d11::BlendStateKey &key = RenderStateCache::GetBlendStateKey(
+ context, mFramebuffer11, blendStateExt, sampleAlphaToCoverage);
+
+ ANGLE_TRY(mRenderer->getBlendState(context, key, &dxBlendState));
+
+ ASSERT(dxBlendState != nullptr);
+
+ // D3D11 does not support CONSTANT_ALPHA as source or destination color factor, so ANGLE sets
+ // the factor to CONSTANT_COLOR and swizzles the color value to aaaa. For this reason, it's
+ // impossible to simultaneously use CONSTANT_ALPHA and CONSTANT_COLOR as source or destination
+ // color factors in the same blend state. This is enforced in the validation layer.
+ float blendColors[4] = {0.0f};
+ blendColors[0] = emulateConstantAlpha ? blendColor.alpha : blendColor.red;
+ blendColors[1] = emulateConstantAlpha ? blendColor.alpha : blendColor.green;
+ blendColors[2] = emulateConstantAlpha ? blendColor.alpha : blendColor.blue;
+ blendColors[3] = blendColor.alpha;
+
+ mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState->get(), blendColors, sampleMask);
+
+ mCurBlendStateExt = blendStateExt;
+ mCurBlendColor = blendColor;
+ mCurSampleMask = sampleMask;
+ mCurSampleAlphaToCoverage = sampleAlphaToCoverage;
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::syncDepthStencilState(const gl::Context *context)
+{
+ const gl::State &glState = context->getState();
+
+ mCurDepthStencilState = glState.getDepthStencilState();
+ mCurStencilRef = glState.getStencilRef();
+ mCurStencilBackRef = glState.getStencilBackRef();
+
+ // get the maximum size of the stencil ref
+ unsigned int maxStencil = 0;
+ if (mCurDepthStencilState.stencilTest && mCurStencilSize > 0)
+ {
+ maxStencil = (1 << mCurStencilSize) - 1;
+ }
+ ASSERT((mCurDepthStencilState.stencilWritemask & maxStencil) ==
+ (mCurDepthStencilState.stencilBackWritemask & maxStencil));
+ ASSERT(gl::clamp(mCurStencilRef, 0, static_cast<int>(maxStencil)) ==
+ gl::clamp(mCurStencilBackRef, 0, static_cast<int>(maxStencil)));
+ ASSERT((mCurDepthStencilState.stencilMask & maxStencil) ==
+ (mCurDepthStencilState.stencilBackMask & maxStencil));
+
+ gl::DepthStencilState modifiedGLState = glState.getDepthStencilState();
+
+ ASSERT(mCurDisableDepth.valid() && mCurDisableStencil.valid());
+
+ if (mCurDisableDepth.value())
+ {
+ modifiedGLState.depthTest = false;
+ modifiedGLState.depthMask = false;
+ }
+
+ if (mCurDisableStencil.value())
+ {
+ modifiedGLState.stencilTest = false;
+ }
+ if (!modifiedGLState.stencilTest)
+ {
+ modifiedGLState.stencilWritemask = 0;
+ modifiedGLState.stencilBackWritemask = 0;
+ }
+
+ // If STENCIL_TEST is disabled in glState, stencil testing and writing should be disabled.
+ // Verify that's true in the modifiedGLState so it is propagated to d3dState.
+ ASSERT(glState.getDepthStencilState().stencilTest ||
+ (!modifiedGLState.stencilTest && modifiedGLState.stencilWritemask == 0 &&
+ modifiedGLState.stencilBackWritemask == 0));
+
+ const d3d11::DepthStencilState *d3dState = nullptr;
+ ANGLE_TRY(mRenderer->getDepthStencilState(context, modifiedGLState, &d3dState));
+ ASSERT(d3dState);
+
+ // Max D3D11 stencil reference value is 0xFF,
+ // corresponding to the max 8 bits in a stencil buffer
+ // GL specifies we should clamp the ref value to the
+ // nearest bit depth when doing stencil ops
+ static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF,
+ "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK");
+ static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF,
+ "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK");
+ UINT dxStencilRef = static_cast<UINT>(gl::clamp(mCurStencilRef, 0, 0xFF));
+
+ mRenderer->getDeviceContext()->OMSetDepthStencilState(d3dState->get(), dxStencilRef);
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::syncRasterizerState(const gl::Context *context,
+ gl::PrimitiveMode mode)
+{
+ // TODO: Remove pointDrawMode and multiSample from gl::RasterizerState.
+ gl::RasterizerState rasterState = context->getState().getRasterizerState();
+ rasterState.pointDrawMode = (mode == gl::PrimitiveMode::Points);
+ rasterState.multiSample = mCurRasterState.multiSample;
+
+ ID3D11RasterizerState *dxRasterState = nullptr;
+
+ if (mCurPresentPathFastEnabled)
+ {
+ gl::RasterizerState modifiedRasterState = rasterState;
+
+ // If prseent path fast is active then we need invert the front face state.
+ // This ensures that both gl_FrontFacing is correct, and front/back culling
+ // is performed correctly.
+ if (modifiedRasterState.frontFace == GL_CCW)
+ {
+ modifiedRasterState.frontFace = GL_CW;
+ }
+ else
+ {
+ ASSERT(modifiedRasterState.frontFace == GL_CW);
+ modifiedRasterState.frontFace = GL_CCW;
+ }
+
+ ANGLE_TRY(mRenderer->getRasterizerState(context, modifiedRasterState, mCurScissorEnabled,
+ &dxRasterState));
+ }
+ else
+ {
+ ANGLE_TRY(mRenderer->getRasterizerState(context, rasterState, mCurScissorEnabled,
+ &dxRasterState));
+ }
+
+ mRenderer->getDeviceContext()->RSSetState(dxRasterState);
+
+ mCurRasterState = rasterState;
+
+ return angle::Result::Continue;
+}
+
+void StateManager11::syncScissorRectangle(const gl::Context *context)
+{
+ const auto &glState = context->getState();
+ gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
+ const gl::Rectangle &scissor = glState.getScissor();
+ const bool enabled = glState.isScissorTestEnabled();
+
+ mCurScissorOffset = framebuffer->getSurfaceTextureOffset();
+
+ int scissorX = scissor.x + mCurScissorOffset.x;
+ int scissorY = scissor.y + mCurScissorOffset.y;
+
+ if (mCurPresentPathFastEnabled)
+ {
+ scissorY = mCurPresentPathFastColorBufferHeight - scissor.height - scissor.y;
+ }
+
+ if (enabled)
+ {
+ D3D11_RECT rect;
+ int x = scissorX;
+ int y = scissorY;
+ rect.left = std::max(0, x);
+ rect.top = std::max(0, y);
+ rect.right = x + std::max(0, scissor.width);
+ rect.bottom = y + std::max(0, scissor.height);
+ mRenderer->getDeviceContext()->RSSetScissorRects(1, &rect);
+ }
+
+ mCurScissorRect = scissor;
+ mCurScissorEnabled = enabled;
+}
+
+void StateManager11::syncViewport(const gl::Context *context)
+{
+ const auto &glState = context->getState();
+ gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
+ float actualZNear = gl::clamp01(glState.getNearPlane());
+ float actualZFar = gl::clamp01(glState.getFarPlane());
+
+ const auto &caps = context->getCaps();
+ int dxMaxViewportBoundsX = caps.maxViewportWidth;
+ int dxMaxViewportBoundsY = caps.maxViewportHeight;
+ int dxMinViewportBoundsX = -dxMaxViewportBoundsX;
+ int dxMinViewportBoundsY = -dxMaxViewportBoundsY;
+
+ bool is9_3 = mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3;
+
+ if (is9_3)
+ {
+ // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget.
+ dxMaxViewportBoundsX = static_cast<int>(mViewportBounds.width);
+ dxMaxViewportBoundsY = static_cast<int>(mViewportBounds.height);
+ dxMinViewportBoundsX = 0;
+ dxMinViewportBoundsY = 0;
+ }
+
+ bool clipSpaceOriginLowerLeft = glState.getClipSpaceOrigin() == gl::ClipSpaceOrigin::LowerLeft;
+ mShaderConstants.onClipControlChange(clipSpaceOriginLowerLeft,
+ glState.isClipControlDepthZeroToOne());
+
+ const auto &viewport = glState.getViewport();
+
+ int dxViewportTopLeftX = 0;
+ int dxViewportTopLeftY = 0;
+ int dxViewportWidth = 0;
+ int dxViewportHeight = 0;
+
+ mCurViewportOffset = framebuffer->getSurfaceTextureOffset();
+
+ dxViewportTopLeftX =
+ gl::clamp(viewport.x + mCurViewportOffset.x, dxMinViewportBoundsX, dxMaxViewportBoundsX);
+ dxViewportTopLeftY =
+ gl::clamp(viewport.y + mCurViewportOffset.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
+ dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
+ dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
+
+ D3D11_VIEWPORT dxViewport;
+ dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
+ if (mCurPresentPathFastEnabled && clipSpaceOriginLowerLeft)
+ {
+ // When present path fast is active and we're rendering to framebuffer 0, we must invert
+ // the viewport in Y-axis.
+ // NOTE: We delay the inversion until right before the call to RSSetViewports, and leave
+ // dxViewportTopLeftY unchanged. This allows us to calculate viewAdjust below using the
+ // unaltered dxViewportTopLeftY value.
+ dxViewport.TopLeftY = static_cast<float>(mCurPresentPathFastColorBufferHeight -
+ dxViewportTopLeftY - dxViewportHeight);
+ }
+ else
+ {
+ dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY);
+ }
+
+ // The es 3.1 spec section 9.2 states that, "If there are no attachments, rendering
+ // will be limited to a rectangle having a lower left of (0, 0) and an upper right of
+ // (width, height), where width and height are the framebuffer object's default width
+ // and height." See http://anglebug.com/1594
+ // If the Framebuffer has no color attachment and the default width or height is smaller
+ // than the current viewport, use the smaller of the two sizes.
+ // If framebuffer default width or height is 0, the params should not set.
+ if (!framebuffer->getFirstNonNullAttachment() &&
+ (framebuffer->getDefaultWidth() || framebuffer->getDefaultHeight()))
+ {
+ dxViewport.Width =
+ static_cast<GLfloat>(std::min(viewport.width, framebuffer->getDefaultWidth()));
+ dxViewport.Height =
+ static_cast<GLfloat>(std::min(viewport.height, framebuffer->getDefaultHeight()));
+ }
+ else
+ {
+ dxViewport.Width = static_cast<float>(dxViewportWidth);
+ dxViewport.Height = static_cast<float>(dxViewportHeight);
+ }
+ dxViewport.MinDepth = actualZNear;
+ dxViewport.MaxDepth = actualZFar;
+
+ mRenderer->getDeviceContext()->RSSetViewports(1, &dxViewport);
+
+ mCurViewport = viewport;
+ mCurNear = actualZNear;
+ mCurFar = actualZFar;
+
+ const D3D11_VIEWPORT adjustViewport = {static_cast<FLOAT>(dxViewportTopLeftX),
+ static_cast<FLOAT>(dxViewportTopLeftY),
+ static_cast<FLOAT>(dxViewportWidth),
+ static_cast<FLOAT>(dxViewportHeight),
+ actualZNear,
+ actualZFar};
+ mShaderConstants.onViewportChange(viewport, adjustViewport, mCurViewportOffset, is9_3,
+ mCurPresentPathFastEnabled);
+}
+
+void StateManager11::invalidateRenderTarget()
+{
+ mRenderTargetIsDirty = true;
+}
+
+void StateManager11::processFramebufferInvalidation(const gl::Context *context)
+{
+ ASSERT(mRenderTargetIsDirty);
+ ASSERT(context);
+
+ mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
+
+ // The pixel shader is dependent on the output layout.
+ invalidateShaders();
+
+ // The D3D11 blend state is heavily dependent on the current render target.
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
+
+ gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
+ ASSERT(fbo);
+
+ // Dirty scissor and viewport because surface texture offset might have changed.
+ if (mCurViewportOffset != fbo->getSurfaceTextureOffset())
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);
+ }
+ if (mCurScissorOffset != fbo->getSurfaceTextureOffset())
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
+ }
+
+ // Disable the depth test/depth write if we are using a stencil-only attachment.
+ // This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read
+ // nor write to the unused depth part of this emulated texture.
+ bool disableDepth = (!fbo->hasDepth() && fbo->hasStencil());
+
+ // Similarly we disable the stencil portion of the DS attachment if the app only binds depth.
+ bool disableStencil = (fbo->hasDepth() && !fbo->hasStencil());
+
+ if (!mCurDisableDepth.valid() || disableDepth != mCurDisableDepth.value() ||
+ !mCurDisableStencil.valid() || disableStencil != mCurDisableStencil.value())
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
+ mCurDisableDepth = disableDepth;
+ mCurDisableStencil = disableStencil;
+ }
+
+ bool multiSample = (fbo->getSamples(context) != 0);
+ if (multiSample != mCurRasterState.multiSample)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+ mCurRasterState.multiSample = multiSample;
+ }
+
+ checkPresentPath(context);
+
+ if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ const auto *firstAttachment = fbo->getFirstNonNullAttachment();
+ if (firstAttachment)
+ {
+ const auto &size = firstAttachment->getSize();
+ if (mViewportBounds.width != size.width || mViewportBounds.height != size.height)
+ {
+ mViewportBounds = gl::Extents(size.width, size.height, 1);
+ invalidateViewport(context);
+ }
+ }
+ }
+}
+
+void StateManager11::invalidateBoundViews()
+{
+ for (SRVCache &curShaderSRV : mCurShaderSRVs)
+ {
+ curShaderSRV.clear();
+ }
+
+ invalidateRenderTarget();
+}
+
+void StateManager11::invalidateVertexBuffer()
+{
+ unsigned int limit = std::min<unsigned int>(mRenderer->getNativeCaps().maxVertexAttributes,
+ gl::MAX_VERTEX_ATTRIBS);
+ mDirtyVertexBufferRange = gl::RangeUI(0, limit);
+ invalidateInputLayout();
+ invalidateShaders();
+ mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS);
+}
+
+void StateManager11::invalidateViewport(const gl::Context *context)
+{
+ mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);
+
+ // Viewport affects the driver constants.
+ invalidateDriverUniforms();
+}
+
+void StateManager11::invalidateTexturesAndSamplers()
+{
+ mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
+ invalidateSwizzles();
+
+ // Texture state affects the driver uniforms (base level, etc).
+ invalidateDriverUniforms();
+}
+
+void StateManager11::invalidateSwizzles()
+{
+ mDirtySwizzles = true;
+}
+
+void StateManager11::invalidateProgramUniforms()
+{
+ mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
+}
+
+void StateManager11::invalidateDriverUniforms()
+{
+ mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
+}
+
+void StateManager11::invalidateProgramUniformBuffers()
+{
+ mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS);
+}
+
+void StateManager11::invalidateProgramAtomicCounterBuffers()
+{
+ mInternalDirtyBits.set(DIRTY_BIT_GRAPHICS_UAV_STATE);
+ mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_UAV_STATE);
+}
+
+void StateManager11::invalidateProgramShaderStorageBuffers()
+{
+ mInternalDirtyBits.set(DIRTY_BIT_GRAPHICS_UAV_STATE);
+ mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_UAV_STATE);
+}
+
+void StateManager11::invalidateImageBindings()
+{
+ mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
+ mInternalDirtyBits.set(DIRTY_BIT_GRAPHICS_SRV_STATE);
+ mInternalDirtyBits.set(DIRTY_BIT_GRAPHICS_UAV_STATE);
+ mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_SRV_STATE);
+ mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_UAV_STATE);
+}
+
+void StateManager11::invalidateConstantBuffer(unsigned int slot)
+{
+ if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER)
+ {
+ invalidateDriverUniforms();
+ }
+ else if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK)
+ {
+ invalidateProgramUniforms();
+ }
+ else
+ {
+ invalidateProgramUniformBuffers();
+ }
+}
+
+void StateManager11::invalidateShaders()
+{
+ mInternalDirtyBits.set(DIRTY_BIT_SHADERS);
+}
+
+void StateManager11::invalidateTransformFeedback()
+{
+ // Transform feedback affects the stream-out geometry shader.
+ invalidateShaders();
+ mInternalDirtyBits.set(DIRTY_BIT_TRANSFORM_FEEDBACK);
+ // syncPrimitiveTopology checks the transform feedback state.
+ mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
+}
+
+void StateManager11::invalidateInputLayout()
+{
+ mInternalDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS_AND_INPUT_LAYOUT);
+}
+
+void StateManager11::invalidateIndexBuffer()
+{
+ mIndexBufferIsDirty = true;
+}
+
+void StateManager11::setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv)
+{
+ if (rtv)
+ {
+ unsetConflictingView(gl::PipelineType::GraphicsPipeline, rtv, true);
+ }
+
+ if (dsv)
+ {
+ unsetConflictingView(gl::PipelineType::GraphicsPipeline, dsv, true);
+ }
+
+ mRenderer->getDeviceContext()->OMSetRenderTargets(1, &rtv, dsv);
+ mCurRTVs.clear();
+ mCurRTVs.update(0, rtv);
+ mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
+}
+
+void StateManager11::setRenderTargets(ID3D11RenderTargetView **rtvs,
+ UINT numRTVs,
+ ID3D11DepthStencilView *dsv)
+{
+ for (UINT rtvIndex = 0; rtvIndex < numRTVs; ++rtvIndex)
+ {
+ unsetConflictingView(gl::PipelineType::GraphicsPipeline, rtvs[rtvIndex], true);
+ }
+
+ if (dsv)
+ {
+ unsetConflictingView(gl::PipelineType::GraphicsPipeline, dsv, true);
+ }
+
+ mRenderer->getDeviceContext()->OMSetRenderTargets(numRTVs, (numRTVs > 0) ? rtvs : nullptr, dsv);
+ mCurRTVs.clear();
+ for (UINT i = 0; i < numRTVs; i++)
+ {
+ mCurRTVs.update(i, rtvs[i]);
+ }
+ mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
+}
+
+void StateManager11::onBeginQuery(Query11 *query)
+{
+ mCurrentQueries.insert(query);
+}
+
+void StateManager11::onDeleteQueryObject(Query11 *query)
+{
+ mCurrentQueries.erase(query);
+}
+
+angle::Result StateManager11::onMakeCurrent(const gl::Context *context)
+{
+ ANGLE_TRY(ensureInitialized(context));
+
+ const gl::State &state = context->getState();
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ for (Query11 *query : mCurrentQueries)
+ {
+ ANGLE_TRY(query->pause(context11));
+ }
+ mCurrentQueries.clear();
+
+ for (gl::QueryType type : angle::AllEnums<gl::QueryType>())
+ {
+ gl::Query *query = state.getActiveQuery(type);
+ if (query != nullptr)
+ {
+ Query11 *query11 = GetImplAs<Query11>(query);
+ ANGLE_TRY(query11->resume(context11));
+ mCurrentQueries.insert(query11);
+ }
+ }
+
+ // Reset the cache objects.
+ mProgramD3D = nullptr;
+ mVertexArray11 = nullptr;
+ mFramebuffer11 = nullptr;
+
+ return angle::Result::Continue;
+}
+
+void StateManager11::unsetConflictingView(gl::PipelineType pipeline,
+ ID3D11View *view,
+ bool isRenderTarget)
+{
+ uintptr_t resource = reinterpret_cast<uintptr_t>(GetViewResource(view));
+
+ unsetConflictingSRVs(pipeline, gl::ShaderType::Vertex, resource, nullptr, isRenderTarget);
+ unsetConflictingSRVs(pipeline, gl::ShaderType::Fragment, resource, nullptr, isRenderTarget);
+ unsetConflictingSRVs(pipeline, gl::ShaderType::Compute, resource, nullptr, isRenderTarget);
+ unsetConflictingUAVs(pipeline, gl::ShaderType::Compute, resource, nullptr);
+}
+
+void StateManager11::unsetConflictingSRVs(gl::PipelineType pipeline,
+ gl::ShaderType shaderType,
+ uintptr_t resource,
+ const gl::ImageIndex *index,
+ bool isRenderTarget)
+{
+ auto *currentSRVs = getSRVCache(shaderType);
+ gl::PipelineType conflictPipeline = gl::GetPipelineType(shaderType);
+ bool foundOne = false;
+ size_t count = std::min(currentSRVs->size(), currentSRVs->highestUsed());
+ for (size_t resourceIndex = 0; resourceIndex < count; ++resourceIndex)
+ {
+ auto &record = (*currentSRVs)[resourceIndex];
+
+ if (record.view && record.resource == resource &&
+ (!index || ImageIndexConflictsWithSRV(*index, record.desc)))
+ {
+ setShaderResourceInternal<d3d11::ShaderResourceView>(
+ shaderType, static_cast<UINT>(resourceIndex), nullptr);
+ foundOne = true;
+ }
+ }
+
+ if (foundOne && (pipeline != conflictPipeline || isRenderTarget))
+ {
+ switch (conflictPipeline)
+ {
+ case gl::PipelineType::GraphicsPipeline:
+ mInternalDirtyBits.set(DIRTY_BIT_GRAPHICS_SRV_STATE);
+ break;
+ case gl::PipelineType::ComputePipeline:
+ mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_SRV_STATE);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+}
+
+void StateManager11::unsetConflictingUAVs(gl::PipelineType pipeline,
+ gl::ShaderType shaderType,
+ uintptr_t resource,
+ const gl::ImageIndex *index)
+{
+ ASSERT(shaderType == gl::ShaderType::Compute);
+ bool foundOne = false;
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ size_t count = std::min(mCurComputeUAVs.size(), mCurComputeUAVs.highestUsed());
+ for (size_t resourceIndex = 0; resourceIndex < count; ++resourceIndex)
+ {
+ auto &record = mCurComputeUAVs[resourceIndex];
+
+ if (record.view && record.resource == resource &&
+ (!index || ImageIndexConflictsWithUAV(*index, record.desc)))
+ {
+ deviceContext->CSSetUnorderedAccessViews(static_cast<UINT>(resourceIndex), 1,
+ &mNullUAVs[0], nullptr);
+ mCurComputeUAVs.update(resourceIndex, nullptr);
+ foundOne = true;
+ }
+ }
+
+ if (foundOne && pipeline == gl::PipelineType::GraphicsPipeline)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_COMPUTE_UAV_STATE);
+ }
+}
+
+void StateManager11::unsetConflictingRTVs(uintptr_t resource)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ size_t count = std::min(mCurRTVs.size(), mCurRTVs.highestUsed());
+ for (size_t resourceIndex = 0; resourceIndex < count; ++resourceIndex)
+ {
+ auto &record = mCurRTVs[resourceIndex];
+
+ if (record.view && record.resource == resource)
+ {
+ deviceContext->OMSetRenderTargets(0, nullptr, nullptr);
+ mCurRTVs.clear();
+ mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET);
+ return;
+ }
+ }
+}
+
+void StateManager11::unsetConflictingAttachmentResources(
+ const gl::FramebufferAttachment &attachment,
+ ID3D11Resource *resource)
+{
+ // Unbind render target SRVs from the shader here to prevent D3D11 warnings.
+ if (attachment.type() == GL_TEXTURE)
+ {
+ uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource);
+ const gl::ImageIndex &index = attachment.getTextureImageIndex();
+ // The index doesn't need to be corrected for the small compressed texture workaround
+ // because a rendertarget is never compressed.
+ unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Vertex,
+ resourcePtr, &index, false);
+ unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Fragment,
+ resourcePtr, &index, false);
+ unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute,
+ resourcePtr, &index, false);
+ unsetConflictingUAVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute,
+ resourcePtr, &index);
+ }
+ else if (attachment.type() == GL_FRAMEBUFFER_DEFAULT)
+ {
+ uintptr_t resourcePtr = reinterpret_cast<uintptr_t>(resource);
+ unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Vertex,
+ resourcePtr, nullptr, false);
+ unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Fragment,
+ resourcePtr, nullptr, false);
+ unsetConflictingSRVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute,
+ resourcePtr, nullptr, false);
+ unsetConflictingUAVs(gl::PipelineType::GraphicsPipeline, gl::ShaderType::Compute,
+ resourcePtr, nullptr);
+ }
+}
+
+angle::Result StateManager11::ensureInitialized(const gl::Context *context)
+{
+ Renderer11 *renderer = GetImplAs<Context11>(context)->getRenderer();
+
+ const gl::Caps &caps = renderer->getNativeCaps();
+ const gl::Extensions &extensions = renderer->getNativeExtensions();
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ const GLuint maxShaderTextureImageUnits =
+ static_cast<GLuint>(caps.maxShaderTextureImageUnits[shaderType]);
+
+ mCurShaderSRVs[shaderType].initialize(maxShaderTextureImageUnits);
+ mForceSetShaderSamplerStates[shaderType].resize(maxShaderTextureImageUnits, true);
+ mCurShaderSamplerStates[shaderType].resize(maxShaderTextureImageUnits);
+ }
+ mCurRTVs.initialize(caps.maxColorAttachments);
+ mCurComputeUAVs.initialize(caps.maxImageUnits);
+
+ // Initialize cached NULL SRV block
+ mNullSRVs.resize(caps.maxShaderTextureImageUnits[gl::ShaderType::Fragment], nullptr);
+
+ mNullUAVs.resize(caps.maxImageUnits, nullptr);
+
+ mCurrentValueAttribs.resize(caps.maxVertexAttributes);
+
+ mShaderConstants.init(caps);
+
+ mIsMultiviewEnabled = extensions.multiviewOVR || extensions.multiview2OVR;
+
+ mIndependentBlendStates = extensions.drawBuffersIndexedAny(); // requires FL10_1
+
+ // FL9_3 is limited to 4; ES3.1 context on FL11_0 is limited to 7
+ mCurBlendStateExt =
+ gl::BlendStateExt(GetImplAs<Context11>(context)->getNativeCaps().maxDrawBuffers);
+
+ ANGLE_TRY(mVertexDataManager.initialize(context));
+
+ mCurrentAttributes.reserve(gl::MAX_VERTEX_ATTRIBS);
+
+ return angle::Result::Continue;
+}
+
+void StateManager11::deinitialize()
+{
+ mCurrentValueAttribs.clear();
+ mInputLayoutCache.clear();
+ mVertexDataManager.deinitialize();
+ mIndexDataManager.deinitialize();
+
+ for (d3d11::Buffer &ShaderDriverConstantBuffer : mShaderDriverConstantBuffers)
+ {
+ ShaderDriverConstantBuffer.reset();
+ }
+
+ mPointSpriteVertexBuffer.reset();
+ mPointSpriteIndexBuffer.reset();
+}
+
+// Applies the render target surface, depth stencil surface, viewport rectangle and
+// scissor rectangle to the renderer
+angle::Result StateManager11::syncFramebuffer(const gl::Context *context)
+{
+ // Check for zero-sized default framebuffer, which is a special case.
+ // in this case we do not wish to modify any state and just silently return false.
+ // this will not report any gl error but will cause the calling method to return.
+ if (mFramebuffer11->getState().isDefault())
+ {
+ RenderTarget11 *firstRT = mFramebuffer11->getFirstRenderTarget();
+ const gl::Extents &size = firstRT->getExtents();
+ if (size.empty())
+ {
+ return angle::Result::Continue;
+ }
+ }
+
+ RTVArray framebufferRTVs = {{}};
+ const auto &colorRTs = mFramebuffer11->getCachedColorRenderTargets();
+
+ size_t appliedRTIndex = 0;
+ bool skipInactiveRTs = mRenderer->getFeatures().mrtPerfWorkaround.enabled;
+ const auto &drawStates = mFramebuffer11->getState().getDrawBufferStates();
+ gl::DrawBufferMask activeProgramOutputs =
+ mProgramD3D->getState().getExecutable().getActiveOutputVariablesMask();
+ UINT maxExistingRT = 0;
+ const auto &colorAttachments = mFramebuffer11->getState().getColorAttachments();
+
+ for (size_t rtIndex = 0; rtIndex < colorRTs.size(); ++rtIndex)
+ {
+ const RenderTarget11 *renderTarget = colorRTs[rtIndex];
+
+ // Skip inactive rendertargets if the workaround is enabled.
+ if (skipInactiveRTs &&
+ (!renderTarget || drawStates[rtIndex] == GL_NONE || !activeProgramOutputs[rtIndex]))
+ {
+ continue;
+ }
+
+ if (renderTarget)
+ {
+ framebufferRTVs[appliedRTIndex] = renderTarget->getRenderTargetView().get();
+ ASSERT(framebufferRTVs[appliedRTIndex]);
+ maxExistingRT = static_cast<UINT>(appliedRTIndex) + 1;
+
+ // Unset conflicting texture SRVs
+ const gl::FramebufferAttachment &attachment = colorAttachments[rtIndex];
+ ASSERT(attachment.isAttached());
+ unsetConflictingAttachmentResources(attachment, renderTarget->getTexture().get());
+ }
+
+ appliedRTIndex++;
+ }
+
+ // Get the depth stencil buffers
+ ID3D11DepthStencilView *framebufferDSV = nullptr;
+ const auto *depthStencilRenderTarget = mFramebuffer11->getCachedDepthStencilRenderTarget();
+ if (depthStencilRenderTarget)
+ {
+ framebufferDSV = depthStencilRenderTarget->getDepthStencilView().get();
+ ASSERT(framebufferDSV);
+
+ // Unset conflicting texture SRVs
+ const gl::FramebufferAttachment *attachment =
+ mFramebuffer11->getState().getDepthOrStencilAttachment();
+ ASSERT(attachment);
+ unsetConflictingAttachmentResources(*attachment,
+ depthStencilRenderTarget->getTexture().get());
+ }
+
+ ASSERT(maxExistingRT <= static_cast<UINT>(context->getCaps().maxDrawBuffers));
+
+ // Apply the render target and depth stencil
+ mRenderer->getDeviceContext()->OMSetRenderTargets(maxExistingRT, framebufferRTVs.data(),
+ framebufferDSV);
+ mCurRTVs.clear();
+ for (UINT i = 0; i < maxExistingRT; i++)
+ {
+ mCurRTVs.update(i, framebufferRTVs[i]);
+ }
+ return angle::Result::Continue;
+}
+
+void StateManager11::invalidateCurrentValueAttrib(size_t attribIndex)
+{
+ mDirtyCurrentValueAttribs.set(attribIndex);
+ mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS);
+ invalidateInputLayout();
+ invalidateShaders();
+}
+
+angle::Result StateManager11::syncCurrentValueAttribs(
+ const gl::Context *context,
+ const std::vector<gl::VertexAttribCurrentValueData> &currentValues)
+{
+ const gl::ProgramExecutable &executable = mProgramD3D->getState().getExecutable();
+ const auto &activeAttribsMask = executable.getActiveAttribLocationsMask();
+ const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs);
+
+ if (!dirtyActiveAttribs.any())
+ {
+ return angle::Result::Continue;
+ }
+
+ const auto &vertexAttributes = mVertexArray11->getState().getVertexAttributes();
+ const auto &vertexBindings = mVertexArray11->getState().getVertexBindings();
+ mDirtyCurrentValueAttribs = (mDirtyCurrentValueAttribs & ~dirtyActiveAttribs);
+
+ for (auto attribIndex : dirtyActiveAttribs)
+ {
+ if (vertexAttributes[attribIndex].enabled)
+ continue;
+
+ const auto *attrib = &vertexAttributes[attribIndex];
+ const auto &currentValue = currentValues[attribIndex];
+ TranslatedAttribute *currentValueAttrib = &mCurrentValueAttribs[attribIndex];
+ currentValueAttrib->currentValueType = currentValue.Type;
+ currentValueAttrib->attribute = attrib;
+ currentValueAttrib->binding = &vertexBindings[attrib->bindingIndex];
+
+ mDirtyVertexBufferRange.extend(static_cast<unsigned int>(attribIndex));
+
+ ANGLE_TRY(mVertexDataManager.storeCurrentValue(context, currentValue, currentValueAttrib,
+ static_cast<size_t>(attribIndex)));
+ }
+
+ return angle::Result::Continue;
+}
+
+void StateManager11::setInputLayout(const d3d11::InputLayout *inputLayout)
+{
+ if (setInputLayoutInternal(inputLayout))
+ {
+ invalidateInputLayout();
+ }
+}
+
+bool StateManager11::setInputLayoutInternal(const d3d11::InputLayout *inputLayout)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ if (inputLayout == nullptr)
+ {
+ if (!mCurrentInputLayout.empty())
+ {
+ deviceContext->IASetInputLayout(nullptr);
+ mCurrentInputLayout.clear();
+ return true;
+ }
+ }
+ else if (inputLayout->getSerial() != mCurrentInputLayout)
+ {
+ deviceContext->IASetInputLayout(inputLayout->get());
+ mCurrentInputLayout = inputLayout->getSerial();
+ return true;
+ }
+
+ return false;
+}
+
+bool StateManager11::queueVertexBufferChange(size_t bufferIndex,
+ ID3D11Buffer *buffer,
+ UINT stride,
+ UINT offset)
+{
+ if (buffer != mCurrentVertexBuffers[bufferIndex] ||
+ stride != mCurrentVertexStrides[bufferIndex] ||
+ offset != mCurrentVertexOffsets[bufferIndex])
+ {
+ mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));
+
+ mCurrentVertexBuffers[bufferIndex] = buffer;
+ mCurrentVertexStrides[bufferIndex] = stride;
+ mCurrentVertexOffsets[bufferIndex] = offset;
+ return true;
+ }
+
+ return false;
+}
+
+void StateManager11::applyVertexBufferChanges()
+{
+ if (mDirtyVertexBufferRange.empty())
+ {
+ return;
+ }
+
+ ASSERT(mDirtyVertexBufferRange.high() <= gl::MAX_VERTEX_ATTRIBS);
+
+ UINT start = static_cast<UINT>(mDirtyVertexBufferRange.low());
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->IASetVertexBuffers(start, static_cast<UINT>(mDirtyVertexBufferRange.length()),
+ &mCurrentVertexBuffers[start], &mCurrentVertexStrides[start],
+ &mCurrentVertexOffsets[start]);
+
+ mDirtyVertexBufferRange = gl::RangeUI(gl::MAX_VERTEX_ATTRIBS, 0);
+}
+
+void StateManager11::setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset)
+{
+ ID3D11Buffer *native = buffer ? buffer->get() : nullptr;
+ if (queueVertexBufferChange(0, native, stride, offset))
+ {
+ invalidateInputLayout();
+ applyVertexBufferChanges();
+ }
+}
+
+angle::Result StateManager11::updateState(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint firstVertex,
+ GLsizei vertexOrIndexCount,
+ gl::DrawElementsType indexTypeOrInvalid,
+ const void *indices,
+ GLsizei instanceCount,
+ GLint baseVertex,
+ GLuint baseInstance,
+ bool promoteDynamic)
+{
+ const gl::State &glState = context->getState();
+
+ // TODO(jmadill): Use dirty bits.
+ if (mRenderTargetIsDirty)
+ {
+ processFramebufferInvalidation(context);
+ mRenderTargetIsDirty = false;
+ }
+
+ // TODO(jmadill): Use dirty bits.
+ if (mProgramD3D->updateSamplerMapping() == ProgramD3D::SamplerMapping::WasDirty)
+ {
+ invalidateTexturesAndSamplers();
+ }
+
+ // TODO(jmadill): Use dirty bits.
+ if (mProgramD3D->anyShaderUniformsDirty())
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS);
+ }
+
+ // Swizzling can cause internal state changes with blit shaders.
+ if (mDirtySwizzles)
+ {
+ ANGLE_TRY(generateSwizzles(context));
+ mDirtySwizzles = false;
+ }
+
+ ANGLE_TRY(mFramebuffer11->markAttachmentsDirty(context));
+
+ // TODO(jiawei.shao@intel.com): This can be recomputed only on framebuffer or multisample mask
+ // state changes.
+ RenderTarget11 *firstRT = mFramebuffer11->getFirstRenderTarget();
+ int samples = (firstRT ? firstRT->getSamples() : 0);
+ unsigned int sampleMask = GetBlendSampleMask(glState, samples);
+ if (sampleMask != mCurSampleMask)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
+ }
+
+ ANGLE_TRY(mVertexArray11->syncStateForDraw(context, firstVertex, vertexOrIndexCount,
+ indexTypeOrInvalid, indices, instanceCount,
+ baseVertex, baseInstance, promoteDynamic));
+
+ // Changes in the draw call can affect the vertex buffer translations.
+ if (!mLastFirstVertex.valid() || mLastFirstVertex.value() != firstVertex)
+ {
+ mLastFirstVertex = firstVertex;
+ invalidateInputLayout();
+ }
+
+ // The ShaderConstants only need to be updated when the program uses vertexID
+ if (mProgramD3D->usesVertexID())
+ {
+ GLint firstVertexOnChange = firstVertex + baseVertex;
+ ASSERT(mVertexArray11);
+ if (mVertexArray11->hasActiveDynamicAttrib(context) &&
+ indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
+ {
+ // drawElements with Dynamic attribute
+ // the firstVertex is already including baseVertex when
+ // doing ComputeStartVertex
+ firstVertexOnChange = firstVertex;
+ }
+
+ if (mShaderConstants.onFirstVertexChange(firstVertexOnChange))
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS);
+ }
+ }
+
+ if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
+ {
+ ANGLE_TRY(applyIndexBuffer(context, vertexOrIndexCount, indexTypeOrInvalid, indices));
+ }
+
+ if (mLastAppliedDrawMode != mode)
+ {
+ mLastAppliedDrawMode = mode;
+ mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
+
+ bool pointDrawMode = (mode == gl::PrimitiveMode::Points);
+ if (pointDrawMode != mCurRasterState.pointDrawMode)
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+
+ // Changing from points to not points (or vice-versa) affects the geometry shader.
+ invalidateShaders();
+ }
+ }
+
+ auto dirtyBitsCopy = mInternalDirtyBits & mGraphicsDirtyBitsMask;
+
+ for (auto iter = dirtyBitsCopy.begin(), end = dirtyBitsCopy.end(); iter != end; ++iter)
+ {
+ mInternalDirtyBits.reset(*iter);
+ switch (*iter)
+ {
+ case DIRTY_BIT_RENDER_TARGET:
+ ANGLE_TRY(syncFramebuffer(context));
+ break;
+ case DIRTY_BIT_VIEWPORT_STATE:
+ syncViewport(context);
+ break;
+ case DIRTY_BIT_SCISSOR_STATE:
+ syncScissorRectangle(context);
+ break;
+ case DIRTY_BIT_RASTERIZER_STATE:
+ ANGLE_TRY(syncRasterizerState(context, mode));
+ break;
+ case DIRTY_BIT_BLEND_STATE:
+ ANGLE_TRY(syncBlendState(
+ context, glState.getBlendStateExt(), glState.getBlendColor(), sampleMask,
+ glState.isSampleAlphaToCoverageEnabled(), glState.hasConstantAlphaBlendFunc()));
+ break;
+ case DIRTY_BIT_DEPTH_STENCIL_STATE:
+ ANGLE_TRY(syncDepthStencilState(context));
+ break;
+ case DIRTY_BIT_GRAPHICS_SRV_STATE:
+ ANGLE_TRY(syncTextures(context));
+ break;
+ case DIRTY_BIT_GRAPHICS_UAV_STATE:
+ ANGLE_TRY(syncUAVsForGraphics(context));
+ break;
+ case DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE:
+ // TODO(jmadill): More fine-grained update.
+ ANGLE_TRY(syncTextures(context));
+ break;
+ case DIRTY_BIT_PROGRAM_UNIFORMS:
+ ANGLE_TRY(applyUniforms(context));
+ break;
+ case DIRTY_BIT_DRIVER_UNIFORMS:
+ // This must happen after viewport sync; the viewport affects builtin uniforms.
+ ANGLE_TRY(applyDriverUniforms(context));
+ break;
+ case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS:
+ ANGLE_TRY(syncUniformBuffers(context));
+ break;
+ case DIRTY_BIT_SHADERS:
+ ANGLE_TRY(syncProgram(context, mode));
+ break;
+ case DIRTY_BIT_CURRENT_VALUE_ATTRIBS:
+ ANGLE_TRY(syncCurrentValueAttribs(context, glState.getVertexAttribCurrentValues()));
+ break;
+ case DIRTY_BIT_TRANSFORM_FEEDBACK:
+ ANGLE_TRY(syncTransformFeedbackBuffers(context));
+ break;
+ case DIRTY_BIT_VERTEX_BUFFERS_AND_INPUT_LAYOUT:
+ ANGLE_TRY(syncVertexBuffersAndInputLayout(context, mode, firstVertex,
+ vertexOrIndexCount, indexTypeOrInvalid,
+ instanceCount));
+ break;
+ case DIRTY_BIT_PRIMITIVE_TOPOLOGY:
+ syncPrimitiveTopology(glState, mode);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+
+ // Check that we haven't set any dirty bits in the flushing of the dirty bits loop, except
+ // DIRTY_BIT_COMPUTE_SRVUAV_STATE dirty bit.
+ ASSERT((mInternalDirtyBits & mGraphicsDirtyBitsMask).none());
+
+ return angle::Result::Continue;
+}
+
+void StateManager11::setShaderResourceShared(gl::ShaderType shaderType,
+ UINT resourceSlot,
+ const d3d11::SharedSRV *srv)
+{
+ setShaderResourceInternal(shaderType, resourceSlot, srv);
+
+ // TODO(jmadill): Narrower dirty region.
+ mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
+}
+
+void StateManager11::setShaderResource(gl::ShaderType shaderType,
+ UINT resourceSlot,
+ const d3d11::ShaderResourceView *srv)
+{
+ setShaderResourceInternal(shaderType, resourceSlot, srv);
+
+ // TODO(jmadill): Narrower dirty region.
+ mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
+}
+
+void StateManager11::setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)
+{
+ if (setPrimitiveTopologyInternal(primitiveTopology))
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_PRIMITIVE_TOPOLOGY);
+ }
+}
+
+bool StateManager11::setPrimitiveTopologyInternal(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology)
+{
+ if (primitiveTopology != mCurrentPrimitiveTopology)
+ {
+ mRenderer->getDeviceContext()->IASetPrimitiveTopology(primitiveTopology);
+ mCurrentPrimitiveTopology = primitiveTopology;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void StateManager11::setDrawShaders(const d3d11::VertexShader *vertexShader,
+ const d3d11::GeometryShader *geometryShader,
+ const d3d11::PixelShader *pixelShader)
+{
+ setVertexShader(vertexShader);
+ setGeometryShader(geometryShader);
+ setPixelShader(pixelShader);
+}
+
+void StateManager11::setVertexShader(const d3d11::VertexShader *shader)
+{
+ ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
+
+ if (serial != mAppliedShaders[gl::ShaderType::Vertex])
+ {
+ ID3D11VertexShader *appliedShader = shader ? shader->get() : nullptr;
+ mRenderer->getDeviceContext()->VSSetShader(appliedShader, nullptr, 0);
+ mAppliedShaders[gl::ShaderType::Vertex] = serial;
+ invalidateShaders();
+ }
+}
+
+void StateManager11::setGeometryShader(const d3d11::GeometryShader *shader)
+{
+ ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
+
+ if (serial != mAppliedShaders[gl::ShaderType::Geometry])
+ {
+ ID3D11GeometryShader *appliedShader = shader ? shader->get() : nullptr;
+ mRenderer->getDeviceContext()->GSSetShader(appliedShader, nullptr, 0);
+ mAppliedShaders[gl::ShaderType::Geometry] = serial;
+ invalidateShaders();
+ }
+}
+
+void StateManager11::setPixelShader(const d3d11::PixelShader *shader)
+{
+ ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
+
+ if (serial != mAppliedShaders[gl::ShaderType::Fragment])
+ {
+ ID3D11PixelShader *appliedShader = shader ? shader->get() : nullptr;
+ mRenderer->getDeviceContext()->PSSetShader(appliedShader, nullptr, 0);
+ mAppliedShaders[gl::ShaderType::Fragment] = serial;
+ invalidateShaders();
+ }
+}
+
+void StateManager11::setComputeShader(const d3d11::ComputeShader *shader)
+{
+ ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0);
+
+ if (serial != mAppliedShaders[gl::ShaderType::Compute])
+ {
+ ID3D11ComputeShader *appliedShader = shader ? shader->get() : nullptr;
+ mRenderer->getDeviceContext()->CSSetShader(appliedShader, nullptr, 0);
+ mAppliedShaders[gl::ShaderType::Compute] = serial;
+ invalidateShaders();
+ }
+}
+
+void StateManager11::setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ auto &currentSerial = mCurrentConstantBufferVS[slot];
+
+ mCurrentConstantBufferVSOffset[slot] = 0;
+ mCurrentConstantBufferVSSize[slot] = 0;
+
+ if (buffer)
+ {
+ if (currentSerial != buffer->getSerial())
+ {
+ deviceContext->VSSetConstantBuffers(slot, 1, buffer->getPointer());
+ currentSerial = buffer->getSerial();
+ invalidateConstantBuffer(slot);
+ }
+ }
+ else
+ {
+ if (!currentSerial.empty())
+ {
+ ID3D11Buffer *nullBuffer = nullptr;
+ deviceContext->VSSetConstantBuffers(slot, 1, &nullBuffer);
+ currentSerial.clear();
+ invalidateConstantBuffer(slot);
+ }
+ }
+}
+
+void StateManager11::setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ auto &currentSerial = mCurrentConstantBufferPS[slot];
+
+ mCurrentConstantBufferPSOffset[slot] = 0;
+ mCurrentConstantBufferPSSize[slot] = 0;
+
+ if (buffer)
+ {
+ if (currentSerial != buffer->getSerial())
+ {
+ deviceContext->PSSetConstantBuffers(slot, 1, buffer->getPointer());
+ currentSerial = buffer->getSerial();
+ invalidateConstantBuffer(slot);
+ }
+ }
+ else
+ {
+ if (!currentSerial.empty())
+ {
+ ID3D11Buffer *nullBuffer = nullptr;
+ deviceContext->PSSetConstantBuffers(slot, 1, &nullBuffer);
+ currentSerial.clear();
+ invalidateConstantBuffer(slot);
+ }
+ }
+}
+
+void StateManager11::setDepthStencilState(const d3d11::DepthStencilState *depthStencilState,
+ UINT stencilRef)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ if (depthStencilState)
+ {
+ deviceContext->OMSetDepthStencilState(depthStencilState->get(), stencilRef);
+ }
+ else
+ {
+ deviceContext->OMSetDepthStencilState(nullptr, stencilRef);
+ }
+
+ mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE);
+}
+
+void StateManager11::setSimpleBlendState(const d3d11::BlendState *blendState)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ if (blendState)
+ {
+ deviceContext->OMSetBlendState(blendState->get(), nullptr, 0xFFFFFFFF);
+ }
+ else
+ {
+ deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFFF);
+ }
+
+ mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE);
+}
+
+void StateManager11::setRasterizerState(const d3d11::RasterizerState *rasterizerState)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ if (rasterizerState)
+ {
+ deviceContext->RSSetState(rasterizerState->get());
+ }
+ else
+ {
+ deviceContext->RSSetState(nullptr);
+ }
+
+ mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE);
+}
+
+void StateManager11::setSimpleViewport(const gl::Extents &extents)
+{
+ setSimpleViewport(extents.width, extents.height);
+}
+
+void StateManager11::setSimpleViewport(int width, int height)
+{
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = static_cast<FLOAT>(width);
+ viewport.Height = static_cast<FLOAT>(height);
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+
+ mRenderer->getDeviceContext()->RSSetViewports(1, &viewport);
+ mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);
+}
+
+void StateManager11::setSimplePixelTextureAndSampler(const d3d11::SharedSRV &srv,
+ const d3d11::SamplerState &samplerState)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ setShaderResourceInternal(gl::ShaderType::Fragment, 0, &srv);
+ deviceContext->PSSetSamplers(0, 1, samplerState.getPointer());
+
+ mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
+ mForceSetShaderSamplerStates[gl::ShaderType::Fragment][0] = true;
+}
+
+void StateManager11::setSimpleScissorRect(const gl::Rectangle &glRect)
+{
+ D3D11_RECT scissorRect;
+ scissorRect.left = glRect.x;
+ scissorRect.right = glRect.x + glRect.width;
+ scissorRect.top = glRect.y;
+ scissorRect.bottom = glRect.y + glRect.height;
+ setScissorRectD3D(scissorRect);
+}
+
+void StateManager11::setScissorRectD3D(const D3D11_RECT &d3dRect)
+{
+ mRenderer->getDeviceContext()->RSSetScissorRects(1, &d3dRect);
+ mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
+}
+
+angle::Result StateManager11::syncTextures(const gl::Context *context)
+{
+ ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Vertex));
+ ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Fragment));
+ if (mProgramD3D->hasShaderStage(gl::ShaderType::Geometry))
+ {
+ ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Geometry));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::setSamplerState(const gl::Context *context,
+ gl::ShaderType type,
+ int index,
+ gl::Texture *texture,
+ const gl::SamplerState &samplerState)
+{
+#if !defined(NDEBUG)
+ // Storage should exist, texture should be complete. Only verified in Debug.
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+ TextureStorage *storage = nullptr;
+ ANGLE_TRY(textureD3D->getNativeTexture(context, &storage));
+ ASSERT(storage);
+#endif // !defined(NDEBUG)
+
+ auto *deviceContext = mRenderer->getDeviceContext();
+
+ ASSERT(index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[type]);
+
+ if (mForceSetShaderSamplerStates[type][index] ||
+ memcmp(&samplerState, &mCurShaderSamplerStates[type][index], sizeof(gl::SamplerState)) != 0)
+ {
+ ID3D11SamplerState *dxSamplerState = nullptr;
+ ANGLE_TRY(mRenderer->getSamplerState(context, samplerState, &dxSamplerState));
+
+ ASSERT(dxSamplerState != nullptr);
+
+ switch (type)
+ {
+ case gl::ShaderType::Vertex:
+ deviceContext->VSSetSamplers(index, 1, &dxSamplerState);
+ break;
+ case gl::ShaderType::Fragment:
+ deviceContext->PSSetSamplers(index, 1, &dxSamplerState);
+ break;
+ case gl::ShaderType::Compute:
+ deviceContext->CSSetSamplers(index, 1, &dxSamplerState);
+ break;
+ case gl::ShaderType::Geometry:
+ deviceContext->GSSetSamplers(index, 1, &dxSamplerState);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ mCurShaderSamplerStates[type][index] = samplerState;
+ }
+
+ mForceSetShaderSamplerStates[type][index] = false;
+
+ // Sampler metadata that's passed to shaders in uniforms is stored separately from rest of the
+ // sampler state since having it in contiguous memory makes it possible to memcpy to a constant
+ // buffer, and it doesn't affect the state set by
+ // PSSetSamplers/VSSetSamplers/CSSetSamplers/GSSetSamplers.
+ mShaderConstants.onSamplerChange(type, index, *texture, samplerState);
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::setTextureForSampler(const gl::Context *context,
+ gl::ShaderType type,
+ int index,
+ gl::Texture *texture,
+ const gl::SamplerState &sampler)
+{
+ const d3d11::SharedSRV *textureSRV = nullptr;
+
+ if (texture)
+ {
+ TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
+
+ TextureStorage *texStorage = nullptr;
+ ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
+
+ // Texture should be complete and have a storage
+ ASSERT(texStorage);
+
+ TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
+
+ ANGLE_TRY(
+ storage11->getSRVForSampler(context, texture->getTextureState(), sampler, &textureSRV));
+
+ // If we get an invalid SRV here, something went wrong in the texture class and we're
+ // unexpectedly missing the shader resource view.
+ ASSERT(textureSRV->valid());
+
+ textureImpl->resetDirty();
+ }
+
+ ASSERT(
+ (type == gl::ShaderType::Fragment &&
+ index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Fragment]) ||
+ (type == gl::ShaderType::Vertex &&
+ index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Vertex]) ||
+ (type == gl::ShaderType::Compute &&
+ index < mRenderer->getNativeCaps().maxShaderTextureImageUnits[gl::ShaderType::Compute]));
+
+ setShaderResourceInternal(type, index, textureSRV);
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::setImageState(const gl::Context *context,
+ gl::ShaderType type,
+ int index,
+ const gl::ImageUnit &imageUnit)
+{
+ ASSERT(index < mRenderer->getNativeCaps().maxShaderImageUniforms[type]);
+
+ if (mShaderConstants.onImageChange(type, index, imageUnit))
+ {
+ invalidateProgramUniforms();
+ }
+
+ return angle::Result::Continue;
+}
+
+// For each Direct3D sampler of either the pixel or vertex stage,
+// looks up the corresponding OpenGL texture image unit and texture type,
+// and sets the texture and its addressing/filtering state (or NULL when inactive).
+// Sampler mapping needs to be up-to-date on the program object before this is called.
+angle::Result StateManager11::applyTexturesForSRVs(const gl::Context *context,
+ gl::ShaderType shaderType)
+{
+ const auto &glState = context->getState();
+ const auto &caps = context->getCaps();
+
+ ASSERT(!mProgramD3D->isSamplerMappingDirty());
+
+ // TODO(jmadill): Use the Program's sampler bindings.
+ const gl::ActiveTexturesCache &completeTextures = glState.getActiveTexturesCache();
+
+ const gl::RangeUI samplerRange = mProgramD3D->getUsedSamplerRange(shaderType);
+ for (unsigned int samplerIndex = samplerRange.low(); samplerIndex < samplerRange.high();
+ samplerIndex++)
+ {
+ GLint textureUnit = mProgramD3D->getSamplerMapping(shaderType, samplerIndex, caps);
+ ASSERT(textureUnit != -1);
+ gl::Texture *texture = completeTextures[textureUnit];
+
+ // A nullptr texture indicates incomplete.
+ if (texture)
+ {
+ gl::Sampler *samplerObject = glState.getSampler(textureUnit);
+
+ const gl::SamplerState &samplerState =
+ samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
+
+ ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
+ ANGLE_TRY(
+ setTextureForSampler(context, shaderType, samplerIndex, texture, samplerState));
+ }
+ else
+ {
+ gl::TextureType textureType =
+ mProgramD3D->getSamplerTextureType(shaderType, samplerIndex);
+
+ // Texture is not sampler complete or it is in use by the framebuffer. Bind the
+ // incomplete texture.
+ gl::Texture *incompleteTexture = nullptr;
+ ANGLE_TRY(mRenderer->getIncompleteTexture(context, textureType, &incompleteTexture));
+ ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
+ incompleteTexture->getSamplerState()));
+ ANGLE_TRY(setTextureForSampler(context, shaderType, samplerIndex, incompleteTexture,
+ incompleteTexture->getSamplerState()));
+ }
+ }
+
+ const gl::RangeUI readonlyImageRange = mProgramD3D->getUsedImageRange(shaderType, true);
+ for (unsigned int readonlyImageIndex = readonlyImageRange.low();
+ readonlyImageIndex < readonlyImageRange.high(); readonlyImageIndex++)
+ {
+ GLint imageUnitIndex =
+ mProgramD3D->getImageMapping(shaderType, readonlyImageIndex, true, caps);
+ ASSERT(imageUnitIndex != -1);
+ const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
+ if (!imageUnit.layered)
+ {
+ ANGLE_TRY(setImageState(context, gl::ShaderType::Compute,
+ readonlyImageIndex - readonlyImageRange.low(), imageUnit));
+ }
+ ANGLE_TRY(setTextureForImage(context, shaderType, readonlyImageIndex, imageUnit));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::getUAVsForRWImages(const gl::Context *context,
+ gl::ShaderType shaderType,
+ UAVList *uavList)
+{
+ const auto &glState = context->getState();
+ const auto &caps = context->getCaps();
+
+ const gl::RangeUI imageRange = mProgramD3D->getUsedImageRange(shaderType, false);
+ for (unsigned int imageIndex = imageRange.low(); imageIndex < imageRange.high(); imageIndex++)
+ {
+ GLint imageUnitIndex = mProgramD3D->getImageMapping(shaderType, imageIndex, false, caps);
+ ASSERT(imageUnitIndex != -1);
+ const gl::ImageUnit &imageUnit = glState.getImageUnit(imageUnitIndex);
+ if (!imageUnit.layered)
+ {
+ ANGLE_TRY(setImageState(context, shaderType, imageIndex - imageRange.low(), imageUnit));
+ }
+ ANGLE_TRY(getUAVForRWImage(context, shaderType, imageIndex, imageUnit, uavList));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::syncTexturesForCompute(const gl::Context *context)
+{
+ ANGLE_TRY(applyTexturesForSRVs(context, gl::ShaderType::Compute));
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::setTextureForImage(const gl::Context *context,
+ gl::ShaderType type,
+ int index,
+ const gl::ImageUnit &imageUnit)
+{
+ TextureD3D *textureImpl = nullptr;
+ if (!imageUnit.texture.get())
+ {
+ setShaderResourceInternal<d3d11::ShaderResourceView>(type, static_cast<UINT>(index),
+ nullptr);
+ return angle::Result::Continue;
+ }
+
+ textureImpl = GetImplAs<TextureD3D>(imageUnit.texture.get());
+
+ // Ensure that texture has unordered access; convert it if not.
+ ANGLE_TRY(textureImpl->ensureUnorderedAccess(context));
+
+ TextureStorage *texStorage = nullptr;
+ ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
+ // Texture should be complete and have a storage
+ ASSERT(texStorage);
+ TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
+
+ const d3d11::SharedSRV *textureSRV = nullptr;
+ ANGLE_TRY(storage11->getSRVForImage(context, imageUnit, &textureSRV));
+ // If we get an invalid SRV here, something went wrong in the texture class and we're
+ // unexpectedly missing the shader resource view.
+ ASSERT(textureSRV->valid());
+ ASSERT((index < mRenderer->getNativeCaps().maxImageUnits));
+ setShaderResourceInternal(type, index, textureSRV);
+
+ textureImpl->resetDirty();
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::getUAVForRWImage(const gl::Context *context,
+ gl::ShaderType type,
+ int index,
+ const gl::ImageUnit &imageUnit,
+ UAVList *uavList)
+{
+ TextureD3D *textureImpl = nullptr;
+ if (!imageUnit.texture.get())
+ {
+ setUnorderedAccessViewInternal<d3d11::UnorderedAccessView>(static_cast<UINT>(index),
+ nullptr, uavList);
+ return angle::Result::Continue;
+ }
+
+ textureImpl = GetImplAs<TextureD3D>(imageUnit.texture.get());
+
+ // Ensure that texture has unordered access; convert it if not.
+ ANGLE_TRY(textureImpl->ensureUnorderedAccess(context));
+
+ TextureStorage *texStorage = nullptr;
+ ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
+ // Texture should be complete and have a storage
+ ASSERT(texStorage);
+ TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
+
+ const d3d11::SharedUAV *textureUAV = nullptr;
+ ANGLE_TRY(storage11->getUAVForImage(context, imageUnit, &textureUAV));
+ // If we get an invalid UAV here, something went wrong in the texture class and we're
+ // unexpectedly missing the unordered access view.
+ ASSERT(textureUAV->valid());
+ ASSERT((index < mRenderer->getNativeCaps().maxImageUnits));
+ setUnorderedAccessViewInternal(index, textureUAV, uavList);
+
+ textureImpl->resetDirty();
+ return angle::Result::Continue;
+}
+
+// Things that affect a program's dirtyness:
+// 1. Directly changing the program executable -> triggered in StateManager11::syncState.
+// 2. The vertex attribute layout -> triggered in VertexArray11::syncState/signal.
+// 3. The fragment shader's rendertargets -> triggered in Framebuffer11::syncState/signal.
+// 4. Enabling/disabling rasterizer discard. -> triggered in StateManager11::syncState.
+// 5. Enabling/disabling transform feedback. -> checked in StateManager11::updateState.
+// 6. An internal shader was used. -> triggered in StateManager11::set*Shader.
+// 7. Drawing with/without point sprites. -> checked in StateManager11::updateState.
+// TODO(jmadill): Use dirty bits for transform feedback.
+angle::Result StateManager11::syncProgram(const gl::Context *context, gl::PrimitiveMode drawMode)
+{
+ Context11 *context11 = GetImplAs<Context11>(context);
+ ANGLE_TRY(context11->triggerDrawCallProgramRecompilation(context, drawMode));
+
+ const auto &glState = context->getState();
+
+ mProgramD3D->updateCachedInputLayout(mVertexArray11->getCurrentStateSerial(), glState);
+
+ // Binaries must be compiled before the sync.
+ ASSERT(mProgramD3D->hasVertexExecutableForCachedInputLayout());
+ ASSERT(mProgramD3D->hasGeometryExecutableForPrimitiveType(glState, drawMode));
+ ASSERT(mProgramD3D->hasPixelExecutableForCachedOutputLayout());
+
+ ShaderExecutableD3D *vertexExe = nullptr;
+ ANGLE_TRY(mProgramD3D->getVertexExecutableForCachedInputLayout(context11, &vertexExe, nullptr));
+
+ ShaderExecutableD3D *pixelExe = nullptr;
+ ANGLE_TRY(mProgramD3D->getPixelExecutableForCachedOutputLayout(context11, &pixelExe, nullptr));
+
+ ShaderExecutableD3D *geometryExe = nullptr;
+ ANGLE_TRY(mProgramD3D->getGeometryExecutableForPrimitiveType(context11, glState, drawMode,
+ &geometryExe, nullptr));
+
+ const d3d11::VertexShader *vertexShader =
+ (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getVertexShader() : nullptr);
+
+ // Skip pixel shader if we're doing rasterizer discard.
+ const d3d11::PixelShader *pixelShader = nullptr;
+ if (!glState.getRasterizerState().rasterizerDiscard)
+ {
+ pixelShader = (pixelExe ? &GetAs<ShaderExecutable11>(pixelExe)->getPixelShader() : nullptr);
+ }
+
+ const d3d11::GeometryShader *geometryShader = nullptr;
+ if (glState.isTransformFeedbackActiveUnpaused())
+ {
+ geometryShader =
+ (vertexExe ? &GetAs<ShaderExecutable11>(vertexExe)->getStreamOutShader() : nullptr);
+ }
+ else
+ {
+ geometryShader =
+ (geometryExe ? &GetAs<ShaderExecutable11>(geometryExe)->getGeometryShader() : nullptr);
+ }
+
+ setDrawShaders(vertexShader, geometryShader, pixelShader);
+
+ // Explicitly clear the shaders dirty bit.
+ mInternalDirtyBits.reset(DIRTY_BIT_SHADERS);
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::syncProgramForCompute(const gl::Context *context)
+{
+ Context11 *context11 = GetImplAs<Context11>(context);
+ ANGLE_TRY(context11->triggerDispatchCallProgramRecompilation(context));
+
+ mProgramD3D->updateCachedComputeImage2DBindLayout(context);
+
+ // Binaries must be compiled before the sync.
+ ASSERT(mProgramD3D->hasComputeExecutableForCachedImage2DBindLayout());
+
+ ShaderExecutableD3D *computeExe = nullptr;
+ ANGLE_TRY(mProgramD3D->getComputeExecutableForImage2DBindLayout(context, context11, &computeExe,
+ nullptr));
+
+ const d3d11::ComputeShader *computeShader =
+ (computeExe ? &GetAs<ShaderExecutable11>(computeExe)->getComputeShader() : nullptr);
+ setComputeShader(computeShader);
+ // Explicitly clear the shaders dirty bit.
+ mInternalDirtyBits.reset(DIRTY_BIT_SHADERS);
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::syncVertexBuffersAndInputLayout(
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint firstVertex,
+ GLsizei vertexOrIndexCount,
+ gl::DrawElementsType indexTypeOrInvalid,
+ GLsizei instanceCount)
+{
+ const auto &vertexArrayAttribs = mVertexArray11->getTranslatedAttribs();
+
+ // Sort the attributes according to ensure we re-use similar input layouts.
+ AttribIndexArray sortedSemanticIndices;
+ SortAttributesByLayout(*mProgramD3D, vertexArrayAttribs, mCurrentValueAttribs,
+ &sortedSemanticIndices, &mCurrentAttributes);
+
+ D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;
+
+ // If we are using FL 9_3, make sure the first attribute is not instanced
+ if (featureLevel <= D3D_FEATURE_LEVEL_9_3 && !mCurrentAttributes.empty())
+ {
+ if (mCurrentAttributes[0]->divisor > 0)
+ {
+ Optional<size_t> firstNonInstancedIndex = FindFirstNonInstanced(mCurrentAttributes);
+ if (firstNonInstancedIndex.valid())
+ {
+ size_t index = firstNonInstancedIndex.value();
+ std::swap(mCurrentAttributes[0], mCurrentAttributes[index]);
+ std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]);
+ }
+ }
+ }
+
+ // Update the applied input layout by querying the cache.
+ const gl::State &state = context->getState();
+ const d3d11::InputLayout *inputLayout = nullptr;
+ ANGLE_TRY(mInputLayoutCache.getInputLayout(GetImplAs<Context11>(context), state,
+ mCurrentAttributes, sortedSemanticIndices, mode,
+ vertexOrIndexCount, instanceCount, &inputLayout));
+ setInputLayoutInternal(inputLayout);
+
+ // Update the applied vertex buffers.
+ ANGLE_TRY(applyVertexBuffers(context, mode, indexTypeOrInvalid, firstVertex));
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::applyVertexBuffers(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType indexTypeOrInvalid,
+ GLint firstVertex)
+{
+ bool programUsesInstancedPointSprites =
+ mProgramD3D->usesPointSize() && mProgramD3D->usesInstancedPointSpriteEmulation();
+ bool instancedPointSpritesActive =
+ programUsesInstancedPointSprites && (mode == gl::PrimitiveMode::Points);
+
+ // Note that if we use instance emulation, we reserve the first buffer slot.
+ size_t reservedBuffers = GetReservedBufferCount(programUsesInstancedPointSprites);
+
+ for (size_t attribIndex = 0; attribIndex < (gl::MAX_VERTEX_ATTRIBS - reservedBuffers);
+ ++attribIndex)
+ {
+ ID3D11Buffer *buffer = nullptr;
+ UINT vertexStride = 0;
+ UINT vertexOffset = 0;
+
+ if (attribIndex < mCurrentAttributes.size())
+ {
+ const TranslatedAttribute &attrib = *mCurrentAttributes[attribIndex];
+ Buffer11 *bufferStorage = attrib.storage ? GetAs<Buffer11>(attrib.storage) : nullptr;
+
+ // If indexed pointsprite emulation is active, then we need to take a less efficent code
+ // path. Emulated indexed pointsprite rendering requires that the vertex buffers match
+ // exactly to the indices passed by the caller. This could expand or shrink the vertex
+ // buffer depending on the number of points indicated by the index list or how many
+ // duplicates are found on the index list.
+ if (bufferStorage == nullptr)
+ {
+ ASSERT(attrib.vertexBuffer.get());
+ buffer = GetAs<VertexBuffer11>(attrib.vertexBuffer.get())->getBuffer().get();
+ }
+ else if (instancedPointSpritesActive &&
+ indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
+ {
+ ASSERT(mVertexArray11->isCachedIndexInfoValid());
+ TranslatedIndexData indexInfo = mVertexArray11->getCachedIndexInfo();
+ if (indexInfo.srcIndexData.srcBuffer != nullptr)
+ {
+ const uint8_t *bufferData = nullptr;
+ ANGLE_TRY(indexInfo.srcIndexData.srcBuffer->getData(context, &bufferData));
+ ASSERT(bufferData != nullptr);
+
+ ptrdiff_t offset =
+ reinterpret_cast<ptrdiff_t>(indexInfo.srcIndexData.srcIndices);
+ indexInfo.srcIndexData.srcBuffer = nullptr;
+ indexInfo.srcIndexData.srcIndices = bufferData + offset;
+ }
+
+ ANGLE_TRY(bufferStorage->getEmulatedIndexedBuffer(context, &indexInfo.srcIndexData,
+ attrib, firstVertex, &buffer));
+
+ mVertexArray11->updateCachedIndexInfo(indexInfo);
+ }
+ else
+ {
+ ANGLE_TRY(bufferStorage->getBuffer(
+ context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, &buffer));
+ }
+
+ vertexStride = attrib.stride;
+ ANGLE_TRY(attrib.computeOffset(context, firstVertex, &vertexOffset));
+ }
+
+ size_t bufferIndex = reservedBuffers + attribIndex;
+
+ queueVertexBufferChange(bufferIndex, buffer, vertexStride, vertexOffset);
+ }
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ // Instanced PointSprite emulation requires two additional ID3D11Buffers. A vertex buffer needs
+ // to be created and added to the list of current buffers, strides and offsets collections.
+ // This buffer contains the vertices for a single PointSprite quad.
+ // An index buffer also needs to be created and applied because rendering instanced data on
+ // D3D11 FL9_3 requires DrawIndexedInstanced() to be used. Shaders that contain gl_PointSize and
+ // used without the GL_POINTS rendering mode require a vertex buffer because some drivers cannot
+ // handle missing vertex data and will TDR the system.
+ if (programUsesInstancedPointSprites)
+ {
+ constexpr UINT kPointSpriteVertexStride = sizeof(float) * 5;
+
+ if (!mPointSpriteVertexBuffer.valid())
+ {
+ static constexpr float kPointSpriteVertices[] = {
+ // Position | TexCoord
+ -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, /* v0 */
+ -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, /* v1 */
+ 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, /* v2 */
+ 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, /* v3 */
+ -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, /* v4 */
+ 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, /* v5 */
+ };
+
+ D3D11_SUBRESOURCE_DATA vertexBufferData = {kPointSpriteVertices, 0, 0};
+ D3D11_BUFFER_DESC vertexBufferDesc;
+ vertexBufferDesc.ByteWidth = sizeof(kPointSpriteVertices);
+ vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ vertexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+ vertexBufferDesc.CPUAccessFlags = 0;
+ vertexBufferDesc.MiscFlags = 0;
+ vertexBufferDesc.StructureByteStride = 0;
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, vertexBufferDesc, &vertexBufferData,
+ &mPointSpriteVertexBuffer));
+ }
+
+ // Set the stride to 0 if GL_POINTS mode is not being used to instruct the driver to avoid
+ // indexing into the vertex buffer.
+ UINT stride = instancedPointSpritesActive ? kPointSpriteVertexStride : 0;
+ queueVertexBufferChange(0, mPointSpriteVertexBuffer.get(), stride, 0);
+
+ if (!mPointSpriteIndexBuffer.valid())
+ {
+ // Create an index buffer and set it for pointsprite rendering
+ static constexpr unsigned short kPointSpriteIndices[] = {
+ 0, 1, 2, 3, 4, 5,
+ };
+
+ D3D11_SUBRESOURCE_DATA indexBufferData = {kPointSpriteIndices, 0, 0};
+ D3D11_BUFFER_DESC indexBufferDesc;
+ indexBufferDesc.ByteWidth = sizeof(kPointSpriteIndices);
+ indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ indexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+ indexBufferDesc.CPUAccessFlags = 0;
+ indexBufferDesc.MiscFlags = 0;
+ indexBufferDesc.StructureByteStride = 0;
+
+ ANGLE_TRY(mRenderer->allocateResource(context11, indexBufferDesc, &indexBufferData,
+ &mPointSpriteIndexBuffer));
+ }
+
+ if (instancedPointSpritesActive)
+ {
+ // The index buffer is applied here because Instanced PointSprite emulation uses the a
+ // non-indexed rendering path in ANGLE (DrawArrays). This means that applyIndexBuffer()
+ // on the renderer will not be called and setting this buffer here ensures that the
+ // rendering path will contain the correct index buffers.
+ syncIndexBuffer(mPointSpriteIndexBuffer.get(), DXGI_FORMAT_R16_UINT, 0);
+ }
+ }
+
+ applyVertexBufferChanges();
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::applyIndexBuffer(const gl::Context *context,
+ GLsizei indexCount,
+ gl::DrawElementsType indexType,
+ const void *indices)
+{
+ if (!mIndexBufferIsDirty)
+ {
+ // No streaming or index buffer application necessary.
+ return angle::Result::Continue;
+ }
+
+ gl::DrawElementsType destElementType = mVertexArray11->getCachedDestinationIndexType();
+ gl::Buffer *elementArrayBuffer = mVertexArray11->getState().getElementArrayBuffer();
+
+ TranslatedIndexData indexInfo;
+ ANGLE_TRY(mIndexDataManager.prepareIndexData(context, indexType, destElementType, indexCount,
+ elementArrayBuffer, indices, &indexInfo));
+
+ ID3D11Buffer *buffer = nullptr;
+ DXGI_FORMAT bufferFormat = (indexInfo.indexType == gl::DrawElementsType::UnsignedInt)
+ ? DXGI_FORMAT_R32_UINT
+ : DXGI_FORMAT_R16_UINT;
+
+ if (indexInfo.storage)
+ {
+ Buffer11 *storage = GetAs<Buffer11>(indexInfo.storage);
+ ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_INDEX, &buffer));
+ }
+ else
+ {
+ IndexBuffer11 *indexBuffer = GetAs<IndexBuffer11>(indexInfo.indexBuffer);
+ buffer = indexBuffer->getBuffer().get();
+ }
+
+ // Track dirty indices in the index range cache.
+ indexInfo.srcIndexData.srcIndicesChanged =
+ syncIndexBuffer(buffer, bufferFormat, indexInfo.startOffset);
+
+ mIndexBufferIsDirty = false;
+
+ mVertexArray11->updateCachedIndexInfo(indexInfo);
+ return angle::Result::Continue;
+}
+
+void StateManager11::setIndexBuffer(ID3D11Buffer *buffer,
+ DXGI_FORMAT indexFormat,
+ unsigned int offset)
+{
+ if (syncIndexBuffer(buffer, indexFormat, offset))
+ {
+ invalidateIndexBuffer();
+ }
+}
+
+bool StateManager11::syncIndexBuffer(ID3D11Buffer *buffer,
+ DXGI_FORMAT indexFormat,
+ unsigned int offset)
+{
+ if (buffer != mAppliedIB || indexFormat != mAppliedIBFormat || offset != mAppliedIBOffset)
+ {
+ mRenderer->getDeviceContext()->IASetIndexBuffer(buffer, indexFormat, offset);
+
+ mAppliedIB = buffer;
+ mAppliedIBFormat = indexFormat;
+ mAppliedIBOffset = offset;
+ return true;
+ }
+
+ return false;
+}
+
+// Vertex buffer is invalidated outside this function.
+angle::Result StateManager11::updateVertexOffsetsForPointSpritesEmulation(
+ const gl::Context *context,
+ GLint startVertex,
+ GLsizei emulatedInstanceId)
+{
+ size_t reservedBuffers = GetReservedBufferCount(true);
+ for (size_t attribIndex = 0; attribIndex < mCurrentAttributes.size(); ++attribIndex)
+ {
+ const auto &attrib = *mCurrentAttributes[attribIndex];
+ size_t bufferIndex = reservedBuffers + attribIndex;
+
+ if (attrib.divisor > 0)
+ {
+ unsigned int offset = 0;
+ ANGLE_TRY(attrib.computeOffset(context, startVertex, &offset));
+ offset += (attrib.stride * (emulatedInstanceId / attrib.divisor));
+ if (offset != mCurrentVertexOffsets[bufferIndex])
+ {
+ invalidateInputLayout();
+ mDirtyVertexBufferRange.extend(static_cast<unsigned int>(bufferIndex));
+ mCurrentVertexOffsets[bufferIndex] = offset;
+ }
+ }
+ }
+
+ applyVertexBufferChanges();
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::generateSwizzle(const gl::Context *context, gl::Texture *texture)
+{
+ if (!texture)
+ {
+ return angle::Result::Continue;
+ }
+
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+ ASSERT(textureD3D);
+
+ TextureStorage *texStorage = nullptr;
+ ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage));
+
+ if (texStorage)
+ {
+ TextureStorage11 *storage11 = GetAs<TextureStorage11>(texStorage);
+ const gl::TextureState &textureState = texture->getTextureState();
+ ANGLE_TRY(storage11->generateSwizzles(context, textureState));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::generateSwizzlesForShader(const gl::Context *context,
+ gl::ShaderType type)
+{
+ const gl::State &glState = context->getState();
+ const gl::RangeUI samplerRange = mProgramD3D->getUsedSamplerRange(type);
+
+ for (unsigned int i = samplerRange.low(); i < samplerRange.high(); i++)
+ {
+ gl::TextureType textureType = mProgramD3D->getSamplerTextureType(type, i);
+ GLint textureUnit = mProgramD3D->getSamplerMapping(type, i, context->getCaps());
+ if (textureUnit != -1)
+ {
+ gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType);
+ ASSERT(texture);
+ if (SwizzleRequired(texture->getTextureState()))
+ {
+ ANGLE_TRY(generateSwizzle(context, texture));
+ }
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::generateSwizzles(const gl::Context *context)
+{
+ ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Vertex));
+ ANGLE_TRY(generateSwizzlesForShader(context, gl::ShaderType::Fragment));
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::applyUniformsForShader(const gl::Context *context,
+ gl::ShaderType shaderType)
+{
+ UniformStorage11 *shaderUniformStorage =
+ GetAs<UniformStorage11>(mProgramD3D->getShaderUniformStorage(shaderType));
+ ASSERT(shaderUniformStorage);
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ const d3d11::Buffer *shaderConstantBuffer = nullptr;
+ ANGLE_TRY(shaderUniformStorage->getConstantBuffer(context, mRenderer, &shaderConstantBuffer));
+
+ if (shaderUniformStorage->size() > 0 && mProgramD3D->areShaderUniformsDirty(shaderType))
+ {
+ UpdateUniformBuffer(deviceContext, shaderUniformStorage, shaderConstantBuffer);
+ }
+
+ unsigned int slot = d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK;
+
+ switch (shaderType)
+ {
+ case gl::ShaderType::Vertex:
+ if (mCurrentConstantBufferVS[slot] != shaderConstantBuffer->getSerial())
+ {
+ deviceContext->VSSetConstantBuffers(slot, 1, shaderConstantBuffer->getPointer());
+ mCurrentConstantBufferVS[slot] = shaderConstantBuffer->getSerial();
+ mCurrentConstantBufferVSOffset[slot] = 0;
+ mCurrentConstantBufferVSSize[slot] = 0;
+ }
+ break;
+
+ case gl::ShaderType::Fragment:
+ if (mCurrentConstantBufferPS[slot] != shaderConstantBuffer->getSerial())
+ {
+ deviceContext->PSSetConstantBuffers(slot, 1, shaderConstantBuffer->getPointer());
+ mCurrentConstantBufferPS[slot] = shaderConstantBuffer->getSerial();
+ mCurrentConstantBufferPSOffset[slot] = 0;
+ mCurrentConstantBufferPSSize[slot] = 0;
+ }
+ break;
+
+ // TODO(jiawei.shao@intel.com): apply geometry shader uniforms
+ case gl::ShaderType::Geometry:
+ UNIMPLEMENTED();
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::applyUniforms(const gl::Context *context)
+{
+ ANGLE_TRY(applyUniformsForShader(context, gl::ShaderType::Vertex));
+ ANGLE_TRY(applyUniformsForShader(context, gl::ShaderType::Fragment));
+ if (mProgramD3D->hasShaderStage(gl::ShaderType::Geometry))
+ {
+ ANGLE_TRY(applyUniformsForShader(context, gl::ShaderType::Geometry));
+ }
+
+ mProgramD3D->markUniformsClean();
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::applyDriverUniformsForShader(const gl::Context *context,
+ gl::ShaderType shaderType)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ d3d11::Buffer &shaderDriverConstantBuffer = mShaderDriverConstantBuffers[shaderType];
+ if (!shaderDriverConstantBuffer.valid())
+ {
+ size_t requiredSize = mShaderConstants.getRequiredBufferSize(shaderType);
+
+ D3D11_BUFFER_DESC constantBufferDescription = {};
+ d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
+ ANGLE_TRY(mRenderer->allocateResource(
+ GetImplAs<Context11>(context), constantBufferDescription, &shaderDriverConstantBuffer));
+
+ ID3D11Buffer *driverConstants = shaderDriverConstantBuffer.get();
+ switch (shaderType)
+ {
+ case gl::ShaderType::Vertex:
+ deviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
+ &driverConstants);
+ break;
+
+ case gl::ShaderType::Fragment:
+ deviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
+ &driverConstants);
+ break;
+
+ case gl::ShaderType::Geometry:
+ deviceContext->GSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
+ &driverConstants);
+ break;
+
+ default:
+ UNREACHABLE();
+ return angle::Result::Continue;
+ }
+ }
+
+ // Sampler metadata and driver constants need to coexist in the same constant buffer to
+ // conserve constant buffer slots. We update both in the constant buffer if needed.
+ ANGLE_TRY(mShaderConstants.updateBuffer(context, mRenderer, shaderType, *mProgramD3D,
+ shaderDriverConstantBuffer));
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::applyDriverUniforms(const gl::Context *context)
+{
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ ANGLE_TRY(applyDriverUniformsForShader(context, gl::ShaderType::Vertex));
+ ANGLE_TRY(applyDriverUniformsForShader(context, gl::ShaderType::Fragment));
+ if (mProgramD3D->hasShaderStage(gl::ShaderType::Geometry))
+ {
+ ANGLE_TRY(applyDriverUniformsForShader(context, gl::ShaderType::Geometry));
+ }
+
+ // needed for the point sprite geometry shader
+ // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it for ES3.
+ if (mRenderer->isES3Capable())
+ {
+ d3d11::Buffer &driverConstantBufferPS =
+ mShaderDriverConstantBuffers[gl::ShaderType::Fragment];
+ if (mCurrentGeometryConstantBuffer != driverConstantBufferPS.getSerial())
+ {
+ ASSERT(driverConstantBufferPS.valid());
+ deviceContext->GSSetConstantBuffers(0, 1, driverConstantBufferPS.getPointer());
+ mCurrentGeometryConstantBuffer = driverConstantBufferPS.getSerial();
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::applyComputeUniforms(const gl::Context *context,
+ ProgramD3D *programD3D)
+{
+ UniformStorage11 *computeUniformStorage =
+ GetAs<UniformStorage11>(programD3D->getShaderUniformStorage(gl::ShaderType::Compute));
+ ASSERT(computeUniformStorage);
+
+ const d3d11::Buffer *constantBuffer = nullptr;
+ ANGLE_TRY(computeUniformStorage->getConstantBuffer(context, mRenderer, &constantBuffer));
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ if (computeUniformStorage->size() > 0 &&
+ programD3D->areShaderUniformsDirty(gl::ShaderType::Compute))
+ {
+ UpdateUniformBuffer(deviceContext, computeUniformStorage, constantBuffer);
+ programD3D->markUniformsClean();
+ }
+
+ if (mCurrentComputeConstantBuffer != constantBuffer->getSerial())
+ {
+ deviceContext->CSSetConstantBuffers(
+ d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1,
+ constantBuffer->getPointer());
+ mCurrentComputeConstantBuffer = constantBuffer->getSerial();
+ }
+
+ if (!mShaderDriverConstantBuffers[gl::ShaderType::Compute].valid())
+ {
+ size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::ShaderType::Compute);
+
+ D3D11_BUFFER_DESC constantBufferDescription = {};
+ d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize);
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), constantBufferDescription,
+ &mShaderDriverConstantBuffers[gl::ShaderType::Compute]));
+ ID3D11Buffer *buffer = mShaderDriverConstantBuffers[gl::ShaderType::Compute].get();
+ deviceContext->CSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1,
+ &buffer);
+ }
+
+ ANGLE_TRY(mShaderConstants.updateBuffer(context, mRenderer, gl::ShaderType::Compute,
+ *programD3D,
+ mShaderDriverConstantBuffers[gl::ShaderType::Compute]));
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::syncUniformBuffersForShader(const gl::Context *context,
+ gl::ShaderType shaderType)
+{
+ const auto &glState = context->getState();
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
+
+ const auto &shaderUniformBuffers = mProgramD3D->getShaderUniformBufferCache(shaderType);
+
+ for (size_t bufferIndex = 0; bufferIndex < shaderUniformBuffers.size(); ++bufferIndex)
+ {
+ const D3DUBOCache cache = shaderUniformBuffers[bufferIndex];
+ if (cache.binding == -1)
+ {
+ continue;
+ }
+
+ const auto &uniformBuffer = glState.getIndexedUniformBuffer(cache.binding);
+ const GLintptr uniformBufferOffset = uniformBuffer.getOffset();
+ const GLsizeiptr uniformBufferSize = uniformBuffer.getSize();
+
+ if (uniformBuffer.get() == nullptr)
+ {
+ continue;
+ }
+
+ Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
+ const d3d11::Buffer *constantBuffer = nullptr;
+ UINT firstConstant = 0;
+ UINT numConstants = 0;
+
+ ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset,
+ uniformBufferSize, &constantBuffer,
+ &firstConstant, &numConstants));
+ ASSERT(constantBuffer);
+
+ switch (shaderType)
+ {
+ case gl::ShaderType::Vertex:
+ {
+ if (mCurrentConstantBufferVS[cache.registerIndex] == constantBuffer->getSerial() &&
+ mCurrentConstantBufferVSOffset[cache.registerIndex] == uniformBufferOffset &&
+ mCurrentConstantBufferVSSize[cache.registerIndex] == uniformBufferSize)
+ {
+ continue;
+ }
+
+ if (firstConstant != 0 && uniformBufferSize != 0)
+ {
+ ASSERT(numConstants != 0);
+ deviceContext1->VSSetConstantBuffers1(cache.registerIndex, 1,
+ constantBuffer->getPointer(),
+ &firstConstant, &numConstants);
+ }
+ else
+ {
+ deviceContext->VSSetConstantBuffers(cache.registerIndex, 1,
+ constantBuffer->getPointer());
+ }
+
+ mCurrentConstantBufferVS[cache.registerIndex] = constantBuffer->getSerial();
+ mCurrentConstantBufferVSOffset[cache.registerIndex] = uniformBufferOffset;
+ mCurrentConstantBufferVSSize[cache.registerIndex] = uniformBufferSize;
+ break;
+ }
+
+ case gl::ShaderType::Fragment:
+ {
+ if (mCurrentConstantBufferPS[cache.registerIndex] == constantBuffer->getSerial() &&
+ mCurrentConstantBufferPSOffset[cache.registerIndex] == uniformBufferOffset &&
+ mCurrentConstantBufferPSSize[cache.registerIndex] == uniformBufferSize)
+ {
+ continue;
+ }
+
+ if (firstConstant != 0 && uniformBufferSize != 0)
+ {
+ deviceContext1->PSSetConstantBuffers1(cache.registerIndex, 1,
+ constantBuffer->getPointer(),
+ &firstConstant, &numConstants);
+ }
+ else
+ {
+ deviceContext->PSSetConstantBuffers(cache.registerIndex, 1,
+ constantBuffer->getPointer());
+ }
+
+ mCurrentConstantBufferPS[cache.registerIndex] = constantBuffer->getSerial();
+ mCurrentConstantBufferPSOffset[cache.registerIndex] = uniformBufferOffset;
+ mCurrentConstantBufferPSSize[cache.registerIndex] = uniformBufferSize;
+ break;
+ }
+
+ case gl::ShaderType::Compute:
+ {
+ if (mCurrentConstantBufferCS[bufferIndex] == constantBuffer->getSerial() &&
+ mCurrentConstantBufferCSOffset[bufferIndex] == uniformBufferOffset &&
+ mCurrentConstantBufferCSSize[bufferIndex] == uniformBufferSize)
+ {
+ continue;
+ }
+
+ if (firstConstant != 0 && uniformBufferSize != 0)
+ {
+ deviceContext1->CSSetConstantBuffers1(cache.registerIndex, 1,
+ constantBuffer->getPointer(),
+ &firstConstant, &numConstants);
+ }
+ else
+ {
+ deviceContext->CSSetConstantBuffers(cache.registerIndex, 1,
+ constantBuffer->getPointer());
+ }
+
+ mCurrentConstantBufferCS[cache.registerIndex] = constantBuffer->getSerial();
+ mCurrentConstantBufferCSOffset[cache.registerIndex] = uniformBufferOffset;
+ mCurrentConstantBufferCSSize[cache.registerIndex] = uniformBufferSize;
+ break;
+ }
+
+ // TODO(jiawei.shao@intel.com): update geometry shader uniform buffers.
+ case gl::ShaderType::Geometry:
+ UNIMPLEMENTED();
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ const auto &shaderUniformBuffersUseSB =
+ mProgramD3D->getShaderUniformBufferCacheUseSB(shaderType);
+ for (size_t bufferIndex = 0; bufferIndex < shaderUniformBuffersUseSB.size(); ++bufferIndex)
+ {
+ const D3DUBOCacheUseSB cache = shaderUniformBuffersUseSB[bufferIndex];
+ if (cache.binding == -1)
+ {
+ continue;
+ }
+
+ const auto &uniformBuffer = glState.getIndexedUniformBuffer(cache.binding);
+ if (uniformBuffer.get() == nullptr)
+ {
+ continue;
+ }
+ const GLintptr uniformBufferOffset = uniformBuffer.getOffset();
+
+ Buffer11 *bufferStorage = GetImplAs<Buffer11>(uniformBuffer.get());
+ const d3d11::ShaderResourceView *bufferSRV = nullptr;
+ ANGLE_TRY(bufferStorage->getStructuredBufferRangeSRV(
+ context, static_cast<unsigned int>(uniformBufferOffset), cache.byteWidth,
+ cache.structureByteStride, &bufferSRV));
+
+ ASSERT(bufferSRV->valid());
+ setShaderResourceInternal(shaderType, cache.registerIndex, bufferSRV);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::getUAVsForShaderStorageBuffers(const gl::Context *context,
+ gl::ShaderType shaderType,
+ UAVList *uavList)
+{
+ const gl::State &glState = context->getState();
+ const gl::Program *program = glState.getProgram();
+ angle::FixedVector<Buffer11 *, gl::IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS>
+ previouslyBound;
+ for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount();
+ blockIndex++)
+ {
+ GLuint binding = program->getShaderStorageBlockBinding(static_cast<GLuint>(blockIndex));
+ const unsigned int registerIndex = mProgramD3D->getShaderStorageBufferRegisterIndex(
+ static_cast<GLuint>(blockIndex), shaderType);
+ // It means this block is active but not statically used.
+ if (registerIndex == GL_INVALID_INDEX)
+ {
+ continue;
+ }
+ const auto &shaderStorageBuffer = glState.getIndexedShaderStorageBuffer(binding);
+ if (shaderStorageBuffer.get() == nullptr)
+ {
+ // We didn't see a driver error like atomic buffer did. But theoretically, the same
+ // thing should be done.
+ setUnorderedAccessViewInternal<d3d11::UnorderedAccessView>(registerIndex, nullptr,
+ uavList);
+ continue;
+ }
+
+ Buffer11 *bufferStorage = GetImplAs<Buffer11>(shaderStorageBuffer.get());
+ if (std::find(previouslyBound.begin(), previouslyBound.end(), bufferStorage) !=
+ previouslyBound.end())
+ {
+ // D3D11 doesn't support binding a buffer multiple times
+ // http://anglebug.com/3032
+ ERR() << "Writing to multiple blocks on the same buffer is not allowed.";
+ return angle::Result::Stop;
+ }
+ previouslyBound.push_back(bufferStorage);
+
+ d3d11::UnorderedAccessView *uavPtr = nullptr;
+ GLsizeiptr viewSize = 0;
+ // Bindings only have a valid size if bound using glBindBufferRange
+ if (shaderStorageBuffer.getSize() > 0)
+ {
+ viewSize = shaderStorageBuffer.getSize();
+ }
+ // We use the buffer size for glBindBufferBase
+ else
+ {
+ viewSize = bufferStorage->getSize();
+ }
+ ANGLE_TRY(bufferStorage->getRawUAVRange(context, shaderStorageBuffer.getOffset(), viewSize,
+ &uavPtr));
+
+ setUnorderedAccessViewInternal(registerIndex, uavPtr, uavList);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::syncUniformBuffers(const gl::Context *context)
+{
+ mProgramD3D->updateUniformBufferCache(context->getCaps());
+
+ if (mProgramD3D->hasShaderStage(gl::ShaderType::Compute))
+ {
+ ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Compute));
+ }
+ else
+ {
+ ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Vertex));
+ ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Fragment));
+ if (mProgramD3D->hasShaderStage(gl::ShaderType::Geometry))
+ {
+ ANGLE_TRY(syncUniformBuffersForShader(context, gl::ShaderType::Geometry));
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::getUAVsForAtomicCounterBuffers(const gl::Context *context,
+ gl::ShaderType shaderType,
+ UAVList *uavList)
+{
+ const gl::State &glState = context->getState();
+ const gl::Program *program = glState.getProgram();
+ for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
+ {
+ GLuint binding = atomicCounterBuffer.binding;
+ const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);
+ const unsigned int registerIndex =
+ mProgramD3D->getAtomicCounterBufferRegisterIndex(binding, shaderType);
+ ASSERT(registerIndex != GL_INVALID_INDEX);
+ if (buffer.get() == nullptr)
+ {
+ // The atomic counter is used in shader. However, there is no buffer binding to it. We
+ // should clear the corresponding UAV in case the previous view type is a texture not a
+ // buffer. Otherwise, below error will be reported. The Unordered Access View dimension
+ // declared in the shader code (BUFFER) does not match the view type bound to slot 0
+ // of the Compute Shader unit (TEXTURE2D).
+ setUnorderedAccessViewInternal<d3d11::UnorderedAccessView>(registerIndex, nullptr,
+ uavList);
+ continue;
+ }
+
+ Buffer11 *bufferStorage = GetImplAs<Buffer11>(buffer.get());
+ // TODO(enrico.galli@intel.com): Check to make sure that we aren't binding the same buffer
+ // multiple times, as this is unsupported by D3D11. http://anglebug.com/3141
+
+ // Bindings only have a valid size if bound using glBindBufferRange. Therefore, we use the
+ // buffer size for glBindBufferBase
+ GLsizeiptr viewSize = (buffer.getSize() > 0) ? buffer.getSize() : bufferStorage->getSize();
+ d3d11::UnorderedAccessView *uavPtr = nullptr;
+ ANGLE_TRY(bufferStorage->getRawUAVRange(context, buffer.getOffset(), viewSize, &uavPtr));
+
+ setUnorderedAccessViewInternal(registerIndex, uavPtr, uavList);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::getUAVsForShader(const gl::Context *context,
+ gl::ShaderType shaderType,
+ UAVList *uavList)
+{
+ ANGLE_TRY(getUAVsForShaderStorageBuffers(context, shaderType, uavList));
+ ANGLE_TRY(getUAVsForRWImages(context, shaderType, uavList));
+ ANGLE_TRY(getUAVsForAtomicCounterBuffers(context, shaderType, uavList));
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::syncUAVsForGraphics(const gl::Context *context)
+{
+ UAVList uavList(mRenderer->getNativeCaps().maxImageUnits);
+
+ ANGLE_TRY(getUAVsForShader(context, gl::ShaderType::Fragment, &uavList));
+ ANGLE_TRY(getUAVsForShader(context, gl::ShaderType::Vertex, &uavList));
+
+ if (uavList.highestUsed >= 0)
+ {
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ UINT baseUAVRegister = static_cast<UINT>(mProgramD3D->getPixelShaderKey().size());
+ deviceContext->OMSetRenderTargetsAndUnorderedAccessViews(
+ D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, baseUAVRegister,
+ uavList.highestUsed + 1, uavList.data.data(), nullptr);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::syncUAVsForCompute(const gl::Context *context)
+{
+ UAVList uavList(mRenderer->getNativeCaps().maxImageUnits);
+
+ ANGLE_TRY(getUAVsForShader(context, gl::ShaderType::Compute, &uavList));
+
+ if (uavList.highestUsed >= 0)
+ {
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->CSSetUnorderedAccessViews(0, uavList.highestUsed + 1, uavList.data.data(),
+ nullptr);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::syncTransformFeedbackBuffers(const gl::Context *context)
+{
+ const auto &glState = context->getState();
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ // If transform feedback is not active, unbind all buffers
+ if (!glState.isTransformFeedbackActiveUnpaused())
+ {
+ if (mAppliedTFSerial != mEmptySerial)
+ {
+ deviceContext->SOSetTargets(0, nullptr, nullptr);
+ mAppliedTFSerial = mEmptySerial;
+ }
+ return angle::Result::Continue;
+ }
+
+ gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback();
+ TransformFeedback11 *tf11 = GetImplAs<TransformFeedback11>(transformFeedback);
+ if (mAppliedTFSerial == tf11->getSerial() && !tf11->isDirty())
+ {
+ return angle::Result::Continue;
+ }
+
+ const std::vector<ID3D11Buffer *> *soBuffers = nullptr;
+ ANGLE_TRY(tf11->getSOBuffers(context, &soBuffers));
+ const std::vector<UINT> &soOffsets = tf11->getSOBufferOffsets();
+
+ deviceContext->SOSetTargets(tf11->getNumSOBuffers(), soBuffers->data(), soOffsets.data());
+
+ mAppliedTFSerial = tf11->getSerial();
+ tf11->onApply();
+
+ return angle::Result::Continue;
+}
+
+void StateManager11::syncPrimitiveTopology(const gl::State &glState,
+ gl::PrimitiveMode currentDrawMode)
+{
+ D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
+ // Don't cull everything by default, this also resets if we were previously culling
+ mCullEverything = false;
+
+ switch (currentDrawMode)
+ {
+ case gl::PrimitiveMode::Points:
+ {
+ bool usesPointSize = mProgramD3D->usesPointSize();
+
+ // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
+ // which affects varying interpolation. Since the value of gl_PointSize is
+ // undefined when not written, just skip drawing to avoid unexpected results.
+ if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused())
+ {
+ // Notify developers of risking undefined behavior.
+ WARN() << "Point rendering without writing to gl_PointSize.";
+ mCullEverything = true;
+ return;
+ }
+
+ // If instanced pointsprites are enabled and the shader uses gl_PointSize, the topology
+ // must be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
+ if (usesPointSize && mRenderer->getFeatures().useInstancedPointSpriteEmulation.enabled)
+ {
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ }
+ else
+ {
+ primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
+ }
+ break;
+ }
+ case gl::PrimitiveMode::Lines:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST;
+ break;
+ case gl::PrimitiveMode::LineLoop:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
+ break;
+ case gl::PrimitiveMode::LineStrip:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
+ break;
+ case gl::PrimitiveMode::Triangles:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ mCullEverything = CullsEverything(glState);
+ break;
+ case gl::PrimitiveMode::TriangleStrip:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
+ mCullEverything = CullsEverything(glState);
+ break;
+ // emulate fans via rewriting index buffer
+ case gl::PrimitiveMode::TriangleFan:
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ mCullEverything = CullsEverything(glState);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ setPrimitiveTopologyInternal(primitiveTopology);
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StateManager11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
new file mode 100644
index 0000000000..d8438a48dc
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
@@ -0,0 +1,692 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StateManager11.h: Defines a class for caching D3D11 state
+
+#ifndef LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_
+#define LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_
+
+#include <array>
+
+#include "libANGLE/State.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h"
+#include "libANGLE/renderer/d3d/d3d11/Query11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+class Buffer11;
+class DisplayD3D;
+class Framebuffer11;
+struct RenderTargetDesc;
+struct Renderer11DeviceCaps;
+class VertexArray11;
+
+class ShaderConstants11 : angle::NonCopyable
+{
+ public:
+ ShaderConstants11();
+ ~ShaderConstants11();
+
+ void init(const gl::Caps &caps);
+ size_t getRequiredBufferSize(gl::ShaderType shaderType) const;
+ void markDirty();
+
+ void setComputeWorkGroups(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ);
+ void setMultiviewWriteToViewportIndex(GLfloat index);
+ void onViewportChange(const gl::Rectangle &glViewport,
+ const D3D11_VIEWPORT &dxViewport,
+ const gl::Offset &glFragCoordOffset,
+ bool is9_3,
+ bool presentPathFast);
+ bool onFirstVertexChange(GLint firstVertex);
+ void onImageLayerChange(gl::ShaderType shaderType, unsigned int imageIndex, int layer);
+ void onSamplerChange(gl::ShaderType shaderType,
+ unsigned int samplerIndex,
+ const gl::Texture &texture,
+ const gl::SamplerState &samplerState);
+ bool onImageChange(gl::ShaderType shaderType,
+ unsigned int imageIndex,
+ const gl::ImageUnit &imageUnit);
+ void onClipControlChange(bool lowerLeft, bool zeroToOne);
+
+ angle::Result updateBuffer(const gl::Context *context,
+ Renderer11 *renderer,
+ gl::ShaderType shaderType,
+ const ProgramD3D &programD3D,
+ const d3d11::Buffer &driverConstantBuffer);
+
+ private:
+ struct Vertex
+ {
+ Vertex()
+ : depthRange{.0f},
+ viewAdjust{.0f},
+ viewCoords{.0f},
+ viewScale{.0f},
+ multiviewWriteToViewportIndex{.0f},
+ clipControlOrigin{-1.0f},
+ clipControlZeroToOne{.0f},
+ firstVertex{0},
+ padding{.0f, .0f}
+ {}
+
+ float depthRange[4];
+ float viewAdjust[4];
+ float viewCoords[4];
+ float viewScale[2];
+ // multiviewWriteToViewportIndex is used to select either the side-by-side or layered
+ // code-path in the GS. It's value, if set, is either 0.0f or 1.0f. The value is updated
+ // whenever a multi-view draw framebuffer is made active.
+ float multiviewWriteToViewportIndex;
+
+ // EXT_clip_control
+ // Multiplied with Y coordinate: -1.0 for GL_LOWER_LEFT_EXT, 1.0f for GL_UPPER_LEFT_EXT
+ float clipControlOrigin;
+ // 0.0 for GL_NEGATIVE_ONE_TO_ONE_EXT, 1.0 for GL_ZERO_TO_ONE_EXT
+ float clipControlZeroToOne;
+
+ uint32_t firstVertex;
+
+ // Added here to manually pad the struct to 16 byte boundary
+ float padding[2];
+ };
+ static_assert(sizeof(Vertex) % 16u == 0,
+ "D3D11 constant buffers must be multiples of 16 bytes");
+
+ struct Pixel
+ {
+ Pixel()
+ : depthRange{.0f},
+ viewCoords{.0f},
+ depthFront{.0f},
+ fragCoordOffset{.0f},
+ viewScale{.0f},
+ multiviewWriteToViewportIndex{.0f},
+ padding{.0f}
+ {}
+
+ float depthRange[4];
+ float viewCoords[4];
+ float depthFront[4];
+ float fragCoordOffset[2];
+ float viewScale[2];
+ // multiviewWriteToViewportIndex is used to select either the side-by-side or layered
+ // code-path in the GS. It's value, if set, is either 0.0f or 1.0f. The value is updated
+ // whenever a multi-view draw framebuffer is made active.
+ float multiviewWriteToViewportIndex;
+
+ // Added here to manually pad the struct.
+ float padding[3];
+ };
+ static_assert(sizeof(Pixel) % 16u == 0, "D3D11 constant buffers must be multiples of 16 bytes");
+
+ struct Compute
+ {
+ Compute() : numWorkGroups{0u}, padding(0u) {}
+ unsigned int numWorkGroups[3];
+ unsigned int padding; // This just pads the struct to 16 bytes
+ };
+
+ struct SamplerMetadata
+ {
+ SamplerMetadata()
+ : baseLevel(0), internalFormatBits(0), wrapModes(0), padding(0), intBorderColor{0}
+ {}
+
+ int baseLevel;
+ int internalFormatBits;
+ int wrapModes;
+ int padding; // This just pads the struct to 32 bytes
+ int intBorderColor[4];
+ };
+
+ static_assert(sizeof(SamplerMetadata) == 32u,
+ "Sampler metadata struct must be two 4-vec --> 32 bytes.");
+
+ struct ImageMetadata
+ {
+ ImageMetadata() : layer(0), level(0), padding{0} {}
+
+ int layer;
+ unsigned int level;
+ int padding[2]; // This just pads the struct to 16 bytes
+ };
+ static_assert(sizeof(ImageMetadata) == 16u,
+ "Image metadata struct must be one 4-vec --> 16 bytes.");
+
+ static size_t GetShaderConstantsStructSize(gl::ShaderType shaderType);
+
+ // Return true if dirty.
+ bool updateSamplerMetadata(SamplerMetadata *data,
+ const gl::Texture &texture,
+ const gl::SamplerState &samplerState);
+
+ // Return true if dirty.
+ bool updateImageMetadata(ImageMetadata *data, const gl::ImageUnit &imageUnit);
+
+ Vertex mVertex;
+ Pixel mPixel;
+ Compute mCompute;
+ gl::ShaderBitSet mShaderConstantsDirty;
+
+ gl::ShaderMap<std::vector<SamplerMetadata>> mShaderSamplerMetadata;
+ gl::ShaderMap<int> mNumActiveShaderSamplers;
+ gl::ShaderMap<std::vector<ImageMetadata>> mShaderReadonlyImageMetadata;
+ gl::ShaderMap<int> mNumActiveShaderReadonlyImages;
+ gl::ShaderMap<std::vector<ImageMetadata>> mShaderImageMetadata;
+ gl::ShaderMap<int> mNumActiveShaderImages;
+};
+
+class StateManager11 final : angle::NonCopyable
+{
+ public:
+ StateManager11(Renderer11 *renderer);
+ ~StateManager11();
+
+ void deinitialize();
+
+ void syncState(const gl::Context *context,
+ const gl::State::DirtyBits &dirtyBits,
+ gl::Command command);
+
+ angle::Result updateStateForCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ);
+
+ void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize);
+
+ // These invalidations methods are called externally.
+
+ // Called from TextureStorage11.
+ void invalidateBoundViews();
+
+ // Called from VertexArray11::updateVertexAttribStorage.
+ void invalidateCurrentValueAttrib(size_t attribIndex);
+
+ // Checks are done on a framebuffer state change to trigger other state changes.
+ // The Context is allowed to be nullptr for these methods, when called in EGL init code.
+ void invalidateRenderTarget();
+
+ // Called by instanced point sprite emulation.
+ void invalidateVertexBuffer();
+
+ // Called by Framebuffer11::syncState for the default sized viewport.
+ void invalidateViewport(const gl::Context *context);
+
+ // Called by TextureStorage11::markLevelDirty.
+ void invalidateSwizzles();
+
+ // Called by the Framebuffer11 and VertexArray11.
+ void invalidateShaders();
+
+ // Called by the Program on Uniform Buffer change. Also called internally.
+ void invalidateProgramUniformBuffers();
+
+ // Called by TransformFeedback11.
+ void invalidateTransformFeedback();
+
+ // Called by VertexArray11.
+ void invalidateInputLayout();
+
+ // Called by VertexArray11 element array buffer sync.
+ void invalidateIndexBuffer();
+
+ // Called by TextureStorage11. Also called internally.
+ void invalidateTexturesAndSamplers();
+
+ void setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv);
+ void setRenderTargets(ID3D11RenderTargetView **rtvs, UINT numRtvs, ID3D11DepthStencilView *dsv);
+
+ void onBeginQuery(Query11 *query);
+ void onDeleteQueryObject(Query11 *query);
+ angle::Result onMakeCurrent(const gl::Context *context);
+
+ void setInputLayout(const d3d11::InputLayout *inputLayout);
+
+ void setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset);
+
+ angle::Result updateState(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint firstVertex,
+ GLsizei vertexOrIndexCount,
+ gl::DrawElementsType indexTypeOrInvalid,
+ const void *indices,
+ GLsizei instanceCount,
+ GLint baseVertex,
+ GLuint baseInstance,
+ bool promoteDynamic);
+
+ void setShaderResourceShared(gl::ShaderType shaderType,
+ UINT resourceSlot,
+ const d3d11::SharedSRV *srv);
+ void setShaderResource(gl::ShaderType shaderType,
+ UINT resourceSlot,
+ const d3d11::ShaderResourceView *srv);
+ void setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology);
+
+ void setDrawShaders(const d3d11::VertexShader *vertexShader,
+ const d3d11::GeometryShader *geometryShader,
+ const d3d11::PixelShader *pixelShader);
+ void setVertexShader(const d3d11::VertexShader *shader);
+ void setGeometryShader(const d3d11::GeometryShader *shader);
+ void setPixelShader(const d3d11::PixelShader *shader);
+ void setComputeShader(const d3d11::ComputeShader *shader);
+ void setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer);
+ void setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer);
+ void setDepthStencilState(const d3d11::DepthStencilState *depthStencilState, UINT stencilRef);
+ void setSimpleBlendState(const d3d11::BlendState *blendState);
+ void setRasterizerState(const d3d11::RasterizerState *rasterizerState);
+ void setSimpleViewport(const gl::Extents &viewportExtents);
+ void setSimpleViewport(int width, int height);
+ void setSimplePixelTextureAndSampler(const d3d11::SharedSRV &srv,
+ const d3d11::SamplerState &samplerState);
+ void setSimpleScissorRect(const gl::Rectangle &glRect);
+ void setScissorRectD3D(const D3D11_RECT &d3dRect);
+
+ void setIndexBuffer(ID3D11Buffer *buffer, DXGI_FORMAT indexFormat, unsigned int offset);
+
+ angle::Result updateVertexOffsetsForPointSpritesEmulation(const gl::Context *context,
+ GLint startVertex,
+ GLsizei emulatedInstanceId);
+
+ // TODO(jmadill): Should be private.
+ angle::Result applyComputeUniforms(const gl::Context *context, ProgramD3D *programD3D);
+
+ // Only used in testing.
+ InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; }
+
+ bool getCullEverything() const { return mCullEverything; }
+ VertexDataManager *getVertexDataManager() { return &mVertexDataManager; }
+
+ ProgramD3D *getProgramD3D() const { return mProgramD3D; }
+
+ private:
+ angle::Result ensureInitialized(const gl::Context *context);
+
+ template <typename SRVType>
+ void setShaderResourceInternal(gl::ShaderType shaderType,
+ UINT resourceSlot,
+ const SRVType *srv);
+
+ struct UAVList
+ {
+ UAVList(size_t size) : data(size) {}
+ std::vector<ID3D11UnorderedAccessView *> data;
+ int highestUsed = -1;
+ };
+
+ template <typename UAVType>
+ void setUnorderedAccessViewInternal(UINT resourceSlot, const UAVType *uav, UAVList *uavList);
+
+ void unsetConflictingView(gl::PipelineType pipeline, ID3D11View *view, bool isRenderTarget);
+ void unsetConflictingSRVs(gl::PipelineType pipeline,
+ gl::ShaderType shaderType,
+ uintptr_t resource,
+ const gl::ImageIndex *index,
+ bool isRenderTarget);
+ void unsetConflictingUAVs(gl::PipelineType pipeline,
+ gl::ShaderType shaderType,
+ uintptr_t resource,
+ const gl::ImageIndex *index);
+ void unsetConflictingRTVs(uintptr_t resource);
+
+ void unsetConflictingAttachmentResources(const gl::FramebufferAttachment &attachment,
+ ID3D11Resource *resource);
+
+ angle::Result syncBlendState(const gl::Context *context,
+ const gl::BlendStateExt &blendStateExt,
+ const gl::ColorF &blendColor,
+ unsigned int sampleMask,
+ bool sampleAlphaToCoverage,
+ bool emulateConstantAlpha);
+
+ angle::Result syncDepthStencilState(const gl::Context *context);
+
+ angle::Result syncRasterizerState(const gl::Context *context, gl::PrimitiveMode mode);
+
+ void syncScissorRectangle(const gl::Context *context);
+
+ void syncViewport(const gl::Context *context);
+
+ void checkPresentPath(const gl::Context *context);
+
+ angle::Result syncFramebuffer(const gl::Context *context);
+ angle::Result syncProgram(const gl::Context *context, gl::PrimitiveMode drawMode);
+ angle::Result syncProgramForCompute(const gl::Context *context);
+
+ angle::Result syncTextures(const gl::Context *context);
+ angle::Result applyTexturesForSRVs(const gl::Context *context, gl::ShaderType shaderType);
+ angle::Result applyTexturesForUAVs(const gl::Context *context, gl::ShaderType shaderType);
+ angle::Result syncTexturesForCompute(const gl::Context *context);
+
+ angle::Result setSamplerState(const gl::Context *context,
+ gl::ShaderType type,
+ int index,
+ gl::Texture *texture,
+ const gl::SamplerState &sampler);
+ angle::Result setTextureForSampler(const gl::Context *context,
+ gl::ShaderType type,
+ int index,
+ gl::Texture *texture,
+ const gl::SamplerState &sampler);
+ angle::Result setImageState(const gl::Context *context,
+ gl::ShaderType type,
+ int index,
+ const gl::ImageUnit &imageUnit);
+ angle::Result setTextureForImage(const gl::Context *context,
+ gl::ShaderType type,
+ int index,
+ const gl::ImageUnit &imageUnit);
+ angle::Result getUAVsForRWImages(const gl::Context *context,
+ gl::ShaderType shaderType,
+ UAVList *uavList);
+ angle::Result getUAVForRWImage(const gl::Context *context,
+ gl::ShaderType type,
+ int index,
+ const gl::ImageUnit &imageUnit,
+ UAVList *uavList);
+
+ void handleMultiviewDrawFramebufferChange(const gl::Context *context);
+
+ angle::Result syncCurrentValueAttribs(
+ const gl::Context *context,
+ const std::vector<gl::VertexAttribCurrentValueData> &currentValues);
+
+ angle::Result generateSwizzle(const gl::Context *context, gl::Texture *texture);
+ angle::Result generateSwizzlesForShader(const gl::Context *context, gl::ShaderType type);
+ angle::Result generateSwizzles(const gl::Context *context);
+
+ angle::Result applyDriverUniforms(const gl::Context *context);
+ angle::Result applyDriverUniformsForShader(const gl::Context *context,
+ gl::ShaderType shaderType);
+ angle::Result applyUniforms(const gl::Context *context);
+ angle::Result applyUniformsForShader(const gl::Context *context, gl::ShaderType shaderType);
+
+ angle::Result getUAVsForShaderStorageBuffers(const gl::Context *context,
+ gl::ShaderType shaderType,
+ UAVList *uavList);
+
+ angle::Result syncUniformBuffers(const gl::Context *context);
+ angle::Result syncUniformBuffersForShader(const gl::Context *context,
+ gl::ShaderType shaderType);
+ angle::Result getUAVsForAtomicCounterBuffers(const gl::Context *context,
+ gl::ShaderType shaderType,
+ UAVList *uavList);
+ angle::Result getUAVsForShader(const gl::Context *context,
+ gl::ShaderType shaderType,
+ UAVList *uavList);
+ angle::Result syncUAVsForGraphics(const gl::Context *context);
+ angle::Result syncUAVsForCompute(const gl::Context *context);
+ angle::Result syncTransformFeedbackBuffers(const gl::Context *context);
+
+ // These are currently only called internally.
+ void invalidateDriverUniforms();
+ void invalidateProgramUniforms();
+ void invalidateConstantBuffer(unsigned int slot);
+ void invalidateProgramAtomicCounterBuffers();
+ void invalidateProgramShaderStorageBuffers();
+ void invalidateImageBindings();
+
+ // Called by the Framebuffer11 directly.
+ void processFramebufferInvalidation(const gl::Context *context);
+
+ bool syncIndexBuffer(ID3D11Buffer *buffer, DXGI_FORMAT indexFormat, unsigned int offset);
+ angle::Result syncVertexBuffersAndInputLayout(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint firstVertex,
+ GLsizei vertexOrIndexCount,
+ gl::DrawElementsType indexTypeOrInvalid,
+ GLsizei instanceCount);
+
+ bool setInputLayoutInternal(const d3d11::InputLayout *inputLayout);
+
+ angle::Result applyVertexBuffers(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType indexTypeOrInvalid,
+ GLint firstVertex);
+ // TODO(jmadill): Migrate to d3d11::Buffer.
+ bool queueVertexBufferChange(size_t bufferIndex,
+ ID3D11Buffer *buffer,
+ UINT stride,
+ UINT offset);
+ void applyVertexBufferChanges();
+ bool setPrimitiveTopologyInternal(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology);
+ void syncPrimitiveTopology(const gl::State &glState, gl::PrimitiveMode currentDrawMode);
+
+ // Not handled by an internal dirty bit because it isn't synced on drawArrays calls.
+ angle::Result applyIndexBuffer(const gl::Context *context,
+ GLsizei indexCount,
+ gl::DrawElementsType indexType,
+ const void *indices);
+
+ enum DirtyBitType
+ {
+ DIRTY_BIT_RENDER_TARGET,
+ DIRTY_BIT_VIEWPORT_STATE,
+ DIRTY_BIT_SCISSOR_STATE,
+ DIRTY_BIT_RASTERIZER_STATE,
+ DIRTY_BIT_BLEND_STATE,
+ DIRTY_BIT_DEPTH_STENCIL_STATE,
+ // DIRTY_BIT_SHADERS and DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE should be dealt before
+ // DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS for update image layers.
+ DIRTY_BIT_SHADERS,
+ // DIRTY_BIT_GRAPHICS_SRV_STATE and DIRTY_BIT_COMPUTE_SRV_STATE should be lower
+ // bits than DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE.
+ DIRTY_BIT_GRAPHICS_SRV_STATE,
+ DIRTY_BIT_GRAPHICS_UAV_STATE,
+ DIRTY_BIT_COMPUTE_SRV_STATE,
+ DIRTY_BIT_COMPUTE_UAV_STATE,
+ DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE,
+ DIRTY_BIT_PROGRAM_UNIFORMS,
+ DIRTY_BIT_DRIVER_UNIFORMS,
+ DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS,
+ DIRTY_BIT_CURRENT_VALUE_ATTRIBS,
+ DIRTY_BIT_TRANSFORM_FEEDBACK,
+ DIRTY_BIT_VERTEX_BUFFERS_AND_INPUT_LAYOUT,
+ DIRTY_BIT_PRIMITIVE_TOPOLOGY,
+ DIRTY_BIT_INVALID,
+ DIRTY_BIT_MAX = DIRTY_BIT_INVALID,
+ };
+
+ using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
+
+ Renderer11 *mRenderer;
+
+ // Internal dirty bits.
+ DirtyBits mInternalDirtyBits;
+ DirtyBits mGraphicsDirtyBitsMask;
+ DirtyBits mComputeDirtyBitsMask;
+
+ bool mCurSampleAlphaToCoverage;
+
+ // Blend State
+ gl::BlendStateExt mCurBlendStateExt;
+ gl::ColorF mCurBlendColor;
+ unsigned int mCurSampleMask;
+
+ // Currently applied depth stencil state
+ gl::DepthStencilState mCurDepthStencilState;
+ int mCurStencilRef;
+ int mCurStencilBackRef;
+ unsigned int mCurStencilSize;
+ Optional<bool> mCurDisableDepth;
+ Optional<bool> mCurDisableStencil;
+
+ // Currently applied rasterizer state
+ gl::RasterizerState mCurRasterState;
+
+ // Currently applied scissor rectangle state
+ bool mCurScissorEnabled;
+ gl::Rectangle mCurScissorRect;
+
+ // Currently applied viewport state
+ gl::Rectangle mCurViewport;
+ float mCurNear;
+ float mCurFar;
+
+ // Currently applied offset to viewport and scissor
+ gl::Offset mCurViewportOffset;
+ gl::Offset mCurScissorOffset;
+
+ // Things needed in viewport state
+ ShaderConstants11 mShaderConstants;
+
+ // Render target variables
+ gl::Extents mViewportBounds;
+ bool mRenderTargetIsDirty;
+
+ // EGL_ANGLE_experimental_present_path variables
+ bool mCurPresentPathFastEnabled;
+ int mCurPresentPathFastColorBufferHeight;
+
+ // Queries that are currently active in this state
+ std::set<Query11 *> mCurrentQueries;
+
+ // Currently applied textures
+ template <typename DescType>
+ struct ViewRecord
+ {
+ uintptr_t view;
+ uintptr_t resource;
+ DescType desc;
+ };
+
+ // A cache of current Views that also tracks the highest 'used' (non-NULL) View.
+ // We might want to investigate a more robust approach that is also fast when there's
+ // a large gap between used Views (e.g. if View 0 and 7 are non-NULL, this approach will
+ // waste time on Views 1-6.)
+ template <typename ViewType, typename DescType>
+ class ViewCache : angle::NonCopyable
+ {
+ public:
+ ViewCache();
+ ~ViewCache();
+
+ void initialize(size_t size) { mCurrentViews.resize(size); }
+
+ size_t size() const { return mCurrentViews.size(); }
+ size_t highestUsed() const { return mHighestUsedView; }
+
+ const ViewRecord<DescType> &operator[](size_t index) const { return mCurrentViews[index]; }
+ void clear();
+ void update(size_t resourceIndex, ViewType *view);
+
+ private:
+ std::vector<ViewRecord<DescType>> mCurrentViews;
+ size_t mHighestUsedView;
+ };
+
+ using SRVCache = ViewCache<ID3D11ShaderResourceView, D3D11_SHADER_RESOURCE_VIEW_DESC>;
+ using UAVCache = ViewCache<ID3D11UnorderedAccessView, D3D11_UNORDERED_ACCESS_VIEW_DESC>;
+ using RTVCache = ViewCache<ID3D11RenderTargetView, D3D11_RENDER_TARGET_VIEW_DESC>;
+ gl::ShaderMap<SRVCache> mCurShaderSRVs;
+ UAVCache mCurComputeUAVs;
+ RTVCache mCurRTVs;
+
+ SRVCache *getSRVCache(gl::ShaderType shaderType);
+
+ // A block of NULL pointers, cached so we don't re-allocate every draw call
+ std::vector<ID3D11ShaderResourceView *> mNullSRVs;
+ std::vector<ID3D11UnorderedAccessView *> mNullUAVs;
+
+ // Current translations of "Current-Value" data - owned by Context, not VertexArray.
+ gl::AttributesMask mDirtyCurrentValueAttribs;
+ std::vector<TranslatedAttribute> mCurrentValueAttribs;
+
+ // Current applied input layout.
+ ResourceSerial mCurrentInputLayout;
+
+ // Current applied vertex states.
+ // TODO(jmadill): Figure out how to use ResourceSerial here.
+ gl::AttribArray<ID3D11Buffer *> mCurrentVertexBuffers;
+ gl::AttribArray<UINT> mCurrentVertexStrides;
+ gl::AttribArray<UINT> mCurrentVertexOffsets;
+ gl::RangeUI mDirtyVertexBufferRange;
+
+ // Currently applied primitive topology
+ D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology;
+ gl::PrimitiveMode mLastAppliedDrawMode;
+ bool mCullEverything;
+
+ // Currently applied shaders
+ gl::ShaderMap<ResourceSerial> mAppliedShaders;
+
+ // Currently applied sampler states
+ gl::ShaderMap<std::vector<bool>> mForceSetShaderSamplerStates;
+ gl::ShaderMap<std::vector<gl::SamplerState>> mCurShaderSamplerStates;
+
+ // Special dirty bit for swizzles. Since they use internal shaders, must be done in a pre-pass.
+ bool mDirtySwizzles;
+
+ // Currently applied index buffer
+ ID3D11Buffer *mAppliedIB;
+ DXGI_FORMAT mAppliedIBFormat;
+ unsigned int mAppliedIBOffset;
+ bool mIndexBufferIsDirty;
+
+ // Vertex, index and input layouts
+ VertexDataManager mVertexDataManager;
+ IndexDataManager mIndexDataManager;
+ InputLayoutCache mInputLayoutCache;
+ std::vector<const TranslatedAttribute *> mCurrentAttributes;
+ Optional<GLint> mLastFirstVertex;
+
+ // ANGLE_multiview.
+ bool mIsMultiviewEnabled;
+
+ bool mIndependentBlendStates;
+
+ // Driver Constants.
+ gl::ShaderMap<d3d11::Buffer> mShaderDriverConstantBuffers;
+
+ ResourceSerial mCurrentComputeConstantBuffer;
+ ResourceSerial mCurrentGeometryConstantBuffer;
+
+ d3d11::Buffer mPointSpriteVertexBuffer;
+ d3d11::Buffer mPointSpriteIndexBuffer;
+
+ template <typename T>
+ using VertexConstantBufferArray =
+ std::array<T, gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS>;
+
+ VertexConstantBufferArray<ResourceSerial> mCurrentConstantBufferVS;
+ VertexConstantBufferArray<GLintptr> mCurrentConstantBufferVSOffset;
+ VertexConstantBufferArray<GLsizeiptr> mCurrentConstantBufferVSSize;
+
+ template <typename T>
+ using FragmentConstantBufferArray =
+ std::array<T, gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS>;
+
+ FragmentConstantBufferArray<ResourceSerial> mCurrentConstantBufferPS;
+ FragmentConstantBufferArray<GLintptr> mCurrentConstantBufferPSOffset;
+ FragmentConstantBufferArray<GLsizeiptr> mCurrentConstantBufferPSSize;
+
+ template <typename T>
+ using ComputeConstantBufferArray =
+ std::array<T, gl::IMPLEMENTATION_MAX_COMPUTE_SHADER_UNIFORM_BUFFERS>;
+
+ ComputeConstantBufferArray<ResourceSerial> mCurrentConstantBufferCS;
+ ComputeConstantBufferArray<GLintptr> mCurrentConstantBufferCSOffset;
+ ComputeConstantBufferArray<GLsizeiptr> mCurrentConstantBufferCSSize;
+
+ // Currently applied transform feedback buffers
+ Serial mAppliedTFSerial;
+
+ Serial mEmptySerial;
+
+ // These objects are cached to avoid having to query the impls.
+ ProgramD3D *mProgramD3D;
+ VertexArray11 *mVertexArray11;
+ Framebuffer11 *mFramebuffer11;
+};
+
+} // namespace rx
+#endif // LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.cpp
new file mode 100644
index 0000000000..e77eba71da
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.cpp
@@ -0,0 +1,166 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StreamProducerD3DTexture.cpp: Implements the stream producer for D3D11 textures
+
+#include "libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.h"
+
+#include "common/utilities.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#include <array>
+
+namespace rx
+{
+
+namespace
+{
+
+egl::Error GetGLDescFromTex(ID3D11Texture2D *const tex,
+ const UINT planeIndex,
+ egl::Stream::GLTextureDescription *const out)
+{
+ if (!tex)
+ return egl::EglBadParameter() << "Texture is null";
+
+ D3D11_TEXTURE2D_DESC desc;
+ tex->GetDesc(&desc);
+
+ if (desc.Width < 1 || desc.Height < 1)
+ return egl::EglBadParameter() << "Width or height < 1";
+
+ out->width = desc.Width;
+ out->height = desc.Height;
+ out->mipLevels = 0;
+
+ std::array<uint32_t, 2> planeFormats = {};
+ switch (desc.Format)
+ {
+ case DXGI_FORMAT_NV12:
+ planeFormats = {GL_R8, GL_RG8};
+ break;
+
+ case DXGI_FORMAT_P010:
+ case DXGI_FORMAT_P016:
+ planeFormats = {GL_R16_EXT, GL_RG16_EXT};
+ break;
+
+ case DXGI_FORMAT_R8_UNORM:
+ planeFormats = {GL_R8};
+ break;
+ case DXGI_FORMAT_R8G8_UNORM:
+ planeFormats[0] = GL_RG8;
+ break;
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ planeFormats[0] = GL_RGBA8;
+ break;
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ planeFormats[0] = GL_BGRA8_EXT;
+ break;
+
+ case DXGI_FORMAT_R16_UNORM:
+ planeFormats[0] = GL_R16_EXT;
+ break;
+ case DXGI_FORMAT_R16G16_UNORM:
+ planeFormats[0] = GL_RG16_EXT;
+ break;
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ planeFormats[0] = GL_RGBA16_EXT;
+ break;
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ planeFormats[0] = GL_RGBA16F;
+ break;
+
+ default:
+ return egl::EglBadParameter() << "Unsupported format";
+ }
+
+ if (planeFormats[1]) // If we have YUV planes, expect 4:2:0.
+ {
+ if ((desc.Width % 2) != 0 || (desc.Height % 2) != 0)
+ return egl::EglBadParameter() << "YUV 4:2:0 textures must have even width and height.";
+ }
+ if (planeIndex > 0)
+ {
+ out->width /= 2;
+ out->height /= 2;
+ }
+
+ out->internalFormat = 0;
+ if (planeIndex < planeFormats.size())
+ {
+ out->internalFormat = planeFormats[planeIndex];
+ }
+ if (!out->internalFormat)
+ return egl::EglBadParameter() << "Plane out of range";
+
+ return egl::NoError();
+}
+
+} // namespace
+
+StreamProducerD3DTexture::StreamProducerD3DTexture(Renderer11 *renderer)
+ : mRenderer(renderer), mTexture(nullptr), mArraySlice(0), mPlaneOffset(0)
+{}
+
+StreamProducerD3DTexture::~StreamProducerD3DTexture()
+{
+ SafeRelease(mTexture);
+}
+
+egl::Error StreamProducerD3DTexture::validateD3DTexture(const void *pointer,
+ const egl::AttributeMap &attributes) const
+{
+ // We must remove the const qualifier because "GetDevice" and "GetDesc" are non-const in D3D11.
+ ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(const_cast<void *>(pointer));
+
+ // Check that the texture originated from our device
+ angle::ComPtr<ID3D11Device> device;
+ textureD3D->GetDevice(&device);
+ if (device.Get() != mRenderer->getDevice())
+ {
+ return egl::EglBadParameter() << "Texture not created on ANGLE D3D device";
+ }
+
+ const auto planeId = static_cast<UINT>(attributes.get(EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG, 0));
+ egl::Stream::GLTextureDescription unused;
+ return GetGLDescFromTex(textureD3D, planeId, &unused);
+}
+
+void StreamProducerD3DTexture::postD3DTexture(void *pointer, const egl::AttributeMap &attributes)
+{
+ ASSERT(pointer != nullptr);
+ ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(pointer);
+
+ // Release the previous texture if there is one
+ SafeRelease(mTexture);
+
+ mTexture = textureD3D;
+ mTexture->AddRef();
+ mPlaneOffset = static_cast<UINT>(attributes.get(EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG, 0));
+ mArraySlice = static_cast<UINT>(attributes.get(EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, 0));
+}
+
+egl::Stream::GLTextureDescription StreamProducerD3DTexture::getGLFrameDescription(int planeIndex)
+{
+ const auto planeOffsetIndex = static_cast<UINT>(planeIndex + mPlaneOffset);
+ egl::Stream::GLTextureDescription ret;
+ ANGLE_SWALLOW_ERR(GetGLDescFromTex(mTexture, planeOffsetIndex, &ret));
+ return ret;
+}
+
+ID3D11Texture2D *StreamProducerD3DTexture::getD3DTexture()
+{
+ return mTexture;
+}
+
+UINT StreamProducerD3DTexture::getArraySlice()
+{
+ return mArraySlice;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.h
new file mode 100644
index 0000000000..bcb0057fde
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.h
@@ -0,0 +1,44 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StreamProducerD3DTexture.h: Interface for a D3D11 texture stream producer
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_
+
+#include "libANGLE/renderer/StreamProducerImpl.h"
+
+namespace rx
+{
+class Renderer11;
+
+class StreamProducerD3DTexture : public StreamProducerImpl
+{
+ public:
+ StreamProducerD3DTexture(Renderer11 *renderer);
+ ~StreamProducerD3DTexture() override;
+
+ egl::Error validateD3DTexture(const void *pointer,
+ const egl::AttributeMap &attributes) const override;
+ void postD3DTexture(void *pointer, const egl::AttributeMap &attributes) override;
+ egl::Stream::GLTextureDescription getGLFrameDescription(int planeIndex) override;
+
+ // Gets a pointer to the internal D3D texture
+ ID3D11Texture2D *getD3DTexture();
+
+ // Gets the slice index for the D3D texture that the frame is in
+ UINT getArraySlice();
+
+ private:
+ Renderer11 *mRenderer;
+
+ ID3D11Texture2D *mTexture;
+ UINT mArraySlice;
+ UINT mPlaneOffset;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
new file mode 100644
index 0000000000..8470510ea8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
@@ -0,0 +1,1119 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain.
+
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+
+#include <EGL/eglext.h>
+
+#include "libANGLE/features.h"
+#include "libANGLE/renderer/d3d/DisplayD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/trace.h"
+
+// Precompiled shaders
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvecolor2dps.h"
+
+#ifdef ANGLE_ENABLE_KEYEDMUTEX
+# define ANGLE_RESOURCE_SHARE_TYPE D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
+#else
+# define ANGLE_RESOURCE_SHARE_TYPE D3D11_RESOURCE_MISC_SHARED
+#endif
+
+namespace rx
+{
+
+namespace
+{
+// To avoid overflow in QPC to Microseconds calculations, since we multiply
+// by kMicrosecondsPerSecond, then the QPC value should not exceed
+// (2^63 - 1) / 1E6. If it exceeds that threshold, we divide then multiply.
+static constexpr int64_t kQPCOverflowThreshold = 0x8637BD05AF7;
+static constexpr int64_t kMicrosecondsPerSecond = 1000000;
+
+bool NeedsOffscreenTexture(Renderer11 *renderer, NativeWindow11 *nativeWindow, EGLint orientation)
+{
+ // We don't need an offscreen texture if either orientation = INVERT_Y,
+ // or present path fast is enabled and we're not rendering onto an offscreen surface.
+ return orientation != EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE &&
+ !(renderer->presentPathFastEnabled() && nativeWindow->getNativeWindow());
+}
+} // anonymous namespace
+
+SwapChain11::SwapChain11(Renderer11 *renderer,
+ NativeWindow11 *nativeWindow,
+ HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation,
+ EGLint samples)
+ : SwapChainD3D(shareHandle, d3dTexture, backBufferFormat, depthBufferFormat),
+ mRenderer(renderer),
+ mWidth(-1),
+ mHeight(-1),
+ mOrientation(orientation),
+ mAppCreatedShareHandle(mShareHandle != nullptr),
+ mSwapInterval(0),
+ mPassThroughResourcesInit(false),
+ mNativeWindow(nativeWindow),
+ mFirstSwap(true),
+ mSwapChain(nullptr),
+ mSwapChain1(nullptr),
+ mKeyedMutex(nullptr),
+ mBackBufferTexture(),
+ mBackBufferRTView(),
+ mBackBufferSRView(),
+ mNeedsOffscreenTexture(NeedsOffscreenTexture(renderer, nativeWindow, orientation)),
+ mOffscreenTexture(),
+ mOffscreenRTView(),
+ mOffscreenSRView(),
+ mNeedsOffscreenTextureCopy(false),
+ mOffscreenTextureCopyForSRV(),
+ mDepthStencilTexture(),
+ mDepthStencilDSView(),
+ mDepthStencilSRView(),
+ mQuadVB(),
+ mPassThroughSampler(),
+ mPassThroughIL(),
+ mPassThroughVS(),
+ mPassThroughOrResolvePS(),
+ mPassThroughRS(),
+ mColorRenderTarget(this, renderer, false),
+ mDepthStencilRenderTarget(this, renderer, true),
+ mEGLSamples(samples)
+{
+ // Check that if present path fast is active then we're using the default orientation
+ ASSERT(!mRenderer->presentPathFastEnabled() || orientation == 0);
+
+ // Get the performance counter
+ LARGE_INTEGER counterFreqency = {};
+ BOOL success = QueryPerformanceFrequency(&counterFreqency);
+ ASSERT(success);
+
+ mQPCFrequency = counterFreqency.QuadPart;
+}
+
+SwapChain11::~SwapChain11()
+{
+ release();
+}
+
+void SwapChain11::release()
+{
+ // TODO(jmadill): Should probably signal that the RenderTarget is dirty.
+
+ SafeRelease(mSwapChain1);
+ SafeRelease(mSwapChain);
+ SafeRelease(mKeyedMutex);
+ mBackBufferTexture.reset();
+ mBackBufferRTView.reset();
+ mBackBufferSRView.reset();
+ mOffscreenTexture.reset();
+ mOffscreenRTView.reset();
+ mOffscreenSRView.reset();
+ mDepthStencilTexture.reset();
+ mDepthStencilDSView.reset();
+ mDepthStencilSRView.reset();
+ mQuadVB.reset();
+ mPassThroughSampler.reset();
+ mPassThroughIL.reset();
+ mPassThroughVS.reset();
+ mPassThroughOrResolvePS.reset();
+ mPassThroughRS.reset();
+
+ if (!mAppCreatedShareHandle)
+ {
+ mShareHandle = nullptr;
+ }
+}
+
+void SwapChain11::releaseOffscreenColorBuffer()
+{
+ mOffscreenTexture.reset();
+ mOffscreenRTView.reset();
+ mOffscreenSRView.reset();
+ mNeedsOffscreenTextureCopy = false;
+ mOffscreenTextureCopyForSRV.reset();
+}
+
+void SwapChain11::releaseOffscreenDepthBuffer()
+{
+ mDepthStencilTexture.reset();
+ mDepthStencilDSView.reset();
+ mDepthStencilSRView.reset();
+}
+
+EGLint SwapChain11::resetOffscreenBuffers(DisplayD3D *displayD3D,
+ int backbufferWidth,
+ int backbufferHeight)
+{
+ if (mNeedsOffscreenTexture)
+ {
+ EGLint result = resetOffscreenColorBuffer(displayD3D, backbufferWidth, backbufferHeight);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+ }
+
+ EGLint result = resetOffscreenDepthBuffer(displayD3D, backbufferWidth, backbufferHeight);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+
+ mWidth = backbufferWidth;
+ mHeight = backbufferHeight;
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::resetOffscreenColorBuffer(DisplayD3D *displayD3D,
+ int backbufferWidth,
+ int backbufferHeight)
+{
+ ASSERT(mNeedsOffscreenTexture);
+
+ ANGLE_TRACE_EVENT0("gpu.angle", "SwapChain11::resetOffscreenTexture");
+ ID3D11Device *device = mRenderer->getDevice();
+
+ ASSERT(device != nullptr);
+
+ // D3D11 does not allow zero size textures
+ ASSERT(backbufferWidth >= 1);
+ ASSERT(backbufferHeight >= 1);
+
+ // Preserve the render target content
+ TextureHelper11 previousOffscreenTexture(std::move(mOffscreenTexture));
+ const int previousWidth = mWidth;
+ const int previousHeight = mHeight;
+
+ releaseOffscreenColorBuffer();
+
+ const d3d11::Format &backbufferFormatInfo =
+ d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps());
+ D3D11_TEXTURE2D_DESC offscreenTextureDesc = {};
+
+ // If the app passed in a share handle or D3D texture, open the resource
+ // See EGL_ANGLE_d3d_share_handle_client_buffer and EGL_ANGLE_d3d_texture_client_buffer
+ if (mAppCreatedShareHandle || mD3DTexture != nullptr)
+ {
+ if (mAppCreatedShareHandle)
+ {
+ ID3D11Resource *tempResource11;
+ HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource),
+ (void **)&tempResource11);
+ if (FAILED(result) && mRenderer->getDevice1())
+ {
+ result = mRenderer->getDevice1()->OpenSharedResource1(
+ mShareHandle, __uuidof(ID3D11Resource), (void **)&tempResource11);
+ }
+
+ if (FAILED(result))
+ {
+ ERR() << "Could not open shared handle. " << gl::FmtHR(result);
+ release();
+ return EGL_BAD_SURFACE;
+ }
+
+ mOffscreenTexture.set(d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11),
+ backbufferFormatInfo);
+ SafeRelease(tempResource11);
+ }
+ else if (mD3DTexture != nullptr)
+ {
+ mOffscreenTexture.set(d3d11::DynamicCastComObject<ID3D11Texture2D>(mD3DTexture),
+ backbufferFormatInfo);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ ASSERT(mOffscreenTexture.valid());
+ mOffscreenTexture.getDesc(&offscreenTextureDesc);
+
+ // Fail if the offscreen texture is not renderable.
+ if ((offscreenTextureDesc.BindFlags & D3D11_BIND_RENDER_TARGET) == 0)
+ {
+ ERR() << "Could not use provided offscreen texture, texture not renderable.";
+ release();
+ return EGL_BAD_SURFACE;
+ }
+ }
+ else
+ {
+ const bool useSharedResource =
+ !mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport();
+
+ offscreenTextureDesc.Width = backbufferWidth;
+ offscreenTextureDesc.Height = backbufferHeight;
+ offscreenTextureDesc.Format = backbufferFormatInfo.texFormat;
+ offscreenTextureDesc.MipLevels = 1;
+ offscreenTextureDesc.ArraySize = 1;
+ offscreenTextureDesc.SampleDesc.Count = getD3DSamples();
+ offscreenTextureDesc.SampleDesc.Quality = 0;
+ offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
+ offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
+ offscreenTextureDesc.CPUAccessFlags = 0;
+ offscreenTextureDesc.MiscFlags = useSharedResource ? ANGLE_RESOURCE_SHARE_TYPE : 0;
+
+ angle::Result result = mRenderer->allocateTexture(displayD3D, offscreenTextureDesc,
+ backbufferFormatInfo, &mOffscreenTexture);
+ if (result == angle::Result::Stop)
+ {
+ ERR() << "Could not create offscreen texture, " << displayD3D->getStoredErrorString();
+ release();
+ return EGL_BAD_ALLOC;
+ }
+
+ mOffscreenTexture.setInternalName("OffscreenBackBufferTexture");
+
+ // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for
+ // the client
+ if (useSharedResource)
+ {
+ IDXGIResource *offscreenTextureResource = nullptr;
+ HRESULT hr = mOffscreenTexture.get()->QueryInterface(
+ __uuidof(IDXGIResource), (void **)&offscreenTextureResource);
+
+ // Fall back to no share handle on failure
+ if (FAILED(hr))
+ {
+ ERR() << "Could not query offscreen texture resource, " << gl::FmtHR(hr);
+ }
+ else
+ {
+ hr = offscreenTextureResource->GetSharedHandle(&mShareHandle);
+ SafeRelease(offscreenTextureResource);
+
+ if (FAILED(hr))
+ {
+ mShareHandle = nullptr;
+ ERR() << "Could not get offscreen texture shared handle, " << gl::FmtHR(hr);
+ }
+ }
+ }
+ }
+
+ // This may return null if the original texture was created without a keyed mutex.
+ mKeyedMutex = d3d11::DynamicCastComObject<IDXGIKeyedMutex>(mOffscreenTexture.get());
+
+ D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc;
+ offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat;
+ offscreenRTVDesc.ViewDimension =
+ (mEGLSamples <= 1) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS;
+ offscreenRTVDesc.Texture2D.MipSlice = 0;
+
+ angle::Result result = mRenderer->allocateResource(displayD3D, offscreenRTVDesc,
+ mOffscreenTexture.get(), &mOffscreenRTView);
+ if (result == angle::Result::Stop)
+ {
+ ERR() << "Could not create offscreen back buffer render target, "
+ << displayD3D->getStoredErrorString();
+ release();
+ return EGL_BAD_ALLOC;
+ }
+ mOffscreenRTView.setInternalName("OffscreenBackBufferRenderTarget");
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc;
+ offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat;
+ offscreenSRVDesc.ViewDimension =
+ (mEGLSamples <= 1) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ offscreenSRVDesc.Texture2D.MostDetailedMip = 0;
+ offscreenSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1);
+
+ if (offscreenTextureDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
+ {
+ result = mRenderer->allocateResource(displayD3D, offscreenSRVDesc, mOffscreenTexture.get(),
+ &mOffscreenSRView);
+ if (result == angle::Result::Stop)
+ {
+ ERR() << "Could not create offscreen back buffer shader resource, "
+ << displayD3D->getStoredErrorString();
+ release();
+ return EGL_BAD_ALLOC;
+ }
+ mOffscreenSRView.setInternalName("OffscreenBackBufferShaderResource");
+ }
+ else
+ {
+ // Special case for external textures that cannot support sampling. Since internally we
+ // assume our SwapChain is always readable, we make a copy texture that is compatible.
+ mNeedsOffscreenTextureCopy = true;
+ }
+
+ if (previousOffscreenTexture.valid())
+ {
+ D3D11_BOX sourceBox = {};
+ sourceBox.left = 0;
+ sourceBox.right = std::min(previousWidth, backbufferWidth);
+ sourceBox.top = std::max(previousHeight - backbufferHeight, 0);
+ sourceBox.bottom = previousHeight;
+ sourceBox.front = 0;
+ sourceBox.back = 1;
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ const int yoffset = std::max(backbufferHeight - previousHeight, 0);
+ deviceContext->CopySubresourceRegion(mOffscreenTexture.get(), 0, 0, yoffset, 0,
+ previousOffscreenTexture.get(), 0, &sourceBox);
+
+ if (mSwapChain)
+ {
+ swapRect(displayD3D, 0, 0, backbufferWidth, backbufferHeight);
+ }
+ }
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::resetOffscreenDepthBuffer(DisplayD3D *displayD3D,
+ int backbufferWidth,
+ int backbufferHeight)
+{
+ releaseOffscreenDepthBuffer();
+
+ if (mDepthBufferFormat != GL_NONE)
+ {
+ const d3d11::Format &depthBufferFormatInfo =
+ d3d11::Format::Get(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps());
+
+ D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
+ depthStencilTextureDesc.Width = backbufferWidth;
+ depthStencilTextureDesc.Height = backbufferHeight;
+ depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat;
+ depthStencilTextureDesc.MipLevels = 1;
+ depthStencilTextureDesc.ArraySize = 1;
+ depthStencilTextureDesc.SampleDesc.Count = getD3DSamples();
+ depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT;
+ depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+
+ // If there is a multisampled offscreen color texture, the offscreen depth-stencil texture
+ // must also have the same quality value.
+ if (mOffscreenTexture.valid() && getD3DSamples() > 1)
+ {
+ D3D11_TEXTURE2D_DESC offscreenTextureDesc = {};
+ mOffscreenTexture.getDesc(&offscreenTextureDesc);
+ depthStencilTextureDesc.SampleDesc.Quality = offscreenTextureDesc.SampleDesc.Quality;
+ }
+ else
+ {
+ depthStencilTextureDesc.SampleDesc.Quality = 0;
+ }
+
+ // Only create an SRV if it is supported
+ bool depthStencilSRV =
+ depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN &&
+ (mRenderer->getRenderer11DeviceCaps().supportsMultisampledDepthStencilSRVs ||
+ depthStencilTextureDesc.SampleDesc.Count <= 1);
+ if (depthStencilSRV)
+ {
+ depthStencilTextureDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
+ }
+
+ depthStencilTextureDesc.CPUAccessFlags = 0;
+ depthStencilTextureDesc.MiscFlags = 0;
+
+ angle::Result result = mRenderer->allocateTexture(
+ displayD3D, depthStencilTextureDesc, depthBufferFormatInfo, &mDepthStencilTexture);
+ if (result == angle::Result::Stop)
+ {
+ ERR() << "Could not create depthstencil surface for new swap chain, "
+ << displayD3D->getStoredErrorString();
+ release();
+ return EGL_BAD_ALLOC;
+ }
+ mDepthStencilTexture.setInternalName("OffscreenDepthStencilTexture");
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc;
+ depthStencilDesc.Format = depthBufferFormatInfo.dsvFormat;
+ depthStencilDesc.ViewDimension =
+ (mEGLSamples <= 1) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS;
+ depthStencilDesc.Flags = 0;
+ depthStencilDesc.Texture2D.MipSlice = 0;
+
+ result = mRenderer->allocateResource(displayD3D, depthStencilDesc,
+ mDepthStencilTexture.get(), &mDepthStencilDSView);
+ ASSERT(result != angle::Result::Stop);
+ mDepthStencilDSView.setInternalName("OffscreenDSV");
+
+ if (depthStencilSRV)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc;
+ depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat;
+ depthStencilSRVDesc.ViewDimension = (mEGLSamples <= 1)
+ ? D3D11_SRV_DIMENSION_TEXTURE2D
+ : D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ depthStencilSRVDesc.Texture2D.MostDetailedMip = 0;
+ depthStencilSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1);
+
+ result = mRenderer->allocateResource(displayD3D, depthStencilSRVDesc,
+ mDepthStencilTexture.get(), &mDepthStencilSRView);
+ ASSERT(result != angle::Result::Stop);
+ mDepthStencilSRView.setInternalName("OffscreenDepthStencilSRV");
+ }
+ }
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::resize(DisplayD3D *displayD3D, EGLint backbufferWidth, EGLint backbufferHeight)
+{
+ ANGLE_TRACE_EVENT0("gpu.angle", "SwapChain11::resize");
+ ID3D11Device *device = mRenderer->getDevice();
+
+ if (device == nullptr)
+ {
+ return EGL_BAD_ACCESS;
+ }
+
+ // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
+ if (backbufferWidth < 1 || backbufferHeight < 1)
+ {
+ return EGL_SUCCESS;
+ }
+
+ // Don't resize unnecessarily
+ if (mWidth == backbufferWidth && mHeight == backbufferHeight)
+ {
+ return EGL_SUCCESS;
+ }
+
+ // Can only call resize if we have already created our swap buffer and resources
+ ASSERT(mSwapChain && mBackBufferTexture.valid() && mBackBufferRTView.valid() &&
+ mBackBufferSRView.valid());
+
+ mBackBufferTexture.reset();
+ mBackBufferRTView.reset();
+ mBackBufferSRView.reset();
+
+ // Resize swap chain
+ DXGI_SWAP_CHAIN_DESC desc;
+ HRESULT hr = mSwapChain->GetDesc(&desc);
+ if (FAILED(hr))
+ {
+ ERR() << "Error reading swap chain description, " << gl::FmtHR(hr);
+ release();
+ return EGL_BAD_ALLOC;
+ }
+
+ hr = mSwapChain->ResizeBuffers(desc.BufferCount, backbufferWidth, backbufferHeight,
+ getSwapChainNativeFormat(), 0);
+
+ if (FAILED(hr))
+ {
+ ERR() << "Error resizing swap chain buffers, " << gl::FmtHR(hr);
+ release();
+
+ if (d3d11::isDeviceLostError(hr))
+ {
+ HRESULT reason = device->GetDeviceRemovedReason();
+ ERR() << "Device lost in SwapChain11::resize " << gl::FmtHR(hr)
+ << ", reason: " << gl::FmtHR(reason);
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+
+ ID3D11Texture2D *backbufferTexture = nullptr;
+ hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
+ reinterpret_cast<void **>(&backbufferTexture));
+ ASSERT(SUCCEEDED(hr));
+ if (SUCCEEDED(hr))
+ {
+ const auto &format =
+ d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps());
+ mBackBufferTexture.set(backbufferTexture, format);
+ mBackBufferTexture.setInternalName("BackBufferTexture");
+
+ angle::Result result = mRenderer->allocateResourceNoDesc(
+ displayD3D, mBackBufferTexture.get(), &mBackBufferRTView);
+ ASSERT(result != angle::Result::Stop);
+ mBackBufferRTView.setInternalName("BackBufferRTV");
+
+ result = mRenderer->allocateResourceNoDesc(displayD3D, mBackBufferTexture.get(),
+ &mBackBufferSRView);
+ ASSERT(result != angle::Result::Stop);
+ mBackBufferSRView.setInternalName("BackBufferSRV");
+ }
+
+ mFirstSwap = true;
+
+ return resetOffscreenBuffers(displayD3D, backbufferWidth, backbufferHeight);
+}
+
+DXGI_FORMAT SwapChain11::getSwapChainNativeFormat() const
+{
+ // Return a render target format for offscreen rendering is supported by IDXGISwapChain.
+ // MSDN https://msdn.microsoft.com/en-us/library/windows/desktop/bb173064(v=vs.85).aspx
+ switch (mOffscreenRenderTargetFormat)
+ {
+ case GL_RGBA8:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGB8:
+ case GL_RGB565:
+ return DXGI_FORMAT_R8G8B8A8_UNORM;
+
+ case GL_BGRA8_EXT:
+ return DXGI_FORMAT_B8G8R8A8_UNORM;
+
+ case GL_RGB10_A2:
+ return DXGI_FORMAT_R10G10B10A2_UNORM;
+
+ case GL_RGBA16F:
+ return DXGI_FORMAT_R16G16B16A16_FLOAT;
+
+ default:
+ UNREACHABLE();
+ return DXGI_FORMAT_UNKNOWN;
+ }
+}
+
+EGLint SwapChain11::reset(DisplayD3D *displayD3D,
+ EGLint backbufferWidth,
+ EGLint backbufferHeight,
+ EGLint swapInterval)
+{
+ mSwapInterval = static_cast<unsigned int>(swapInterval);
+ if (mSwapInterval > 4)
+ {
+ // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4]
+ // range
+ return EGL_BAD_PARAMETER;
+ }
+
+ // If the swap chain already exists, just resize
+ if (mSwapChain != nullptr)
+ {
+ return resize(displayD3D, backbufferWidth, backbufferHeight);
+ }
+
+ ANGLE_TRACE_EVENT0("gpu.angle", "SwapChain11::reset");
+ ID3D11Device *device = mRenderer->getDevice();
+
+ if (device == nullptr)
+ {
+ return EGL_BAD_ACCESS;
+ }
+
+ // Release specific resources to free up memory for the new render target, while the
+ // old render target still exists for the purpose of preserving its contents.
+ SafeRelease(mSwapChain1);
+ SafeRelease(mSwapChain);
+ mBackBufferTexture.reset();
+ mBackBufferRTView.reset();
+
+ // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
+ if (backbufferWidth < 1 || backbufferHeight < 1)
+ {
+ releaseOffscreenColorBuffer();
+ return EGL_SUCCESS;
+ }
+
+ if (mNativeWindow->getNativeWindow())
+ {
+ HRESULT hr = mNativeWindow->createSwapChain(
+ device, mRenderer->getDxgiFactory(), getSwapChainNativeFormat(), backbufferWidth,
+ backbufferHeight, mNeedsOffscreenTexture ? 1 : getD3DSamples(), &mSwapChain);
+
+ if (FAILED(hr))
+ {
+ ERR() << "Could not create additional swap chains or offscreen surfaces, "
+ << gl::FmtHR(hr);
+ release();
+
+ if (d3d11::isDeviceLostError(hr))
+ {
+ HRESULT reason = device->GetDeviceRemovedReason();
+ ERR() << "Device lost in SwapChain11::reset " << gl::FmtHR(hr)
+ << ", reason: " << gl::FmtHR(reason);
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+
+ if (mRenderer->getRenderer11DeviceCaps().supportsDXGI1_2)
+ {
+ mSwapChain1 = d3d11::DynamicCastComObject<IDXGISwapChain1>(mSwapChain);
+ }
+
+ ID3D11Texture2D *backbufferTex = nullptr;
+ hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D),
+ reinterpret_cast<LPVOID *>(&backbufferTex));
+ ASSERT(SUCCEEDED(hr));
+ const auto &format =
+ d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps());
+ mBackBufferTexture.set(backbufferTex, format);
+ mBackBufferTexture.setInternalName("BackBufferTexture");
+
+ angle::Result result = mRenderer->allocateResourceNoDesc(
+ displayD3D, mBackBufferTexture.get(), &mBackBufferRTView);
+ ASSERT(result != angle::Result::Stop);
+ mBackBufferRTView.setInternalName("BackBufferRTV");
+
+ result = mRenderer->allocateResourceNoDesc(displayD3D, mBackBufferTexture.get(),
+ &mBackBufferSRView);
+ ASSERT(result != angle::Result::Stop);
+ mBackBufferSRView.setInternalName("BackBufferSRV");
+ }
+
+ mFirstSwap = true;
+
+ return resetOffscreenBuffers(displayD3D, backbufferWidth, backbufferHeight);
+}
+
+angle::Result SwapChain11::initPassThroughResources(DisplayD3D *displayD3D)
+{
+ if (mPassThroughResourcesInit)
+ {
+ return angle::Result::Continue;
+ }
+
+ ANGLE_TRACE_EVENT0("gpu.angle", "SwapChain11::initPassThroughResources");
+ ID3D11Device *device = mRenderer->getDevice();
+
+ ASSERT(device != nullptr);
+
+ // Make sure our resources are all not allocated, when we create
+ ASSERT(!mQuadVB.valid() && !mPassThroughSampler.valid());
+ ASSERT(!mPassThroughIL.valid() && !mPassThroughVS.valid() && !mPassThroughOrResolvePS.valid());
+
+ D3D11_BUFFER_DESC vbDesc;
+ vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4;
+ vbDesc.Usage = D3D11_USAGE_DYNAMIC;
+ vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ vbDesc.MiscFlags = 0;
+ vbDesc.StructureByteStride = 0;
+
+ ANGLE_TRY(mRenderer->allocateResource(displayD3D, vbDesc, &mQuadVB));
+ mQuadVB.setInternalName("SwapChainQuadVB");
+
+ D3D11_SAMPLER_DESC samplerDesc;
+ samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
+ samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
+ samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
+ samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
+ samplerDesc.MipLODBias = 0.0f;
+ samplerDesc.MaxAnisotropy = 0;
+ samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+ samplerDesc.BorderColor[0] = 0.0f;
+ samplerDesc.BorderColor[1] = 0.0f;
+ samplerDesc.BorderColor[2] = 0.0f;
+ samplerDesc.BorderColor[3] = 0.0f;
+ samplerDesc.MinLOD = 0;
+ samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
+
+ ANGLE_TRY(mRenderer->allocateResource(displayD3D, samplerDesc, &mPassThroughSampler));
+ mPassThroughSampler.setInternalName("SwapChainPassThroughSampler");
+
+ D3D11_INPUT_ELEMENT_DESC quadLayout[] = {
+ {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
+ {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
+ };
+
+ InputElementArray quadElements(quadLayout);
+ ShaderData vertexShaderData(g_VS_Passthrough2D);
+
+ ANGLE_TRY(
+ mRenderer->allocateResource(displayD3D, quadElements, &vertexShaderData, &mPassThroughIL));
+ mPassThroughIL.setInternalName("SwapChainPassThroughIL");
+
+ ANGLE_TRY(mRenderer->allocateResource(displayD3D, vertexShaderData, &mPassThroughVS));
+ mPassThroughVS.setInternalName("SwapChainPassThroughVS");
+
+ if (mEGLSamples <= 1)
+ {
+ ShaderData pixelShaderData(g_PS_PassthroughRGBA2D);
+ ANGLE_TRY(
+ mRenderer->allocateResource(displayD3D, pixelShaderData, &mPassThroughOrResolvePS));
+ }
+ else
+ {
+ if (mNativeWindow->getNativeWindow() && mNeedsOffscreenTexture)
+ {
+ ShaderData pixelShaderData(g_PS_ResolveColor2D);
+ ANGLE_TRY(
+ mRenderer->allocateResource(displayD3D, pixelShaderData, &mPassThroughOrResolvePS));
+ }
+ else
+ {
+ ShaderData pixelShaderData(g_PS_PassthroughRGBA2DMS);
+ ANGLE_TRY(
+ mRenderer->allocateResource(displayD3D, pixelShaderData, &mPassThroughOrResolvePS));
+ }
+ }
+
+ mPassThroughOrResolvePS.setInternalName("SwapChainPassThroughPS");
+
+ // Use the default rasterizer state but without culling
+ D3D11_RASTERIZER_DESC rasterizerDesc;
+ rasterizerDesc.FillMode = D3D11_FILL_SOLID;
+ rasterizerDesc.CullMode = D3D11_CULL_NONE;
+ rasterizerDesc.FrontCounterClockwise = FALSE;
+ rasterizerDesc.DepthBias = 0;
+ rasterizerDesc.SlopeScaledDepthBias = 0.0f;
+ rasterizerDesc.DepthBiasClamp = 0.0f;
+ rasterizerDesc.DepthClipEnable = TRUE;
+ rasterizerDesc.ScissorEnable = FALSE;
+ rasterizerDesc.MultisampleEnable = FALSE;
+ rasterizerDesc.AntialiasedLineEnable = FALSE;
+
+ ANGLE_TRY(mRenderer->allocateResource(displayD3D, rasterizerDesc, &mPassThroughRS));
+ mPassThroughRS.setInternalName("SwapChainPassThroughRasterizerState");
+
+ mPassThroughResourcesInit = true;
+ return angle::Result::Continue;
+}
+
+// parameters should be validated/clamped by caller
+EGLint SwapChain11::swapRect(DisplayD3D *displayD3D,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height)
+{
+ if (mNeedsOffscreenTexture)
+ {
+ EGLint result = copyOffscreenToBackbuffer(displayD3D, x, y, width, height);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+ }
+
+ EGLint result = present(displayD3D, x, y, width, height);
+ if (result != EGL_SUCCESS)
+ {
+ return result;
+ }
+
+ mRenderer->onSwap();
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::copyOffscreenToBackbuffer(DisplayD3D *displayD3D,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height)
+{
+ if (!mSwapChain)
+ {
+ return EGL_SUCCESS;
+ }
+
+ if (initPassThroughResources(displayD3D) == angle::Result::Stop)
+ {
+ return EGL_BAD_ALLOC;
+ }
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ // Set vertices
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result =
+ deviceContext->Map(mQuadVB.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return EGL_BAD_ACCESS;
+ }
+
+ d3d11::PositionTexCoordVertex *vertices =
+ static_cast<d3d11::PositionTexCoordVertex *>(mappedResource.pData);
+
+ // Create a quad in homogeneous coordinates
+ float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
+ float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
+ float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
+ float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
+
+ float u1 = x / float(mWidth);
+ float v1 = y / float(mHeight);
+ float u2 = (x + width) / float(mWidth);
+ float v2 = (y + height) / float(mHeight);
+
+ // Invert the quad vertices depending on the surface orientation.
+ if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0)
+ {
+ std::swap(x1, x2);
+ }
+ if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE) != 0)
+ {
+ std::swap(y1, y2);
+ }
+
+ d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
+ d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
+ d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
+ d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
+
+ deviceContext->Unmap(mQuadVB.get(), 0);
+
+ StateManager11 *stateManager = mRenderer->getStateManager();
+
+ constexpr UINT stride = sizeof(d3d11::PositionTexCoordVertex);
+ stateManager->setSingleVertexBuffer(&mQuadVB, stride, 0);
+
+ // Apply state
+ stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
+ stateManager->setSimpleBlendState(nullptr);
+ stateManager->setRasterizerState(&mPassThroughRS);
+
+ // Apply shaders
+ stateManager->setInputLayout(&mPassThroughIL);
+ stateManager->setPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+ stateManager->setDrawShaders(&mPassThroughVS, nullptr, &mPassThroughOrResolvePS);
+
+ // Apply render targets. Use the proxy context in display.
+ stateManager->setRenderTarget(mBackBufferRTView.get(), nullptr);
+
+ // Set the viewport
+ stateManager->setSimpleViewport(mWidth, mHeight);
+
+ // Apply textures
+ stateManager->setSimplePixelTextureAndSampler(mOffscreenSRView, mPassThroughSampler);
+
+ // Draw
+ deviceContext->Draw(4, 0);
+
+ return EGL_SUCCESS;
+}
+
+EGLint SwapChain11::present(DisplayD3D *displayD3D, EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ if (!mSwapChain)
+ {
+ return EGL_SUCCESS;
+ }
+
+ UINT swapInterval = mSwapInterval;
+#if ANGLE_VSYNC == ANGLE_DISABLED
+ swapInterval = 0;
+#endif
+
+ HRESULT result = S_OK;
+
+ // Use IDXGISwapChain1::Present1 with a dirty rect if DXGI 1.2 is available.
+ // Dirty rect present is not supported with a multisampled swapchain.
+ if (mSwapChain1 != nullptr && mEGLSamples <= 1)
+ {
+ if (mFirstSwap)
+ {
+ // Can't swap with a dirty rect if this swap chain has never swapped before
+ DXGI_PRESENT_PARAMETERS params = {0, nullptr, nullptr, nullptr};
+ result = mSwapChain1->Present1(swapInterval, 0, &params);
+ }
+ else
+ {
+ RECT rect = {static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height),
+ static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)};
+ DXGI_PRESENT_PARAMETERS params = {1, &rect, nullptr, nullptr};
+ result = mSwapChain1->Present1(swapInterval, 0, &params);
+ }
+ }
+ else
+ {
+ result = mSwapChain->Present(swapInterval, 0);
+ }
+
+ mFirstSwap = false;
+
+ // Some swapping mechanisms such as DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL unbind the current render
+ // target. Mark it dirty. Use the proxy context in display since there is none available.
+ mRenderer->getStateManager()->invalidateRenderTarget();
+
+ if (result == DXGI_ERROR_DEVICE_REMOVED)
+ {
+ ERR() << "Present failed: the D3D11 device was removed, "
+ << gl::FmtHR(mRenderer->getDevice()->GetDeviceRemovedReason());
+ return EGL_CONTEXT_LOST;
+ }
+ else if (result == DXGI_ERROR_DEVICE_RESET)
+ {
+ ERR() << "Present failed: the D3D11 device was reset from a bad command.";
+ return EGL_CONTEXT_LOST;
+ }
+ else if (FAILED(result))
+ {
+ ERR() << "Present failed with " << gl::FmtHR(result);
+ }
+
+ mNativeWindow->commitChange();
+
+ return EGL_SUCCESS;
+}
+
+const TextureHelper11 &SwapChain11::getOffscreenTexture()
+{
+ return mNeedsOffscreenTexture ? mOffscreenTexture : mBackBufferTexture;
+}
+
+const d3d11::RenderTargetView &SwapChain11::getRenderTarget()
+{
+ return mNeedsOffscreenTexture ? mOffscreenRTView : mBackBufferRTView;
+}
+
+angle::Result SwapChain11::getRenderTargetShaderResource(d3d::Context *context,
+ const d3d11::SharedSRV **outSRV)
+{
+ *outSRV = nullptr;
+
+ if (!mNeedsOffscreenTexture)
+ {
+ ASSERT(mBackBufferSRView.valid());
+ *outSRV = &mBackBufferSRView;
+ return angle::Result::Continue;
+ }
+
+ if (!mNeedsOffscreenTextureCopy)
+ {
+ ASSERT(mOffscreenSRView.valid());
+ *outSRV = &mOffscreenSRView;
+ return angle::Result::Continue;
+ }
+
+ if (!mOffscreenTextureCopyForSRV.valid())
+ {
+ const d3d11::Format &backbufferFormatInfo =
+ d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps());
+
+ D3D11_TEXTURE2D_DESC offscreenCopyDesc;
+ mOffscreenTexture.getDesc(&offscreenCopyDesc);
+
+ offscreenCopyDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+ offscreenCopyDesc.MiscFlags = 0;
+ offscreenCopyDesc.CPUAccessFlags = 0;
+ TextureHelper11 offscreenTextureCopyForSRV;
+ ANGLE_TRY(mRenderer->allocateTexture(context, offscreenCopyDesc, backbufferFormatInfo,
+ &offscreenTextureCopyForSRV));
+ offscreenTextureCopyForSRV.setInternalName("OffscreenBackBufferCopyForSRV");
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc;
+ offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat;
+ offscreenSRVDesc.ViewDimension =
+ (mEGLSamples <= 1) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
+ offscreenSRVDesc.Texture2D.MostDetailedMip = 0;
+ offscreenSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1);
+
+ d3d11::SharedSRV offscreenSRView;
+ ANGLE_TRY(mRenderer->allocateResource(context, offscreenSRVDesc,
+ offscreenTextureCopyForSRV.get(), &offscreenSRView));
+ offscreenSRView.setInternalName("OffscreenBackBufferSRV");
+
+ // Commit created objects in one step so we don't end up with half baked member variables.
+ mOffscreenTextureCopyForSRV = std::move(offscreenTextureCopyForSRV);
+ mOffscreenSRView = std::move(offscreenSRView);
+ }
+
+ // Need to copy the offscreen texture into the shader-readable copy, since it's external and
+ // we don't know if the copy is up-to-date. This works around the problem we have when the app
+ // passes in a texture that isn't shader-readable.
+ mRenderer->getDeviceContext()->CopyResource(mOffscreenTextureCopyForSRV.get(),
+ mOffscreenTexture.get());
+ *outSRV = &mOffscreenSRView;
+ return angle::Result::Continue;
+}
+
+const d3d11::DepthStencilView &SwapChain11::getDepthStencil()
+{
+ return mDepthStencilDSView;
+}
+
+const d3d11::SharedSRV &SwapChain11::getDepthStencilShaderResource()
+{
+ return mDepthStencilSRView;
+}
+
+const TextureHelper11 &SwapChain11::getDepthStencilTexture()
+{
+ return mDepthStencilTexture;
+}
+
+void *SwapChain11::getKeyedMutex()
+{
+ return mKeyedMutex;
+}
+
+void SwapChain11::recreate()
+{
+ // possibly should use this method instead of reset
+}
+
+RenderTargetD3D *SwapChain11::getColorRenderTarget()
+{
+ return &mColorRenderTarget;
+}
+
+RenderTargetD3D *SwapChain11::getDepthStencilRenderTarget()
+{
+ return &mDepthStencilRenderTarget;
+}
+
+egl::Error SwapChain11::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
+{
+ if (!mSwapChain)
+ {
+ return egl::EglNotInitialized() << "Swap chain uninitialized";
+ }
+
+ DXGI_FRAME_STATISTICS stats = {};
+ HRESULT result = mSwapChain->GetFrameStatistics(&stats);
+
+ if (FAILED(result))
+ {
+ return egl::EglBadAlloc() << "Failed to get frame statistics, " << gl::FmtHR(result);
+ }
+
+ // Conversion from DXGI_FRAME_STATISTICS to the output values:
+ // stats.SyncRefreshCount -> msc
+ // stats.PresentCount -> sbc
+ // stats.SyncQPCTime -> ust with conversion to microseconds via QueryPerformanceFrequency
+ *msc = stats.SyncRefreshCount;
+ *sbc = stats.PresentCount;
+
+ LONGLONG syncQPCValue = stats.SyncQPCTime.QuadPart;
+ // If the QPC Value is below the overflow threshold, we proceed with
+ // simple multiply and divide.
+ if (syncQPCValue < kQPCOverflowThreshold)
+ {
+ *ust = syncQPCValue * kMicrosecondsPerSecond / mQPCFrequency;
+ }
+ else
+ {
+ // Otherwise, calculate microseconds in a round about manner to avoid
+ // overflow and precision issues.
+ int64_t wholeSeconds = syncQPCValue / mQPCFrequency;
+ int64_t leftoverTicks = syncQPCValue - (wholeSeconds * mQPCFrequency);
+ *ust = wholeSeconds * kMicrosecondsPerSecond +
+ leftoverTicks * kMicrosecondsPerSecond / mQPCFrequency;
+ }
+
+ return egl::NoError();
+}
+
+UINT SwapChain11::getD3DSamples() const
+{
+ return (mEGLSamples == 0) ? 1 : mEGLSamples;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
new file mode 100644
index 0000000000..2d7f0a00ee
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
@@ -0,0 +1,134 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChain11.h: Defines a back-end specific class for the D3D11 swap chain.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+
+namespace rx
+{
+class Renderer11;
+class NativeWindow11;
+
+class SwapChain11 final : public SwapChainD3D
+{
+ public:
+ SwapChain11(Renderer11 *renderer,
+ NativeWindow11 *nativeWindow,
+ HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation,
+ EGLint samples);
+ ~SwapChain11() override;
+
+ EGLint resize(DisplayD3D *displayD3D, EGLint backbufferWidth, EGLint backbufferHeight) override;
+ EGLint reset(DisplayD3D *displayD3D,
+ EGLint backbufferWidth,
+ EGLint backbufferHeight,
+ EGLint swapInterval) override;
+ EGLint swapRect(DisplayD3D *displayD3D,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height) override;
+ void recreate() override;
+
+ RenderTargetD3D *getColorRenderTarget() override;
+ RenderTargetD3D *getDepthStencilRenderTarget() override;
+
+ const TextureHelper11 &getOffscreenTexture();
+ const d3d11::RenderTargetView &getRenderTarget();
+ angle::Result getRenderTargetShaderResource(d3d::Context *context,
+ const d3d11::SharedSRV **outSRV);
+
+ const TextureHelper11 &getDepthStencilTexture();
+ const d3d11::DepthStencilView &getDepthStencil();
+ const d3d11::SharedSRV &getDepthStencilShaderResource();
+
+ EGLint getWidth() const { return mWidth; }
+ EGLint getHeight() const { return mHeight; }
+ void *getKeyedMutex() override;
+ EGLint getSamples() const { return mEGLSamples; }
+
+ egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
+
+ private:
+ void release();
+ angle::Result initPassThroughResources(DisplayD3D *displayD3D);
+
+ void releaseOffscreenColorBuffer();
+ void releaseOffscreenDepthBuffer();
+ EGLint resetOffscreenBuffers(DisplayD3D *displayD3D, int backbufferWidth, int backbufferHeight);
+ EGLint resetOffscreenColorBuffer(DisplayD3D *displayD3D,
+ int backbufferWidth,
+ int backbufferHeight);
+ EGLint resetOffscreenDepthBuffer(DisplayD3D *displayD3D,
+ int backbufferWidth,
+ int backbufferHeight);
+
+ DXGI_FORMAT getSwapChainNativeFormat() const;
+
+ EGLint copyOffscreenToBackbuffer(DisplayD3D *displayD3D,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height);
+ EGLint present(DisplayD3D *displayD3D, EGLint x, EGLint y, EGLint width, EGLint height);
+ UINT getD3DSamples() const;
+
+ Renderer11 *mRenderer;
+ EGLint mWidth;
+ EGLint mHeight;
+ const EGLint mOrientation;
+ bool mAppCreatedShareHandle;
+ unsigned int mSwapInterval;
+ bool mPassThroughResourcesInit;
+
+ NativeWindow11 *mNativeWindow; // Handler for the Window that the surface is created for.
+
+ bool mFirstSwap;
+ IDXGISwapChain *mSwapChain;
+ IDXGISwapChain1 *mSwapChain1;
+ IDXGIKeyedMutex *mKeyedMutex;
+
+ TextureHelper11 mBackBufferTexture;
+ d3d11::RenderTargetView mBackBufferRTView;
+ d3d11::SharedSRV mBackBufferSRView;
+
+ const bool mNeedsOffscreenTexture;
+ TextureHelper11 mOffscreenTexture;
+ d3d11::RenderTargetView mOffscreenRTView;
+ d3d11::SharedSRV mOffscreenSRView;
+ bool mNeedsOffscreenTextureCopy;
+ TextureHelper11 mOffscreenTextureCopyForSRV;
+
+ TextureHelper11 mDepthStencilTexture;
+ d3d11::DepthStencilView mDepthStencilDSView;
+ d3d11::SharedSRV mDepthStencilSRView;
+
+ d3d11::Buffer mQuadVB;
+ d3d11::SamplerState mPassThroughSampler;
+ d3d11::InputLayout mPassThroughIL;
+ d3d11::VertexShader mPassThroughVS;
+ d3d11::PixelShader mPassThroughOrResolvePS;
+ d3d11::RasterizerState mPassThroughRS;
+
+ SurfaceRenderTarget11 mColorRenderTarget;
+ SurfaceRenderTarget11 mDepthStencilRenderTarget;
+
+ EGLint mEGLSamples;
+ LONGLONG mQPCFrequency;
+};
+
+} // namespace rx
+#endif // LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
new file mode 100644
index 0000000000..f1277462a9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -0,0 +1,4352 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived
+// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11
+// texture.
+
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+
+#include <tuple>
+
+#include "common/MemoryBuffer.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/EGLImageD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Image11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.h"
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+namespace rx
+{
+TextureStorage11::SamplerKey::SamplerKey()
+ : baseLevel(0), mipLevels(0), swizzle(false), dropStencil(false)
+{}
+
+TextureStorage11::SamplerKey::SamplerKey(int baseLevel,
+ int mipLevels,
+ bool swizzle,
+ bool dropStencil)
+ : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle), dropStencil(dropStencil)
+{}
+
+bool TextureStorage11::SamplerKey::operator<(const SamplerKey &rhs) const
+{
+ return std::tie(baseLevel, mipLevels, swizzle, dropStencil) <
+ std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle, rhs.dropStencil);
+}
+
+TextureStorage11::ImageKey::ImageKey()
+ : level(0), layered(false), layer(0), access(GL_READ_ONLY), format(GL_R32UI)
+{}
+
+TextureStorage11::ImageKey::ImageKey(int level,
+ bool layered,
+ int layer,
+ GLenum access,
+ GLenum format)
+ : level(level), layered(layered), layer(layer), access(access), format(format)
+{}
+
+bool TextureStorage11::ImageKey::operator<(const ImageKey &rhs) const
+{
+ return std::tie(level, layered, layer, access, format) <
+ std::tie(rhs.level, rhs.layered, rhs.layer, rhs.access, rhs.format);
+}
+
+MultisampledRenderToTextureInfo::MultisampledRenderToTextureInfo(const GLsizei samples,
+ const gl::ImageIndex &indexSS,
+ const gl::ImageIndex &indexMS)
+ : samples(samples), indexSS(indexSS), indexMS(indexMS), msTextureNeedsResolve(false)
+{}
+
+MultisampledRenderToTextureInfo::~MultisampledRenderToTextureInfo() {}
+
+TextureStorage11::TextureStorage11(Renderer11 *renderer,
+ UINT bindFlags,
+ UINT miscFlags,
+ GLenum internalFormat,
+ const std::string &label)
+ : TextureStorage(label),
+ mRenderer(renderer),
+ mTopLevel(0),
+ mMipLevels(0),
+ mFormatInfo(d3d11::Format::Get(internalFormat, mRenderer->getRenderer11DeviceCaps())),
+ mTextureWidth(0),
+ mTextureHeight(0),
+ mTextureDepth(0),
+ mDropStencilTexture(),
+ mBindFlags(bindFlags),
+ mMiscFlags(miscFlags)
+{}
+
+TextureStorage11::~TextureStorage11()
+{
+ mSrvCacheForSampler.clear();
+}
+
+DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat,
+ const Renderer11DeviceCaps &renderer11DeviceCaps,
+ BindFlags flags)
+{
+ UINT bindFlags = 0;
+
+ const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
+ if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ bindFlags |= D3D11_BIND_SHADER_RESOURCE;
+ }
+ if (formatInfo.uavFormat != DXGI_FORMAT_UNKNOWN && flags.unorderedAccess)
+ {
+ bindFlags |= D3D11_BIND_UNORDERED_ACCESS;
+ }
+ if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ bindFlags |= D3D11_BIND_DEPTH_STENCIL;
+ }
+ if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN && flags.renderTarget)
+ {
+ bindFlags |= D3D11_BIND_RENDER_TARGET;
+ }
+
+ return bindFlags;
+}
+
+DWORD TextureStorage11::GetTextureMiscFlags(GLenum internalFormat,
+ const Renderer11DeviceCaps &renderer11DeviceCaps,
+ BindFlags bindFlags,
+ int levels)
+{
+ UINT miscFlags = 0;
+
+ const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
+ if (bindFlags.renderTarget)
+ {
+ if (d3d11::SupportsMipGen(formatInfo.texFormat, renderer11DeviceCaps.featureLevel))
+ {
+ miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS;
+ }
+ }
+
+ return miscFlags;
+}
+
+UINT TextureStorage11::getBindFlags() const
+{
+ return mBindFlags;
+}
+
+UINT TextureStorage11::getMiscFlags() const
+{
+ return mMiscFlags;
+}
+
+int TextureStorage11::getTopLevel() const
+{
+ // Applying top level is meant to be encapsulated inside TextureStorage11.
+ UNREACHABLE();
+ return mTopLevel;
+}
+
+bool TextureStorage11::isRenderTarget() const
+{
+ return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0;
+}
+
+bool TextureStorage11::isManaged() const
+{
+ return false;
+}
+
+bool TextureStorage11::supportsNativeMipmapFunction() const
+{
+ return (mMiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS) != 0;
+}
+
+int TextureStorage11::getLevelCount() const
+{
+ return mMipLevels - mTopLevel;
+}
+
+int TextureStorage11::getLevelWidth(int mipLevel) const
+{
+ return std::max(static_cast<int>(mTextureWidth) >> mipLevel, 1);
+}
+
+int TextureStorage11::getLevelHeight(int mipLevel) const
+{
+ return std::max(static_cast<int>(mTextureHeight) >> mipLevel, 1);
+}
+
+int TextureStorage11::getLevelDepth(int mipLevel) const
+{
+ return std::max(static_cast<int>(mTextureDepth) >> mipLevel, 1);
+}
+
+angle::Result TextureStorage11::getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ return getResource(context, outResource);
+}
+
+angle::Result TextureStorage11::getSubresourceIndex(const gl::Context *context,
+ const gl::ImageIndex &index,
+ UINT *outSubresourceIndex) const
+{
+ UINT mipSlice = static_cast<UINT>(index.getLevelIndex() + mTopLevel);
+ UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.getLayerIndex() : 0);
+ UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
+ ASSERT(subresource != std::numeric_limits<UINT>::max());
+ *outSubresourceIndex = subresource;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11::getSRVForSampler(const gl::Context *context,
+ const gl::TextureState &textureState,
+ const gl::SamplerState &sampler,
+ const d3d11::SharedSRV **outSRV)
+{
+ ANGLE_TRY(resolveTexture(context));
+ // Make sure to add the level offset for our tiny compressed texture workaround
+ const GLuint effectiveBaseLevel = textureState.getEffectiveBaseLevel();
+ const bool swizzleRequired = SwizzleRequired(textureState);
+ const bool mipmapping = gl::IsMipmapFiltered(sampler.getMinFilter());
+ unsigned int mipLevels =
+ mipmapping ? (textureState.getEffectiveMaxLevel() - effectiveBaseLevel + 1) : 1;
+
+ // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level,
+ // which corresponds to GL level 0)
+ mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - effectiveBaseLevel);
+
+ if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ ASSERT(!swizzleRequired);
+ ASSERT(mipLevels == 1 || mipLevels == mMipLevels);
+ }
+
+ if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ // We must ensure that the level zero texture is in sync with mipped texture.
+ ANGLE_TRY(useLevelZeroWorkaroundTexture(context, mipLevels == 1));
+ }
+
+ if (swizzleRequired)
+ {
+ verifySwizzleExists(GetEffectiveSwizzle(textureState));
+ }
+
+ // We drop the stencil when sampling from the SRV if three conditions hold:
+ // 1. the drop stencil workaround is enabled.
+ const bool emulateTinyStencilTextures =
+ mRenderer->getFeatures().emulateTinyStencilTextures.enabled;
+ // 2. this is a stencil texture.
+ const bool hasStencil = (mFormatInfo.format().stencilBits > 0);
+ // 3. the texture has a 1x1 or 2x2 mip.
+ const int effectiveTopLevel = effectiveBaseLevel + mipLevels - 1;
+ const bool hasSmallMips =
+ (getLevelWidth(effectiveTopLevel) <= 2 || getLevelHeight(effectiveTopLevel) <= 2);
+
+ const bool useDropStencil = (emulateTinyStencilTextures && hasStencil && hasSmallMips);
+ const SamplerKey key(effectiveBaseLevel, mipLevels, swizzleRequired, useDropStencil);
+ if (useDropStencil)
+ {
+ // Ensure drop texture gets created.
+ DropStencil result = DropStencil::CREATED;
+ ANGLE_TRY(ensureDropStencilTexture(context, &result));
+
+ // Clear the SRV cache if necessary.
+ // TODO(jmadill): Re-use find query result.
+ const auto srvEntry = mSrvCacheForSampler.find(key);
+ if (result == DropStencil::CREATED && srvEntry != mSrvCacheForSampler.end())
+ {
+ mSrvCacheForSampler.erase(key);
+ }
+ }
+
+ ANGLE_TRY(getCachedOrCreateSRVForSampler(context, key, outSRV));
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11::getCachedOrCreateSRVForSampler(const gl::Context *context,
+ const SamplerKey &key,
+ const d3d11::SharedSRV **outSRV)
+{
+ auto iter = mSrvCacheForSampler.find(key);
+ if (iter != mSrvCacheForSampler.end())
+ {
+ *outSRV = &iter->second;
+ return angle::Result::Continue;
+ }
+
+ const TextureHelper11 *texture = nullptr;
+ DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
+
+ if (key.swizzle)
+ {
+ const auto &swizzleFormat =
+ mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
+ ASSERT(!key.dropStencil || swizzleFormat.format().stencilBits == 0);
+ ANGLE_TRY(getSwizzleTexture(context, &texture));
+ format = swizzleFormat.srvFormat;
+ }
+ else if (key.dropStencil)
+ {
+ ASSERT(mDropStencilTexture.valid());
+ texture = &mDropStencilTexture;
+ format = DXGI_FORMAT_R32_FLOAT;
+ }
+ else
+ {
+ ANGLE_TRY(getResource(context, &texture));
+ format = mFormatInfo.srvFormat;
+ }
+
+ d3d11::SharedSRV srv;
+
+ ANGLE_TRY(createSRVForSampler(context, key.baseLevel, key.mipLevels, format, *texture, &srv));
+
+ const auto &insertIt = mSrvCacheForSampler.insert(std::make_pair(key, std::move(srv)));
+ *outSRV = &insertIt.first->second;
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11::getSRVLevel(const gl::Context *context,
+ int mipLevel,
+ SRVType srvType,
+ const d3d11::SharedSRV **outSRV)
+{
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+
+ ANGLE_TRY(resolveTexture(context));
+ if (srvType == SRVType::Stencil)
+ {
+ if (!mLevelStencilSRVs[mipLevel].valid())
+ {
+ const TextureHelper11 *resource = nullptr;
+ ANGLE_TRY(getResource(context, &resource));
+
+ ANGLE_TRY(createSRVForSampler(context, mipLevel, 1, mFormatInfo.stencilSRVFormat,
+ *resource, &mLevelStencilSRVs[mipLevel]));
+ }
+ *outSRV = &mLevelStencilSRVs[mipLevel];
+ return angle::Result::Continue;
+ }
+
+ auto &levelSRVs = srvType == SRVType::Blit ? mLevelBlitSRVs : mLevelSRVs;
+ auto &otherLevelSRVs = srvType == SRVType::Blit ? mLevelSRVs : mLevelBlitSRVs;
+
+ if (!levelSRVs[mipLevel].valid())
+ {
+ // Only create a different SRV for blit if blit format is different from regular srv format
+ if (otherLevelSRVs[mipLevel].valid() && mFormatInfo.srvFormat == mFormatInfo.blitSRVFormat)
+ {
+ levelSRVs[mipLevel] = otherLevelSRVs[mipLevel].makeCopy();
+ }
+ else
+ {
+ const TextureHelper11 *resource = nullptr;
+ ANGLE_TRY(getResource(context, &resource));
+
+ DXGI_FORMAT resourceFormat =
+ srvType == SRVType::Blit ? mFormatInfo.blitSRVFormat : mFormatInfo.srvFormat;
+ ANGLE_TRY(createSRVForSampler(context, mipLevel, 1, resourceFormat, *resource,
+ &levelSRVs[mipLevel]));
+ }
+ }
+
+ *outSRV = &levelSRVs[mipLevel];
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11::getSRVLevels(const gl::Context *context,
+ GLint baseLevel,
+ GLint maxLevel,
+ const d3d11::SharedSRV **outSRV)
+{
+ ANGLE_TRY(resolveTexture(context));
+ unsigned int mipLevels = maxLevel - baseLevel + 1;
+
+ // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level,
+ // which corresponds to GL level 0)
+ mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - baseLevel);
+
+ if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ ASSERT(mipLevels == 1 || mipLevels == mMipLevels);
+ }
+
+ if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ // We must ensure that the level zero texture is in sync with mipped texture.
+ ANGLE_TRY(useLevelZeroWorkaroundTexture(context, mipLevels == 1));
+ }
+
+ // TODO(jmadill): Assert we don't need to drop stencil.
+
+ SamplerKey key(baseLevel, mipLevels, false, false);
+ ANGLE_TRY(getCachedOrCreateSRVForSampler(context, key, outSRV));
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11::getSRVForImage(const gl::Context *context,
+ const gl::ImageUnit &imageUnit,
+ const d3d11::SharedSRV **outSRV)
+{
+ ANGLE_TRY(resolveTexture(context));
+ // TODO(Xinghua.cao@intel.com): Add solution to handle swizzle required.
+ ImageKey key(imageUnit.level, (imageUnit.layered == GL_TRUE), imageUnit.layer, imageUnit.access,
+ imageUnit.format);
+ ANGLE_TRY(getCachedOrCreateSRVForImage(context, key, outSRV));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11::getCachedOrCreateSRVForImage(const gl::Context *context,
+ const ImageKey &key,
+ const d3d11::SharedSRV **outSRV)
+{
+ auto iter = mSrvCacheForImage.find(key);
+ if (iter != mSrvCacheForImage.end())
+ {
+ *outSRV = &iter->second;
+ return angle::Result::Continue;
+ }
+ const TextureHelper11 *texture = nullptr;
+ ANGLE_TRY(getResource(context, &texture));
+ DXGI_FORMAT format =
+ d3d11::Format::Get(key.format, mRenderer->getRenderer11DeviceCaps()).srvFormat;
+ d3d11::SharedSRV srv;
+ ANGLE_TRY(createSRVForImage(context, key.level, format, *texture, &srv));
+ const auto &insertIt = mSrvCacheForImage.insert(std::make_pair(key, std::move(srv)));
+ *outSRV = &insertIt.first->second;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11::getUAVForImage(const gl::Context *context,
+ const gl::ImageUnit &imageUnit,
+ const d3d11::SharedUAV **outUAV)
+{
+ ANGLE_TRY(resolveTexture(context));
+ // TODO(Xinghua.cao@intel.com): Add solution to handle swizzle required.
+ ImageKey key(imageUnit.level, (imageUnit.layered == GL_TRUE), imageUnit.layer, imageUnit.access,
+ imageUnit.format);
+ ANGLE_TRY(getCachedOrCreateUAVForImage(context, key, outUAV));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11::getCachedOrCreateUAVForImage(const gl::Context *context,
+ const ImageKey &key,
+ const d3d11::SharedUAV **outUAV)
+{
+ auto iter = mUavCacheForImage.find(key);
+ if (iter != mUavCacheForImage.end())
+ {
+ *outUAV = &iter->second;
+ return angle::Result::Continue;
+ }
+ const TextureHelper11 *texture = nullptr;
+ ANGLE_TRY(getResource(context, &texture));
+ DXGI_FORMAT format =
+ d3d11::Format::Get(key.format, mRenderer->getRenderer11DeviceCaps()).uavFormat;
+ ASSERT(format != DXGI_FORMAT_UNKNOWN);
+ d3d11::SharedUAV uav;
+ ANGLE_TRY(createUAVForImage(context, key.level, format, *texture, &uav));
+ const auto &insertIt = mUavCacheForImage.insert(std::make_pair(key, std::move(uav)));
+ *outUAV = &insertIt.first->second;
+ return angle::Result::Continue;
+}
+
+const d3d11::Format &TextureStorage11::getFormatSet() const
+{
+ return mFormatInfo;
+}
+
+angle::Result TextureStorage11::generateSwizzles(const gl::Context *context,
+ const gl::TextureState &textureState)
+{
+ ANGLE_TRY(resolveTexture(context));
+ gl::SwizzleState swizzleTarget = GetEffectiveSwizzle(textureState);
+ for (int level = 0; level < getLevelCount(); level++)
+ {
+ // Check if the swizzle for this level is out of date
+ if (mSwizzleCache[level] != swizzleTarget)
+ {
+ // Need to re-render the swizzle for this level
+ const d3d11::SharedSRV *sourceSRV = nullptr;
+ ANGLE_TRY(getSRVLevel(context, level,
+ textureState.isStencilMode() ? SRVType::Stencil : SRVType::Blit,
+ &sourceSRV));
+
+ const d3d11::RenderTargetView *destRTV;
+ ANGLE_TRY(getSwizzleRenderTarget(context, level, &destRTV));
+
+ gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
+
+ Blit11 *blitter = mRenderer->getBlitter();
+
+ ANGLE_TRY(blitter->swizzleTexture(context, *sourceSRV, *destRTV, size, swizzleTarget));
+
+ mSwizzleCache[level] = swizzleTarget;
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+void TextureStorage11::markLevelDirty(int mipLevel)
+{
+ if (mipLevel >= 0 && static_cast<size_t>(mipLevel) < mSwizzleCache.size())
+ {
+ // The default constructor of SwizzleState has GL_INVALID_INDEX for all channels which is
+ // not a valid swizzle combination
+ if (mSwizzleCache[mipLevel] != gl::SwizzleState())
+ {
+ // TODO(jmadill): Invalidate specific swizzle.
+ mRenderer->getStateManager()->invalidateSwizzles();
+ mSwizzleCache[mipLevel] = gl::SwizzleState();
+ }
+ }
+
+ if (mDropStencilTexture.valid())
+ {
+ mDropStencilTexture.reset();
+ }
+}
+
+void TextureStorage11::markDirty()
+{
+ for (size_t mipLevel = 0; mipLevel < mSwizzleCache.size(); ++mipLevel)
+ {
+ markLevelDirty(static_cast<int>(mipLevel));
+ }
+}
+
+angle::Result TextureStorage11::updateSubresourceLevel(const gl::Context *context,
+ const TextureHelper11 &srcTexture,
+ unsigned int sourceSubresource,
+ const gl::ImageIndex &index,
+ const gl::Box &copyArea)
+{
+ ASSERT(srcTexture.valid());
+
+ ANGLE_TRY(resolveTexture(context));
+ const GLint level = index.getLevelIndex();
+
+ markLevelDirty(level);
+
+ gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level));
+
+ bool fullCopy = copyArea.coversSameExtent(texSize);
+
+ const TextureHelper11 *dstTexture = nullptr;
+
+ // If the zero-LOD workaround is active and we want to update a level greater than zero, then we
+ // should update the mipmapped texture, even if mapmaps are currently disabled.
+ if (level > 0 && mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ ANGLE_TRY(getMippedResource(context, &dstTexture));
+ }
+ else
+ {
+ ANGLE_TRY(getResource(context, &dstTexture));
+ }
+
+ unsigned int dstSubresource = 0;
+ ANGLE_TRY(getSubresourceIndex(context, index, &dstSubresource));
+
+ ASSERT(dstTexture->valid());
+
+ const d3d11::DXGIFormatSize &dxgiFormatSizeInfo =
+ d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat);
+ if (!fullCopy && mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead
+ Blit11 *blitter = mRenderer->getBlitter();
+ return blitter->copyDepthStencil(context, srcTexture, sourceSubresource, copyArea, texSize,
+ *dstTexture, dstSubresource, copyArea, texSize, nullptr);
+ }
+
+ D3D11_BOX srcBox;
+ srcBox.left = copyArea.x;
+ srcBox.top = copyArea.y;
+ srcBox.right =
+ copyArea.x + roundUp(static_cast<UINT>(copyArea.width), dxgiFormatSizeInfo.blockWidth);
+ srcBox.bottom =
+ copyArea.y + roundUp(static_cast<UINT>(copyArea.height), dxgiFormatSizeInfo.blockHeight);
+ srcBox.front = copyArea.z;
+ srcBox.back = copyArea.z + copyArea.depth;
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ deviceContext->CopySubresourceRegion(dstTexture->get(), dstSubresource, copyArea.x, copyArea.y,
+ copyArea.z, srcTexture.get(), sourceSubresource,
+ fullCopy ? nullptr : &srcBox);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11::copySubresourceLevel(const gl::Context *context,
+ const TextureHelper11 &dstTexture,
+ unsigned int dstSubresource,
+ const gl::ImageIndex &index,
+ const gl::Box &region)
+{
+ ASSERT(dstTexture.valid());
+
+ ANGLE_TRY(resolveTexture(context));
+ const TextureHelper11 *srcTexture = nullptr;
+
+ // If the zero-LOD workaround is active and we want to update a level greater than zero, then we
+ // should update the mipmapped texture, even if mapmaps are currently disabled.
+ if (index.getLevelIndex() > 0 && mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ ANGLE_TRY(getMippedResource(context, &srcTexture));
+ }
+ else
+ {
+ ANGLE_TRY(getResource(context, &srcTexture));
+ }
+
+ ASSERT(srcTexture->valid());
+
+ unsigned int srcSubresource = 0;
+ ANGLE_TRY(getSubresourceIndex(context, index, &srcSubresource));
+
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox
+ // should be nullptr.
+ D3D11_BOX srcBox;
+ D3D11_BOX *pSrcBox = nullptr;
+ if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ GLsizei width = region.width;
+ GLsizei height = region.height;
+ d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, nullptr);
+
+ // Keep srcbox as nullptr if we're dealing with tiny mips of compressed textures.
+ if (width == region.width && height == region.height)
+ {
+ // However, D3D10Level9 doesn't always perform CopySubresourceRegion correctly unless
+ // the source box is specified. This is okay, since we don't perform
+ // CopySubresourceRegion on depth/stencil textures on 9_3.
+ ASSERT(mFormatInfo.dsvFormat == DXGI_FORMAT_UNKNOWN);
+ srcBox.left = region.x;
+ srcBox.right = region.x + region.width;
+ srcBox.top = region.y;
+ srcBox.bottom = region.y + region.height;
+ srcBox.front = region.z;
+ srcBox.back = region.z + region.depth;
+ pSrcBox = &srcBox;
+ }
+ }
+
+ deviceContext->CopySubresourceRegion(dstTexture.get(), dstSubresource, region.x, region.y,
+ region.z, srcTexture->get(), srcSubresource, pSrcBox);
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11::generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex)
+{
+ ASSERT(sourceIndex.getLayerIndex() == destIndex.getLayerIndex());
+
+ ANGLE_TRY(resolveTexture(context));
+ markLevelDirty(destIndex.getLevelIndex());
+
+ RenderTargetD3D *source = nullptr;
+ ANGLE_TRY(getRenderTarget(context, sourceIndex, 0, &source));
+
+ // dest will always have 0 since, we have just released the MS Texture struct
+ RenderTargetD3D *dest = nullptr;
+ ANGLE_TRY(getRenderTarget(context, destIndex, 0, &dest));
+
+ RenderTarget11 *srcRT11 = GetAs<RenderTarget11>(source);
+ RenderTarget11 *dstRT11 = GetAs<RenderTarget11>(dest);
+ const d3d11::RenderTargetView &destRTV = dstRT11->getRenderTargetView();
+ const d3d11::SharedSRV *sourceSRV;
+ ANGLE_TRY(srcRT11->getBlitShaderResourceView(context, &sourceSRV));
+
+ gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth());
+ gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth());
+
+ gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth());
+ gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth());
+
+ Blit11 *blitter = mRenderer->getBlitter();
+ const gl::InternalFormat &sourceInternalFormat =
+ gl::GetSizedInternalFormatInfo(source->getInternalFormat());
+ GLenum format = sourceInternalFormat.format;
+ GLenum type = sourceInternalFormat.type;
+ return blitter->copyTexture(context, *sourceSRV, sourceArea, sourceSize, format, destRTV,
+ destArea, destSize, nullptr, format, type, GL_LINEAR, false, false,
+ false);
+}
+
+void TextureStorage11::verifySwizzleExists(const gl::SwizzleState &swizzleState)
+{
+ for (unsigned int level = 0; level < mMipLevels; level++)
+ {
+ ASSERT(mSwizzleCache[level] == swizzleState);
+ }
+}
+
+void TextureStorage11::clearSRVCache()
+{
+ markDirty();
+ mSrvCacheForSampler.clear();
+
+ for (size_t level = 0; level < mLevelSRVs.size(); level++)
+ {
+ mLevelSRVs[level].reset();
+ mLevelBlitSRVs[level].reset();
+ }
+}
+
+angle::Result TextureStorage11::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
+{
+ ASSERT(destStorage);
+
+ ANGLE_TRY(resolveTexture(context));
+ const TextureHelper11 *sourceResouce = nullptr;
+ ANGLE_TRY(getResource(context, &sourceResouce));
+
+ TextureStorage11 *dest11 = GetAs<TextureStorage11>(destStorage);
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
+
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+ immediateContext->CopyResource(destResource->get(), sourceResouce->get());
+
+ dest11->markDirty();
+
+ return angle::Result::Continue;
+}
+
+void TextureStorage11::invalidateTextures()
+{
+ mRenderer->getStateManager()->invalidateTexturesAndSamplers();
+}
+
+angle::Result TextureStorage11::setData(const gl::Context *context,
+ const gl::ImageIndex &index,
+ ImageD3D *image,
+ const gl::Box *destBox,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixelData)
+{
+ ASSERT(!image->isDirty());
+
+ ANGLE_TRY(resolveTexture(context));
+ markLevelDirty(index.getLevelIndex());
+
+ const TextureHelper11 *resource = nullptr;
+ ANGLE_TRY(getResource(context, &resource));
+ ASSERT(resource && resource->valid());
+
+ UINT destSubresource = 0;
+ ANGLE_TRY(getSubresourceIndex(context, index, &destSubresource));
+
+ const gl::InternalFormat &internalFormatInfo =
+ gl::GetInternalFormatInfo(image->getInternalFormat(), type);
+
+ gl::Box levelBox(0, 0, 0, getLevelWidth(index.getLevelIndex()),
+ getLevelHeight(index.getLevelIndex()), getLevelDepth(index.getLevelIndex()));
+ bool fullUpdate = (destBox == nullptr || *destBox == levelBox);
+ ASSERT(internalFormatInfo.depthBits == 0 || fullUpdate);
+
+ // TODO(jmadill): Handle compressed formats
+ // Compressed formats have different load syntax, so we'll have to handle them with slightly
+ // different logic. Will implemnent this in a follow-up patch, and ensure we do not use SetData
+ // with compressed formats in the calling logic.
+ ASSERT(!internalFormatInfo.compressed);
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ const int width = destBox ? destBox->width : static_cast<int>(image->getWidth());
+ const int height = destBox ? destBox->height : static_cast<int>(image->getHeight());
+ const int depth = destBox ? destBox->depth : static_cast<int>(image->getDepth());
+ GLuint srcRowPitch = 0;
+ ANGLE_CHECK_GL_MATH(context11,
+ internalFormatInfo.computeRowPitch(type, width, unpack.alignment,
+ unpack.rowLength, &srcRowPitch));
+ GLuint srcDepthPitch = 0;
+ ANGLE_CHECK_GL_MATH(context11, internalFormatInfo.computeDepthPitch(
+ height, unpack.imageHeight, srcRowPitch, &srcDepthPitch));
+ GLuint srcSkipBytes = 0;
+ ANGLE_CHECK_GL_MATH(
+ context11, internalFormatInfo.computeSkipBytes(type, srcRowPitch, srcDepthPitch, unpack,
+ index.usesTex3D(), &srcSkipBytes));
+
+ const d3d11::Format &d3d11Format =
+ d3d11::Format::Get(image->getInternalFormat(), mRenderer->getRenderer11DeviceCaps());
+ const d3d11::DXGIFormatSize &dxgiFormatInfo =
+ d3d11::GetDXGIFormatSizeInfo(d3d11Format.texFormat);
+
+ const size_t outputPixelSize = dxgiFormatInfo.pixelBytes;
+
+ UINT bufferRowPitch = static_cast<unsigned int>(outputPixelSize) * width;
+ UINT bufferDepthPitch = bufferRowPitch * height;
+
+ const size_t neededSize = bufferDepthPitch * depth;
+ angle::MemoryBuffer *conversionBuffer = nullptr;
+ const uint8_t *data = nullptr;
+
+ LoadImageFunctionInfo loadFunctionInfo = d3d11Format.getLoadFunctions()(type);
+ if (loadFunctionInfo.requiresConversion)
+ {
+ ANGLE_TRY(mRenderer->getScratchMemoryBuffer(context11, neededSize, &conversionBuffer));
+ loadFunctionInfo.loadFunction(width, height, depth, pixelData + srcSkipBytes, srcRowPitch,
+ srcDepthPitch, conversionBuffer->data(), bufferRowPitch,
+ bufferDepthPitch);
+ data = conversionBuffer->data();
+ }
+ else
+ {
+ data = pixelData + srcSkipBytes;
+ bufferRowPitch = srcRowPitch;
+ bufferDepthPitch = srcDepthPitch;
+ }
+
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+
+ if (!fullUpdate)
+ {
+ ASSERT(destBox);
+
+ D3D11_BOX destD3DBox;
+ destD3DBox.left = destBox->x;
+ destD3DBox.right = destBox->x + destBox->width;
+ destD3DBox.top = destBox->y;
+ destD3DBox.bottom = destBox->y + destBox->height;
+ destD3DBox.front = destBox->z;
+ destD3DBox.back = destBox->z + destBox->depth;
+
+ immediateContext->UpdateSubresource(resource->get(), destSubresource, &destD3DBox, data,
+ bufferRowPitch, bufferDepthPitch);
+ }
+ else
+ {
+ immediateContext->UpdateSubresource(resource->get(), destSubresource, nullptr, data,
+ bufferRowPitch, bufferDepthPitch);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11::ensureDropStencilTexture(
+ const gl::Context *context,
+ TextureStorage11::DropStencil *dropStencilOut)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11::initDropStencilTexture(const gl::Context *context,
+ const gl::ImageIndexIterator &it)
+{
+ const TextureHelper11 *sourceTexture = nullptr;
+ ANGLE_TRY(getResource(context, &sourceTexture));
+
+ gl::ImageIndexIterator itCopy = it;
+
+ while (itCopy.hasNext())
+ {
+ gl::ImageIndex index = itCopy.next();
+ gl::Box wholeArea(0, 0, 0, getLevelWidth(index.getLevelIndex()),
+ getLevelHeight(index.getLevelIndex()), 1);
+ gl::Extents wholeSize(wholeArea.width, wholeArea.height, 1);
+
+ UINT subresource = 0;
+ ANGLE_TRY(getSubresourceIndex(context, index, &subresource));
+
+ ANGLE_TRY(mRenderer->getBlitter()->copyDepthStencil(
+ context, *sourceTexture, subresource, wholeArea, wholeSize, mDropStencilTexture,
+ subresource, wholeArea, wholeSize, nullptr));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11::resolveTextureHelper(const gl::Context *context,
+ const TextureHelper11 &texture)
+{
+ UINT subresourceIndexSS;
+ ANGLE_TRY(getSubresourceIndex(context, mMSTexInfo->indexSS, &subresourceIndexSS));
+ UINT subresourceIndexMS;
+ ANGLE_TRY(getSubresourceIndex(context, mMSTexInfo->indexMS, &subresourceIndexMS));
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ const TextureHelper11 *resource = nullptr;
+ ANGLE_TRY(mMSTexInfo->msTex->getResource(context, &resource));
+ deviceContext->ResolveSubresource(texture.get(), subresourceIndexSS, resource->get(),
+ subresourceIndexMS, texture.getFormat());
+ mMSTexInfo->msTextureNeedsResolve = false;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11::releaseMultisampledTexStorageForLevel(size_t level)
+{
+ if (mMSTexInfo && mMSTexInfo->indexSS.getLevelIndex() == static_cast<int>(level))
+ {
+ mMSTexInfo->msTex.reset();
+ onStateChange(angle::SubjectMessage::ContentsChanged);
+ }
+ return angle::Result::Continue;
+}
+
+GLsizei TextureStorage11::getRenderToTextureSamples() const
+{
+ if (mMSTexInfo)
+ {
+ return mMSTexInfo->samples;
+ }
+ return 0;
+}
+
+angle::Result TextureStorage11::findMultisampledRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const
+{
+ const int level = index.getLevelIndex();
+ if (!mMSTexInfo || level != mMSTexInfo->indexSS.getLevelIndex() ||
+ samples != mMSTexInfo->samples || !mMSTexInfo->msTex)
+ {
+ *outRT = nullptr;
+ return angle::Result::Continue;
+ }
+ RenderTargetD3D *rt;
+ ANGLE_TRY(mMSTexInfo->msTex->findRenderTarget(context, mMSTexInfo->indexMS, samples, &rt));
+ *outRT = rt;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11::getMultisampledRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ const int level = index.getLevelIndex();
+ if (!mMSTexInfo || level != mMSTexInfo->indexSS.getLevelIndex() ||
+ samples != mMSTexInfo->samples || !mMSTexInfo->msTex)
+ {
+ // if mMSTexInfo already exists, then we want to resolve and release it
+ // since the mMSTexInfo must be for a different sample count or level
+ ANGLE_TRY(resolveTexture(context));
+
+ // Now we can create a new object for the correct sample and level
+ GLsizei width = getLevelWidth(level);
+ GLsizei height = getLevelHeight(level);
+ GLenum internalFormat = mFormatInfo.internalFormat;
+ std::unique_ptr<TextureStorage11_2DMultisample> texMS(
+ GetAs<TextureStorage11_2DMultisample>(mRenderer->createTextureStorage2DMultisample(
+ internalFormat, width, height, level, samples, true, mKHRDebugLabel)));
+
+ // make sure multisample object has the blitted information.
+ gl::Rectangle area(0, 0, width, height);
+ RenderTargetD3D *readRenderTarget = nullptr;
+ // use incoming index here since the index will correspond to the single sampled texture
+ ANGLE_TRY(getRenderTarget(context, index, 0, &readRenderTarget));
+ gl::ImageIndex indexMS = gl::ImageIndex::Make2DMultisample();
+ RenderTargetD3D *drawRenderTarget = nullptr;
+ ANGLE_TRY(texMS->getRenderTarget(context, indexMS, samples, &drawRenderTarget));
+
+ // blit SS -> MS
+ // mask: GL_COLOR_BUFFER_BIT, filter: GL_NEAREST
+ ANGLE_TRY(mRenderer->blitRenderbufferRect(context, area, area, 0, 0, readRenderTarget,
+ drawRenderTarget, GL_NEAREST, nullptr, true,
+ false, false));
+ mMSTexInfo = std::make_unique<MultisampledRenderToTextureInfo>(samples, index, indexMS);
+ mMSTexInfo->msTex = std::move(texMS);
+ }
+ RenderTargetD3D *rt;
+ ANGLE_TRY(mMSTexInfo->msTex->getRenderTarget(context, mMSTexInfo->indexMS, samples, &rt));
+ // By returning the multisampled render target to the caller, the render target
+ // is expected to be changed so we need to resolve to a single sampled texture
+ // next time resolveTexture is called.
+ mMSTexInfo->msTextureNeedsResolve = true;
+ *outRT = rt;
+ return angle::Result::Continue;
+}
+
+TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer,
+ SwapChain11 *swapchain,
+ const std::string &label)
+ : TextureStorage11(renderer,
+ D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
+ 0,
+ swapchain->getRenderTargetInternalFormat(),
+ label),
+ mTexture(swapchain->getOffscreenTexture()),
+ mLevelZeroTexture(),
+ mLevelZeroRenderTarget(nullptr),
+ mUseLevelZeroTexture(false),
+ mSwizzleTexture()
+{
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mAssociatedImages[i] = nullptr;
+ mRenderTarget[i] = nullptr;
+ }
+
+ D3D11_TEXTURE2D_DESC texDesc;
+ mTexture.getDesc(&texDesc);
+ mMipLevels = texDesc.MipLevels;
+ mTextureWidth = texDesc.Width;
+ mTextureHeight = texDesc.Height;
+ mTextureDepth = 1;
+ mHasKeyedMutex = (texDesc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0;
+}
+
+TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer,
+ GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ const std::string &label,
+ bool hintLevelZeroOnly)
+ : TextureStorage11(
+ renderer,
+ GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), bindFlags),
+ GetTextureMiscFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ bindFlags,
+ levels),
+ internalformat,
+ label),
+ mTexture(),
+ mHasKeyedMutex(false),
+ mLevelZeroTexture(),
+ mLevelZeroRenderTarget(nullptr),
+ mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1),
+ mSwizzleTexture()
+{
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mAssociatedImages[i] = nullptr;
+ mRenderTarget[i] = nullptr;
+ }
+
+ d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
+ mMipLevels = mTopLevel + levels;
+ mTextureWidth = width;
+ mTextureHeight = height;
+ mTextureDepth = 1;
+
+ // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
+ ASSERT(!mUseLevelZeroTexture || mRenderer->getFeatures().zeroMaxLodWorkaround.enabled);
+}
+
+void TextureStorage11_2D::onLabelUpdate()
+{
+ if (mTexture.valid())
+ {
+ mTexture.setKHRDebugLabel(&mKHRDebugLabel);
+ }
+ if (mLevelZeroTexture.valid())
+ {
+ mLevelZeroTexture.setKHRDebugLabel(&mKHRDebugLabel);
+ }
+ if (mSwizzleTexture.valid())
+ {
+ mSwizzleTexture.setKHRDebugLabel(&mKHRDebugLabel);
+ }
+}
+
+angle::Result TextureStorage11_2D::onDestroy(const gl::Context *context)
+{
+ for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ if (mAssociatedImages[i] != nullptr)
+ {
+ mAssociatedImages[i]->verifyAssociatedStorageValid(this);
+
+ // We must let the Images recover their data before we delete it from the
+ // TextureStorage.
+ ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context));
+ }
+ }
+
+ if (mHasKeyedMutex)
+ {
+ // If the keyed mutex is released that will unbind it and cause the state cache to become
+ // desynchronized.
+ mRenderer->getStateManager()->invalidateBoundViews();
+ }
+
+ return angle::Result::Continue;
+}
+
+TextureStorage11_2D::~TextureStorage11_2D() {}
+
+angle::Result TextureStorage11_2D::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
+{
+ ASSERT(destStorage);
+
+ TextureStorage11_2D *dest11 = GetAs<TextureStorage11_2D>(destStorage);
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+
+ if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the
+ // corresponding textures in destStorage.
+ if (mTexture.valid())
+ {
+ ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, false));
+
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
+
+ immediateContext->CopyResource(destResource->get(), mTexture.get());
+ }
+
+ if (mLevelZeroTexture.valid())
+ {
+ ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, true));
+
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
+
+ immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get());
+ }
+
+ return angle::Result::Continue;
+ }
+
+ const TextureHelper11 *sourceResouce = nullptr;
+ ANGLE_TRY(getResource(context, &sourceResouce));
+
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
+
+ immediateContext->CopyResource(destResource->get(), sourceResouce->get());
+ dest11->markDirty();
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2D::useLevelZeroWorkaroundTexture(const gl::Context *context,
+ bool useLevelZeroTexture)
+{
+ if (useLevelZeroTexture && mMipLevels > 1)
+ {
+ if (!mUseLevelZeroTexture && mTexture.valid())
+ {
+ ANGLE_TRY(ensureTextureExists(context, 1));
+
+ // Pull data back from the mipped texture if necessary.
+ ASSERT(mLevelZeroTexture.valid());
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->CopySubresourceRegion(mLevelZeroTexture.get(), 0, 0, 0, 0,
+ mTexture.get(), 0, nullptr);
+ }
+
+ mUseLevelZeroTexture = true;
+ }
+ else
+ {
+ if (mUseLevelZeroTexture && mLevelZeroTexture.valid())
+ {
+ ANGLE_TRY(ensureTextureExists(context, mMipLevels));
+
+ // Pull data back from the level zero texture if necessary.
+ ASSERT(mTexture.valid());
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->CopySubresourceRegion(mTexture.get(), 0, 0, 0, 0,
+ mLevelZeroTexture.get(), 0, nullptr);
+ }
+
+ mUseLevelZeroTexture = false;
+ }
+
+ return angle::Result::Continue;
+}
+
+void TextureStorage11_2D::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+ const GLint level = index.getLevelIndex();
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ mAssociatedImages[level] = image;
+ }
+}
+
+void TextureStorage11_2D::verifyAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+ const GLint level = index.getLevelIndex();
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ // This validation check should never return false. It means the Image/TextureStorage
+ // association is broken.
+ ASSERT(mAssociatedImages[level] == expectedImage);
+}
+
+// disassociateImage allows an Image to end its association with a Storage.
+void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
+{
+ const GLint level = index.getLevelIndex();
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(mAssociatedImages[level] == expectedImage);
+ mAssociatedImages[level] = nullptr;
+}
+
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
+// recover its data before ending the association.
+angle::Result TextureStorage11_2D::releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage)
+{
+ const GLint level = index.getLevelIndex();
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ // No need to let the old Image recover its data, if it is also the incoming Image.
+ if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage)
+ {
+ // Ensure that the Image is still associated with this TextureStorage.
+ mAssociatedImages[level]->verifyAssociatedStorageValid(this);
+
+ // Force the image to recover from storage before its data is overwritten.
+ // This will reset mAssociatedImages[level] to nullptr too.
+ ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage(context));
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2D::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ if (mUseLevelZeroTexture && mMipLevels > 1)
+ {
+ ANGLE_TRY(ensureTextureExists(context, 1));
+
+ *outResource = &mLevelZeroTexture;
+ return angle::Result::Continue;
+ }
+
+ ANGLE_TRY(ensureTextureExists(context, mMipLevels));
+
+ *outResource = &mTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2D::getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ // This shouldn't be called unless the zero max LOD workaround is active.
+ ASSERT(mRenderer->getFeatures().zeroMaxLodWorkaround.enabled);
+
+ ANGLE_TRY(ensureTextureExists(context, mMipLevels));
+
+ *outResource = &mTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2D::ensureTextureExists(const gl::Context *context, int mipLevels)
+{
+ // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
+ ANGLE_TRY(resolveTexture(context));
+ bool useLevelZeroTexture = mRenderer->getFeatures().zeroMaxLodWorkaround.enabled
+ ? (mipLevels == 1) && (mMipLevels > 1)
+ : false;
+ TextureHelper11 *outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
+
+ // if the width or height is not positive this should be treated as an incomplete texture
+ // we handle that here by skipping the d3d texture creation
+ if (!outputTexture->valid() && mTextureWidth > 0 && mTextureHeight > 0)
+ {
+ ASSERT(mipLevels > 0);
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth; // Compressed texture size constraints?
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mipLevels;
+ desc.ArraySize = 1;
+ desc.Format = isUnorderedAccess() ? mFormatInfo.typelessFormat : mFormatInfo.texFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = getMiscFlags();
+
+ ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
+ outputTexture));
+
+ if (useLevelZeroTexture)
+ {
+ outputTexture->setLabels("TexStorage2D.Level0Texture", &mKHRDebugLabel);
+ }
+ else
+ {
+ outputTexture->setLabels("TexStorage2D.Texture", &mKHRDebugLabel);
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2D::findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const
+{
+ ASSERT(!index.hasLayer());
+
+ const int level = index.getLevelIndex();
+ ASSERT(level >= 0 && level < getLevelCount());
+
+ bool needMS = samples > 0;
+ if (needMS)
+ {
+ return findMultisampledRenderTarget(context, index, samples, outRT);
+ }
+
+ ASSERT(outRT);
+ if (mRenderTarget[level])
+ {
+ *outRT = mRenderTarget[level].get();
+ return angle::Result::Continue;
+ }
+
+ if (mUseLevelZeroTexture)
+ {
+ ASSERT(level == 0);
+ *outRT = mLevelZeroRenderTarget.get();
+ return angle::Result::Continue;
+ }
+
+ *outRT = nullptr;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2D::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(!index.hasLayer());
+
+ const int level = index.getLevelIndex();
+ ASSERT(level >= 0 && level < getLevelCount());
+
+ bool needMS = samples > 0;
+ if (needMS)
+ {
+ return getMultisampledRenderTarget(context, index, samples, outRT);
+ }
+ else
+ {
+ ANGLE_TRY(resolveTexture(context));
+ }
+
+ // In GL ES 2.0, the application can only render to level zero of the texture (Section 4.4.3 of
+ // the GLES 2.0 spec, page 113 of version 2.0.25). Other parts of TextureStorage11_2D could
+ // create RTVs on non-zero levels of the texture (e.g. generateMipmap).
+ // On Feature Level 9_3, this is unlikely to be useful. The renderer can't create SRVs on the
+ // individual levels of the texture, so methods like generateMipmap can't do anything useful
+ // with non-zero-level RTVs. Therefore if level > 0 on 9_3 then there's almost certainly
+ // something wrong.
+ ASSERT(
+ !(mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 && level > 0));
+ ASSERT(outRT);
+ if (mRenderTarget[level])
+ {
+ *outRT = mRenderTarget[level].get();
+ return angle::Result::Continue;
+ }
+
+ if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ ASSERT(level == 0);
+ ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true));
+ }
+
+ const TextureHelper11 *texture = nullptr;
+ ANGLE_TRY(getResource(context, &texture));
+
+ const d3d11::SharedSRV *srv = nullptr;
+ ANGLE_TRY(getSRVLevel(context, level, SRVType::Sample, &srv));
+
+ const d3d11::SharedSRV *blitSRV = nullptr;
+ ANGLE_TRY(getSRVLevel(context, level, SRVType::Blit, &blitSRV));
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ if (mUseLevelZeroTexture)
+ {
+ if (!mLevelZeroRenderTarget)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = mTopLevel + level;
+
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(
+ mRenderer->allocateResource(context11, rtvDesc, mLevelZeroTexture.get(), &rtv));
+ rtv.setLabels("TexStorage2D.Level0RTV", &mKHRDebugLabel);
+
+ mLevelZeroRenderTarget.reset(new TextureRenderTarget11(
+ std::move(rtv), mLevelZeroTexture, d3d11::SharedSRV(), d3d11::SharedSRV(),
+ mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level),
+ getLevelHeight(level), 1, 0));
+ }
+
+ *outRT = mLevelZeroRenderTarget.get();
+ return angle::Result::Continue;
+ }
+
+ if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = mTopLevel + level;
+
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
+ rtv.setLabels("TexStorage2D.RTV", &mKHRDebugLabel);
+
+ mRenderTarget[level].reset(new TextureRenderTarget11(
+ std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(level), getLevelHeight(level), 1, 0));
+
+ *outRT = mRenderTarget[level].get();
+ return angle::Result::Continue;
+ }
+
+ ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Format = mFormatInfo.dsvFormat;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
+ dsvDesc.Texture2D.MipSlice = mTopLevel + level;
+ dsvDesc.Flags = 0;
+
+ d3d11::DepthStencilView dsv;
+ ANGLE_TRY(mRenderer->allocateResource(context11, dsvDesc, texture->get(), &dsv));
+ dsv.setLabels("TexStorage2D.DSV", &mKHRDebugLabel);
+
+ mRenderTarget[level].reset(new TextureRenderTarget11(
+ std::move(dsv), *texture, *srv, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(level), getLevelHeight(level), 1, 0));
+
+ *outRT = mRenderTarget[level].get();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2D::createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ ASSERT(outSRV);
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
+ srvDesc.Texture2D.MipLevels = mipLevels;
+
+ const TextureHelper11 *srvTexture = &texture;
+
+ if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ ASSERT(mTopLevel == 0);
+ ASSERT(baseLevel == 0);
+ // This code also assumes that the incoming texture equals either mLevelZeroTexture or
+ // mTexture.
+
+ if (mipLevels == 1 && mMipLevels > 1)
+ {
+ // We must use a SRV on the level-zero-only texture.
+ ANGLE_TRY(ensureTextureExists(context, 1));
+ srvTexture = &mLevelZeroTexture;
+ }
+ else
+ {
+ ASSERT(mipLevels == static_cast<int>(mMipLevels));
+ ASSERT(mTexture.valid() && texture == mTexture);
+ srvTexture = &mTexture;
+ }
+ }
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, srvTexture->get(),
+ outSRV));
+ outSRV->setLabels("TexStorage2D.SRV", &mKHRDebugLabel);
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2D::createSRVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ ASSERT(outSRV);
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MostDetailedMip = mTopLevel + level;
+ srvDesc.Texture2D.MipLevels = 1;
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
+ outSRV->setLabels("TexStorage2D.SRVForImage", &mKHRDebugLabel);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2D::createUAVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedUAV *outUAV)
+{
+ ASSERT(outUAV);
+ D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
+ uavDesc.Format = format;
+ uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
+ uavDesc.Texture2D.MipSlice = mTopLevel + level;
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
+ outUAV->setLabels("TexStorage2D.UAVForImage", &mKHRDebugLabel);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2D::getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture)
+{
+ ASSERT(outTexture);
+
+ if (!mSwizzleTexture.valid())
+ {
+ const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = 1;
+ desc.Format = format.texFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
+ &mSwizzleTexture));
+ mSwizzleTexture.setLabels("TexStorage2D.SwizzleTexture", &mKHRDebugLabel);
+ }
+
+ *outTexture = &mSwizzleTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2D::getSwizzleRenderTarget(const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV)
+{
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+ ASSERT(outRTV);
+
+ if (!mSwizzleRenderTargets[mipLevel].valid())
+ {
+ const TextureHelper11 *swizzleTexture = nullptr;
+ ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format =
+ mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
+ mSwizzleTexture.get(),
+ &mSwizzleRenderTargets[mipLevel]));
+ }
+
+ *outRTV = &mSwizzleRenderTargets[mipLevel];
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2D::ensureDropStencilTexture(const gl::Context *context,
+ DropStencil *dropStencilOut)
+{
+ if (mDropStencilTexture.valid())
+ {
+ *dropStencilOut = DropStencil::ALREADY_EXISTS;
+ return angle::Result::Continue;
+ }
+
+ D3D11_TEXTURE2D_DESC dropDesc = {};
+ dropDesc.ArraySize = 1;
+ dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
+ dropDesc.CPUAccessFlags = 0;
+ dropDesc.Format = DXGI_FORMAT_R32_TYPELESS;
+ dropDesc.Height = mTextureHeight;
+ dropDesc.MipLevels = mMipLevels;
+ dropDesc.MiscFlags = 0;
+ dropDesc.SampleDesc.Count = 1;
+ dropDesc.SampleDesc.Quality = 0;
+ dropDesc.Usage = D3D11_USAGE_DEFAULT;
+ dropDesc.Width = mTextureWidth;
+
+ const auto &format =
+ d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
+ ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), dropDesc, format,
+ &mDropStencilTexture));
+ mDropStencilTexture.setLabels("TexStorage2D.DropStencil", &mKHRDebugLabel);
+
+ ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::Make2D(0, mMipLevels)));
+
+ *dropStencilOut = DropStencil::CREATED;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2D::resolveTexture(const gl::Context *context)
+{
+ if (mMSTexInfo && mMSTexInfo->msTex && mMSTexInfo->msTextureNeedsResolve)
+ {
+ ANGLE_TRY(resolveTextureHelper(context, mTexture));
+ onStateChange(angle::SubjectMessage::ContentsChanged);
+ }
+ return angle::Result::Continue;
+}
+
+TextureStorage11_External::TextureStorage11_External(
+ Renderer11 *renderer,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &glDesc,
+ const std::string &label)
+ : TextureStorage11(renderer, D3D11_BIND_SHADER_RESOURCE, 0, glDesc.internalFormat, label)
+{
+ ASSERT(stream->getProducerType() == egl::Stream::ProducerType::D3D11Texture);
+ auto *producer = static_cast<StreamProducerD3DTexture *>(stream->getImplementation());
+ mTexture.set(producer->getD3DTexture(), mFormatInfo);
+ mSubresourceIndex = producer->getArraySlice();
+ mTexture.get()->AddRef();
+ mMipLevels = 1;
+
+ D3D11_TEXTURE2D_DESC desc;
+ mTexture.getDesc(&desc);
+ mTextureWidth = desc.Width;
+ mTextureHeight = desc.Height;
+ mTextureDepth = 1;
+ mHasKeyedMutex = (desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0;
+}
+
+angle::Result TextureStorage11_External::onDestroy(const gl::Context *context)
+{
+ if (mHasKeyedMutex)
+ {
+ // If the keyed mutex is released that will unbind it and cause the state cache to become
+ // desynchronized.
+ mRenderer->getStateManager()->invalidateBoundViews();
+ }
+
+ return angle::Result::Continue;
+}
+
+TextureStorage11_External::~TextureStorage11_External() {}
+
+angle::Result TextureStorage11_External::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
+{
+ UNIMPLEMENTED();
+ return angle::Result::Continue;
+}
+
+void TextureStorage11_External::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+ ASSERT(index.getLevelIndex() == 0);
+ mAssociatedImage = image;
+}
+
+void TextureStorage11_External::verifyAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+ ASSERT(index.getLevelIndex() == 0 && mAssociatedImage == expectedImage);
+}
+
+void TextureStorage11_External::disassociateImage(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+ ASSERT(index.getLevelIndex() == 0);
+ ASSERT(mAssociatedImage == expectedImage);
+ mAssociatedImage = nullptr;
+}
+
+angle::Result TextureStorage11_External::releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage)
+{
+ ASSERT(index.getLevelIndex() == 0);
+
+ if (mAssociatedImage != nullptr && mAssociatedImage != incomingImage)
+ {
+ mAssociatedImage->verifyAssociatedStorageValid(this);
+
+ ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage(context));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_External::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ *outResource = &mTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_External::getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ *outResource = &mTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_External::findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const
+{
+ // Render targets are not supported for external textures
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_External::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ // Render targets are not supported for external textures
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_External::createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ // Since external textures are treates as non-mipmapped textures, we ignore mipmap levels and
+ // use the specified subresource ID the storage was created with.
+ ASSERT(mipLevels == 1);
+ ASSERT(outSRV);
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ // subresource index is equal to the mip level for 2D textures
+ srvDesc.Texture2DArray.MostDetailedMip = 0;
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = mSubresourceIndex;
+ srvDesc.Texture2DArray.ArraySize = 1;
+
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
+ outSRV->setLabels("TexStorage2D.SRV", &mKHRDebugLabel);
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_External::createSRVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_External::createUAVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedUAV *outUAV)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_External::getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_External::getSwizzleRenderTarget(
+ const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+void TextureStorage11_External::onLabelUpdate()
+{
+ if (mTexture.valid())
+ {
+ mTexture.setKHRDebugLabel(&mKHRDebugLabel);
+ }
+}
+
+TextureStorage11ImmutableBase::TextureStorage11ImmutableBase(Renderer11 *renderer,
+ UINT bindFlags,
+ UINT miscFlags,
+ GLenum internalFormat,
+ const std::string &label)
+ : TextureStorage11(renderer, bindFlags, miscFlags, internalFormat, label)
+{}
+
+void TextureStorage11ImmutableBase::associateImage(Image11 *, const gl::ImageIndex &) {}
+
+void TextureStorage11ImmutableBase::disassociateImage(const gl::ImageIndex &, Image11 *) {}
+
+void TextureStorage11ImmutableBase::verifyAssociatedImageValid(const gl::ImageIndex &, Image11 *) {}
+
+angle::Result TextureStorage11ImmutableBase::releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &,
+ Image11 *)
+{
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11ImmutableBase::createSRVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11ImmutableBase::createUAVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedUAV *outUAV)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer,
+ EGLImageD3D *eglImage,
+ RenderTarget11 *renderTarget11,
+ const std::string &label)
+ : TextureStorage11ImmutableBase(renderer,
+ D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE,
+ 0,
+ renderTarget11->getInternalFormat(),
+ label),
+ mImage(eglImage),
+ mCurrentRenderTarget(0),
+ mSwizzleTexture(),
+ mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+{
+ mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
+
+ mMipLevels = 1;
+ mTextureWidth = renderTarget11->getWidth();
+ mTextureHeight = renderTarget11->getHeight();
+ mTextureDepth = 1;
+}
+
+TextureStorage11_EGLImage::~TextureStorage11_EGLImage() {}
+
+angle::Result TextureStorage11_EGLImage::getSubresourceIndex(const gl::Context *context,
+ const gl::ImageIndex &index,
+ UINT *outSubresourceIndex) const
+{
+ ASSERT(index.getType() == gl::TextureType::_2D);
+ ASSERT(index.getLevelIndex() == 0);
+
+ RenderTarget11 *renderTarget11 = nullptr;
+ ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
+ *outSubresourceIndex = renderTarget11->getSubresourceIndex();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_EGLImage::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ ANGLE_TRY(checkForUpdatedRenderTarget(context));
+
+ RenderTarget11 *renderTarget11 = nullptr;
+ ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
+ *outResource = &renderTarget11->getTexture();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_EGLImage::getSRVForSampler(const gl::Context *context,
+ const gl::TextureState &textureState,
+ const gl::SamplerState &sampler,
+ const d3d11::SharedSRV **outSRV)
+{
+ ANGLE_TRY(checkForUpdatedRenderTarget(context));
+ return TextureStorage11::getSRVForSampler(context, textureState, sampler, outSRV);
+}
+
+angle::Result TextureStorage11_EGLImage::getMippedResource(const gl::Context *context,
+ const TextureHelper11 **)
+{
+ // This shouldn't be called unless the zero max LOD workaround is active.
+ // EGL images are unavailable in this configuration.
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_EGLImage::findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const
+{
+ // Since the render target of an EGL image will be updated when orphaning, trying to find a
+ // cache of it can be rarely useful.
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_EGLImage::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(!index.hasLayer());
+ ASSERT(index.getLevelIndex() == 0);
+
+ ANGLE_TRY(checkForUpdatedRenderTarget(context));
+
+ return mImage->getRenderTarget(context, outRT);
+}
+
+angle::Result TextureStorage11_EGLImage::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
+{
+ const TextureHelper11 *sourceResouce = nullptr;
+ ANGLE_TRY(getResource(context, &sourceResouce));
+
+ ASSERT(destStorage);
+ TextureStorage11_2D *dest11 = GetAs<TextureStorage11_2D>(destStorage);
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
+
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+ immediateContext->CopyResource(destResource->get(), sourceResouce->get());
+
+ dest11->markDirty();
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_EGLImage::useLevelZeroWorkaroundTexture(const gl::Context *context,
+ bool)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_EGLImage::getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture)
+{
+ ASSERT(outTexture);
+
+ if (!mSwizzleTexture.valid())
+ {
+ const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = 1;
+ desc.Format = format.texFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
+ &mSwizzleTexture));
+ mSwizzleTexture.setLabels("TexStorageEGLImage.SwizzleTexture", &mKHRDebugLabel);
+ }
+
+ *outTexture = &mSwizzleTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_EGLImage::getSwizzleRenderTarget(
+ const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV)
+{
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+ ASSERT(outRTV);
+
+ if (!mSwizzleRenderTargets[mipLevel].valid())
+ {
+ const TextureHelper11 *swizzleTexture = nullptr;
+ ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format =
+ mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel;
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
+ mSwizzleTexture.get(),
+ &mSwizzleRenderTargets[mipLevel]));
+ }
+
+ *outRTV = &mSwizzleRenderTargets[mipLevel];
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_EGLImage::checkForUpdatedRenderTarget(const gl::Context *context)
+{
+ RenderTarget11 *renderTarget11 = nullptr;
+ ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
+
+ if (mCurrentRenderTarget != reinterpret_cast<uintptr_t>(renderTarget11))
+ {
+ clearSRVCache();
+ mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_EGLImage::createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ ASSERT(baseLevel == 0);
+ ASSERT(mipLevels == 1);
+ ASSERT(outSRV);
+
+ // Create a new SRV only for the swizzle texture. Otherwise just return the Image's
+ // RenderTarget's SRV.
+ if (texture == mSwizzleTexture)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
+ srvDesc.Texture2D.MipLevels = mipLevels;
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(),
+ outSRV));
+ outSRV->setLabels("TexStorageEGLImage.SRV", &mKHRDebugLabel);
+ }
+ else
+ {
+ RenderTarget11 *renderTarget = nullptr;
+ ANGLE_TRY(getImageRenderTarget(context, &renderTarget));
+
+ ASSERT(texture == renderTarget->getTexture());
+
+ const d3d11::SharedSRV *srv;
+ ANGLE_TRY(renderTarget->getShaderResourceView(context, &srv));
+
+ *outSRV = srv->makeCopy();
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_EGLImage::getImageRenderTarget(const gl::Context *context,
+ RenderTarget11 **outRT) const
+{
+ RenderTargetD3D *renderTargetD3D = nullptr;
+ ANGLE_TRY(mImage->getRenderTarget(context, &renderTargetD3D));
+ *outRT = GetAs<RenderTarget11>(renderTargetD3D);
+ return angle::Result::Continue;
+}
+
+void TextureStorage11_EGLImage::onLabelUpdate()
+{
+ if (mSwizzleTexture.valid())
+ {
+ mSwizzleTexture.setKHRDebugLabel(&mKHRDebugLabel);
+ }
+}
+
+TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer,
+ GLenum internalformat,
+ BindFlags bindFlags,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly,
+ const std::string &label)
+ : TextureStorage11(
+ renderer,
+ GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), bindFlags),
+ GetTextureMiscFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ bindFlags,
+ levels),
+ internalformat,
+ label),
+ mTexture(),
+ mLevelZeroTexture(),
+ mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1),
+ mSwizzleTexture()
+{
+ for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ for (unsigned int face = 0; face < gl::kCubeFaceCount; face++)
+ {
+ mAssociatedImages[face][level] = nullptr;
+ mRenderTarget[face][level] = nullptr;
+ }
+ }
+
+ for (unsigned int face = 0; face < gl::kCubeFaceCount; face++)
+ {
+ mLevelZeroRenderTarget[face] = nullptr;
+ }
+
+ // adjust size if needed for compressed textures
+ int height = size;
+ d3d11::MakeValidSize(false, mFormatInfo.texFormat, &size, &height, &mTopLevel);
+
+ mMipLevels = mTopLevel + levels;
+ mTextureWidth = size;
+ mTextureHeight = size;
+ mTextureDepth = 1;
+
+ // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
+ ASSERT(!mUseLevelZeroTexture || mRenderer->getFeatures().zeroMaxLodWorkaround.enabled);
+}
+
+angle::Result TextureStorage11_Cube::onDestroy(const gl::Context *context)
+{
+ for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ {
+ for (unsigned int face = 0; face < gl::kCubeFaceCount; face++)
+ {
+ if (mAssociatedImages[face][level] != nullptr)
+ {
+ mAssociatedImages[face][level]->verifyAssociatedStorageValid(this);
+
+ // We must let the Images recover their data before we delete it from the
+ // TextureStorage.
+ ANGLE_TRY(mAssociatedImages[face][level]->recoverFromAssociatedStorage(context));
+ }
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+TextureStorage11_Cube::~TextureStorage11_Cube() {}
+
+angle::Result TextureStorage11_Cube::getSubresourceIndex(const gl::Context *context,
+ const gl::ImageIndex &index,
+ UINT *outSubresourceIndex) const
+{
+ UINT arraySlice = index.cubeMapFaceIndex();
+ if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled && mUseLevelZeroTexture &&
+ index.getLevelIndex() == 0)
+ {
+ UINT subresource = D3D11CalcSubresource(0, arraySlice, 1);
+ ASSERT(subresource != std::numeric_limits<UINT>::max());
+ *outSubresourceIndex = subresource;
+ }
+ else
+ {
+ UINT mipSlice = static_cast<UINT>(index.getLevelIndex() + mTopLevel);
+ UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
+ ASSERT(subresource != std::numeric_limits<UINT>::max());
+ *outSubresourceIndex = subresource;
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Cube::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
+{
+ ASSERT(destStorage);
+
+ TextureStorage11_Cube *dest11 = GetAs<TextureStorage11_Cube>(destStorage);
+
+ if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+
+ // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the
+ // corresponding textures in destStorage.
+ if (mTexture.valid())
+ {
+ ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, false));
+
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
+
+ immediateContext->CopyResource(destResource->get(), mTexture.get());
+ }
+
+ if (mLevelZeroTexture.valid())
+ {
+ ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, true));
+
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
+
+ immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get());
+ }
+ }
+ else
+ {
+ const TextureHelper11 *sourceResouce = nullptr;
+ ANGLE_TRY(getResource(context, &sourceResouce));
+
+ const TextureHelper11 *destResource = nullptr;
+ ANGLE_TRY(dest11->getResource(context, &destResource));
+
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+ immediateContext->CopyResource(destResource->get(), sourceResouce->get());
+ }
+
+ dest11->markDirty();
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Cube::useLevelZeroWorkaroundTexture(const gl::Context *context,
+ bool useLevelZeroTexture)
+{
+ if (useLevelZeroTexture && mMipLevels > 1)
+ {
+ if (!mUseLevelZeroTexture && mTexture.valid())
+ {
+ ANGLE_TRY(ensureTextureExists(context, 1));
+
+ // Pull data back from the mipped texture if necessary.
+ ASSERT(mLevelZeroTexture.valid());
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ for (int face = 0; face < 6; face++)
+ {
+ deviceContext->CopySubresourceRegion(mLevelZeroTexture.get(),
+ D3D11CalcSubresource(0, face, 1), 0, 0, 0,
+ mTexture.get(), face * mMipLevels, nullptr);
+ }
+ }
+
+ mUseLevelZeroTexture = true;
+ }
+ else
+ {
+ if (mUseLevelZeroTexture && mLevelZeroTexture.valid())
+ {
+ ANGLE_TRY(ensureTextureExists(context, mMipLevels));
+
+ // Pull data back from the level zero texture if necessary.
+ ASSERT(mTexture.valid());
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+
+ for (int face = 0; face < 6; face++)
+ {
+ deviceContext->CopySubresourceRegion(mTexture.get(),
+ D3D11CalcSubresource(0, face, mMipLevels), 0,
+ 0, 0, mLevelZeroTexture.get(), face, nullptr);
+ }
+ }
+
+ mUseLevelZeroTexture = false;
+ }
+
+ return angle::Result::Continue;
+}
+
+void TextureStorage11_Cube::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+ const GLint level = index.getLevelIndex();
+ const GLint layerTarget = index.cubeMapFaceIndex();
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
+
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ if (0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount))
+ {
+ mAssociatedImages[layerTarget][level] = image;
+ }
+ }
+}
+
+void TextureStorage11_Cube::verifyAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+ const GLint level = index.getLevelIndex();
+ const GLint layerTarget = index.cubeMapFaceIndex();
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
+ // This validation check should never return false. It means the Image/TextureStorage
+ // association is broken.
+ ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
+}
+
+// disassociateImage allows an Image to end its association with a Storage.
+void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
+{
+ const GLint level = index.getLevelIndex();
+ const GLint layerTarget = index.cubeMapFaceIndex();
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
+ ASSERT(mAssociatedImages[layerTarget][level] == expectedImage);
+ mAssociatedImages[layerTarget][level] = nullptr;
+}
+
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
+// recover its data before ending the association.
+angle::Result TextureStorage11_Cube::releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage)
+{
+ const GLint level = index.getLevelIndex();
+ const GLint layerTarget = index.cubeMapFaceIndex();
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount));
+
+ if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
+ {
+ if (0 <= layerTarget && layerTarget < static_cast<GLint>(gl::kCubeFaceCount))
+ {
+ // No need to let the old Image recover its data, if it is also the incoming Image.
+ if (mAssociatedImages[layerTarget][level] != nullptr &&
+ mAssociatedImages[layerTarget][level] != incomingImage)
+ {
+ // Ensure that the Image is still associated with this TextureStorage.
+ mAssociatedImages[layerTarget][level]->verifyAssociatedStorageValid(this);
+
+ // Force the image to recover from storage before its data is overwritten.
+ // This will reset mAssociatedImages[level] to nullptr too.
+ ANGLE_TRY(
+ mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(context));
+ }
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Cube::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ if (mUseLevelZeroTexture && mMipLevels > 1)
+ {
+ ANGLE_TRY(ensureTextureExists(context, 1));
+ *outResource = &mLevelZeroTexture;
+ }
+ else
+ {
+ ANGLE_TRY(ensureTextureExists(context, mMipLevels));
+ *outResource = &mTexture;
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Cube::getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ // This shouldn't be called unless the zero max LOD workaround is active.
+ ASSERT(mRenderer->getFeatures().zeroMaxLodWorkaround.enabled);
+
+ ANGLE_TRY(ensureTextureExists(context, mMipLevels));
+ *outResource = &mTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Cube::ensureTextureExists(const gl::Context *context, int mipLevels)
+{
+ // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
+ ANGLE_TRY(resolveTexture(context));
+ bool useLevelZeroTexture = mRenderer->getFeatures().zeroMaxLodWorkaround.enabled
+ ? (mipLevels == 1) && (mMipLevels > 1)
+ : false;
+ TextureHelper11 *outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
+
+ // if the size is not positive this should be treated as an incomplete texture
+ // we handle that here by skipping the d3d texture creation
+ if (!outputTexture->valid() && mTextureWidth > 0 && mTextureHeight > 0)
+ {
+ ASSERT(mMipLevels > 0);
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mipLevels;
+ desc.ArraySize = gl::kCubeFaceCount;
+ desc.Format = isUnorderedAccess() ? mFormatInfo.typelessFormat : mFormatInfo.texFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE | getMiscFlags();
+
+ ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
+ outputTexture));
+ outputTexture->setLabels("TexStorageCube.Texture", &mKHRDebugLabel);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Cube::findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const
+{
+ const int faceIndex = index.cubeMapFaceIndex();
+ const int level = index.getLevelIndex();
+
+ ASSERT(level >= 0 && level < getLevelCount());
+ ASSERT(faceIndex >= 0 && faceIndex < static_cast<GLint>(gl::kCubeFaceCount));
+
+ bool needMS = samples > 0;
+ if (needMS)
+ {
+ return findMultisampledRenderTarget(context, index, samples, outRT);
+ }
+
+ if (!mRenderTarget[faceIndex][level])
+ {
+ if (mUseLevelZeroTexture)
+ {
+ ASSERT(index.getLevelIndex() == 0);
+ ASSERT(outRT);
+ *outRT = mLevelZeroRenderTarget[faceIndex].get();
+ return angle::Result::Continue;
+ }
+ }
+
+ ASSERT(outRT);
+ *outRT = mRenderTarget[faceIndex][level].get();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Cube::createRenderTargetSRV(const gl::Context *context,
+ const TextureHelper11 &texture,
+ const gl::ImageIndex &index,
+ DXGI_FORMAT resourceFormat,
+ d3d11::SharedSRV *srv) const
+{
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = resourceFormat;
+ srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.getLevelIndex();
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = index.cubeMapFaceIndex();
+ srvDesc.Texture2DArray.ArraySize = 1;
+
+ if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_10_0)
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+ }
+ else
+ {
+ // Will be used with Texture2D sampler, not TextureCube
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ }
+
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), srv));
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Cube::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ const int faceIndex = index.cubeMapFaceIndex();
+ const int level = index.getLevelIndex();
+
+ ASSERT(level >= 0 && level < getLevelCount());
+ ASSERT(faceIndex >= 0 && faceIndex < static_cast<GLint>(gl::kCubeFaceCount));
+
+ bool needMS = samples > 0;
+ if (needMS)
+ {
+ return getMultisampledRenderTarget(context, index, samples, outRT);
+ }
+ else
+ {
+ ANGLE_TRY(resolveTexture(context));
+ }
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ if (!mRenderTarget[faceIndex][level])
+ {
+ if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ ASSERT(index.getLevelIndex() == 0);
+ ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true));
+ }
+
+ const TextureHelper11 *texture = nullptr;
+ ANGLE_TRY(getResource(context, &texture));
+
+ if (mUseLevelZeroTexture)
+ {
+ if (!mLevelZeroRenderTarget[faceIndex])
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = mTopLevel + level;
+ rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
+ rtvDesc.Texture2DArray.ArraySize = 1;
+
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(
+ mRenderer->allocateResource(context11, rtvDesc, mLevelZeroTexture.get(), &rtv));
+
+ mLevelZeroRenderTarget[faceIndex].reset(new TextureRenderTarget11(
+ std::move(rtv), mLevelZeroTexture, d3d11::SharedSRV(), d3d11::SharedSRV(),
+ mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level),
+ getLevelHeight(level), 1, 0));
+ }
+
+ ASSERT(outRT);
+ *outRT = mLevelZeroRenderTarget[faceIndex].get();
+ return angle::Result::Continue;
+ }
+
+ d3d11::SharedSRV srv;
+ ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.srvFormat, &srv));
+ d3d11::SharedSRV blitSRV;
+ if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
+ {
+ ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.blitSRVFormat,
+ &blitSRV));
+ }
+ else
+ {
+ blitSRV = srv.makeCopy();
+ }
+
+ srv.setLabels("TexStorageCube.RenderTargetSRV", &mKHRDebugLabel);
+
+ if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = mTopLevel + level;
+ rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
+ rtvDesc.Texture2DArray.ArraySize = 1;
+
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
+ rtv.setLabels("TexStorageCube.RenderTargetRTV", &mKHRDebugLabel);
+
+ mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11(
+ std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(level), getLevelHeight(level), 1, 0));
+ }
+ else if (mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Format = mFormatInfo.dsvFormat;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
+ dsvDesc.Flags = 0;
+ dsvDesc.Texture2DArray.MipSlice = mTopLevel + level;
+ dsvDesc.Texture2DArray.FirstArraySlice = faceIndex;
+ dsvDesc.Texture2DArray.ArraySize = 1;
+
+ d3d11::DepthStencilView dsv;
+ ANGLE_TRY(mRenderer->allocateResource(context11, dsvDesc, texture->get(), &dsv));
+ dsv.setLabels("TexStorageCube.RenderTargetDSV", &mKHRDebugLabel);
+
+ mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11(
+ std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(level), getLevelHeight(level), 1, 0));
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+
+ ASSERT(outRT);
+ *outRT = mRenderTarget[faceIndex][level].get();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Cube::createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ ASSERT(outSRV);
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+
+ // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six
+ // 2D textures
+ const GLenum componentType = d3d11::GetComponentType(format);
+ if (componentType == GL_INT || componentType == GL_UNSIGNED_INT)
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
+ srvDesc.Texture2DArray.MipLevels = mipLevels;
+ srvDesc.Texture2DArray.FirstArraySlice = 0;
+ srvDesc.Texture2DArray.ArraySize = gl::kCubeFaceCount;
+ }
+ else
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+ srvDesc.TextureCube.MipLevels = mipLevels;
+ srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel;
+ }
+
+ const TextureHelper11 *srvTexture = &texture;
+
+ if (mRenderer->getFeatures().zeroMaxLodWorkaround.enabled)
+ {
+ ASSERT(mTopLevel == 0);
+ ASSERT(baseLevel == 0);
+ // This code also assumes that the incoming texture equals either mLevelZeroTexture or
+ // mTexture.
+
+ if (mipLevels == 1 && mMipLevels > 1)
+ {
+ // We must use a SRV on the level-zero-only texture.
+ ANGLE_TRY(ensureTextureExists(context, 1));
+ srvTexture = &mLevelZeroTexture;
+ }
+ else
+ {
+ ASSERT(mipLevels == static_cast<int>(mMipLevels));
+ ASSERT(mTexture.valid() && texture == mTexture);
+ srvTexture = &mTexture;
+ }
+ }
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, srvTexture->get(),
+ outSRV));
+ outSRV->setLabels("TexStorageCube.SRV", &mKHRDebugLabel);
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Cube::createSRVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ ASSERT(outSRV);
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level;
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = 0;
+ srvDesc.Texture2DArray.ArraySize = gl::kCubeFaceCount;
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
+ outSRV->setLabels("TexStorageCube.SRVForImage", &mKHRDebugLabel);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Cube::createUAVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedUAV *outUAV)
+{
+ ASSERT(outUAV);
+ D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
+ uavDesc.Format = format;
+ uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
+ uavDesc.Texture2DArray.MipSlice = mTopLevel + level;
+ uavDesc.Texture2DArray.FirstArraySlice = 0;
+ uavDesc.Texture2DArray.ArraySize = gl::kCubeFaceCount;
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
+ outUAV->setLabels("TexStorageCube.UAVForImage", &mKHRDebugLabel);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Cube::getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture)
+{
+ ASSERT(outTexture);
+
+ if (!mSwizzleTexture.valid())
+ {
+ const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = gl::kCubeFaceCount;
+ desc.Format = format.texFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
+
+ ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
+ &mSwizzleTexture));
+ mSwizzleTexture.setLabels("TexStorageCube.SwizzleTexture", &mKHRDebugLabel);
+ }
+
+ *outTexture = &mSwizzleTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Cube::getSwizzleRenderTarget(const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV)
+{
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+ ASSERT(outRTV);
+
+ if (!mSwizzleRenderTargets[mipLevel].valid())
+ {
+ const TextureHelper11 *swizzleTexture = nullptr;
+ ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format =
+ mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Texture2DArray.FirstArraySlice = 0;
+ rtvDesc.Texture2DArray.ArraySize = gl::kCubeFaceCount;
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
+ mSwizzleTexture.get(),
+ &mSwizzleRenderTargets[mipLevel]));
+ }
+
+ *outRTV = &mSwizzleRenderTargets[mipLevel];
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Cube::ensureDropStencilTexture(const gl::Context *context,
+ DropStencil *dropStencilOut)
+{
+ if (mDropStencilTexture.valid())
+ {
+ *dropStencilOut = DropStencil::ALREADY_EXISTS;
+ return angle::Result::Continue;
+ }
+
+ D3D11_TEXTURE2D_DESC dropDesc = {};
+ dropDesc.ArraySize = 6;
+ dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
+ dropDesc.CPUAccessFlags = 0;
+ dropDesc.Format = DXGI_FORMAT_R32_TYPELESS;
+ dropDesc.Height = mTextureHeight;
+ dropDesc.MipLevels = mMipLevels;
+ dropDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
+ dropDesc.SampleDesc.Count = 1;
+ dropDesc.SampleDesc.Quality = 0;
+ dropDesc.Usage = D3D11_USAGE_DEFAULT;
+ dropDesc.Width = mTextureWidth;
+
+ const auto &format =
+ d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
+ ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), dropDesc, format,
+ &mDropStencilTexture));
+ mDropStencilTexture.setLabels("TexStorageCube.DropStencil", &mKHRDebugLabel);
+
+ ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::MakeCube(0, mMipLevels)));
+
+ *dropStencilOut = DropStencil::CREATED;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Cube::resolveTexture(const gl::Context *context)
+{
+ if (mMSTexInfo && mMSTexInfo->msTex && mMSTexInfo->msTextureNeedsResolve)
+ {
+ ANGLE_TRY(resolveTextureHelper(context, mTexture));
+ onStateChange(angle::SubjectMessage::ContentsChanged);
+ }
+ return angle::Result::Continue;
+}
+
+void TextureStorage11_Cube::onLabelUpdate()
+{
+ if (mTexture.valid())
+ {
+ mTexture.setKHRDebugLabel(&mKHRDebugLabel);
+ }
+ if (mLevelZeroTexture.valid())
+ {
+ mLevelZeroTexture.setKHRDebugLabel(&mKHRDebugLabel);
+ }
+ if (mSwizzleTexture.valid())
+ {
+ mSwizzleTexture.setKHRDebugLabel(&mKHRDebugLabel);
+ }
+}
+
+TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer,
+ GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ const std::string &label)
+ : TextureStorage11(
+ renderer,
+ GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), bindFlags),
+ GetTextureMiscFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ bindFlags,
+ levels),
+ internalformat,
+ label)
+{
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ mAssociatedImages[i] = nullptr;
+ mLevelRenderTargets[i] = nullptr;
+ }
+
+ // adjust size if needed for compressed textures
+ d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
+
+ mMipLevels = mTopLevel + levels;
+ mTextureWidth = width;
+ mTextureHeight = height;
+ mTextureDepth = depth;
+}
+
+angle::Result TextureStorage11_3D::onDestroy(const gl::Context *context)
+{
+ for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
+ {
+ if (mAssociatedImages[i] != nullptr)
+ {
+ mAssociatedImages[i]->verifyAssociatedStorageValid(this);
+
+ // We must let the Images recover their data before we delete it from the
+ // TextureStorage.
+ ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context));
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+TextureStorage11_3D::~TextureStorage11_3D() {}
+
+void TextureStorage11_3D::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+ const GLint level = index.getLevelIndex();
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ mAssociatedImages[level] = image;
+ }
+}
+
+void TextureStorage11_3D::verifyAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+ const GLint level = index.getLevelIndex();
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ // This validation check should never return false. It means the Image/TextureStorage
+ // association is broken.
+ ASSERT(mAssociatedImages[level] == expectedImage);
+}
+
+// disassociateImage allows an Image to end its association with a Storage.
+void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
+{
+ const GLint level = index.getLevelIndex();
+
+ ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ ASSERT(mAssociatedImages[level] == expectedImage);
+ mAssociatedImages[level] = nullptr;
+}
+
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
+// recover its data before ending the association.
+angle::Result TextureStorage11_3D::releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage)
+{
+ const GLint level = index.getLevelIndex();
+
+ ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS));
+
+ if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ // No need to let the old Image recover its data, if it is also the incoming Image.
+ if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage)
+ {
+ // Ensure that the Image is still associated with this TextureStorage.
+ mAssociatedImages[level]->verifyAssociatedStorageValid(this);
+
+ // Force the image to recover from storage before its data is overwritten.
+ // This will reset mAssociatedImages[level] to nullptr too.
+ ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage(context));
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_3D::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ // If the width, height or depth are not positive this should be treated as an incomplete
+ // texture. We handle that here by skipping the d3d texture creation.
+ if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
+ {
+ ASSERT(mMipLevels > 0);
+
+ D3D11_TEXTURE3D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.Depth = mTextureDepth;
+ desc.MipLevels = mMipLevels;
+ desc.Format = isUnorderedAccess() ? mFormatInfo.typelessFormat : mFormatInfo.texFormat;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = getMiscFlags();
+
+ ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
+ &mTexture));
+ mTexture.setLabels("TexStorage3D.Texture", &mKHRDebugLabel);
+ }
+
+ *outResource = &mTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_3D::createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ ASSERT(outSRV);
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
+ srvDesc.Texture3D.MostDetailedMip = baseLevel;
+ srvDesc.Texture3D.MipLevels = mipLevels;
+
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
+ outSRV->setLabels("TexStorage3D.SRV", &mKHRDebugLabel);
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_3D::createSRVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ ASSERT(outSRV);
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D;
+ srvDesc.Texture3D.MostDetailedMip = mTopLevel + level;
+ srvDesc.Texture3D.MipLevels = 1;
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
+ outSRV->setLabels("TexStorage3D.SRVForImage", &mKHRDebugLabel);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_3D::createUAVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedUAV *outUAV)
+{
+ ASSERT(outUAV);
+ D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
+ uavDesc.Format = format;
+ uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
+ uavDesc.Texture3D.MipSlice = mTopLevel + level;
+ uavDesc.Texture3D.FirstWSlice = 0;
+ uavDesc.Texture3D.WSize = mTextureDepth;
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
+ outUAV->setLabels("TexStorage3D.UAVForImage", &mKHRDebugLabel);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_3D::findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const
+{
+ const int mipLevel = index.getLevelIndex();
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+
+ if (!index.hasLayer())
+ {
+ ASSERT(outRT);
+ *outRT = mLevelRenderTargets[mipLevel].get();
+ return angle::Result::Continue;
+ }
+
+ const int layer = index.getLayerIndex();
+
+ LevelLayerKey key(mipLevel, layer);
+ if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
+ {
+ ASSERT(outRT);
+ *outRT = nullptr;
+ return angle::Result::Continue;
+ }
+
+ ASSERT(outRT);
+ *outRT = mLevelLayerRenderTargets.at(key).get();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_3D::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ const int mipLevel = index.getLevelIndex();
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+
+ ASSERT(mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ if (!index.hasLayer())
+ {
+ if (!mLevelRenderTargets[mipLevel])
+ {
+ const TextureHelper11 *texture = nullptr;
+ ANGLE_TRY(getResource(context, &texture));
+
+ const d3d11::SharedSRV *srv = nullptr;
+ ANGLE_TRY(getSRVLevel(context, mipLevel, SRVType::Sample, &srv));
+
+ const d3d11::SharedSRV *blitSRV = nullptr;
+ ANGLE_TRY(getSRVLevel(context, mipLevel, SRVType::Blit, &blitSRV));
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+ rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Texture3D.FirstWSlice = 0;
+ rtvDesc.Texture3D.WSize = static_cast<UINT>(-1);
+
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
+ rtv.setLabels("TexStorage3D.RTV", &mKHRDebugLabel);
+
+ mLevelRenderTargets[mipLevel].reset(new TextureRenderTarget11(
+ std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat,
+ getFormatSet(), getLevelWidth(mipLevel), getLevelHeight(mipLevel),
+ getLevelDepth(mipLevel), 0));
+ }
+
+ ASSERT(outRT);
+ *outRT = mLevelRenderTargets[mipLevel].get();
+ return angle::Result::Continue;
+ }
+
+ const int layer = index.getLayerIndex();
+
+ LevelLayerKey key(mipLevel, layer);
+ if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end())
+ {
+ const TextureHelper11 *texture = nullptr;
+ ANGLE_TRY(getResource(context, &texture));
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+ rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Texture3D.FirstWSlice = layer;
+ rtvDesc.Texture3D.WSize = 1;
+
+ const d3d11::SharedSRV *srv = nullptr;
+ ANGLE_TRY(getSRVLevel(context, mipLevel, SRVType::Sample, &srv));
+
+ const d3d11::SharedSRV *blitSRV = nullptr;
+ ANGLE_TRY(getSRVLevel(context, mipLevel, SRVType::Blit, &blitSRV));
+
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
+ rtv.setLabels("TexStorage3D.LayerRTV", &mKHRDebugLabel);
+
+ mLevelLayerRenderTargets[key].reset(new TextureRenderTarget11(
+ std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
+ }
+
+ ASSERT(outRT);
+ *outRT = mLevelLayerRenderTargets[key].get();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_3D::getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture)
+{
+ ASSERT(outTexture);
+
+ if (!mSwizzleTexture.valid())
+ {
+ const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
+
+ D3D11_TEXTURE3D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.Depth = mTextureDepth;
+ desc.MipLevels = mMipLevels;
+ desc.Format = format.texFormat;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
+ &mSwizzleTexture));
+ mSwizzleTexture.setLabels("TexStorage3D.SwizzleTexture", &mKHRDebugLabel);
+ }
+
+ *outTexture = &mSwizzleTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_3D::getSwizzleRenderTarget(const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV)
+{
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+ ASSERT(outRTV);
+
+ if (!mSwizzleRenderTargets[mipLevel].valid())
+ {
+ const TextureHelper11 *swizzleTexture = nullptr;
+ ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format =
+ mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
+ rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Texture3D.FirstWSlice = 0;
+ rtvDesc.Texture3D.WSize = static_cast<UINT>(-1);
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
+ mSwizzleTexture.get(),
+ &mSwizzleRenderTargets[mipLevel]));
+ mSwizzleRenderTargets[mipLevel].setLabels("TexStorage3D.SwizzleRTV", &mKHRDebugLabel);
+ }
+
+ *outRTV = &mSwizzleRenderTargets[mipLevel];
+ return angle::Result::Continue;
+}
+
+void TextureStorage11_3D::onLabelUpdate()
+{
+ if (mTexture.valid())
+ {
+ mTexture.setKHRDebugLabel(&mKHRDebugLabel);
+ }
+ if (mSwizzleTexture.valid())
+ {
+ mSwizzleTexture.setKHRDebugLabel(&mKHRDebugLabel);
+ }
+}
+
+TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer,
+ GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ const std::string &label)
+ : TextureStorage11(
+ renderer,
+ GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), bindFlags),
+ GetTextureMiscFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ bindFlags,
+ levels),
+ internalformat,
+ label)
+{
+ // adjust size if needed for compressed textures
+ d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel);
+
+ mMipLevels = mTopLevel + levels;
+ mTextureWidth = width;
+ mTextureHeight = height;
+ mTextureDepth = depth;
+}
+
+angle::Result TextureStorage11_2DArray::onDestroy(const gl::Context *context)
+{
+ for (auto iter : mAssociatedImages)
+ {
+ if (iter.second)
+ {
+ iter.second->verifyAssociatedStorageValid(this);
+
+ // We must let the Images recover their data before we delete it from the
+ // TextureStorage.
+ ANGLE_TRY(iter.second->recoverFromAssociatedStorage(context));
+ }
+ }
+ mAssociatedImages.clear();
+
+ return angle::Result::Continue;
+}
+
+TextureStorage11_2DArray::~TextureStorage11_2DArray() {}
+
+void TextureStorage11_2DArray::associateImage(Image11 *image, const gl::ImageIndex &index)
+{
+ const GLint level = index.getLevelIndex();
+ const GLint layerTarget = index.getLayerIndex();
+ const GLint numLayers = index.getLayerCount();
+
+ ASSERT(0 <= level && level < getLevelCount());
+
+ if (0 <= level && level < getLevelCount())
+ {
+ LevelLayerRangeKey key(level, layerTarget, numLayers);
+ mAssociatedImages[key] = image;
+ }
+}
+
+void TextureStorage11_2DArray::verifyAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+ const GLint level = index.getLevelIndex();
+ const GLint layerTarget = index.getLayerIndex();
+ const GLint numLayers = index.getLayerCount();
+
+ LevelLayerRangeKey key(level, layerTarget, numLayers);
+
+ // This validation check should never return false. It means the Image/TextureStorage
+ // association is broken.
+ bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() &&
+ (mAssociatedImages[key] == expectedImage));
+ ASSERT(retValue);
+}
+
+// disassociateImage allows an Image to end its association with a Storage.
+void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{
+ const GLint level = index.getLevelIndex();
+ const GLint layerTarget = index.getLayerIndex();
+ const GLint numLayers = index.getLayerCount();
+
+ LevelLayerRangeKey key(level, layerTarget, numLayers);
+
+ bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() &&
+ (mAssociatedImages[key] == expectedImage));
+ ASSERT(imageAssociationCorrect);
+ mAssociatedImages[key] = nullptr;
+}
+
+// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image
+// recover its data before ending the association.
+angle::Result TextureStorage11_2DArray::releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage)
+{
+ const GLint level = index.getLevelIndex();
+ const GLint layerTarget = index.getLayerIndex();
+ const GLint numLayers = index.getLayerCount();
+
+ LevelLayerRangeKey key(level, layerTarget, numLayers);
+
+ if (mAssociatedImages.find(key) != mAssociatedImages.end())
+ {
+ if (mAssociatedImages[key] != nullptr && mAssociatedImages[key] != incomingImage)
+ {
+ // Ensure that the Image is still associated with this TextureStorage.
+ mAssociatedImages[key]->verifyAssociatedStorageValid(this);
+
+ // Force the image to recover from storage before its data is overwritten.
+ // This will reset mAssociatedImages[level] to nullptr too.
+ ANGLE_TRY(mAssociatedImages[key]->recoverFromAssociatedStorage(context));
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DArray::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ // if the width, height or depth is not positive this should be treated as an incomplete texture
+ // we handle that here by skipping the d3d texture creation
+ if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0)
+ {
+ ASSERT(mMipLevels > 0);
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = mTextureDepth;
+ desc.Format = isUnorderedAccess() ? mFormatInfo.typelessFormat : mFormatInfo.texFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags();
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = getMiscFlags();
+
+ ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
+ &mTexture));
+ mTexture.setLabels("TexStorage2DArray.Texture", &mKHRDebugLabel);
+ }
+
+ *outResource = &mTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DArray::createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel;
+ srvDesc.Texture2DArray.MipLevels = mipLevels;
+ srvDesc.Texture2DArray.FirstArraySlice = 0;
+ srvDesc.Texture2DArray.ArraySize = mTextureDepth;
+
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
+ outSRV->setLabels("TexStorage2DArray.SRV", &mKHRDebugLabel);
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DArray::createSRVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ ASSERT(outSRV);
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level;
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = 0;
+ srvDesc.Texture2DArray.ArraySize = mTextureDepth;
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
+ outSRV->setLabels("TexStorage2DArray.SRVForImage", &mKHRDebugLabel);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DArray::createUAVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedUAV *outUAV)
+{
+ ASSERT(outUAV);
+ D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
+ uavDesc.Format = format;
+ uavDesc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY;
+ uavDesc.Texture2DArray.MipSlice = mTopLevel + level;
+ uavDesc.Texture2DArray.FirstArraySlice = 0;
+ uavDesc.Texture2DArray.ArraySize = mTextureDepth;
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
+ outUAV->setLabels("TexStorage2DArray.UAVForImage", &mKHRDebugLabel);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DArray::findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const
+{
+ ASSERT(index.hasLayer());
+
+ const int mipLevel = index.getLevelIndex();
+ const int layer = index.getLayerIndex();
+ const int numLayers = index.getLayerCount();
+
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+
+ LevelLayerRangeKey key(mipLevel, layer, numLayers);
+ if (mRenderTargets.find(key) == mRenderTargets.end())
+ {
+ ASSERT(outRT);
+ *outRT = nullptr;
+ return angle::Result::Continue;
+ }
+
+ ASSERT(outRT);
+ *outRT = mRenderTargets.at(key).get();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DArray::createRenderTargetSRV(const gl::Context *context,
+ const TextureHelper11 &texture,
+ const gl::ImageIndex &index,
+ DXGI_FORMAT resourceFormat,
+ d3d11::SharedSRV *srv) const
+{
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = resourceFormat;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
+ srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.getLevelIndex();
+ srvDesc.Texture2DArray.MipLevels = 1;
+ srvDesc.Texture2DArray.FirstArraySlice = index.getLayerIndex();
+ srvDesc.Texture2DArray.ArraySize = index.getLayerCount();
+
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), srv));
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DArray::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(index.hasLayer());
+
+ const int mipLevel = index.getLevelIndex();
+ const int layer = index.getLayerIndex();
+ const int numLayers = index.getLayerCount();
+
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+
+ LevelLayerRangeKey key(mipLevel, layer, numLayers);
+ if (mRenderTargets.find(key) == mRenderTargets.end())
+ {
+ const TextureHelper11 *texture = nullptr;
+ ANGLE_TRY(getResource(context, &texture));
+ d3d11::SharedSRV srv;
+ ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.srvFormat, &srv));
+ d3d11::SharedSRV blitSRV;
+ if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
+ {
+ ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.blitSRVFormat,
+ &blitSRV));
+ }
+ else
+ {
+ blitSRV = srv.makeCopy();
+ }
+
+ srv.setLabels("TexStorage2DArray.RenderTargetSRV", &mKHRDebugLabel);
+
+ if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Texture2DArray.FirstArraySlice = layer;
+ rtvDesc.Texture2DArray.ArraySize = numLayers;
+
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
+ texture->get(), &rtv));
+ rtv.setLabels("TexStorage2DArray.RenderTargetRTV", &mKHRDebugLabel);
+
+ mRenderTargets[key].reset(new TextureRenderTarget11(
+ std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
+ }
+ else
+ {
+ ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Format = mFormatInfo.dsvFormat;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY;
+ dsvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
+ dsvDesc.Texture2DArray.FirstArraySlice = layer;
+ dsvDesc.Texture2DArray.ArraySize = numLayers;
+ dsvDesc.Flags = 0;
+
+ d3d11::DepthStencilView dsv;
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), dsvDesc,
+ texture->get(), &dsv));
+ dsv.setLabels("TexStorage2DArray.RenderTargetDSV", &mKHRDebugLabel);
+
+ mRenderTargets[key].reset(new TextureRenderTarget11(
+ std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0));
+ }
+ }
+
+ ASSERT(outRT);
+ *outRT = mRenderTargets[key].get();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DArray::getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture)
+{
+ if (!mSwizzleTexture.valid())
+ {
+ const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps());
+
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mMipLevels;
+ desc.ArraySize = mTextureDepth;
+ desc.Format = format.texFormat;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = 0;
+
+ ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, format,
+ &mSwizzleTexture));
+ mSwizzleTexture.setLabels("TexStorage2DArray.SwizzleTexture", &mKHRDebugLabel);
+ }
+
+ *outTexture = &mSwizzleTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DArray::getSwizzleRenderTarget(
+ const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV)
+{
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+ ASSERT(outRTV);
+
+ if (!mSwizzleRenderTargets[mipLevel].valid())
+ {
+ const TextureHelper11 *swizzleTexture = nullptr;
+ ANGLE_TRY(getSwizzleTexture(context, &swizzleTexture));
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format =
+ mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel;
+ rtvDesc.Texture2DArray.FirstArraySlice = 0;
+ rtvDesc.Texture2DArray.ArraySize = mTextureDepth;
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
+ mSwizzleTexture.get(),
+ &mSwizzleRenderTargets[mipLevel]));
+ }
+
+ *outRTV = &mSwizzleRenderTargets[mipLevel];
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DArray::ensureDropStencilTexture(const gl::Context *context,
+ DropStencil *dropStencilOut)
+{
+ if (mDropStencilTexture.valid())
+ {
+ *dropStencilOut = DropStencil::ALREADY_EXISTS;
+ return angle::Result::Continue;
+ }
+
+ D3D11_TEXTURE2D_DESC dropDesc = {};
+ dropDesc.ArraySize = mTextureDepth;
+ dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
+ dropDesc.CPUAccessFlags = 0;
+ dropDesc.Format = DXGI_FORMAT_R32_TYPELESS;
+ dropDesc.Height = mTextureHeight;
+ dropDesc.MipLevels = mMipLevels;
+ dropDesc.MiscFlags = 0;
+ dropDesc.SampleDesc.Count = 1;
+ dropDesc.SampleDesc.Quality = 0;
+ dropDesc.Usage = D3D11_USAGE_DEFAULT;
+ dropDesc.Width = mTextureWidth;
+
+ const auto &format =
+ d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps());
+ ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), dropDesc, format,
+ &mDropStencilTexture));
+ mDropStencilTexture.setLabels("TexStorage2DArray.DropStencil", &mKHRDebugLabel);
+
+ std::vector<GLsizei> layerCounts(mMipLevels, mTextureDepth);
+
+ ANGLE_TRY(initDropStencilTexture(
+ context, gl::ImageIndexIterator::Make2DArray(0, mMipLevels, layerCounts.data())));
+
+ *dropStencilOut = DropStencil::CREATED;
+ return angle::Result::Continue;
+}
+
+void TextureStorage11_2DArray::onLabelUpdate()
+{
+ if (mTexture.valid())
+ {
+ mTexture.setKHRDebugLabel(&mKHRDebugLabel);
+ }
+ if (mSwizzleTexture.valid())
+ {
+ mSwizzleTexture.setKHRDebugLabel(&mKHRDebugLabel);
+ }
+}
+
+TextureStorage11_2DMultisample::TextureStorage11_2DMultisample(Renderer11 *renderer,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ int samples,
+ bool fixedSampleLocations,
+ const std::string &label)
+ : TextureStorage11ImmutableBase(renderer,
+ GetTextureBindFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ BindFlags::RenderTarget()),
+ GetTextureMiscFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ BindFlags::RenderTarget(),
+ levels),
+ internalformat,
+ label),
+ mTexture(),
+ mRenderTarget(nullptr)
+{
+ // There are no multisampled compressed formats, so there's no need to adjust texture size
+ // according to block size.
+ ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockWidth <= 1);
+ ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockHeight <= 1);
+
+ mMipLevels = 1;
+ mTextureWidth = width;
+ mTextureHeight = height;
+ mTextureDepth = 1;
+ mSamples = samples;
+ mFixedSampleLocations = fixedSampleLocations;
+}
+
+angle::Result TextureStorage11_2DMultisample::onDestroy(const gl::Context *context)
+{
+ mRenderTarget.reset();
+ return angle::Result::Continue;
+}
+
+TextureStorage11_2DMultisample::~TextureStorage11_2DMultisample() {}
+
+angle::Result TextureStorage11_2DMultisample::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_2DMultisample::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ ANGLE_TRY(ensureTextureExists(context, 1));
+
+ *outResource = &mTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DMultisample::ensureTextureExists(const gl::Context *context,
+ int mipLevels)
+{
+ // For Multisampled textures, mipLevels always equals 1.
+ ASSERT(mipLevels == 1);
+
+ // if the width or height is not positive this should be treated as an incomplete texture
+ // we handle that here by skipping the d3d texture creation
+ if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0)
+ {
+ D3D11_TEXTURE2D_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Width = mTextureWidth; // Compressed texture size constraints?
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mipLevels;
+ desc.ArraySize = 1;
+ desc.Format = mFormatInfo.texFormat;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags() & ~D3D11_BIND_UNORDERED_ACCESS;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = getMiscFlags();
+
+ const gl::TextureCaps &textureCaps =
+ mRenderer->getNativeTextureCaps().get(mFormatInfo.internalFormat);
+ GLuint supportedSamples = textureCaps.getNearestSamples(mSamples);
+ desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
+ desc.SampleDesc.Quality = mRenderer->getSampleDescQuality(supportedSamples);
+
+ ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
+ &mTexture));
+ mTexture.setLabels("TexStorage2DMS.Texture", &mKHRDebugLabel);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DMultisample::findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const
+{
+ ASSERT(!index.hasLayer());
+
+ const int level = index.getLevelIndex();
+ ASSERT(level == 0);
+
+ ASSERT(outRT);
+ *outRT = mRenderTarget.get();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DMultisample::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(!index.hasLayer());
+
+ const int level = index.getLevelIndex();
+ ASSERT(level == 0);
+
+ ASSERT(outRT);
+ if (mRenderTarget)
+ {
+ *outRT = mRenderTarget.get();
+ return angle::Result::Continue;
+ }
+
+ const TextureHelper11 *texture = nullptr;
+ ANGLE_TRY(getResource(context, &texture));
+
+ const d3d11::SharedSRV *srv = nullptr;
+ ANGLE_TRY(getSRVLevel(context, level, SRVType::Sample, &srv));
+
+ const d3d11::SharedSRV *blitSRV = nullptr;
+ ANGLE_TRY(getSRVLevel(context, level, SRVType::Blit, &blitSRV));
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+
+ if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
+
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, texture->get(), &rtv));
+
+ mRenderTarget.reset(new TextureRenderTarget11(
+ std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(level), getLevelHeight(level), 1, mSamples));
+
+ *outRT = mRenderTarget.get();
+ return angle::Result::Continue;
+ }
+
+ ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Format = mFormatInfo.dsvFormat;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
+ dsvDesc.Flags = 0;
+
+ d3d11::DepthStencilView dsv;
+ ANGLE_TRY(mRenderer->allocateResource(context11, dsvDesc, texture->get(), &dsv));
+
+ mRenderTarget.reset(new TextureRenderTarget11(
+ std::move(dsv), *texture, *srv, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(level), getLevelHeight(level), 1, mSamples));
+
+ *outRT = mRenderTarget.get();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DMultisample::createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ ASSERT(outSRV);
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
+
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
+ outSRV->setLabels("TexStorage2DMS.SRV", &mKHRDebugLabel);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DMultisample::getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_2DMultisample::getSwizzleRenderTarget(
+ const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_2DMultisample::ensureDropStencilTexture(const gl::Context *context,
+ DropStencil *dropStencilOut)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+void TextureStorage11_2DMultisample::onLabelUpdate()
+{
+ if (mTexture.valid())
+ {
+ mTexture.setKHRDebugLabel(&mKHRDebugLabel);
+ }
+}
+
+TextureStorage11_2DMultisampleArray::TextureStorage11_2DMultisampleArray(Renderer11 *renderer,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ int samples,
+ bool fixedSampleLocations,
+ const std::string &label)
+ : TextureStorage11ImmutableBase(renderer,
+ GetTextureBindFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ BindFlags::RenderTarget()),
+ GetTextureMiscFlags(internalformat,
+ renderer->getRenderer11DeviceCaps(),
+ BindFlags::RenderTarget(),
+ levels),
+ internalformat,
+ label),
+ mTexture()
+{
+ // There are no multisampled compressed formats, so there's no need to adjust texture size
+ // according to block size.
+ ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockWidth <= 1);
+ ASSERT(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat).blockHeight <= 1);
+
+ mMipLevels = 1;
+ mTextureWidth = width;
+ mTextureHeight = height;
+ mTextureDepth = depth;
+ mSamples = samples;
+ mFixedSampleLocations = fixedSampleLocations;
+}
+
+angle::Result TextureStorage11_2DMultisampleArray::onDestroy(const gl::Context *context)
+{
+ return angle::Result::Continue;
+}
+
+TextureStorage11_2DMultisampleArray::~TextureStorage11_2DMultisampleArray() {}
+
+angle::Result TextureStorage11_2DMultisampleArray::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_2DMultisampleArray::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ ANGLE_TRY(ensureTextureExists(context, 1));
+
+ *outResource = &mTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DMultisampleArray::ensureTextureExists(const gl::Context *context,
+ int mipLevels)
+{
+ // For multisampled textures, mipLevels always equals 1.
+ ASSERT(mipLevels == 1);
+
+ // if the width or height is not positive this should be treated as an incomplete texture
+ // we handle that here by skipping the d3d texture creation
+ if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0)
+ {
+ D3D11_TEXTURE2D_DESC desc;
+ ZeroMemory(&desc, sizeof(desc));
+ desc.Width = mTextureWidth;
+ desc.Height = mTextureHeight;
+ desc.MipLevels = mipLevels;
+ desc.ArraySize = mTextureDepth;
+ desc.Format = mFormatInfo.texFormat;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = getBindFlags() & ~D3D11_BIND_UNORDERED_ACCESS;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = getMiscFlags();
+
+ const gl::TextureCaps &textureCaps =
+ mRenderer->getNativeTextureCaps().get(mFormatInfo.internalFormat);
+ GLuint supportedSamples = textureCaps.getNearestSamples(mSamples);
+ desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples;
+ desc.SampleDesc.Quality = mRenderer->getSampleDescQuality(supportedSamples);
+
+ ANGLE_TRY(mRenderer->allocateTexture(GetImplAs<Context11>(context), desc, mFormatInfo,
+ &mTexture));
+ mTexture.setLabels("TexStorage2DMSArray.Texture", &mKHRDebugLabel);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DMultisampleArray::findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const
+{
+ ASSERT(index.hasLayer());
+
+ const int mipLevel = index.getLevelIndex();
+ ASSERT(mipLevel == 0);
+ const int layer = index.getLayerIndex();
+ const int numLayers = index.getLayerCount();
+
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+
+ TextureStorage11_2DArray::LevelLayerRangeKey key(mipLevel, layer, numLayers);
+ if (mRenderTargets.find(key) == mRenderTargets.end())
+ {
+ ASSERT(outRT);
+ *outRT = nullptr;
+ return angle::Result::Continue;
+ }
+
+ ASSERT(outRT);
+ *outRT = mRenderTargets.at(key).get();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DMultisampleArray::createRenderTargetSRV(
+ const gl::Context *context,
+ const TextureHelper11 &texture,
+ const gl::ImageIndex &index,
+ DXGI_FORMAT resourceFormat,
+ d3d11::SharedSRV *srv) const
+{
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = resourceFormat;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
+ srvDesc.Texture2DMSArray.FirstArraySlice = index.getLayerIndex();
+ srvDesc.Texture2DMSArray.ArraySize = index.getLayerCount();
+
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), srv));
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DMultisampleArray::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(index.hasLayer());
+
+ const int mipLevel = index.getLevelIndex();
+ ASSERT(mipLevel == 0);
+ const int layer = index.getLayerIndex();
+ const int numLayers = index.getLayerCount();
+
+ ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
+
+ TextureStorage11_2DArray::LevelLayerRangeKey key(mipLevel, layer, numLayers);
+ if (mRenderTargets.find(key) == mRenderTargets.end())
+ {
+ const TextureHelper11 *texture = nullptr;
+ ANGLE_TRY(getResource(context, &texture));
+ d3d11::SharedSRV srv;
+ ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.srvFormat, &srv));
+ d3d11::SharedSRV blitSRV;
+ if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat)
+ {
+ ANGLE_TRY(createRenderTargetSRV(context, *texture, index, mFormatInfo.blitSRVFormat,
+ &blitSRV));
+ }
+ else
+ {
+ blitSRV = srv.makeCopy();
+ }
+
+ srv.setLabels("TexStorage2DMSArray.RenderTargetSRV", &mKHRDebugLabel);
+
+ if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mFormatInfo.rtvFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
+ rtvDesc.Texture2DMSArray.FirstArraySlice = layer;
+ rtvDesc.Texture2DMSArray.ArraySize = numLayers;
+
+ d3d11::RenderTargetView rtv;
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), rtvDesc,
+ texture->get(), &rtv));
+ rtv.setLabels("TexStorage2DMSArray.RenderTargetRTV", &mKHRDebugLabel);
+
+ mRenderTargets[key].reset(new TextureRenderTarget11(
+ std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, mSamples));
+ }
+ else
+ {
+ ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN);
+
+ D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
+ dsvDesc.Format = mFormatInfo.dsvFormat;
+ dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY;
+ dsvDesc.Texture2DMSArray.FirstArraySlice = layer;
+ dsvDesc.Texture2DMSArray.ArraySize = numLayers;
+ dsvDesc.Flags = 0;
+
+ d3d11::DepthStencilView dsv;
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), dsvDesc,
+ texture->get(), &dsv));
+ dsv.setLabels("TexStorage2DMSArray.RenderTargetDSV", &mKHRDebugLabel);
+
+ mRenderTargets[key].reset(new TextureRenderTarget11(
+ std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(),
+ getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, mSamples));
+ }
+ }
+
+ ASSERT(outRT);
+ *outRT = mRenderTargets[key].get();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DMultisampleArray::createSRVForSampler(
+ const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ ASSERT(outSRV);
+
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
+ srvDesc.Texture2DMSArray.FirstArraySlice = 0;
+ srvDesc.Texture2DMSArray.ArraySize = mTextureDepth;
+
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
+ outSRV->setLabels("TexStorage2DMSArray.SRV", &mKHRDebugLabel);
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_2DMultisampleArray::getSwizzleTexture(
+ const gl::Context *context,
+ const TextureHelper11 **outTexture)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_2DMultisampleArray::getSwizzleRenderTarget(
+ const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_2DMultisampleArray::ensureDropStencilTexture(
+ const gl::Context *context,
+ DropStencil *dropStencilOut)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+void TextureStorage11_2DMultisampleArray::onLabelUpdate()
+{
+ if (mTexture.valid())
+ {
+ mTexture.setKHRDebugLabel(&mKHRDebugLabel);
+ }
+}
+
+TextureStorage11_Buffer::TextureStorage11_Buffer(Renderer11 *renderer,
+ const gl::OffsetBindingPointer<gl::Buffer> &buffer,
+ GLenum internalFormat,
+ const std::string &label)
+ : TextureStorage11(renderer,
+ D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE,
+ 0,
+ internalFormat,
+ label),
+ mTexture(),
+ mBuffer(buffer),
+ mDataSize(GetBoundBufferAvailableSize(buffer))
+{
+ unsigned int bytesPerPixel =
+ static_cast<unsigned int>(d3d11::GetDXGIFormatSizeInfo(mFormatInfo.srvFormat).pixelBytes);
+ mMipLevels = 1;
+ mTextureWidth = static_cast<unsigned int>(mDataSize / bytesPerPixel);
+ mTextureHeight = 1;
+ mTextureDepth = 1;
+}
+
+TextureStorage11_Buffer::~TextureStorage11_Buffer() {}
+
+angle::Result TextureStorage11_Buffer::initTexture(const gl::Context *context)
+{
+ if (!mTexture.valid())
+ {
+ ID3D11Buffer *buffer = nullptr;
+ Buffer11 *buffer11 = GetImplAs<Buffer11>(mBuffer.get());
+ ANGLE_TRY(buffer11->getBuffer(context, rx::BufferUsage::BUFFER_USAGE_TYPED_UAV, &buffer));
+ mTexture.set(buffer, mFormatInfo);
+ mTexture.get()->AddRef();
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Buffer::getResource(const gl::Context *context,
+ const TextureHelper11 **outResource)
+{
+ ANGLE_TRY(initTexture(context));
+ *outResource = &mTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Buffer::getMippedResource(const gl::Context *context,
+ const TextureHelper11 **)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_Buffer::findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_Buffer::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_Buffer::getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_Buffer::getSwizzleRenderTarget(
+ const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage11_Buffer::createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ ASSERT(baseLevel == 0);
+ ASSERT(mipLevels == 1);
+ ASSERT(outSRV);
+ ANGLE_TRY(initTexture(context));
+ UINT bytesPerPixel = static_cast<UINT>(d3d11::GetDXGIFormatSizeInfo(format).pixelBytes);
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
+ ASSERT(mBuffer.getOffset() % bytesPerPixel == 0);
+ srvDesc.Buffer.FirstElement = static_cast<UINT>(mBuffer.getOffset() / bytesPerPixel);
+ srvDesc.Buffer.NumElements = static_cast<UINT>(mDataSize / bytesPerPixel);
+
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
+ outSRV->setLabels("TexBuffer.SRV", &mKHRDebugLabel);
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage11_Buffer::createSRVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV)
+{
+ ANGLE_TRY(initTexture(context));
+ UINT bytesPerPixel = static_cast<UINT>(d3d11::GetDXGIFormatSizeInfo(format).pixelBytes);
+ D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
+ srvDesc.Format = format;
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
+ ASSERT(mBuffer.getOffset() % bytesPerPixel == 0);
+ srvDesc.Buffer.FirstElement = static_cast<UINT>(mBuffer.getOffset() / bytesPerPixel);
+ srvDesc.Buffer.NumElements = static_cast<UINT>(mDataSize / bytesPerPixel);
+
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), srvDesc, texture.get(), outSRV));
+ outSRV->setLabels("TexBuffer.SRVForImage", &mKHRDebugLabel);
+
+ return angle::Result::Continue;
+}
+angle::Result TextureStorage11_Buffer::createUAVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedUAV *outUAV)
+{
+ ANGLE_TRY(initTexture(context));
+ unsigned bytesPerPixel = d3d11::GetDXGIFormatSizeInfo(format).pixelBytes;
+ D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc;
+ uavDesc.Format = format;
+ uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
+ ASSERT(mBuffer.getOffset() % bytesPerPixel == 0);
+ uavDesc.Buffer.FirstElement = static_cast<UINT>(mBuffer.getOffset() / bytesPerPixel);
+ uavDesc.Buffer.NumElements = static_cast<UINT>(mDataSize / bytesPerPixel);
+ uavDesc.Buffer.Flags = 0;
+
+ ANGLE_TRY(
+ mRenderer->allocateResource(GetImplAs<Context11>(context), uavDesc, texture.get(), outUAV));
+ outUAV->setLabels("TexBuffer.UAVForImage", &mKHRDebugLabel);
+
+ return angle::Result::Continue;
+}
+
+void TextureStorage11_Buffer::associateImage(Image11 *image, const gl::ImageIndex &index) {}
+void TextureStorage11_Buffer::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage)
+{}
+void TextureStorage11_Buffer::verifyAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage)
+{}
+angle::Result TextureStorage11_Buffer::releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage)
+{
+ return angle::Result::Continue;
+}
+
+void TextureStorage11_Buffer::onLabelUpdate()
+{
+ if (mTexture.valid())
+ {
+ mTexture.setKHRDebugLabel(&mKHRDebugLabel);
+ }
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
new file mode 100644
index 0000000000..72bc1b802c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
@@ -0,0 +1,1003 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureStorage11.h: Defines the abstract rx::TextureStorage11 class and its concrete derived
+// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11
+// texture.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
+
+#include "libANGLE/Error.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+#include <array>
+#include <map>
+
+namespace gl
+{
+class ImageIndex;
+} // namespace gl
+
+namespace rx
+{
+class EGLImageD3D;
+class RenderTargetD3D;
+class RenderTarget11;
+class Renderer11;
+class SwapChain11;
+class Image11;
+struct Renderer11DeviceCaps;
+class TextureStorage11_2DMultisample;
+
+template <typename T>
+using CubeFaceArray = std::array<T, gl::kCubeFaceCount>;
+
+struct MultisampledRenderToTextureInfo
+{
+ MultisampledRenderToTextureInfo(const GLsizei samples,
+ const gl::ImageIndex &indexSS,
+ const gl::ImageIndex &indexMS);
+ ~MultisampledRenderToTextureInfo();
+
+ // How many samples the multisampled texture contains
+ GLsizei samples;
+ // This is the image index for the single sampled texture
+ // This will hold the relevant level information
+ gl::ImageIndex indexSS;
+ // This is the image index for the multisampled texture
+ // For multisampled indexes, there is no level Index since they should
+ // account for the entire level.
+ gl::ImageIndex indexMS;
+ // True when multisampled texture has been written to and needs to be
+ // resolved to the single sampled texture
+ bool msTextureNeedsResolve;
+ std::unique_ptr<TextureStorage11_2DMultisample> msTex;
+};
+
+class TextureStorage11 : public TextureStorage
+{
+ public:
+ ~TextureStorage11() override;
+
+ static DWORD GetTextureBindFlags(GLenum internalFormat,
+ const Renderer11DeviceCaps &renderer11DeviceCaps,
+ BindFlags flags);
+ static DWORD GetTextureMiscFlags(GLenum internalFormat,
+ const Renderer11DeviceCaps &renderer11DeviceCaps,
+ BindFlags flags,
+ int levels);
+
+ UINT getBindFlags() const;
+ UINT getMiscFlags() const;
+ const d3d11::Format &getFormatSet() const;
+ angle::Result getSRVLevels(const gl::Context *context,
+ GLint baseLevel,
+ GLint maxLevel,
+ const d3d11::SharedSRV **outSRV);
+ angle::Result generateSwizzles(const gl::Context *context,
+ const gl::TextureState &textureState);
+ void markLevelDirty(int mipLevel);
+ void markDirty();
+
+ angle::Result updateSubresourceLevel(const gl::Context *context,
+ const TextureHelper11 &texture,
+ unsigned int sourceSubresource,
+ const gl::ImageIndex &index,
+ const gl::Box &copyArea);
+
+ angle::Result copySubresourceLevel(const gl::Context *context,
+ const TextureHelper11 &dstTexture,
+ unsigned int dstSubresource,
+ const gl::ImageIndex &index,
+ const gl::Box &region);
+
+ // TextureStorage virtual functions
+ int getTopLevel() const override;
+ bool isRenderTarget() const override;
+ bool isManaged() const override;
+ bool supportsNativeMipmapFunction() const override;
+ int getLevelCount() const override;
+ bool isUnorderedAccess() const override { return mBindFlags & D3D11_BIND_UNORDERED_ACCESS; }
+ angle::Result generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex) override;
+ angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
+ angle::Result setData(const gl::Context *context,
+ const gl::ImageIndex &index,
+ ImageD3D *image,
+ const gl::Box *destBox,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixelData) override;
+ void invalidateTextures() override;
+
+ virtual angle::Result getSRVForSampler(const gl::Context *context,
+ const gl::TextureState &textureState,
+ const gl::SamplerState &sampler,
+ const d3d11::SharedSRV **outSRV);
+ angle::Result getSRVForImage(const gl::Context *context,
+ const gl::ImageUnit &imageUnit,
+ const d3d11::SharedSRV **outSRV);
+ angle::Result getUAVForImage(const gl::Context *context,
+ const gl::ImageUnit &imageUnit,
+ const d3d11::SharedUAV **outUAV);
+ virtual angle::Result getSubresourceIndex(const gl::Context *context,
+ const gl::ImageIndex &index,
+ UINT *outSubresourceIndex) const;
+ virtual angle::Result getResource(const gl::Context *context,
+ const TextureHelper11 **outResource) = 0;
+ virtual void associateImage(Image11 *image, const gl::ImageIndex &index) = 0;
+ virtual void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) = 0;
+ virtual void verifyAssociatedImageValid(const gl::ImageIndex &index,
+ Image11 *expectedImage) = 0;
+ virtual angle::Result releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) = 0;
+
+ GLsizei getRenderToTextureSamples() const override;
+
+ protected:
+ TextureStorage11(Renderer11 *renderer,
+ UINT bindFlags,
+ UINT miscFlags,
+ GLenum internalFormat,
+ const std::string &label);
+ int getLevelWidth(int mipLevel) const;
+ int getLevelHeight(int mipLevel) const;
+ int getLevelDepth(int mipLevel) const;
+
+ // Some classes (e.g. TextureStorage11_2D) will override getMippedResource.
+ virtual angle::Result getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource);
+
+ virtual angle::Result getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture) = 0;
+ virtual angle::Result getSwizzleRenderTarget(const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV) = 0;
+
+ enum class SRVType
+ {
+ Sample,
+ Blit,
+ Stencil
+ };
+ angle::Result getSRVLevel(const gl::Context *context,
+ int mipLevel,
+ SRVType srvType,
+ const d3d11::SharedSRV **outSRV);
+
+ // Get a version of a depth texture with only depth information, not stencil.
+ enum DropStencil
+ {
+ CREATED,
+ ALREADY_EXISTS
+ };
+ virtual angle::Result ensureDropStencilTexture(const gl::Context *context,
+ DropStencil *dropStencilOut);
+ angle::Result initDropStencilTexture(const gl::Context *context,
+ const gl::ImageIndexIterator &it);
+
+ // The baseLevel parameter should *not* have mTopLevel applied.
+ virtual angle::Result createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) = 0;
+ virtual angle::Result createSRVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) = 0;
+ virtual angle::Result createUAVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedUAV *outUAV) = 0;
+
+ void verifySwizzleExists(const gl::SwizzleState &swizzleState);
+
+ // Clear all cached non-swizzle SRVs and invalidate the swizzle cache.
+ void clearSRVCache();
+
+ // Helper for resolving MS shadowed texture
+ angle::Result resolveTextureHelper(const gl::Context *context, const TextureHelper11 &texture);
+ angle::Result releaseMultisampledTexStorageForLevel(size_t level) override;
+ angle::Result findMultisampledRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const;
+ angle::Result getMultisampledRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT);
+
+ Renderer11 *mRenderer;
+ int mTopLevel;
+ unsigned int mMipLevels;
+
+ const d3d11::Format &mFormatInfo;
+ unsigned int mTextureWidth;
+ unsigned int mTextureHeight;
+ unsigned int mTextureDepth;
+
+ gl::TexLevelArray<gl::SwizzleState> mSwizzleCache;
+ TextureHelper11 mDropStencilTexture;
+
+ std::unique_ptr<MultisampledRenderToTextureInfo> mMSTexInfo;
+
+ private:
+ const UINT mBindFlags;
+ const UINT mMiscFlags;
+
+ struct SamplerKey
+ {
+ SamplerKey();
+ SamplerKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil);
+
+ bool operator<(const SamplerKey &rhs) const;
+
+ int baseLevel;
+ int mipLevels;
+ bool swizzle;
+ bool dropStencil;
+ };
+
+ angle::Result getCachedOrCreateSRVForSampler(const gl::Context *context,
+ const SamplerKey &key,
+ const d3d11::SharedSRV **outSRV);
+
+ using SRVCacheForSampler = std::map<SamplerKey, d3d11::SharedSRV>;
+ SRVCacheForSampler mSrvCacheForSampler;
+
+ struct ImageKey
+ {
+ ImageKey();
+ ImageKey(int level, bool layered, int layer, GLenum access, GLenum format);
+ bool operator<(const ImageKey &rhs) const;
+ int level;
+ bool layered;
+ int layer;
+ GLenum access;
+ GLenum format;
+ };
+
+ angle::Result getCachedOrCreateSRVForImage(const gl::Context *context,
+ const ImageKey &key,
+ const d3d11::SharedSRV **outSRV);
+ angle::Result getCachedOrCreateUAVForImage(const gl::Context *context,
+ const ImageKey &key,
+ const d3d11::SharedUAV **outUAV);
+
+ using SRVCacheForImage = std::map<ImageKey, d3d11::SharedSRV>;
+ SRVCacheForImage mSrvCacheForImage;
+ using UAVCacheForImage = std::map<ImageKey, d3d11::SharedUAV>;
+ UAVCacheForImage mUavCacheForImage;
+
+ gl::TexLevelArray<d3d11::SharedSRV> mLevelSRVs;
+ gl::TexLevelArray<d3d11::SharedSRV> mLevelBlitSRVs;
+ gl::TexLevelArray<d3d11::SharedSRV> mLevelStencilSRVs;
+};
+
+class TextureStorage11_2D : public TextureStorage11
+{
+ public:
+ TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain, const std::string &label);
+ TextureStorage11_2D(Renderer11 *renderer,
+ GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ const std::string &label,
+ bool hintLevelZeroOnly = false);
+ ~TextureStorage11_2D() override;
+
+ angle::Result onDestroy(const gl::Context *context) override;
+
+ angle::Result getResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ angle::Result getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ angle::Result findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const override;
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
+
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ angle::Result releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) override;
+
+ angle::Result useLevelZeroWorkaroundTexture(const gl::Context *context,
+ bool useLevelZeroTexture) override;
+ void onLabelUpdate() override;
+
+ protected:
+ angle::Result getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture) override;
+ angle::Result getSwizzleRenderTarget(const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV) override;
+
+ angle::Result ensureDropStencilTexture(const gl::Context *context,
+ DropStencil *dropStencilOut) override;
+
+ angle::Result ensureTextureExists(const gl::Context *context, int mipLevels);
+
+ angle::Result resolveTexture(const gl::Context *context) override;
+
+ private:
+ angle::Result createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+ angle::Result createSRVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+ angle::Result createUAVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedUAV *outUAV) override;
+
+ TextureHelper11 mTexture;
+ gl::TexLevelArray<std::unique_ptr<RenderTarget11>> mRenderTarget;
+ bool mHasKeyedMutex;
+
+ // These are members related to the zero max-LOD workaround.
+ // D3D11 Feature Level 9_3 can't disable mipmaps on a mipmapped texture (i.e. solely sample from
+ // level zero). These members are used to work around this limitation. Usually only mTexture XOR
+ // mLevelZeroTexture will exist. For example, if an app creates a texture with only one level,
+ // then 9_3 will only create mLevelZeroTexture. However, in some scenarios, both textures have
+ // to be created. This incurs additional memory overhead. One example of this is an application
+ // that creates a texture, calls glGenerateMipmap, and then disables mipmaps on the texture. A
+ // more likely example is an app that creates an empty texture, renders to it, and then calls
+ // glGenerateMipmap
+ // TODO: In this rendering scenario, release the mLevelZeroTexture after mTexture has been
+ // created to save memory.
+ TextureHelper11 mLevelZeroTexture;
+ std::unique_ptr<RenderTarget11> mLevelZeroRenderTarget;
+ bool mUseLevelZeroTexture;
+
+ // Swizzle-related variables
+ TextureHelper11 mSwizzleTexture;
+ gl::TexLevelArray<d3d11::RenderTargetView> mSwizzleRenderTargets;
+
+ gl::TexLevelArray<Image11 *> mAssociatedImages;
+};
+
+class TextureStorage11_External : public TextureStorage11
+{
+ public:
+ TextureStorage11_External(Renderer11 *renderer,
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &glDesc,
+ const std::string &label);
+ ~TextureStorage11_External() override;
+
+ angle::Result onDestroy(const gl::Context *context) override;
+
+ angle::Result getResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ angle::Result getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ angle::Result findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const override;
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
+
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ angle::Result releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) override;
+ void onLabelUpdate() override;
+
+ protected:
+ angle::Result getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture) override;
+ angle::Result getSwizzleRenderTarget(const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV) override;
+
+ private:
+ angle::Result createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+ angle::Result createSRVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+ angle::Result createUAVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedUAV *outUAV) override;
+
+ TextureHelper11 mTexture;
+ int mSubresourceIndex;
+ bool mHasKeyedMutex;
+
+ Image11 *mAssociatedImage;
+};
+
+// A base class for texture storage classes where the associated images are not changed, nor are
+// they accessible as images in GLES3.1+ shaders.
+class TextureStorage11ImmutableBase : public TextureStorage11
+{
+ public:
+ TextureStorage11ImmutableBase(Renderer11 *renderer,
+ UINT bindFlags,
+ UINT miscFlags,
+ GLenum internalFormat,
+ const std::string &label);
+
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ angle::Result releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) override;
+
+ angle::Result createSRVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+ angle::Result createUAVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedUAV *outUAV) override;
+};
+
+class TextureStorage11_EGLImage final : public TextureStorage11ImmutableBase
+{
+ public:
+ TextureStorage11_EGLImage(Renderer11 *renderer,
+ EGLImageD3D *eglImage,
+ RenderTarget11 *renderTarget11,
+ const std::string &label);
+ ~TextureStorage11_EGLImage() override;
+
+ angle::Result getSubresourceIndex(const gl::Context *context,
+ const gl::ImageIndex &index,
+ UINT *outSubresourceIndex) const override;
+ angle::Result getResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ angle::Result getSRVForSampler(const gl::Context *context,
+ const gl::TextureState &textureState,
+ const gl::SamplerState &sampler,
+ const d3d11::SharedSRV **outSRV) override;
+ angle::Result getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ angle::Result findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const override;
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
+
+ angle::Result useLevelZeroWorkaroundTexture(const gl::Context *context,
+ bool useLevelZeroTexture) override;
+ void onLabelUpdate() override;
+
+ protected:
+ angle::Result getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture) override;
+ angle::Result getSwizzleRenderTarget(const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV) override;
+
+ private:
+ // Check if the EGL image's render target has been updated due to orphaning and delete
+ // any SRVs and other resources based on the image's old render target.
+ angle::Result checkForUpdatedRenderTarget(const gl::Context *context);
+
+ angle::Result createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+
+ angle::Result getImageRenderTarget(const gl::Context *context, RenderTarget11 **outRT) const;
+
+ EGLImageD3D *mImage;
+ uintptr_t mCurrentRenderTarget;
+
+ // Swizzle-related variables
+ TextureHelper11 mSwizzleTexture;
+ std::vector<d3d11::RenderTargetView> mSwizzleRenderTargets;
+};
+
+class TextureStorage11_Cube : public TextureStorage11
+{
+ public:
+ TextureStorage11_Cube(Renderer11 *renderer,
+ GLenum internalformat,
+ BindFlags bindFlags,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly,
+ const std::string &label);
+ ~TextureStorage11_Cube() override;
+
+ angle::Result onDestroy(const gl::Context *context) override;
+
+ angle::Result getSubresourceIndex(const gl::Context *context,
+ const gl::ImageIndex &index,
+ UINT *outSubresourceIndex) const override;
+
+ angle::Result getResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ angle::Result getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ angle::Result findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const override;
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
+
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ angle::Result releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) override;
+
+ angle::Result useLevelZeroWorkaroundTexture(const gl::Context *context,
+ bool useLevelZeroTexture) override;
+ void onLabelUpdate() override;
+
+ protected:
+ angle::Result getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture) override;
+ angle::Result getSwizzleRenderTarget(const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV) override;
+
+ angle::Result ensureDropStencilTexture(const gl::Context *context,
+ DropStencil *dropStencilOut) override;
+
+ angle::Result ensureTextureExists(const gl::Context *context, int mipLevels);
+
+ angle::Result resolveTexture(const gl::Context *context) override;
+
+ private:
+ angle::Result createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+ angle::Result createSRVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+ angle::Result createUAVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedUAV *outUAV) override;
+ angle::Result createRenderTargetSRV(const gl::Context *context,
+ const TextureHelper11 &texture,
+ const gl::ImageIndex &index,
+ DXGI_FORMAT resourceFormat,
+ d3d11::SharedSRV *srv) const;
+
+ TextureHelper11 mTexture;
+ CubeFaceArray<gl::TexLevelArray<std::unique_ptr<RenderTarget11>>> mRenderTarget;
+
+ // Level-zero workaround members. See TextureStorage11_2D's workaround members for a
+ // description.
+ TextureHelper11 mLevelZeroTexture;
+ CubeFaceArray<std::unique_ptr<RenderTarget11>> mLevelZeroRenderTarget;
+ bool mUseLevelZeroTexture;
+
+ TextureHelper11 mSwizzleTexture;
+ gl::TexLevelArray<d3d11::RenderTargetView> mSwizzleRenderTargets;
+
+ CubeFaceArray<gl::TexLevelArray<Image11 *>> mAssociatedImages;
+};
+
+class TextureStorage11_3D : public TextureStorage11
+{
+ public:
+ TextureStorage11_3D(Renderer11 *renderer,
+ GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ const std::string &label);
+ ~TextureStorage11_3D() override;
+
+ angle::Result onDestroy(const gl::Context *context) override;
+
+ angle::Result getResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+
+ // Handles both layer and non-layer RTs
+ angle::Result findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const override;
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ angle::Result releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) override;
+ void onLabelUpdate() override;
+
+ protected:
+ angle::Result getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture) override;
+ angle::Result getSwizzleRenderTarget(const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV) override;
+
+ private:
+ angle::Result createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+ angle::Result createSRVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+ angle::Result createUAVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedUAV *outUAV) override;
+
+ typedef std::pair<int, int> LevelLayerKey;
+ std::map<LevelLayerKey, std::unique_ptr<RenderTarget11>> mLevelLayerRenderTargets;
+
+ gl::TexLevelArray<std::unique_ptr<RenderTarget11>> mLevelRenderTargets;
+
+ TextureHelper11 mTexture;
+ TextureHelper11 mSwizzleTexture;
+ gl::TexLevelArray<d3d11::RenderTargetView> mSwizzleRenderTargets;
+
+ gl::TexLevelArray<Image11 *> mAssociatedImages;
+};
+
+class TextureStorage11_2DArray : public TextureStorage11
+{
+ public:
+ TextureStorage11_2DArray(Renderer11 *renderer,
+ GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ const std::string &label);
+ ~TextureStorage11_2DArray() override;
+
+ angle::Result onDestroy(const gl::Context *context) override;
+
+ angle::Result getResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ angle::Result findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const override;
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ angle::Result releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) override;
+ void onLabelUpdate() override;
+
+ struct LevelLayerRangeKey
+ {
+ LevelLayerRangeKey(int mipLevelIn, int layerIn, int numLayersIn)
+ : mipLevel(mipLevelIn), layer(layerIn), numLayers(numLayersIn)
+ {}
+ bool operator<(const LevelLayerRangeKey &other) const
+ {
+ if (mipLevel != other.mipLevel)
+ {
+ return mipLevel < other.mipLevel;
+ }
+ if (layer != other.layer)
+ {
+ return layer < other.layer;
+ }
+ return numLayers < other.numLayers;
+ }
+ int mipLevel;
+ int layer;
+ int numLayers;
+ };
+
+ protected:
+ angle::Result getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture) override;
+ angle::Result getSwizzleRenderTarget(const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV) override;
+
+ angle::Result ensureDropStencilTexture(const gl::Context *context,
+ DropStencil *dropStencilOut) override;
+
+ private:
+ angle::Result createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+ angle::Result createSRVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+ angle::Result createUAVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedUAV *outUAV) override;
+ angle::Result createRenderTargetSRV(const gl::Context *context,
+ const TextureHelper11 &texture,
+ const gl::ImageIndex &index,
+ DXGI_FORMAT resourceFormat,
+ d3d11::SharedSRV *srv) const;
+
+ std::map<LevelLayerRangeKey, std::unique_ptr<RenderTarget11>> mRenderTargets;
+
+ TextureHelper11 mTexture;
+
+ TextureHelper11 mSwizzleTexture;
+ gl::TexLevelArray<d3d11::RenderTargetView> mSwizzleRenderTargets;
+
+ typedef std::map<LevelLayerRangeKey, Image11 *> ImageMap;
+ ImageMap mAssociatedImages;
+};
+
+class TextureStorage11_2DMultisample final : public TextureStorage11ImmutableBase
+{
+ public:
+ TextureStorage11_2DMultisample(Renderer11 *renderer,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ int samples,
+ bool fixedSampleLocations,
+ const std::string &label);
+ ~TextureStorage11_2DMultisample() override;
+
+ angle::Result onDestroy(const gl::Context *context) override;
+
+ angle::Result getResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ angle::Result findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const override;
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
+ void onLabelUpdate() override;
+
+ protected:
+ angle::Result getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture) override;
+ angle::Result getSwizzleRenderTarget(const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV) override;
+
+ angle::Result ensureDropStencilTexture(const gl::Context *context,
+ DropStencil *dropStencilOut) override;
+
+ angle::Result ensureTextureExists(const gl::Context *context, int mipLevels);
+
+ private:
+ angle::Result createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+
+ TextureHelper11 mTexture;
+ std::unique_ptr<RenderTarget11> mRenderTarget;
+
+ unsigned int mSamples;
+ GLboolean mFixedSampleLocations;
+};
+
+class TextureStorage11_2DMultisampleArray final : public TextureStorage11ImmutableBase
+{
+ public:
+ TextureStorage11_2DMultisampleArray(Renderer11 *renderer,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ int samples,
+ bool fixedSampleLocations,
+ const std::string &label);
+ ~TextureStorage11_2DMultisampleArray() override;
+
+ angle::Result onDestroy(const gl::Context *context) override;
+
+ angle::Result getResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ angle::Result findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const override;
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
+ void onLabelUpdate() override;
+
+ protected:
+ angle::Result getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture) override;
+ angle::Result getSwizzleRenderTarget(const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV) override;
+
+ angle::Result ensureDropStencilTexture(const gl::Context *context,
+ DropStencil *dropStencilOut) override;
+
+ angle::Result ensureTextureExists(const gl::Context *context, int mipLevels);
+
+ private:
+ angle::Result createRenderTargetSRV(const gl::Context *context,
+ const TextureHelper11 &texture,
+ const gl::ImageIndex &index,
+ DXGI_FORMAT resourceFormat,
+ d3d11::SharedSRV *srv) const;
+
+ angle::Result createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+
+ TextureHelper11 mTexture;
+ std::map<TextureStorage11_2DArray::LevelLayerRangeKey, std::unique_ptr<RenderTarget11>>
+ mRenderTargets;
+
+ unsigned int mSamples;
+ GLboolean mFixedSampleLocations;
+};
+
+class TextureStorage11_Buffer : public TextureStorage11
+{
+ public:
+ TextureStorage11_Buffer(Renderer11 *renderer,
+ const gl::OffsetBindingPointer<gl::Buffer> &buffer,
+ GLenum internalFormat,
+ const std::string &label);
+ ~TextureStorage11_Buffer() override;
+
+ angle::Result getResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ angle::Result getMippedResource(const gl::Context *context,
+ const TextureHelper11 **outResource) override;
+ angle::Result findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const override;
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+
+ void onLabelUpdate() override;
+
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
+ angle::Result releaseAssociatedImage(const gl::Context *context,
+ const gl::ImageIndex &index,
+ Image11 *incomingImage) override;
+
+ protected:
+ angle::Result getSwizzleTexture(const gl::Context *context,
+ const TextureHelper11 **outTexture) override;
+ angle::Result getSwizzleRenderTarget(const gl::Context *context,
+ int mipLevel,
+ const d3d11::RenderTargetView **outRTV) override;
+
+ private:
+ angle::Result createSRVForSampler(const gl::Context *context,
+ int baseLevel,
+ int mipLevels,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+ angle::Result createSRVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedSRV *outSRV) override;
+ angle::Result createUAVForImage(const gl::Context *context,
+ int level,
+ DXGI_FORMAT format,
+ const TextureHelper11 &texture,
+ d3d11::SharedUAV *outUAV) override;
+
+ angle::Result initTexture(const gl::Context *context);
+
+ TextureHelper11 mTexture;
+ const gl::OffsetBindingPointer<gl::Buffer> &mBuffer;
+ GLint64 mDataSize;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp
new file mode 100644
index 0000000000..1dcd62cd45
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp
@@ -0,0 +1,131 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers.
+
+#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+TransformFeedback11::TransformFeedback11(const gl::TransformFeedbackState &state,
+ Renderer11 *renderer)
+ : TransformFeedbackImpl(state),
+ mRenderer(renderer),
+ mIsDirty(true),
+ mBuffers(state.getIndexedBuffers().size(), nullptr),
+ mBufferOffsets(state.getIndexedBuffers().size(), 0),
+ mSerial(mRenderer->generateSerial())
+{}
+
+TransformFeedback11::~TransformFeedback11() {}
+
+angle::Result TransformFeedback11::begin(const gl::Context *context,
+ gl::PrimitiveMode primitiveMode)
+{
+ // Reset all the cached offsets to the binding offsets
+ mIsDirty = true;
+ for (size_t bindingIdx = 0; bindingIdx < mBuffers.size(); bindingIdx++)
+ {
+ const auto &binding = mState.getIndexedBuffer(bindingIdx);
+ if (binding.get() != nullptr)
+ {
+ mBufferOffsets[bindingIdx] = static_cast<UINT>(binding.getOffset());
+ }
+ else
+ {
+ mBufferOffsets[bindingIdx] = 0;
+ }
+ }
+ mRenderer->getStateManager()->invalidateTransformFeedback();
+ return angle::Result::Continue;
+}
+
+angle::Result TransformFeedback11::end(const gl::Context *context)
+{
+ mRenderer->getStateManager()->invalidateTransformFeedback();
+ if (mRenderer->getFeatures().flushAfterEndingTransformFeedback.enabled)
+ {
+ mRenderer->getDeviceContext()->Flush();
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result TransformFeedback11::pause(const gl::Context *context)
+{
+ mRenderer->getStateManager()->invalidateTransformFeedback();
+ return angle::Result::Continue;
+}
+
+angle::Result TransformFeedback11::resume(const gl::Context *context)
+{
+ mRenderer->getStateManager()->invalidateTransformFeedback();
+ return angle::Result::Continue;
+}
+
+angle::Result TransformFeedback11::bindIndexedBuffer(
+ const gl::Context *context,
+ size_t index,
+ const gl::OffsetBindingPointer<gl::Buffer> &binding)
+{
+ mIsDirty = true;
+ mBufferOffsets[index] = static_cast<UINT>(binding.getOffset());
+ mRenderer->getStateManager()->invalidateTransformFeedback();
+ return angle::Result::Continue;
+}
+
+void TransformFeedback11::onApply()
+{
+ mIsDirty = false;
+
+ // Change all buffer offsets to -1 so that if any of them need to be re-applied, the are set to
+ // append
+ std::fill(mBufferOffsets.begin(), mBufferOffsets.end(), -1);
+}
+
+bool TransformFeedback11::isDirty() const
+{
+ return mIsDirty;
+}
+
+UINT TransformFeedback11::getNumSOBuffers() const
+{
+ return static_cast<UINT>(mBuffers.size());
+}
+
+angle::Result TransformFeedback11::getSOBuffers(const gl::Context *context,
+ const std::vector<ID3D11Buffer *> **buffersOut)
+{
+ for (size_t bindingIdx = 0; bindingIdx < mBuffers.size(); bindingIdx++)
+ {
+ const auto &binding = mState.getIndexedBuffer(bindingIdx);
+ if (binding.get() != nullptr)
+ {
+ Buffer11 *storage = GetImplAs<Buffer11>(binding.get());
+ ANGLE_TRY(storage->getBuffer(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK,
+ &mBuffers[bindingIdx]));
+ }
+ }
+
+ *buffersOut = &mBuffers;
+ return angle::Result::Continue;
+}
+
+const std::vector<UINT> &TransformFeedback11::getSOBufferOffsets() const
+{
+ return mBufferOffsets;
+}
+
+Serial TransformFeedback11::getSerial() const
+{
+ return mSerial;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h
new file mode 100644
index 0000000000..69ae90671b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h
@@ -0,0 +1,61 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TransformFeedback11.h: Implements the abstract rx::TransformFeedbackImpl class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_
+
+#include "common/platform.h"
+
+#include "libANGLE/Error.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+#include "libANGLE/renderer/serial_utils.h"
+
+namespace rx
+{
+
+class Renderer11;
+
+class TransformFeedback11 : public TransformFeedbackImpl
+{
+ public:
+ TransformFeedback11(const gl::TransformFeedbackState &state, Renderer11 *renderer);
+ ~TransformFeedback11() override;
+
+ angle::Result begin(const gl::Context *context, gl::PrimitiveMode primitiveMode) override;
+ angle::Result end(const gl::Context *context) override;
+ angle::Result pause(const gl::Context *context) override;
+ angle::Result resume(const gl::Context *context) override;
+
+ angle::Result bindIndexedBuffer(const gl::Context *context,
+ size_t index,
+ const gl::OffsetBindingPointer<gl::Buffer> &binding) override;
+
+ void onApply();
+
+ bool isDirty() const;
+
+ UINT getNumSOBuffers() const;
+ angle::Result getSOBuffers(const gl::Context *context,
+ const std::vector<ID3D11Buffer *> **buffersOut);
+ const std::vector<UINT> &getSOBufferOffsets() const;
+
+ Serial getSerial() const;
+
+ private:
+ Renderer11 *mRenderer;
+
+ bool mIsDirty;
+ std::vector<ID3D11Buffer *> mBuffers;
+ std::vector<UINT> mBufferOffsets;
+
+ Serial mSerial;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp
new file mode 100644
index 0000000000..ac6d9a5220
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp
@@ -0,0 +1,103 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Trim11.cpp: Trim support utility class.
+
+#include "libANGLE/renderer/d3d/d3d11/Trim11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#if defined(ANGLE_ENABLE_WINDOWS_UWP)
+# include <windows.applicationmodel.core.h>
+# include <wrl.h>
+# include <wrl/wrappers/corewrappers.h>
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::ApplicationModel;
+using namespace ABI::Windows::ApplicationModel::Core;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+#endif
+
+namespace rx
+{
+
+Trim11::Trim11(rx::Renderer11 *renderer) : mRenderer(renderer)
+{
+ bool result = true;
+ result = registerForRendererTrimRequest();
+ ASSERT(result);
+}
+
+Trim11::~Trim11()
+{
+ unregisterForRendererTrimRequest();
+}
+
+void Trim11::trim()
+{
+ if (!mRenderer)
+ {
+ return;
+ }
+
+#if defined(ANGLE_ENABLE_WINDOWS_UWP)
+ ID3D11Device *device = mRenderer->getDevice();
+ IDXGIDevice3 *dxgiDevice3 = d3d11::DynamicCastComObject<IDXGIDevice3>(device);
+ if (dxgiDevice3)
+ {
+ dxgiDevice3->Trim();
+ }
+ SafeRelease(dxgiDevice3);
+#endif
+}
+
+bool Trim11::registerForRendererTrimRequest()
+{
+#if defined(ANGLE_ENABLE_WINDOWS_UWP)
+ ICoreApplication *coreApplication = nullptr;
+ HRESULT result = GetActivationFactory(
+ HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
+ &coreApplication);
+ if (SUCCEEDED(result))
+ {
+ auto suspendHandler = Callback<IEventHandler<SuspendingEventArgs *>>(
+ [this](IInspectable *, ISuspendingEventArgs *) -> HRESULT {
+ trim();
+ return S_OK;
+ });
+ result =
+ coreApplication->add_Suspending(suspendHandler.Get(), &mApplicationSuspendedEventToken);
+ }
+ SafeRelease(coreApplication);
+
+ if (FAILED(result))
+ {
+ return false;
+ }
+#endif
+ return true;
+}
+
+void Trim11::unregisterForRendererTrimRequest()
+{
+#if defined(ANGLE_ENABLE_WINDOWS_UWP)
+ if (mApplicationSuspendedEventToken.value != 0)
+ {
+ ICoreApplication *coreApplication = nullptr;
+ if (SUCCEEDED(GetActivationFactory(
+ HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
+ &coreApplication)))
+ {
+ coreApplication->remove_Suspending(mApplicationSuspendedEventToken);
+ }
+ mApplicationSuspendedEventToken.value = 0;
+ SafeRelease(coreApplication);
+ }
+#endif
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Trim11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Trim11.h
new file mode 100644
index 0000000000..eb1f3e7e13
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/Trim11.h
@@ -0,0 +1,43 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Trim11.h: Trim support utility class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/angletypes.h"
+
+#if defined(ANGLE_ENABLE_WINDOWS_UWP)
+# include <EventToken.h>
+#endif
+
+namespace rx
+{
+class Renderer11;
+
+class Trim11 : angle::NonCopyable
+{
+ public:
+ explicit Trim11(Renderer11 *renderer);
+ ~Trim11();
+
+ private:
+ Renderer11 *mRenderer;
+#if defined(ANGLE_ENABLE_WINDOWS_UWP)
+ EventRegistrationToken mApplicationSuspendedEventToken;
+#endif
+
+ void trim();
+ bool registerForRendererTrimRequest();
+ void unregisterForRendererTrimRequest();
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
new file mode 100644
index 0000000000..a5f8b6a176
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
@@ -0,0 +1,375 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// VertexArray11:
+// Implementation of rx::VertexArray11.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
+
+#include "common/bitset_utils.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+
+using namespace angle;
+
+namespace rx
+{
+VertexArray11::VertexArray11(const gl::VertexArrayState &data)
+ : VertexArrayImpl(data),
+ mAttributeStorageTypes(data.getMaxAttribs(), VertexStorageType::CURRENT_VALUE),
+ mTranslatedAttribs(data.getMaxAttribs()),
+ mAppliedNumViewsToDivisor(1),
+ mCurrentElementArrayStorage(IndexStorageType::Invalid),
+ mCachedDestinationIndexType(gl::DrawElementsType::InvalidEnum)
+{}
+
+VertexArray11::~VertexArray11() {}
+
+void VertexArray11::destroy(const gl::Context *context) {}
+
+// As VertexAttribPointer can modify both attribute and binding, we should also set other attributes
+// that are also using this binding dirty.
+#define ANGLE_VERTEX_DIRTY_ATTRIB_FUNC(INDEX) \
+ case gl::VertexArray::DIRTY_BIT_ATTRIB_0 + INDEX: \
+ if ((*attribBits)[INDEX][gl::VertexArray::DirtyAttribBitType::DIRTY_ATTRIB_POINTER]) \
+ { \
+ attributesToUpdate |= mState.getBindingToAttributesMask(INDEX); \
+ } \
+ else \
+ { \
+ attributesToUpdate.set(INDEX); \
+ } \
+ invalidateVertexBuffer = true; \
+ (*attribBits)[INDEX].reset(); \
+ break;
+
+#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
+ case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
+ attributesToUpdate |= mState.getBindingToAttributesMask(INDEX); \
+ invalidateVertexBuffer = true; \
+ (*bindingBits)[INDEX].reset(); \
+ break;
+
+#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
+ case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
+ if (mAttributeStorageTypes[INDEX] == VertexStorageType::STATIC) \
+ { \
+ invalidateVertexBuffer = true; \
+ mAttribsToTranslate.set(INDEX); \
+ } \
+ break;
+
+angle::Result VertexArray11::syncState(const gl::Context *context,
+ const gl::VertexArray::DirtyBits &dirtyBits,
+ gl::VertexArray::DirtyAttribBitsArray *attribBits,
+ gl::VertexArray::DirtyBindingBitsArray *bindingBits)
+{
+ ASSERT(dirtyBits.any());
+
+ Renderer11 *renderer = GetImplAs<Context11>(context)->getRenderer();
+ StateManager11 *stateManager = renderer->getStateManager();
+
+ // Generate a state serial. This serial is used in the program class to validate the cached
+ // input layout, and skip recomputation in the fast path.
+ mCurrentStateSerial = renderer->generateSerial();
+
+ bool invalidateVertexBuffer = false;
+
+ gl::AttributesMask attributesToUpdate;
+
+ // Make sure we trigger re-translation for static index or vertex data.
+ for (size_t dirtyBit : dirtyBits)
+ {
+ switch (dirtyBit)
+ {
+ case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER:
+ case gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
+ {
+ mLastDrawElementsType.reset();
+ mLastDrawElementsIndices.reset();
+ mLastPrimitiveRestartEnabled.reset();
+ mCachedIndexInfo.reset();
+ break;
+ }
+
+ ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC)
+ ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC)
+ ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC)
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+
+ for (size_t attribIndex : attributesToUpdate)
+ {
+ updateVertexAttribStorage(context, stateManager, attribIndex);
+ }
+
+ if (invalidateVertexBuffer)
+ {
+ // TODO(jmadill): Individual attribute invalidation.
+ stateManager->invalidateVertexBuffer();
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result VertexArray11::syncStateForDraw(const gl::Context *context,
+ GLint firstVertex,
+ GLsizei vertexOrIndexCount,
+ gl::DrawElementsType indexTypeOrInvalid,
+ const void *indices,
+ GLsizei instances,
+ GLint baseVertex,
+ GLuint baseInstance,
+ bool promoteDynamic)
+{
+ Renderer11 *renderer = GetImplAs<Context11>(context)->getRenderer();
+ StateManager11 *stateManager = renderer->getStateManager();
+
+ const gl::State &glState = context->getState();
+ const gl::Program *program = glState.getProgram();
+ ASSERT(program);
+ const gl::ProgramExecutable &executable = program->getExecutable();
+
+ mAppliedNumViewsToDivisor = (program->usesMultiview() ? program->getNumViews() : 1);
+
+ if (mAttribsToTranslate.any())
+ {
+ const gl::AttributesMask &activeLocations = executable.getActiveAttribLocationsMask();
+ gl::AttributesMask activeDirtyAttribs = (mAttribsToTranslate & activeLocations);
+ if (activeDirtyAttribs.any())
+ {
+ ANGLE_TRY(updateDirtyAttribs(context, activeDirtyAttribs));
+ stateManager->invalidateInputLayout();
+ }
+ }
+
+ if (mDynamicAttribsMask.any())
+ {
+ const gl::AttributesMask &activeLocations = executable.getActiveAttribLocationsMask();
+ gl::AttributesMask activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
+
+ if (activeDynamicAttribs.any())
+ {
+ ANGLE_TRY(updateDynamicAttribs(context, stateManager->getVertexDataManager(),
+ firstVertex, vertexOrIndexCount, indexTypeOrInvalid,
+ indices, instances, baseVertex, baseInstance,
+ promoteDynamic, activeDynamicAttribs));
+ stateManager->invalidateInputLayout();
+ }
+ }
+
+ if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
+ {
+ bool restartEnabled = context->getState().isPrimitiveRestartEnabled();
+ if (!mLastDrawElementsType.valid() || mLastDrawElementsType.value() != indexTypeOrInvalid ||
+ mLastDrawElementsIndices.value() != indices ||
+ mLastPrimitiveRestartEnabled.value() != restartEnabled)
+ {
+ mLastDrawElementsType = indexTypeOrInvalid;
+ mLastDrawElementsIndices = indices;
+ mLastPrimitiveRestartEnabled = restartEnabled;
+
+ ANGLE_TRY(updateElementArrayStorage(context, vertexOrIndexCount, indexTypeOrInvalid,
+ indices, restartEnabled));
+ stateManager->invalidateIndexBuffer();
+ }
+ else if (mCurrentElementArrayStorage == IndexStorageType::Dynamic)
+ {
+ stateManager->invalidateIndexBuffer();
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result VertexArray11::updateElementArrayStorage(const gl::Context *context,
+ GLsizei indexCount,
+ gl::DrawElementsType indexType,
+ const void *indices,
+ bool restartEnabled)
+{
+ bool usePrimitiveRestartWorkaround = UsePrimitiveRestartWorkaround(restartEnabled, indexType);
+
+ ANGLE_TRY(GetIndexTranslationDestType(context, indexCount, indexType, indices,
+ usePrimitiveRestartWorkaround,
+ &mCachedDestinationIndexType));
+
+ unsigned int offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices));
+
+ mCurrentElementArrayStorage =
+ ClassifyIndexStorage(context->getState(), mState.getElementArrayBuffer(), indexType,
+ mCachedDestinationIndexType, offset);
+
+ return angle::Result::Continue;
+}
+
+void VertexArray11::updateVertexAttribStorage(const gl::Context *context,
+ StateManager11 *stateManager,
+ size_t attribIndex)
+{
+ const gl::VertexAttribute &attrib = mState.getVertexAttribute(attribIndex);
+ const gl::VertexBinding &binding = mState.getBindingFromAttribIndex(attribIndex);
+
+ VertexStorageType newStorageType = ClassifyAttributeStorage(context, attrib, binding);
+
+ // Note: having an unchanged storage type doesn't mean the attribute is clean.
+ mAttribsToTranslate.set(attribIndex, newStorageType != VertexStorageType::DYNAMIC);
+
+ if (mAttributeStorageTypes[attribIndex] == newStorageType)
+ return;
+
+ mAttributeStorageTypes[attribIndex] = newStorageType;
+ mDynamicAttribsMask.set(attribIndex, newStorageType == VertexStorageType::DYNAMIC);
+
+ if (newStorageType == VertexStorageType::CURRENT_VALUE)
+ {
+ stateManager->invalidateCurrentValueAttrib(attribIndex);
+ }
+}
+
+bool VertexArray11::hasActiveDynamicAttrib(const gl::Context *context)
+{
+ const auto &activeLocations =
+ context->getState().getProgramExecutable()->getActiveAttribLocationsMask();
+ gl::AttributesMask activeDynamicAttribs = (mDynamicAttribsMask & activeLocations);
+ return activeDynamicAttribs.any();
+}
+
+angle::Result VertexArray11::updateDirtyAttribs(const gl::Context *context,
+ const gl::AttributesMask &activeDirtyAttribs)
+{
+ const auto &glState = context->getState();
+ const auto &attribs = mState.getVertexAttributes();
+ const auto &bindings = mState.getVertexBindings();
+
+ for (size_t dirtyAttribIndex : activeDirtyAttribs)
+ {
+ auto *translatedAttrib = &mTranslatedAttribs[dirtyAttribIndex];
+ const auto &currentValue = glState.getVertexAttribCurrentValue(dirtyAttribIndex);
+
+ // Record basic attrib info
+ translatedAttrib->attribute = &attribs[dirtyAttribIndex];
+ translatedAttrib->binding = &bindings[translatedAttrib->attribute->bindingIndex];
+ translatedAttrib->currentValueType = currentValue.Type;
+ translatedAttrib->divisor =
+ translatedAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor;
+
+ switch (mAttributeStorageTypes[dirtyAttribIndex])
+ {
+ case VertexStorageType::DIRECT:
+ VertexDataManager::StoreDirectAttrib(context, translatedAttrib);
+ break;
+ case VertexStorageType::STATIC:
+ {
+ ANGLE_TRY(VertexDataManager::StoreStaticAttrib(context, translatedAttrib));
+ break;
+ }
+ case VertexStorageType::CURRENT_VALUE:
+ // Current value attribs are managed by the StateManager11.
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ // Make sure we reset the dirty bit after the switch because STATIC can early exit.
+ mAttribsToTranslate.reset(dirtyAttribIndex);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result VertexArray11::updateDynamicAttribs(const gl::Context *context,
+ VertexDataManager *vertexDataManager,
+ GLint firstVertex,
+ GLsizei vertexOrIndexCount,
+ gl::DrawElementsType indexTypeOrInvalid,
+ const void *indices,
+ GLsizei instances,
+ GLint baseVertex,
+ GLuint baseInstance,
+ bool promoteDynamic,
+ const gl::AttributesMask &activeDynamicAttribs)
+{
+ const auto &glState = context->getState();
+ const auto &attribs = mState.getVertexAttributes();
+ const auto &bindings = mState.getVertexBindings();
+
+ GLint startVertex;
+ size_t vertexCount;
+ ANGLE_TRY(GetVertexRangeInfo(context, firstVertex, vertexOrIndexCount, indexTypeOrInvalid,
+ indices, baseVertex, &startVertex, &vertexCount));
+
+ for (size_t dynamicAttribIndex : activeDynamicAttribs)
+ {
+ auto *dynamicAttrib = &mTranslatedAttribs[dynamicAttribIndex];
+ const auto &currentValue = glState.getVertexAttribCurrentValue(dynamicAttribIndex);
+
+ // Record basic attrib info
+ dynamicAttrib->attribute = &attribs[dynamicAttribIndex];
+ dynamicAttrib->binding = &bindings[dynamicAttrib->attribute->bindingIndex];
+ dynamicAttrib->currentValueType = currentValue.Type;
+ dynamicAttrib->divisor = dynamicAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor;
+ }
+
+ ANGLE_TRY(vertexDataManager->storeDynamicAttribs(context, &mTranslatedAttribs,
+ activeDynamicAttribs, startVertex, vertexCount,
+ instances, baseInstance));
+
+ if (promoteDynamic)
+ {
+ VertexDataManager::PromoteDynamicAttribs(context, mTranslatedAttribs, activeDynamicAttribs,
+ vertexCount);
+ }
+
+ return angle::Result::Continue;
+}
+
+const std::vector<TranslatedAttribute> &VertexArray11::getTranslatedAttribs() const
+{
+ return mTranslatedAttribs;
+}
+
+void VertexArray11::markAllAttributeDivisorsForAdjustment(int numViews)
+{
+ if (mAppliedNumViewsToDivisor != numViews)
+ {
+ mAppliedNumViewsToDivisor = numViews;
+ mAttribsToTranslate.set();
+ // mDynamicAttribsMask may have already been set (updateVertexAttribStorage
+ // We don't want to override DYNAMIC attribs as they will be handled separately.
+ mAttribsToTranslate = mAttribsToTranslate ^ mDynamicAttribsMask;
+ }
+}
+
+const TranslatedIndexData &VertexArray11::getCachedIndexInfo() const
+{
+ ASSERT(mCachedIndexInfo.valid());
+ return mCachedIndexInfo.value();
+}
+
+void VertexArray11::updateCachedIndexInfo(const TranslatedIndexData &indexInfo)
+{
+ mCachedIndexInfo = indexInfo;
+}
+
+bool VertexArray11::isCachedIndexInfoValid() const
+{
+ return mCachedIndexInfo.valid();
+}
+
+gl::DrawElementsType VertexArray11::getCachedDestinationIndexType() const
+{
+ return mCachedDestinationIndexType;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
new file mode 100644
index 0000000000..a0ac5d74f1
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
@@ -0,0 +1,112 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexArray11.h: Defines the rx::VertexArray11 class which implements rx::VertexArrayImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
+
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/renderer/VertexArrayImpl.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+class Renderer11;
+
+class VertexArray11 : public VertexArrayImpl
+{
+ public:
+ VertexArray11(const gl::VertexArrayState &data);
+ ~VertexArray11() override;
+ void destroy(const gl::Context *context) override;
+
+ // Does not apply any state updates - these are done in syncStateForDraw which as access to
+ // the draw call parameters.
+ angle::Result syncState(const gl::Context *context,
+ const gl::VertexArray::DirtyBits &dirtyBits,
+ gl::VertexArray::DirtyAttribBitsArray *attribBits,
+ gl::VertexArray::DirtyBindingBitsArray *bindingBits) override;
+
+ // Applied buffer pointers are updated here.
+ angle::Result syncStateForDraw(const gl::Context *context,
+ GLint firstVertex,
+ GLsizei vertexOrIndexCount,
+ gl::DrawElementsType indexTypeOrInvalid,
+ const void *indices,
+ GLsizei instances,
+ GLint baseVertex,
+ GLuint baseInstance,
+ bool promoteDynamic);
+
+ // This will check the dynamic attribs mask.
+ bool hasActiveDynamicAttrib(const gl::Context *context);
+
+ const std::vector<TranslatedAttribute> &getTranslatedAttribs() const;
+
+ Serial getCurrentStateSerial() const { return mCurrentStateSerial; }
+
+ // In case of a multi-view program change, we have to update all attributes so that the divisor
+ // is adjusted.
+ void markAllAttributeDivisorsForAdjustment(int numViews);
+
+ const TranslatedIndexData &getCachedIndexInfo() const;
+ void updateCachedIndexInfo(const TranslatedIndexData &indexInfo);
+ bool isCachedIndexInfoValid() const;
+
+ gl::DrawElementsType getCachedDestinationIndexType() const;
+
+ private:
+ void updateVertexAttribStorage(const gl::Context *context,
+ StateManager11 *stateManager,
+ size_t attribIndex);
+ angle::Result updateDirtyAttribs(const gl::Context *context,
+ const gl::AttributesMask &activeDirtyAttribs);
+ angle::Result updateDynamicAttribs(const gl::Context *context,
+ VertexDataManager *vertexDataManager,
+ GLint firstVertex,
+ GLsizei vertexOrIndexCount,
+ gl::DrawElementsType indexTypeOrInvalid,
+ const void *indices,
+ GLsizei instances,
+ GLint baseVertex,
+ GLuint baseInstance,
+ bool promoteDynamic,
+ const gl::AttributesMask &activeDynamicAttribs);
+
+ angle::Result updateElementArrayStorage(const gl::Context *context,
+ GLsizei indexCount,
+ gl::DrawElementsType indexType,
+ const void *indices,
+ bool restartEnabled);
+
+ std::vector<VertexStorageType> mAttributeStorageTypes;
+ std::vector<TranslatedAttribute> mTranslatedAttribs;
+
+ // The mask of attributes marked as dynamic.
+ gl::AttributesMask mDynamicAttribsMask;
+
+ // A set of attributes we know are dirty, and need to be re-translated.
+ gl::AttributesMask mAttribsToTranslate;
+
+ Serial mCurrentStateSerial;
+
+ // The numViews value used to adjust the divisor.
+ int mAppliedNumViewsToDivisor;
+
+ // If the index buffer needs re-streaming.
+ Optional<gl::DrawElementsType> mLastDrawElementsType;
+ Optional<const void *> mLastDrawElementsIndices;
+ Optional<bool> mLastPrimitiveRestartEnabled;
+ IndexStorageType mCurrentElementArrayStorage;
+ Optional<TranslatedIndexData> mCachedIndexInfo;
+ gl::DrawElementsType mCachedDestinationIndexType;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp
new file mode 100644
index 0000000000..9daa8f83f9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp
@@ -0,0 +1,167 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation.
+
+#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+
+VertexBuffer11::VertexBuffer11(Renderer11 *const renderer)
+ : mRenderer(renderer),
+ mBuffer(),
+ mBufferSize(0),
+ mDynamicUsage(false),
+ mMappedResourceData(nullptr)
+{}
+
+VertexBuffer11::~VertexBuffer11()
+{
+ ASSERT(mMappedResourceData == nullptr);
+}
+
+angle::Result VertexBuffer11::initialize(const gl::Context *context,
+ unsigned int size,
+ bool dynamicUsage)
+{
+ mBuffer.reset();
+ updateSerial();
+
+ if (size > 0)
+ {
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = size;
+ bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
+ bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.StructureByteStride = 0;
+
+ ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), bufferDesc, &mBuffer));
+
+ if (dynamicUsage)
+ {
+ mBuffer.setInternalName("VertexBuffer11(dynamic)");
+ }
+ else
+ {
+ mBuffer.setInternalName("VertexBuffer11(static)");
+ }
+ }
+
+ mBufferSize = size;
+ mDynamicUsage = dynamicUsage;
+
+ return angle::Result::Continue;
+}
+
+angle::Result VertexBuffer11::mapResource(const gl::Context *context)
+{
+ if (mMappedResourceData == nullptr)
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+
+ ANGLE_TRY(mRenderer->mapResource(context, mBuffer.get(), 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0,
+ &mappedResource));
+
+ mMappedResourceData = static_cast<uint8_t *>(mappedResource.pData);
+ }
+
+ return angle::Result::Continue;
+}
+
+void VertexBuffer11::hintUnmapResource()
+{
+ if (mMappedResourceData != nullptr)
+ {
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+ dxContext->Unmap(mBuffer.get(), 0);
+
+ mMappedResourceData = nullptr;
+ }
+}
+
+angle::Result VertexBuffer11::storeVertexAttributes(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ gl::VertexAttribType currentValueType,
+ GLint start,
+ size_t count,
+ GLsizei instances,
+ unsigned int offset,
+ const uint8_t *sourceData)
+{
+ ASSERT(mBuffer.valid());
+
+ int inputStride = static_cast<int>(ComputeVertexAttributeStride(attrib, binding));
+
+ // This will map the resource if it isn't already mapped.
+ ANGLE_TRY(mapResource(context));
+
+ uint8_t *output = mMappedResourceData + offset;
+
+ const uint8_t *input = sourceData;
+
+ if (instances == 0 || binding.getDivisor() == 0)
+ {
+ input += inputStride * start;
+ }
+
+ angle::FormatID vertexFormatID = gl::GetVertexFormatID(attrib, currentValueType);
+ const D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel;
+ const d3d11::VertexFormat &vertexFormatInfo =
+ d3d11::GetVertexFormatInfo(vertexFormatID, featureLevel);
+ ASSERT(vertexFormatInfo.copyFunction != nullptr);
+ vertexFormatInfo.copyFunction(input, inputStride, count, output);
+
+ return angle::Result::Continue;
+}
+
+unsigned int VertexBuffer11::getBufferSize() const
+{
+ return mBufferSize;
+}
+
+angle::Result VertexBuffer11::setBufferSize(const gl::Context *context, unsigned int size)
+{
+ if (size > mBufferSize)
+ {
+ return initialize(context, size, mDynamicUsage);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result VertexBuffer11::discard(const gl::Context *context)
+{
+ ASSERT(mBuffer.valid());
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ ANGLE_TRY(mRenderer->mapResource(context, mBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
+ &mappedResource));
+
+ mRenderer->getDeviceContext()->Unmap(mBuffer.get(), 0);
+
+ return angle::Result::Continue;
+}
+
+const d3d11::Buffer &VertexBuffer11::getBuffer() const
+{
+ return mBuffer;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h
new file mode 100644
index 0000000000..46b52cb602
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h
@@ -0,0 +1,65 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexBuffer11.h: Defines the D3D11 VertexBuffer implementation.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_
+
+#include <stdint.h>
+
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+
+namespace rx
+{
+class Renderer11;
+
+class VertexBuffer11 : public VertexBuffer
+{
+ public:
+ explicit VertexBuffer11(Renderer11 *const renderer);
+
+ angle::Result initialize(const gl::Context *context,
+ unsigned int size,
+ bool dynamicUsage) override;
+
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+ // function.
+ angle::Result storeVertexAttributes(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ gl::VertexAttribType currentValueType,
+ GLint start,
+ size_t count,
+ GLsizei instances,
+ unsigned int offset,
+ const uint8_t *sourceData) override;
+
+ unsigned int getBufferSize() const override;
+ angle::Result setBufferSize(const gl::Context *context, unsigned int size) override;
+ angle::Result discard(const gl::Context *context) override;
+
+ void hintUnmapResource() override;
+
+ const d3d11::Buffer &getBuffer() const;
+
+ private:
+ ~VertexBuffer11() override;
+ angle::Result mapResource(const gl::Context *context);
+
+ Renderer11 *const mRenderer;
+
+ d3d11::Buffer mBuffer;
+ unsigned int mBufferSize;
+ bool mDynamicUsage;
+
+ uint8_t *mMappedResourceData;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.cpp
new file mode 100644
index 0000000000..0e64f78d53
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.cpp
@@ -0,0 +1,457 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CompositorNativeWindow11.cpp: Implementation of NativeWindow11 using Windows.UI.Composition APIs
+// which work in both Win32 and WinRT contexts.
+
+#include "libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#include "common/debug.h"
+
+using namespace Microsoft::WRL;
+
+namespace rx
+{
+
+CompositorNativeWindow11::CompositorNativeWindow11(EGLNativeWindowType window, bool hasAlpha)
+ : NativeWindow11(window), mHasAlpha(hasAlpha)
+{
+ ABI::Windows::UI::Composition::ISpriteVisual *inspPtr =
+ reinterpret_cast<ABI::Windows::UI::Composition::ISpriteVisual *>(window);
+ mHostVisual = Microsoft::WRL::ComPtr<ABI::Windows::UI::Composition::ISpriteVisual>{inspPtr};
+}
+
+CompositorNativeWindow11::~CompositorNativeWindow11() = default;
+
+bool CompositorNativeWindow11::initialize()
+{
+ return true;
+}
+
+bool CompositorNativeWindow11::getClientRect(LPRECT rect) const
+{
+ ComPtr<ABI::Windows::UI::Composition::IVisual> visual;
+ mHostVisual.As(&visual);
+
+ ABI::Windows::Foundation::Numerics::Vector2 size;
+ HRESULT hr = visual->get_Size(&size);
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ ABI::Windows::Foundation::Numerics::Vector3 offset;
+ hr = visual->get_Offset(&offset);
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ rect->top = static_cast<LONG>(offset.Y);
+ rect->left = static_cast<LONG>(offset.X);
+ rect->right = static_cast<LONG>(offset.X) + static_cast<LONG>(size.X);
+ rect->bottom = static_cast<LONG>(offset.Y) + static_cast<LONG>(size.Y);
+
+ return true;
+}
+
+bool CompositorNativeWindow11::isIconic() const
+{
+ return false;
+}
+
+HRESULT CompositorNativeWindow11::createSwapChain(ID3D11Device *device,
+ IDXGIFactory *factory,
+ DXGI_FORMAT format,
+ UINT width,
+ UINT height,
+ UINT samples,
+ IDXGISwapChain **swapChain)
+{
+ if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 ||
+ height == 0)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr{E_FAIL};
+
+ ComPtr<ABI::Windows::UI::Composition::ICompositionObject> hostVisual;
+ hr = mHostVisual.As(&hostVisual);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ Microsoft::WRL::ComPtr<ABI::Windows::UI::Composition::ICompositor> compositor;
+ hr = hostVisual->get_Compositor(&compositor);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ ComPtr<ABI::Windows::UI::Composition::ICompositorInterop> interop;
+
+ hr = compositor.As(&interop);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ ComPtr<IDXGIFactory2> factory2;
+ factory2.Attach(d3d11::DynamicCastComObject<IDXGIFactory2>(factory));
+
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
+ swapChainDesc.Width = width;
+ swapChainDesc.Height = height;
+ swapChainDesc.Format = format;
+ swapChainDesc.Stereo = FALSE;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage =
+ DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_SHADER_INPUT;
+ swapChainDesc.BufferCount = 2;
+ swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ swapChainDesc.AlphaMode = mHasAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE;
+#ifndef ANGLE_ENABLE_WINDOWS_UWP
+ swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG::DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
+#endif
+ Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain1;
+ hr = factory2->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, &swapChain1);
+ if (SUCCEEDED(hr))
+ {
+ swapChain1.CopyTo(swapChain);
+ }
+
+ hr = interop->CreateCompositionSurfaceForSwapChain(swapChain1.Get(), &mSurface);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = compositor->CreateSurfaceBrushWithSurface(mSurface.Get(), &mSurfaceBrush);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = mSurfaceBrush.As(&mCompositionBrush);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = mHostVisual->put_Brush(mCompositionBrush.Get());
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ return hr;
+}
+
+void CompositorNativeWindow11::commitChange()
+{
+ // Windows::UI::Composition uses an implicit commit model hence no action needed here
+}
+
+// static
+bool CompositorNativeWindow11::IsValidNativeWindow(EGLNativeWindowType window)
+{
+ return IsSupportedWinRelease() && IsSpriteVisual(window);
+}
+
+// static
+bool CompositorNativeWindow11::IsSupportedWinRelease()
+{
+ RoHelper helper;
+ if (!helper.WinRtAvailable())
+ {
+ return false;
+ }
+
+ return helper.SupportedWindowsRelease();
+}
+
+bool CompositorNativeWindow11::IsSpriteVisual(EGLNativeWindowType window)
+{
+ RoHelper helper;
+
+ ABI::Windows::UI::Composition::ISpriteVisual *inspp =
+ reinterpret_cast<ABI::Windows::UI::Composition::ISpriteVisual *>(window);
+ HSTRING className, spriteClassName;
+ HSTRING_HEADER spriteClassNameHeader;
+
+ auto hr = helper.GetStringReference(RuntimeClass_Windows_UI_Composition_SpriteVisual,
+ &spriteClassName, &spriteClassNameHeader);
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ hr = inspp->GetRuntimeClassName(&className);
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ INT32 result = -1;
+ hr = helper.WindowsCompareStringOrdinal(className, spriteClassName, &result);
+
+ helper.WindowsDeleteString(className);
+
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ if (result == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// RoHelperImpl
+
+template <typename T>
+bool AssignProcAddress(HMODULE comBaseModule, const char *name, T *&outProc)
+{
+ outProc = reinterpret_cast<T *>(GetProcAddress(comBaseModule, name));
+ return *outProc != nullptr;
+}
+
+RoHelper::RoHelper()
+ : mFpWindowsCreateStringReference(nullptr),
+ mFpGetActivationFactory(nullptr),
+ mFpWindowsCompareStringOrdinal(nullptr),
+ mFpCreateDispatcherQueueController(nullptr),
+ mFpWindowsDeleteString(nullptr),
+ mFpRoInitialize(nullptr),
+ mFpRoUninitialize(nullptr),
+ mWinRtAvailable(false),
+ mWinRtInitialized(false),
+ mComBaseModule(nullptr),
+ mCoreMessagingModule(nullptr)
+{
+
+#ifdef ANGLE_ENABLE_WINDOWS_UWP
+ mFpWindowsCreateStringReference = &::WindowsCreateStringReference;
+ mFpRoInitialize = &::RoInitialize;
+ mFpRoUninitialize = &::RoUninitialize;
+ mFpWindowsDeleteString = &::WindowsDeleteString;
+ mFpGetActivationFactory = &::RoGetActivationFactory;
+ mFpWindowsCompareStringOrdinal = &::WindowsCompareStringOrdinal;
+ mFpCreateDispatcherQueueController = &::CreateDispatcherQueueController;
+ mWinRtAvailable = true;
+#else
+
+ mComBaseModule = LoadLibraryA("ComBase.dll");
+
+ if (mComBaseModule == nullptr)
+ {
+ return;
+ }
+
+ if (!AssignProcAddress(mComBaseModule, "WindowsCreateStringReference",
+ mFpWindowsCreateStringReference))
+ {
+ return;
+ }
+
+ if (!AssignProcAddress(mComBaseModule, "RoGetActivationFactory", mFpGetActivationFactory))
+ {
+ return;
+ }
+
+ if (!AssignProcAddress(mComBaseModule, "WindowsCompareStringOrdinal",
+ mFpWindowsCompareStringOrdinal))
+ {
+ return;
+ }
+
+ if (!AssignProcAddress(mComBaseModule, "WindowsDeleteString", mFpWindowsDeleteString))
+ {
+ return;
+ }
+
+ if (!AssignProcAddress(mComBaseModule, "RoInitialize", mFpRoInitialize))
+ {
+ return;
+ }
+
+ if (!AssignProcAddress(mComBaseModule, "RoUninitialize", mFpRoUninitialize))
+ {
+ return;
+ }
+
+ mCoreMessagingModule = LoadLibraryA("coremessaging.dll");
+
+ if (mCoreMessagingModule == nullptr)
+ {
+ return;
+ }
+
+ if (!AssignProcAddress(mCoreMessagingModule, "CreateDispatcherQueueController",
+ mFpCreateDispatcherQueueController))
+ {
+ return;
+ }
+
+ auto result = RoInitialize(RO_INIT_MULTITHREADED);
+
+ if (SUCCEEDED(result) || result == RPC_E_CHANGED_MODE)
+ {
+ mWinRtAvailable = true;
+
+ if (SUCCEEDED(result))
+ {
+ mWinRtInitialized = true;
+ }
+ }
+#endif
+}
+
+RoHelper::~RoHelper()
+{
+#ifndef ANGLE_ENABLE_WINDOWS_UWP
+ if (mWinRtInitialized)
+ {
+ RoUninitialize();
+ }
+
+ if (mCoreMessagingModule != nullptr)
+ {
+ FreeLibrary(mCoreMessagingModule);
+ mCoreMessagingModule = nullptr;
+ }
+
+ if (mComBaseModule != nullptr)
+ {
+ FreeLibrary(mComBaseModule);
+ mComBaseModule = nullptr;
+ }
+#endif
+}
+
+bool RoHelper::WinRtAvailable() const
+{
+ return mWinRtAvailable;
+}
+
+bool RoHelper::SupportedWindowsRelease()
+{
+ if (!mWinRtAvailable)
+ {
+ return false;
+ }
+
+ HSTRING className, contractName;
+ HSTRING_HEADER classNameHeader, contractNameHeader;
+ boolean isSupported = false;
+
+ HRESULT hr = GetStringReference(RuntimeClass_Windows_Foundation_Metadata_ApiInformation,
+ &className, &classNameHeader);
+
+ if (FAILED(hr))
+ {
+ return !!isSupported;
+ }
+
+ Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Metadata::IApiInformationStatics> api;
+
+ hr = GetActivationFactory(
+ className, __uuidof(ABI::Windows::Foundation::Metadata::IApiInformationStatics), &api);
+
+ if (FAILED(hr))
+ {
+ return !!isSupported;
+ }
+
+ hr = GetStringReference(L"Windows.Foundation.UniversalApiContract", &contractName,
+ &contractNameHeader);
+ if (FAILED(hr))
+ {
+ return !!isSupported;
+ }
+
+ api->IsApiContractPresentByMajor(contractName, 6, &isSupported);
+
+ return !!isSupported;
+}
+
+HRESULT RoHelper::GetStringReference(PCWSTR source, HSTRING *act, HSTRING_HEADER *header)
+{
+ if (!mWinRtAvailable)
+ {
+ return E_FAIL;
+ }
+
+ const wchar_t *str = static_cast<const wchar_t *>(source);
+
+ unsigned int length;
+ HRESULT hr = SizeTToUInt32(::wcslen(str), &length);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ return mFpWindowsCreateStringReference(source, length, header, act);
+}
+
+HRESULT RoHelper::GetActivationFactory(const HSTRING act, const IID &interfaceId, void **fac)
+{
+ if (!mWinRtAvailable)
+ {
+ return E_FAIL;
+ }
+ auto hr = mFpGetActivationFactory(act, interfaceId, fac);
+ return hr;
+}
+
+HRESULT RoHelper::WindowsCompareStringOrdinal(HSTRING one, HSTRING two, int *result)
+{
+ if (!mWinRtAvailable)
+ {
+ return E_FAIL;
+ }
+ return mFpWindowsCompareStringOrdinal(one, two, result);
+}
+
+HRESULT RoHelper::CreateDispatcherQueueController(
+ DispatcherQueueOptions options,
+ ABI::Windows::System::IDispatcherQueueController **dispatcherQueueController)
+{
+ if (!mWinRtAvailable)
+ {
+ return E_FAIL;
+ }
+ return mFpCreateDispatcherQueueController(options, dispatcherQueueController);
+}
+
+HRESULT RoHelper::WindowsDeleteString(HSTRING one)
+{
+ if (!mWinRtAvailable)
+ {
+ return E_FAIL;
+ }
+ return mFpWindowsDeleteString(one);
+}
+
+HRESULT RoHelper::RoInitialize(RO_INIT_TYPE type)
+{
+ return mFpRoInitialize(type);
+}
+
+void RoHelper::RoUninitialize()
+{
+ mFpRoUninitialize();
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h
new file mode 100644
index 0000000000..82857322e0
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h
@@ -0,0 +1,116 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CompositorNativeWindow11.h: Implementation of NativeWindow11 using Windows.UI.Composition APIs
+// which work in both Win32 and WinRT contexts.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_CONVERGED_COMPOSITORNATIVEWINDOW11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_CONVERGED_COMPOSITORNATIVEWINDOW11_H_
+
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h"
+
+#include <dispatcherqueue.h>
+#include <versionhelpers.h>
+#include <windows.foundation.metadata.h>
+#include <windows.ui.composition.h>
+#include <windows.ui.composition.interop.h>
+#include <wrl.h>
+
+namespace rx
+{
+
+class RoHelper
+{
+ public:
+ RoHelper();
+ ~RoHelper();
+ bool WinRtAvailable() const;
+ bool SupportedWindowsRelease();
+ HRESULT GetStringReference(PCWSTR source, HSTRING *act, HSTRING_HEADER *header);
+ HRESULT GetActivationFactory(const HSTRING act, const IID &interfaceId, void **fac);
+ HRESULT WindowsCompareStringOrdinal(HSTRING one, HSTRING two, int *result);
+ HRESULT CreateDispatcherQueueController(
+ DispatcherQueueOptions options,
+ ABI::Windows::System::IDispatcherQueueController **dispatcherQueueController);
+ HRESULT WindowsDeleteString(HSTRING one);
+ HRESULT RoInitialize(RO_INIT_TYPE type);
+ void RoUninitialize();
+
+ private:
+ using WindowsCreateStringReference_ = HRESULT __stdcall(PCWSTR,
+ UINT32,
+ HSTRING_HEADER *,
+ HSTRING *);
+
+ using GetActivationFactory_ = HRESULT __stdcall(HSTRING, REFIID, void **);
+
+ using WindowsCompareStringOrginal_ = HRESULT __stdcall(HSTRING, HSTRING, int *);
+
+ using WindowsDeleteString_ = HRESULT __stdcall(HSTRING);
+
+ using CreateDispatcherQueueController_ =
+ HRESULT __stdcall(DispatcherQueueOptions,
+ ABI::Windows::System::IDispatcherQueueController **);
+
+ using RoInitialize_ = HRESULT __stdcall(RO_INIT_TYPE);
+ using RoUninitialize_ = void __stdcall();
+
+ WindowsCreateStringReference_ *mFpWindowsCreateStringReference;
+ GetActivationFactory_ *mFpGetActivationFactory;
+ WindowsCompareStringOrginal_ *mFpWindowsCompareStringOrdinal;
+ CreateDispatcherQueueController_ *mFpCreateDispatcherQueueController;
+ WindowsDeleteString_ *mFpWindowsDeleteString;
+ RoInitialize_ *mFpRoInitialize;
+ RoUninitialize_ *mFpRoUninitialize;
+
+ bool mWinRtAvailable;
+ bool mWinRtInitialized;
+
+ HMODULE mComBaseModule;
+ HMODULE mCoreMessagingModule;
+};
+
+class CompositorNativeWindow11 : public NativeWindow11
+{
+ public:
+ CompositorNativeWindow11(EGLNativeWindowType window, bool hasAlpha);
+ ~CompositorNativeWindow11() override;
+
+ bool initialize() override;
+ bool getClientRect(LPRECT rect) const override;
+ bool isIconic() const override;
+
+ HRESULT createSwapChain(ID3D11Device *device,
+ IDXGIFactory *factory,
+ DXGI_FORMAT format,
+ UINT width,
+ UINT height,
+ UINT samples,
+ IDXGISwapChain **swapChain) override;
+
+ void commitChange() override;
+
+ static bool IsValidNativeWindow(EGLNativeWindowType window);
+
+ static bool IsSupportedWinRelease();
+
+ private:
+ static bool IsSpriteVisual(EGLNativeWindowType window);
+
+ bool mHasAlpha;
+
+ RoHelper mRoHelper;
+
+ // Namespace prefix required here for some reason despite using namespace
+ Microsoft::WRL::ComPtr<ABI::Windows::UI::Composition::ISpriteVisual> mHostVisual;
+ Microsoft::WRL::ComPtr<ABI::Windows::UI::Composition::ICompositionBrush> mCompositionBrush;
+ Microsoft::WRL::ComPtr<ABI::Windows::UI::Composition::ICompositionSurface> mSurface;
+ Microsoft::WRL::ComPtr<ABI::Windows::UI::Composition::ICompositionSurfaceBrush> mSurfaceBrush;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_CONVERGED_COMPOSITORNATIVEWINDOW11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp
new file mode 100644
index 0000000000..75ddbd9ea1
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp
@@ -0,0 +1,1029 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// formatutils11.cpp: Queries for GL image formats and their translations to D3D11
+// formats.
+
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/copyvertex.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/dxgi_support_table.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+bool SupportsMipGen(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel)
+{
+ const auto &support = GetDXGISupport(dxgiFormat, featureLevel);
+ ASSERT((support.optionallySupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) == 0);
+ return ((support.alwaysSupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) != 0);
+}
+
+DXGIFormatSize::DXGIFormatSize(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight)
+ : pixelBytes(pixelBits / 8), blockWidth(blockWidth), blockHeight(blockHeight)
+{}
+
+const DXGIFormatSize &GetDXGIFormatSizeInfo(DXGI_FORMAT format)
+{
+ static const DXGIFormatSize sizeUnknown(0, 0, 0);
+ static const DXGIFormatSize size128(128, 1, 1);
+ static const DXGIFormatSize size96(96, 1, 1);
+ static const DXGIFormatSize size64(64, 1, 1);
+ static const DXGIFormatSize size32(32, 1, 1);
+ static const DXGIFormatSize size16(16, 1, 1);
+ static const DXGIFormatSize size8(8, 1, 1);
+ static const DXGIFormatSize sizeBC1(64, 4, 4);
+ static const DXGIFormatSize sizeBC2(128, 4, 4);
+ static const DXGIFormatSize sizeBC3(128, 4, 4);
+ static const DXGIFormatSize sizeBC4(64, 4, 4);
+ static const DXGIFormatSize sizeBC5(128, 4, 4);
+ static const DXGIFormatSize sizeBC6H(128, 4, 4);
+ static const DXGIFormatSize sizeBC7(128, 4, 4);
+ switch (format)
+ {
+ case DXGI_FORMAT_UNKNOWN:
+ return sizeUnknown;
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ return size128;
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ case DXGI_FORMAT_R32G32B32_UINT:
+ case DXGI_FORMAT_R32G32B32_SINT:
+ return size96;
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ case DXGI_FORMAT_R32G32_FLOAT:
+ case DXGI_FORMAT_R32G32_UINT:
+ case DXGI_FORMAT_R32G32_SINT:
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ return size64;
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ case DXGI_FORMAT_R16G16_FLOAT:
+ case DXGI_FORMAT_R16G16_UNORM:
+ case DXGI_FORMAT_R16G16_UINT:
+ case DXGI_FORMAT_R16G16_SNORM:
+ case DXGI_FORMAT_R16G16_SINT:
+ case DXGI_FORMAT_R32_TYPELESS:
+ case DXGI_FORMAT_D32_FLOAT:
+ case DXGI_FORMAT_R32_FLOAT:
+ case DXGI_FORMAT_R32_UINT:
+ case DXGI_FORMAT_R32_SINT:
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ return size32;
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ case DXGI_FORMAT_R8G8_UNORM:
+ case DXGI_FORMAT_R8G8_UINT:
+ case DXGI_FORMAT_R8G8_SNORM:
+ case DXGI_FORMAT_R8G8_SINT:
+ case DXGI_FORMAT_R16_TYPELESS:
+ case DXGI_FORMAT_R16_FLOAT:
+ case DXGI_FORMAT_D16_UNORM:
+ case DXGI_FORMAT_R16_UNORM:
+ case DXGI_FORMAT_R16_UINT:
+ case DXGI_FORMAT_R16_SNORM:
+ case DXGI_FORMAT_R16_SINT:
+ return size16;
+ case DXGI_FORMAT_R8_TYPELESS:
+ case DXGI_FORMAT_R8_UNORM:
+ case DXGI_FORMAT_R8_UINT:
+ case DXGI_FORMAT_R8_SNORM:
+ case DXGI_FORMAT_R8_SINT:
+ case DXGI_FORMAT_A8_UNORM:
+ return size8;
+ case DXGI_FORMAT_R1_UNORM:
+ UNREACHABLE();
+ return sizeUnknown;
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ return size32;
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ return sizeBC1;
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ return sizeBC2;
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ return sizeBC3;
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ case DXGI_FORMAT_BC4_SNORM:
+ return sizeBC4;
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ case DXGI_FORMAT_BC5_SNORM:
+ return sizeBC5;
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ return size16;
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ return size32;
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ case DXGI_FORMAT_BC6H_SF16:
+ return sizeBC6H;
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ return sizeBC7;
+ case DXGI_FORMAT_AYUV:
+ case DXGI_FORMAT_Y410:
+ case DXGI_FORMAT_Y416:
+ case DXGI_FORMAT_NV12:
+ case DXGI_FORMAT_P010:
+ case DXGI_FORMAT_P016:
+ case DXGI_FORMAT_420_OPAQUE:
+ case DXGI_FORMAT_YUY2:
+ case DXGI_FORMAT_Y210:
+ case DXGI_FORMAT_Y216:
+ case DXGI_FORMAT_NV11:
+ case DXGI_FORMAT_AI44:
+ case DXGI_FORMAT_IA44:
+ case DXGI_FORMAT_P8:
+ case DXGI_FORMAT_A8P8:
+ UNREACHABLE();
+ return sizeUnknown;
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ return size16;
+ default:
+ UNREACHABLE();
+ return sizeUnknown;
+ }
+}
+
+constexpr VertexFormat::VertexFormat()
+ : conversionType(VERTEX_CONVERT_NONE), nativeFormat(DXGI_FORMAT_UNKNOWN), copyFunction(nullptr)
+{}
+
+constexpr VertexFormat::VertexFormat(VertexConversionType conversionTypeIn,
+ DXGI_FORMAT nativeFormatIn,
+ VertexCopyFunction copyFunctionIn)
+ : conversionType(conversionTypeIn), nativeFormat(nativeFormatIn), copyFunction(copyFunctionIn)
+{}
+
+const VertexFormat *GetVertexFormatInfo_FL_9_3(angle::FormatID vertexFormatID)
+{
+ // D3D11 Feature Level 9_3 doesn't support as many formats for vertex buffer resource as Feature
+ // Level 10_0+.
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/ff471324(v=vs.85).aspx
+
+ switch (vertexFormatID)
+ {
+ // GL_BYTE -- unnormalized
+ case angle::FormatID::R8_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT,
+ &Copy8SintTo16SintVertexData<1, 2>);
+ return &info;
+ }
+ case angle::FormatID::R8G8_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT,
+ &Copy8SintTo16SintVertexData<2, 2>);
+ return &info;
+ }
+ case angle::FormatID::R8G8B8_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT,
+ &Copy8SintTo16SintVertexData<3, 4>);
+ return &info;
+ }
+ case angle::FormatID::R8G8B8A8_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT,
+ &Copy8SintTo16SintVertexData<4, 4>);
+ return &info;
+ }
+
+ // GL_BYTE -- normalized
+ case angle::FormatID::R8_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM,
+ &Copy8SnormTo16SnormVertexData<1, 2>);
+ return &info;
+ }
+ case angle::FormatID::R8G8_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM,
+ &Copy8SnormTo16SnormVertexData<2, 2>);
+ return &info;
+ }
+ case angle::FormatID::R8G8B8_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM,
+ &Copy8SnormTo16SnormVertexData<3, 4>);
+ return &info;
+ }
+ case angle::FormatID::R8G8B8A8_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM,
+ &Copy8SnormTo16SnormVertexData<4, 4>);
+ return &info;
+ }
+
+ // GL_UNSIGNED_BYTE -- un-normalized
+ // NOTE: 3 and 4 component unnormalized GL_UNSIGNED_BYTE should use the default format
+ // table.
+ case angle::FormatID::R8_USCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 1, 4, 1>);
+ return &info;
+ }
+ case angle::FormatID::R8G8_USCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 2, 4, 1>);
+ return &info;
+ }
+
+ // GL_UNSIGNED_BYTE -- normalized
+ // NOTE: 3 and 4 component normalized GL_UNSIGNED_BYTE should use the default format table.
+
+ // GL_UNSIGNED_BYTE -- normalized
+ case angle::FormatID::R8_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM,
+ &CopyNativeVertexData<GLubyte, 1, 4, UINT8_MAX>);
+ return &info;
+ }
+ case angle::FormatID::R8G8_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM,
+ &CopyNativeVertexData<GLubyte, 2, 4, UINT8_MAX>);
+ return &info;
+ }
+
+ // GL_SHORT -- un-normalized
+ // NOTE: 2, 3 and 4 component unnormalized GL_SHORT should use the default format table.
+ case angle::FormatID::R16_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT,
+ &CopyNativeVertexData<GLshort, 1, 2, 0>);
+ return &info;
+ }
+
+ // GL_SHORT -- normalized
+ // NOTE: 2, 3 and 4 component normalized GL_SHORT should use the default format table.
+ case angle::FormatID::R16_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM,
+ &CopyNativeVertexData<GLshort, 1, 2, 0>);
+ return &info;
+ }
+
+ // GL_UNSIGNED_SHORT -- un-normalized
+ case angle::FormatID::R16_USCALED:
+ {
+ static constexpr VertexFormat info(
+ VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyToFloatVertexData<GLushort, 1, 2, false, false>);
+ return &info;
+ }
+ case angle::FormatID::R16G16_USCALED:
+ {
+ static constexpr VertexFormat info(
+ VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyToFloatVertexData<GLushort, 2, 2, false, false>);
+ return &info;
+ }
+ case angle::FormatID::R16G16B16_USCALED:
+ {
+ static constexpr VertexFormat info(
+ VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+ &CopyToFloatVertexData<GLushort, 3, 3, false, false>);
+ return &info;
+ }
+ case angle::FormatID::R16G16B16A16_USCALED:
+ {
+ static constexpr VertexFormat info(
+ VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyToFloatVertexData<GLushort, 4, 4, false, false>);
+ return &info;
+ }
+
+ // GL_UNSIGNED_SHORT -- normalized
+ case angle::FormatID::R16_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyToFloatVertexData<GLushort, 1, 2, true, false>);
+ return &info;
+ }
+ case angle::FormatID::R16G16_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyToFloatVertexData<GLushort, 2, 2, true, false>);
+ return &info;
+ }
+ case angle::FormatID::R16G16B16_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+ &CopyToFloatVertexData<GLushort, 3, 3, true, false>);
+ return &info;
+ }
+ case angle::FormatID::R16G16B16A16_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyToFloatVertexData<GLushort, 4, 4, true, false>);
+ return &info;
+ }
+
+ // GL_FIXED
+ // TODO: Add test to verify that this works correctly.
+ // NOTE: 2, 3 and 4 component GL_FIXED should use the default format table.
+ case angle::FormatID::R32_FIXED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &Copy32FixedTo32FVertexData<1, 2>);
+ return &info;
+ }
+
+ // GL_FLOAT
+ // TODO: Add test to verify that this works correctly.
+ // NOTE: 2, 3 and 4 component GL_FLOAT should use the default format table.
+ case angle::FormatID::R32_FLOAT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyNativeVertexData<GLfloat, 1, 2, 0>);
+ return &info;
+ }
+
+ default:
+ return nullptr;
+ }
+}
+
+const VertexFormat &GetVertexFormatInfo(angle::FormatID vertexFormatID,
+ D3D_FEATURE_LEVEL featureLevel)
+{
+ if (featureLevel == D3D_FEATURE_LEVEL_9_3)
+ {
+ const VertexFormat *result = GetVertexFormatInfo_FL_9_3(vertexFormatID);
+ if (result)
+ {
+ return *result;
+ }
+ }
+
+ switch (vertexFormatID)
+ {
+ //
+ // Float formats
+ //
+
+ // GL_BYTE -- un-normalized
+ case angle::FormatID::R8_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT,
+ &CopyNativeVertexData<GLbyte, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R8G8_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT,
+ &CopyNativeVertexData<GLbyte, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R8G8B8_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT,
+ &CopyNativeVertexData<GLbyte, 3, 4, 1>);
+ return info;
+ }
+ case angle::FormatID::R8G8B8A8_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT,
+ &CopyNativeVertexData<GLbyte, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_BYTE -- normalized
+ case angle::FormatID::R8_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM,
+ &CopyNativeVertexData<GLbyte, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R8G8_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM,
+ &CopyNativeVertexData<GLbyte, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R8G8B8_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM,
+ &CopyNativeVertexData<GLbyte, 3, 4, INT8_MAX>);
+ return info;
+ }
+ case angle::FormatID::R8G8B8A8_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM,
+ &CopyNativeVertexData<GLbyte, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_BYTE -- un-normalized
+ case angle::FormatID::R8_USCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT,
+ &CopyNativeVertexData<GLubyte, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R8G8_USCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT,
+ &CopyNativeVertexData<GLubyte, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R8G8B8_USCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 3, 4, 1>);
+ return info;
+ }
+ case angle::FormatID::R8G8B8A8_USCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_BYTE -- normalized
+ case angle::FormatID::R8_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM,
+ &CopyNativeVertexData<GLubyte, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R8G8_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM,
+ &CopyNativeVertexData<GLubyte, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R8G8B8_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM,
+ &CopyNativeVertexData<GLubyte, 3, 4, UINT8_MAX>);
+ return info;
+ }
+ case angle::FormatID::R8G8B8A8_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM,
+ &CopyNativeVertexData<GLubyte, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_SHORT -- un-normalized
+ case angle::FormatID::R16_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT,
+ &CopyNativeVertexData<GLshort, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R16G16_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT,
+ &CopyNativeVertexData<GLshort, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R16G16B16_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT,
+ &CopyNativeVertexData<GLshort, 3, 4, 1>);
+ return info;
+ }
+ case angle::FormatID::R16G16B16A16_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT,
+ &CopyNativeVertexData<GLshort, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_SHORT -- normalized
+ case angle::FormatID::R16_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM,
+ &CopyNativeVertexData<GLshort, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R16G16_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM,
+ &CopyNativeVertexData<GLshort, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R16G16B16_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM,
+ &CopyNativeVertexData<GLshort, 3, 4, INT16_MAX>);
+ return info;
+ }
+ case angle::FormatID::R16G16B16A16_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM,
+ &CopyNativeVertexData<GLshort, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_SHORT -- un-normalized
+ case angle::FormatID::R16_USCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT,
+ &CopyNativeVertexData<GLushort, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R16G16_USCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT,
+ &CopyNativeVertexData<GLushort, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R16G16B16_USCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT,
+ &CopyNativeVertexData<GLushort, 3, 4, 1>);
+ return info;
+ }
+ case angle::FormatID::R16G16B16A16_USCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT,
+ &CopyNativeVertexData<GLushort, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_SHORT -- normalized
+ case angle::FormatID::R16_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM,
+ &CopyNativeVertexData<GLushort, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R16G16_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM,
+ &CopyNativeVertexData<GLushort, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R16G16B16_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM,
+ &CopyNativeVertexData<GLushort, 3, 4, UINT16_MAX>);
+ return info;
+ }
+ case angle::FormatID::R16G16B16A16_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM,
+ &CopyNativeVertexData<GLushort, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_INT -- un-normalized
+ case angle::FormatID::R32_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT,
+ &CopyNativeVertexData<GLint, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R32G32_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT,
+ &CopyNativeVertexData<GLint, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT,
+ &CopyNativeVertexData<GLint, 3, 3, 0>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32A32_SSCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT,
+ &CopyNativeVertexData<GLint, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_INT -- normalized
+ case angle::FormatID::R32_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT,
+ &CopyToFloatVertexData<GLint, 1, 1, true, false>);
+ return info;
+ }
+ case angle::FormatID::R32G32_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyToFloatVertexData<GLint, 2, 2, true, false>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+ &CopyToFloatVertexData<GLint, 3, 3, true, false>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32A32_SNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyToFloatVertexData<GLint, 4, 4, true, false>);
+ return info;
+ }
+
+ // GL_UNSIGNED_INT -- un-normalized
+ case angle::FormatID::R32_USCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT,
+ &CopyNativeVertexData<GLuint, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R32G32_USCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT,
+ &CopyNativeVertexData<GLuint, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32_USCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT,
+ &CopyNativeVertexData<GLuint, 3, 3, 0>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32A32_USCALED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT,
+ &CopyNativeVertexData<GLuint, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_INT -- normalized
+ case angle::FormatID::R32_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT,
+ &CopyToFloatVertexData<GLuint, 1, 1, true, false>);
+ return info;
+ }
+ case angle::FormatID::R32G32_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyToFloatVertexData<GLuint, 2, 2, true, false>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+ &CopyToFloatVertexData<GLuint, 3, 3, true, false>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32A32_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyToFloatVertexData<GLuint, 4, 4, true, false>);
+ return info;
+ }
+
+ // GL_FIXED
+ case angle::FormatID::R32_FIXED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT,
+ &Copy32FixedTo32FVertexData<1, 1>);
+ return info;
+ }
+ case angle::FormatID::R32G32_FIXED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT,
+ &Copy32FixedTo32FVertexData<2, 2>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32_FIXED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT,
+ &Copy32FixedTo32FVertexData<3, 3>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32A32_FIXED:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &Copy32FixedTo32FVertexData<4, 4>);
+ return info;
+ }
+
+ // GL_HALF_FLOAT
+ case angle::FormatID::R16_FLOAT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT,
+ &CopyNativeVertexData<GLhalf, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R16G16_FLOAT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT,
+ &CopyNativeVertexData<GLhalf, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R16G16B16_FLOAT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT,
+ &CopyNativeVertexData<GLhalf, 3, 4, gl::Float16One>);
+ return info;
+ }
+ case angle::FormatID::R16G16B16A16_FLOAT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT,
+ &CopyNativeVertexData<GLhalf, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_FLOAT
+ case angle::FormatID::R32_FLOAT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT,
+ &CopyNativeVertexData<GLfloat, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R32G32_FLOAT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT,
+ &CopyNativeVertexData<GLfloat, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32_FLOAT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT,
+ &CopyNativeVertexData<GLfloat, 3, 3, 0>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32A32_FLOAT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyNativeVertexData<GLfloat, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_INT_2_10_10_10_REV
+ case angle::FormatID::R10G10B10A2_SSCALED:
+ {
+ static constexpr VertexFormat info(
+ VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyXYZ10W2ToXYZWFloatVertexData<true, false, true, false>);
+ return info;
+ }
+ case angle::FormatID::R10G10B10A2_SNORM:
+ {
+ static constexpr VertexFormat info(
+ VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyXYZ10W2ToXYZWFloatVertexData<true, true, true, false>);
+ return info;
+ }
+
+ // GL_UNSIGNED_INT_2_10_10_10_REV
+ case angle::FormatID::R10G10B10A2_USCALED:
+ {
+ static constexpr VertexFormat info(
+ VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT,
+ &CopyXYZ10W2ToXYZWFloatVertexData<false, false, true, false>);
+ return info;
+ }
+ case angle::FormatID::R10G10B10A2_UNORM:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM,
+ &CopyNativeVertexData<GLuint, 1, 1, 0>);
+ return info;
+ }
+
+ //
+ // Integer Formats
+ //
+
+ // GL_BYTE
+ case angle::FormatID::R8_SINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT,
+ &CopyNativeVertexData<GLbyte, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R8G8_SINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT,
+ &CopyNativeVertexData<GLbyte, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R8G8B8_SINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT,
+ &CopyNativeVertexData<GLbyte, 3, 4, 1>);
+ return info;
+ }
+ case angle::FormatID::R8G8B8A8_SINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT,
+ &CopyNativeVertexData<GLbyte, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_BYTE
+ case angle::FormatID::R8_UINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT,
+ &CopyNativeVertexData<GLubyte, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R8G8_UINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT,
+ &CopyNativeVertexData<GLubyte, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R8G8B8_UINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 3, 4, 1>);
+ return info;
+ }
+ case angle::FormatID::R8G8B8A8_UINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT,
+ &CopyNativeVertexData<GLubyte, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_SHORT
+ case angle::FormatID::R16_SINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT,
+ &CopyNativeVertexData<GLshort, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R16G16_SINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT,
+ &CopyNativeVertexData<GLshort, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R16G16B16_SINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT,
+ &CopyNativeVertexData<GLshort, 3, 4, 1>);
+ return info;
+ }
+ case angle::FormatID::R16G16B16A16_SINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT,
+ &CopyNativeVertexData<GLshort, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_SHORT
+ case angle::FormatID::R16_UINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT,
+ &CopyNativeVertexData<GLushort, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R16G16_UINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT,
+ &CopyNativeVertexData<GLushort, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R16G16B16_UINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT,
+ &CopyNativeVertexData<GLushort, 3, 4, 1>);
+ return info;
+ }
+ case angle::FormatID::R16G16B16A16_UINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT,
+ &CopyNativeVertexData<GLushort, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_INT
+ case angle::FormatID::R32_SINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT,
+ &CopyNativeVertexData<GLint, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R32G32_SINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT,
+ &CopyNativeVertexData<GLint, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32_SINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT,
+ &CopyNativeVertexData<GLint, 3, 3, 0>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32A32_SINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT,
+ &CopyNativeVertexData<GLint, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_UNSIGNED_INT
+ case angle::FormatID::R32_UINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT,
+ &CopyNativeVertexData<GLuint, 1, 1, 0>);
+ return info;
+ }
+ case angle::FormatID::R32G32_UINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT,
+ &CopyNativeVertexData<GLuint, 2, 2, 0>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32_UINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT,
+ &CopyNativeVertexData<GLuint, 3, 3, 0>);
+ return info;
+ }
+ case angle::FormatID::R32G32B32A32_UINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT,
+ &CopyNativeVertexData<GLuint, 4, 4, 0>);
+ return info;
+ }
+
+ // GL_INT_2_10_10_10_REV
+ case angle::FormatID::R10G10B10A2_SINT:
+ {
+ static constexpr VertexFormat info(
+ VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT,
+ &CopyXYZ10W2ToXYZWFloatVertexData<true, true, false, false>);
+ return info;
+ }
+
+ // GL_UNSIGNED_INT_2_10_10_10_REV
+ case angle::FormatID::R10G10B10A2_UINT:
+ {
+ static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT,
+ &CopyNativeVertexData<GLuint, 1, 1, 0>);
+ return info;
+ }
+
+ default:
+ {
+ static constexpr VertexFormat info;
+ return info;
+ }
+ }
+}
+
+} // namespace d3d11
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/formatutils11.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/formatutils11.h
new file mode 100644
index 0000000000..e4c3994280
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/formatutils11.h
@@ -0,0 +1,64 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// formatutils11.h: Queries for GL image formats and their translations to D3D11
+// formats.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_
+
+#include <map>
+
+#include "common/platform.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/copyvertex.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.h"
+#include "libANGLE/renderer/dxgi_format_map.h"
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace rx
+{
+struct Renderer11DeviceCaps;
+
+namespace d3d11
+{
+
+// A texture might be stored as DXGI_FORMAT_R16_TYPELESS but store integer components,
+// which are accessed through an DXGI_FORMAT_R16_SINT view. It's easy to write code which queries
+// information about the wrong format. Therefore, use of this should be avoided where possible.
+
+bool SupportsMipGen(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel);
+
+struct DXGIFormatSize
+{
+ DXGIFormatSize(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight);
+
+ GLuint pixelBytes;
+ GLuint blockWidth;
+ GLuint blockHeight;
+};
+const DXGIFormatSize &GetDXGIFormatSizeInfo(DXGI_FORMAT format);
+
+struct VertexFormat : private angle::NonCopyable
+{
+ constexpr VertexFormat();
+ constexpr VertexFormat(VertexConversionType conversionType,
+ DXGI_FORMAT nativeFormat,
+ VertexCopyFunction copyFunction);
+
+ VertexConversionType conversionType;
+ DXGI_FORMAT nativeFormat;
+ VertexCopyFunction copyFunction;
+};
+
+const VertexFormat &GetVertexFormatInfo(angle::FormatID vertexFormatID,
+ D3D_FEATURE_LEVEL featureLevel);
+} // namespace d3d11
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
new file mode 100644
index 0000000000..8cd97ee43d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -0,0 +1,2751 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// renderer11_utils.cpp: Conversion functions and other utility routines
+// specific to the D3D11 renderer.
+
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#include <versionhelpers.h>
+#include <algorithm>
+
+#include "common/debug.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/Context11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+#include "libANGLE/renderer/driver_utils.h"
+#include "libANGLE/renderer/dxgi_support_table.h"
+#include "platform/FeaturesD3D_autogen.h"
+#include "platform/PlatformMethods.h"
+
+namespace rx
+{
+
+namespace d3d11_gl
+{
+namespace
+{
+// TODO(xinghua.cao@intel.com): Get a more accurate limit.
+static D3D_FEATURE_LEVEL kMinimumFeatureLevelForES31 = D3D_FEATURE_LEVEL_11_0;
+
+// Helper functor for querying DXGI support. Saves passing the parameters repeatedly.
+class DXGISupportHelper : angle::NonCopyable
+{
+ public:
+ DXGISupportHelper(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel)
+ : mDevice(device), mFeatureLevel(featureLevel)
+ {}
+
+ bool query(DXGI_FORMAT dxgiFormat, UINT supportMask)
+ {
+ if (dxgiFormat == DXGI_FORMAT_UNKNOWN)
+ return false;
+
+ auto dxgiSupport = d3d11::GetDXGISupport(dxgiFormat, mFeatureLevel);
+
+ UINT supportedBits = dxgiSupport.alwaysSupportedFlags;
+
+ if ((dxgiSupport.optionallySupportedFlags & supportMask) != 0)
+ {
+ UINT formatSupport;
+ if (SUCCEEDED(mDevice->CheckFormatSupport(dxgiFormat, &formatSupport)))
+ {
+ supportedBits |= (formatSupport & supportMask);
+ }
+ else
+ {
+ // TODO(jmadill): find out why we fail this call sometimes in FL9_3
+ // ERR() << "Error checking format support for format 0x" << std::hex << dxgiFormat;
+ }
+ }
+
+ return ((supportedBits & supportMask) == supportMask);
+ }
+
+ private:
+ ID3D11Device *mDevice;
+ D3D_FEATURE_LEVEL mFeatureLevel;
+};
+
+gl::TextureCaps GenerateTextureFormatCaps(gl::Version maxClientVersion,
+ GLenum internalFormat,
+ ID3D11Device *device,
+ const Renderer11DeviceCaps &renderer11DeviceCaps)
+{
+ gl::TextureCaps textureCaps;
+
+ DXGISupportHelper support(device, renderer11DeviceCaps.featureLevel);
+ const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
+
+ UINT texSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D;
+ if (internalFormatInfo.depthBits == 0 && internalFormatInfo.stencilBits == 0)
+ {
+ texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURECUBE;
+ if (maxClientVersion.major > 2)
+ {
+ texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
+ }
+ }
+
+ textureCaps.texturable = support.query(formatInfo.texFormat, texSupportMask);
+ textureCaps.filterable =
+ support.query(formatInfo.srvFormat, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE);
+ textureCaps.textureAttachment =
+ (support.query(formatInfo.rtvFormat, D3D11_FORMAT_SUPPORT_RENDER_TARGET)) ||
+ (support.query(formatInfo.dsvFormat, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL));
+ textureCaps.renderbuffer = textureCaps.textureAttachment;
+ textureCaps.blendable = textureCaps.renderbuffer;
+
+ DXGI_FORMAT renderFormat = DXGI_FORMAT_UNKNOWN;
+ if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ renderFormat = formatInfo.dsvFormat;
+ }
+ else if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ renderFormat = formatInfo.rtvFormat;
+ }
+ if (renderFormat != DXGI_FORMAT_UNKNOWN &&
+ support.query(renderFormat, D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET))
+ {
+ // Assume 1x
+ textureCaps.sampleCounts.insert(1);
+
+ for (unsigned int sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT;
+ sampleCount *= 2)
+ {
+ UINT qualityCount = 0;
+ if (SUCCEEDED(device->CheckMultisampleQualityLevels(renderFormat, sampleCount,
+ &qualityCount)))
+ {
+ // Assume we always support lower sample counts
+ if (qualityCount == 0)
+ {
+ break;
+ }
+ textureCaps.sampleCounts.insert(sampleCount);
+ }
+ }
+ }
+
+ return textureCaps;
+}
+
+bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
+
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return false;
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_MAX_MAXANISOTROPY;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_MAX_MAXANISOTROPY;
+
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ return 16;
+
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
+
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
+ // ID3D11Device::CreateQuery
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ return true;
+ case D3D_FEATURE_LEVEL_9_1:
+ return false;
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
+{
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
+ // ID3D11Device::CreateQuery
+
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return true;
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
+ // ID3D11Device::CreateInputLayout
+
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
+
+ // Feature Level 9_3 supports instancing, but slot 0 in the input layout must not be
+ // instanced.
+ // D3D9 has a similar restriction, where stream 0 must not be instanced.
+ // This restriction can be worked around by remapping any non-instanced slot to slot
+ // 0.
+ // This works because HLSL uses shader semantics to match the vertex inputs to the
+ // elements in the input layout, rather than the slots.
+ // Note that we only support instancing via ANGLE_instanced_array on 9_3, since 9_3
+ // doesn't support OpenGL ES 3.0
+ case D3D_FEATURE_LEVEL_9_3:
+ return true;
+
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return false;
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return false;
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return false;
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that
+ // shader model
+ // ps_2_x is required for the ddx (and other derivative functions).
+
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that
+ // feature level
+ // 9.3 supports shader model ps_2_x.
+
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ case D3D_FEATURE_LEVEL_9_3:
+ return true;
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return false;
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return true;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return false;
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+int GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel)
+{
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx
+ // ID3D11Device::CreateInputLayout
+
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT;
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_TEXTURECUBE_DIMENSION;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_REQ_TEXTURECUBE_DIMENSION;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION;
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_VIEWPORT_BOUNDS_MAX;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_VIEWPORT_BOUNDS_MAX;
+
+ // No constants for D3D11 Feature Level 9 viewport size limits, use the maximum
+ // texture sizes
+ case D3D_FEATURE_LEVEL_9_3:
+ return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel)
+{
+ // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since
+ // that's what's
+ // returned from glGetInteger
+ static_assert(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32,
+ "Unexpected D3D11 constant value.");
+ static_assert(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32,
+ "Unexpected D3D11 constant value.");
+
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return std::numeric_limits<GLint>::max();
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT;
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel)
+{
+ // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since
+ // that's what's
+ // returned from glGetInteger
+ static_assert(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
+ static_assert(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
+
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return std::numeric_limits<GLint>::max();
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT;
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_STANDARD_VERTEX_ELEMENT_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT;
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_STANDARD_VERTEX_ELEMENT_COUNT;
+
+ // From http://http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
+ // "Max Input Slots"
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 16;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
+ // ID3D11DeviceContext::VSSetConstantBuffers
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 255 - d3d11_gl::GetReservedVertexUniformVectors(featureLevel);
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
+ d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
+ d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
+
+ // Uniform blocks not supported on D3D11 Feature Level 9
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+ // According to The OpenGL ES Shading Language specifications
+ // (Language Version 1.00 section 10.16, Language Version 3.10 section 12.21)
+ // built-in special variables (e.g. gl_FragCoord, or gl_PointCoord)
+ // which are statically used in the shader should be included in the variable packing
+ // algorithm.
+ // Therefore, we should not reserve output vectors for them.
+
+ switch (featureLevel)
+ {
+ // We must reserve one output vector for dx_Position.
+ // We also reserve one for gl_Position, which we unconditionally output on Feature
+ // Levels 10_0+,
+ // even if it's unused in the shader (e.g. for transform feedback). TODO: This could
+ // be improved.
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return 2;
+
+ // Just reserve dx_Position on Feature Level 9, since we don't ever need to output
+ // gl_Position.
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 1;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+ static_assert(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT,
+ "Unexpected D3D11 constant value.");
+
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+
+ case D3D_FEATURE_LEVEL_10_1:
+ return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+
+ // Use Shader Model 2.X limits
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 8 - GetReservedVertexOutputVectors(featureLevel);
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT;
+
+ // Vertex textures not supported on D3D11 Feature Level 9 according to
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
+ // ID3D11DeviceContext::VSSetSamplers and ID3D11DeviceContext::VSSetShaderResources
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+ // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return 1024; // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
+ // ID3D11DeviceContext::PSSetConstantBuffers
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 32 - d3d11_gl::GetReservedFragmentUniformVectors(featureLevel);
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
+ d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
+ d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
+
+ // Uniform blocks not supported on D3D11 Feature Level 9
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+
+ // Use Shader Model 2.X limits
+ case D3D_FEATURE_LEVEL_9_3:
+ return 8 - GetReservedVertexOutputVectors(featureLevel);
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 8 - GetReservedVertexOutputVectors(featureLevel);
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT;
+
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
+ // ID3D11DeviceContext::PSSetShaderResources
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 16;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+std::array<GLint, 3> GetMaxComputeWorkGroupCount(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return {{D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION,
+ D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION,
+ D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION}};
+ default:
+ return {{0, 0, 0}};
+ }
+}
+
+std::array<GLint, 3> GetMaxComputeWorkGroupSize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return {{D3D11_CS_THREAD_GROUP_MAX_X, D3D11_CS_THREAD_GROUP_MAX_Y,
+ D3D11_CS_THREAD_GROUP_MAX_Z}};
+ default:
+ return {{0, 0, 0}};
+ }
+}
+
+int GetMaxComputeWorkGroupInvocations(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP;
+ default:
+ return 0;
+ }
+}
+
+int GetMaxComputeSharedMemorySize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ // In D3D11 the maximum total size of all variables with the groupshared storage class is
+ // 32kb.
+ // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx-graphics-hlsl-variable-syntax
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return 32768;
+ default:
+ return 0;
+ }
+}
+
+int GetMaximumComputeUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+ default:
+ return 0;
+ }
+}
+
+int GetMaximumComputeUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -
+ d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT;
+ default:
+ return 0;
+ }
+}
+
+int GetMaximumComputeTextureUnits(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
+ default:
+ return 0;
+ }
+}
+
+void SetUAVRelatedResourceLimits(D3D_FEATURE_LEVEL featureLevel, gl::Caps *caps)
+{
+ ASSERT(caps);
+
+ GLuint reservedUAVsForAtomicCounterBuffers = 0u;
+
+ // For pixel shaders, the render targets and unordered access views share the same resource
+ // slots when being written out.
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/ff476465(v=vs.85).aspx
+ GLuint maxNumRTVsAndUAVs = 0u;
+
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ // Currently we allocate 4 UAV slots for atomic counter buffers on feature level 11_1.
+ reservedUAVsForAtomicCounterBuffers = 4u;
+ maxNumRTVsAndUAVs = D3D11_1_UAV_SLOT_COUNT;
+ break;
+ case D3D_FEATURE_LEVEL_11_0:
+ // Currently we allocate 1 UAV slot for atomic counter buffers on feature level 11_0.
+ reservedUAVsForAtomicCounterBuffers = 1u;
+ maxNumRTVsAndUAVs = D3D11_PS_CS_UAV_REGISTER_COUNT;
+ break;
+ default:
+ return;
+ }
+
+ // Set limits on atomic counter buffers in fragment shaders and compute shaders.
+ caps->maxCombinedAtomicCounterBuffers = reservedUAVsForAtomicCounterBuffers;
+ caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Compute] =
+ reservedUAVsForAtomicCounterBuffers;
+ caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Fragment] =
+ reservedUAVsForAtomicCounterBuffers;
+ caps->maxAtomicCounterBufferBindings = reservedUAVsForAtomicCounterBuffers;
+
+ // Setting MAX_COMPUTE_ATOMIC_COUNTERS to a conservative number of 1024 * the number of UAV
+ // reserved for atomic counters. It could theoretically be set to max buffer size / 4 but that
+ // number could cause problems.
+ caps->maxCombinedAtomicCounters = reservedUAVsForAtomicCounterBuffers * 1024;
+ caps->maxShaderAtomicCounters[gl::ShaderType::Compute] = caps->maxCombinedAtomicCounters;
+
+ // See
+ // https://docs.microsoft.com/en-us/windows/desktop/direct3d11/overviews-direct3d-11-resources-limits
+ // Resource size (in MB) for any of the preceding resources is min(max(128,0.25f * (amount of
+ // dedicated VRAM)), 2048) MB. So we set it to 128MB to keep same with GL backend.
+ caps->maxShaderStorageBlockSize =
+ D3D11_REQ_RESOURCE_SIZE_IN_MEGABYTES_EXPRESSION_A_TERM * 1024 * 1024;
+
+ // Allocate the remaining slots for images and shader storage blocks.
+ // The maximum number of fragment shader outputs depends on the current context version, so we
+ // will not set it here. See comments in Context11::initialize().
+ caps->maxCombinedShaderOutputResources =
+ maxNumRTVsAndUAVs - reservedUAVsForAtomicCounterBuffers;
+
+ // Set limits on images and shader storage blocks in fragment shaders and compute shaders.
+ caps->maxCombinedShaderStorageBlocks = caps->maxCombinedShaderOutputResources;
+ caps->maxShaderStorageBlocks[gl::ShaderType::Compute] = caps->maxCombinedShaderOutputResources;
+ caps->maxShaderStorageBlocks[gl::ShaderType::Fragment] = caps->maxCombinedShaderOutputResources;
+ caps->maxShaderStorageBufferBindings = caps->maxCombinedShaderOutputResources;
+
+ caps->maxImageUnits = caps->maxCombinedShaderOutputResources;
+ caps->maxCombinedImageUniforms = caps->maxCombinedShaderOutputResources;
+ caps->maxShaderImageUniforms[gl::ShaderType::Compute] = caps->maxCombinedShaderOutputResources;
+ caps->maxShaderImageUniforms[gl::ShaderType::Fragment] = caps->maxCombinedShaderOutputResources;
+
+ // On feature level 11_1, UAVs are also available in vertex shaders and geometry shaders.
+ if (featureLevel == D3D_FEATURE_LEVEL_11_1)
+ {
+ caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Vertex] =
+ caps->maxCombinedAtomicCounterBuffers;
+ caps->maxShaderAtomicCounterBuffers[gl::ShaderType::Geometry] =
+ caps->maxCombinedAtomicCounterBuffers;
+
+ caps->maxShaderImageUniforms[gl::ShaderType::Vertex] =
+ caps->maxCombinedShaderOutputResources;
+ caps->maxShaderStorageBlocks[gl::ShaderType::Vertex] =
+ caps->maxCombinedShaderOutputResources;
+ caps->maxShaderImageUniforms[gl::ShaderType::Geometry] =
+ caps->maxCombinedShaderOutputResources;
+ caps->maxShaderStorageBlocks[gl::ShaderType::Geometry] =
+ caps->maxCombinedShaderOutputResources;
+ }
+}
+
+int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
+
+ // Sampling functions with offsets are not available below shader model 4.0.
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
+
+ // Sampling functions with offsets are not available below shader model 4.0.
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMinimumTextureGatherOffset(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/gather4-po--sm5---asm-
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return -32;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumTextureGatherOffset(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/gather4-po--sm5---asm-
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return 31;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel)
+{
+ // Returns a size_t despite the limit being a GLuint64 because size_t is the maximum
+ // size of
+ // any buffer that could be allocated.
+
+ const size_t bytesPerComponent = 4 * sizeof(float);
+
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
+
+ // Limits from http://msdn.microsoft.com/en-us/library/windows/desktop/ff476501.aspx
+ // remarks section
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 4096 * bytesPerComponent;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_SO_BUFFER_SLOT_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1:
+ return D3D10_1_SO_BUFFER_SLOT_COUNT;
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_SO_BUFFER_SLOT_COUNT;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return GetMaximumVertexOutputVectors(featureLevel) * 4;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return GetMaximumStreamOutputInterleavedComponents(featureLevel) /
+ GetMaximumStreamOutputBuffers(featureLevel);
+
+ // D3D 10 and 10.1 only allow one output per output slot if an output slot other
+ // than zero is used.
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return 4;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+int GetMaximumRenderToBufferWindowSize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_REQ_RENDER_TO_BUFFER_WINDOW_WIDTH;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return D3D10_REQ_RENDER_TO_BUFFER_WINDOW_WIDTH;
+
+ // REQ_RENDER_TO_BUFFER_WINDOW_WIDTH not supported on D3D11 Feature Level 9,
+ // use the maximum texture sizes
+ case D3D_FEATURE_LEVEL_9_3:
+ return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+IntelDriverVersion GetIntelDriverVersion(const Optional<LARGE_INTEGER> driverVersion)
+{
+ if (!driverVersion.valid())
+ return IntelDriverVersion(0);
+
+ DWORD lowPart = driverVersion.value().LowPart;
+ return IntelDriverVersion(HIWORD(lowPart) * 10000 + LOWORD(lowPart));
+}
+
+} // anonymous namespace
+
+unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return 0;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 3; // dx_ViewAdjust, dx_ViewCoords and dx_ViewScale
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return 0;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 4; // dx_ViewCoords, dx_DepthFront, dx_DepthRange, dx_FragCoordOffset
+
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+gl::Version GetMaximumClientVersion(const Renderer11DeviceCaps &caps)
+{
+ switch (caps.featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return gl::Version(3, 1);
+ case D3D_FEATURE_LEVEL_10_1:
+ return gl::Version(3, 0);
+
+ case D3D_FEATURE_LEVEL_10_0:
+ if (caps.allowES3OnFL10_0)
+ {
+ return gl::Version(3, 0);
+ }
+ else
+ {
+ return gl::Version(2, 0);
+ }
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return gl::Version(2, 0);
+
+ default:
+ UNREACHABLE();
+ return gl::Version(0, 0);
+ }
+}
+
+D3D_FEATURE_LEVEL GetMinimumFeatureLevelForES31()
+{
+ return kMinimumFeatureLevelForES31;
+}
+
+unsigned int GetMaxViewportAndScissorRectanglesPerPipeline(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 1;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+bool IsMultiviewSupported(D3D_FEATURE_LEVEL featureLevel)
+{
+ // The ANGLE_multiview extension can always be supported in D3D11 through geometry shaders.
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return true;
+ default:
+ return false;
+ }
+}
+
+int GetMaxSampleMaskWords(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ // D3D10+ only allows 1 sample mask.
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+ return 1;
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1:
+ return 0;
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+bool HasTextureBufferSupport(ID3D11Device *device, const Renderer11DeviceCaps &renderer11DeviceCaps)
+{
+ if (renderer11DeviceCaps.featureLevel < D3D_FEATURE_LEVEL_11_0)
+ return false;
+
+ if (!renderer11DeviceCaps.supportsTypedUAVLoadAdditionalFormats)
+ return false;
+
+ // https://docs.microsoft.com/en-us/windows/win32/direct3d12/typed-unordered-access-view-loads
+ // we don't need to check the typed store. from the spec,
+ // https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#FormatList
+ // all the following format support typed stored.
+ // According to spec,
+ // https://www.khronos.org/registry/OpenGL-Refpages/es3/html/glBindImageTexture.xhtml the
+ // required image unit format are GL_RGBA32F, GL_RGBA32UI, GL_RGBA32I, GL_RGBA16F, GL_RGBA16UI,
+ // GL_RGBA16I, GL_RGBA8, GL_RGBAUI, GL_RGBA8I, GL_RGBA8_SNORM, GL_R32F, GL_R32UI, GL_R32I,
+ const std::array<DXGI_FORMAT, 2> &optionalFormats = {
+ DXGI_FORMAT_R32G32B32A32_FLOAT, // test for GL_RGBA32(UIF), GL_RGBA16(UIF),
+ // GL_RGBA8(UIUnorm)
+ DXGI_FORMAT_R8G8B8A8_SNORM, // test for GL_RGBA8_SNORM,
+ };
+
+ for (DXGI_FORMAT dxgiFormat : optionalFormats)
+ {
+ D3D11_FEATURE_DATA_FORMAT_SUPPORT FormatSupport = {dxgiFormat, 0};
+ if (!SUCCEEDED(device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT, &FormatSupport,
+ sizeof(FormatSupport))))
+ {
+ WARN() << "Error checking typed load support for format 0x" << std::hex << dxgiFormat;
+ return false;
+ }
+ if ((FormatSupport.OutFormatSupport & D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD) == 0)
+ return false;
+ }
+ return true;
+}
+
+void GenerateCaps(ID3D11Device *device,
+ ID3D11DeviceContext *deviceContext,
+ const Renderer11DeviceCaps &renderer11DeviceCaps,
+ const angle::FeaturesD3D &features,
+ const char *description,
+ gl::Caps *caps,
+ gl::TextureCapsMap *textureCapsMap,
+ gl::Extensions *extensions,
+ gl::Limitations *limitations)
+{
+ D3D_FEATURE_LEVEL featureLevel = renderer11DeviceCaps.featureLevel;
+ const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
+ for (GLenum internalFormat : allFormats)
+ {
+ gl::TextureCaps textureCaps =
+ GenerateTextureFormatCaps(GetMaximumClientVersion(renderer11DeviceCaps), internalFormat,
+ device, renderer11DeviceCaps);
+ textureCapsMap->insert(internalFormat, textureCaps);
+ }
+
+ // GL core feature limits
+ // Reserve MAX_UINT for D3D11's primitive restart.
+ caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max() - 1);
+ caps->max3DTextureSize = GetMaximum3DTextureSize(featureLevel);
+ caps->max2DTextureSize = GetMaximum2DTextureSize(featureLevel);
+ caps->maxCubeMapTextureSize = GetMaximumCubeMapTextureSize(featureLevel);
+ caps->maxArrayTextureLayers = GetMaximum2DTextureArraySize(featureLevel);
+
+ // Unimplemented, set to minimum required
+ caps->maxLODBias = 2.0f;
+
+ // No specific limits on render target size, maximum 2D texture size is equivalent
+ caps->maxRenderbufferSize = caps->max2DTextureSize;
+
+ // Maximum draw buffers and color attachments are the same, max color attachments could
+ // eventually be increased to 16
+ caps->maxDrawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel);
+ caps->maxColorAttachments = GetMaximumSimultaneousRenderTargets(featureLevel);
+
+ // D3D11 has the same limit for viewport width and height
+ caps->maxViewportWidth = GetMaximumViewportSize(featureLevel);
+ caps->maxViewportHeight = caps->maxViewportWidth;
+
+ // Choose a reasonable maximum, enforced in the shader.
+ caps->minAliasedPointSize = 1.0f;
+ caps->maxAliasedPointSize = 1024.0f;
+
+ // Wide lines not supported
+ caps->minAliasedLineWidth = 1.0f;
+ caps->maxAliasedLineWidth = 1.0f;
+
+ // Primitive count limits
+ caps->maxElementsIndices = GetMaximumDrawIndexedIndexCount(featureLevel);
+ caps->maxElementsVertices = GetMaximumDrawVertexCount(featureLevel);
+
+ // Program and shader binary formats (no supported shader binary formats)
+ caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
+
+ caps->vertexHighpFloat.setIEEEFloat();
+ caps->vertexMediumpFloat.setIEEEFloat();
+ caps->vertexLowpFloat.setIEEEFloat();
+ caps->fragmentHighpFloat.setIEEEFloat();
+ caps->fragmentMediumpFloat.setIEEEFloat();
+ caps->fragmentLowpFloat.setIEEEFloat();
+
+ // 32-bit integers are natively supported
+ caps->vertexHighpInt.setTwosComplementInt(32);
+ caps->vertexMediumpInt.setTwosComplementInt(32);
+ caps->vertexLowpInt.setTwosComplementInt(32);
+ caps->fragmentHighpInt.setTwosComplementInt(32);
+ caps->fragmentMediumpInt.setTwosComplementInt(32);
+ caps->fragmentLowpInt.setTwosComplementInt(32);
+
+ // We do not wait for server fence objects internally, so report a max timeout of zero.
+ caps->maxServerWaitTimeout = 0;
+
+ // Vertex shader limits
+ caps->maxVertexAttributes = GetMaximumVertexInputSlots(featureLevel);
+ caps->maxVertexUniformVectors = GetMaximumVertexUniformVectors(featureLevel);
+ if (features.skipVSConstantRegisterZero.enabled)
+ {
+ caps->maxVertexUniformVectors -= 1;
+ }
+ caps->maxShaderUniformComponents[gl::ShaderType::Vertex] = caps->maxVertexUniformVectors * 4;
+ caps->maxShaderUniformBlocks[gl::ShaderType::Vertex] =
+ GetMaximumVertexUniformBlocks(featureLevel);
+ caps->maxVertexOutputComponents = GetMaximumVertexOutputVectors(featureLevel) * 4;
+ caps->maxShaderTextureImageUnits[gl::ShaderType::Vertex] =
+ GetMaximumVertexTextureUnits(featureLevel);
+
+ // Vertex Attribute Bindings are emulated on D3D11.
+ caps->maxVertexAttribBindings = caps->maxVertexAttributes;
+ // Experimental testing confirmed there is no explicit limit on maximum buffer offset in D3D11.
+ caps->maxVertexAttribRelativeOffset = std::numeric_limits<GLint>::max();
+ // Experimental testing confirmed 2048 is the maximum stride that D3D11 can support on all
+ // platforms.
+ caps->maxVertexAttribStride = 2048;
+
+ // Fragment shader limits
+ caps->maxFragmentUniformVectors = GetMaximumPixelUniformVectors(featureLevel);
+ caps->maxShaderUniformComponents[gl::ShaderType::Fragment] =
+ caps->maxFragmentUniformVectors * 4;
+ caps->maxShaderUniformBlocks[gl::ShaderType::Fragment] =
+ GetMaximumPixelUniformBlocks(featureLevel);
+ caps->maxFragmentInputComponents = GetMaximumPixelInputVectors(featureLevel) * 4;
+ caps->maxShaderTextureImageUnits[gl::ShaderType::Fragment] =
+ GetMaximumPixelTextureUnits(featureLevel);
+ caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel);
+ caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel);
+
+ // Compute shader limits
+ caps->maxComputeWorkGroupCount = GetMaxComputeWorkGroupCount(featureLevel);
+ caps->maxComputeWorkGroupSize = GetMaxComputeWorkGroupSize(featureLevel);
+ caps->maxComputeWorkGroupInvocations = GetMaxComputeWorkGroupInvocations(featureLevel);
+ caps->maxComputeSharedMemorySize = GetMaxComputeSharedMemorySize(featureLevel);
+ caps->maxShaderUniformComponents[gl::ShaderType::Compute] =
+ GetMaximumComputeUniformVectors(featureLevel) * 4;
+ caps->maxShaderUniformBlocks[gl::ShaderType::Compute] =
+ GetMaximumComputeUniformBlocks(featureLevel);
+ caps->maxShaderTextureImageUnits[gl::ShaderType::Compute] =
+ GetMaximumComputeTextureUnits(featureLevel);
+
+ SetUAVRelatedResourceLimits(featureLevel, caps);
+
+ // Aggregate shader limits
+ caps->maxUniformBufferBindings = caps->maxShaderUniformBlocks[gl::ShaderType::Vertex] +
+ caps->maxShaderUniformBlocks[gl::ShaderType::Fragment];
+ caps->maxUniformBlockSize = static_cast<GLuint64>(GetMaximumConstantBufferSize(featureLevel));
+
+ // TODO(oetuaho): Get a more accurate limit. For now using the minimum requirement for GLES 3.1.
+ caps->maxUniformLocations = 1024;
+
+ // With DirectX 11.1, constant buffer offset and size must be a multiple of 16 constants of 16
+ // bytes each.
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx
+ // With DirectX 11.0, we emulate UBO offsets using copies of ranges of the UBO however
+ // we still keep the same alignment as 11.1 for consistency.
+ caps->uniformBufferOffsetAlignment = 256;
+
+ caps->maxCombinedUniformBlocks = caps->maxShaderUniformBlocks[gl::ShaderType::Vertex] +
+ caps->maxShaderUniformBlocks[gl::ShaderType::Fragment];
+
+ // A shader storage block will be translated to a structure in HLSL. So We reference the HLSL
+ // structure packing rules
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx. The
+ // resulting size of any structure will always be evenly divisible by sizeof(four-component
+ // vector).
+ caps->shaderStorageBufferOffsetAlignment = 16;
+
+ for (gl::ShaderType shaderType : gl::AllShaderTypes())
+ {
+ caps->maxCombinedShaderUniformComponents[shaderType] =
+ static_cast<GLint64>(caps->maxShaderUniformBlocks[shaderType]) *
+ static_cast<GLint64>(caps->maxUniformBlockSize / 4) +
+ static_cast<GLint64>(caps->maxShaderUniformComponents[shaderType]);
+ }
+
+ caps->maxVaryingComponents = GetMaximumVertexOutputVectors(featureLevel) * 4;
+ caps->maxVaryingVectors = GetMaximumVertexOutputVectors(featureLevel);
+ caps->maxCombinedTextureImageUnits = caps->maxShaderTextureImageUnits[gl::ShaderType::Vertex] +
+ caps->maxShaderTextureImageUnits[gl::ShaderType::Fragment];
+
+ // Transform feedback limits
+ caps->maxTransformFeedbackInterleavedComponents =
+ GetMaximumStreamOutputInterleavedComponents(featureLevel);
+ caps->maxTransformFeedbackSeparateAttributes = GetMaximumStreamOutputBuffers(featureLevel);
+ caps->maxTransformFeedbackSeparateComponents =
+ GetMaximumStreamOutputSeparateComponents(featureLevel);
+
+ // Defer the computation of multisample limits to Context::updateCaps() where max*Samples values
+ // are determined according to available sample counts for each individual format.
+ caps->maxSamples = std::numeric_limits<GLint>::max();
+ caps->maxColorTextureSamples = std::numeric_limits<GLint>::max();
+ caps->maxDepthTextureSamples = std::numeric_limits<GLint>::max();
+ caps->maxIntegerSamples = std::numeric_limits<GLint>::max();
+
+ // Sample mask words limits
+ caps->maxSampleMaskWords = GetMaxSampleMaskWords(featureLevel);
+
+ // Framebuffer limits
+ caps->maxFramebufferSamples = std::numeric_limits<GLint>::max();
+ caps->maxFramebufferWidth = GetMaximumRenderToBufferWindowSize(featureLevel);
+ caps->maxFramebufferHeight = caps->maxFramebufferWidth;
+
+ // Texture gather offset limits
+ caps->minProgramTextureGatherOffset = GetMinimumTextureGatherOffset(featureLevel);
+ caps->maxProgramTextureGatherOffset = GetMaximumTextureGatherOffset(featureLevel);
+
+ caps->maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel);
+ caps->queryCounterBitsTimeElapsed = 64;
+ caps->queryCounterBitsTimestamp = 0; // Timestamps cannot be supported due to D3D11 limitations
+ caps->maxDualSourceDrawBuffers = 1;
+
+ // GL extension support
+ extensions->setTextureExtensionSupport(*textureCapsMap);
+
+ // Explicitly disable GL_OES_compressed_ETC1_RGB8_texture because it's emulated and never
+ // becomes core. WebGL doesn't want to expose it unless there is native support.
+ extensions->compressedETC1RGB8TextureOES = false;
+ extensions->compressedETC1RGB8SubTextureEXT = false;
+
+ extensions->elementIndexUintOES = true;
+ extensions->getProgramBinaryOES = true;
+ extensions->rgb8Rgba8OES = true;
+ extensions->readFormatBgraEXT = true;
+ extensions->pixelBufferObjectNV = true;
+ extensions->mapbufferOES = true;
+ extensions->mapBufferRangeEXT = true;
+ extensions->textureNpotOES = GetNPOTTextureSupport(featureLevel);
+ extensions->drawBuffersEXT = GetMaximumSimultaneousRenderTargets(featureLevel) > 1;
+ extensions->drawBuffersIndexedEXT =
+ (renderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_1);
+ extensions->drawBuffersIndexedOES = extensions->drawBuffersIndexedEXT;
+ extensions->textureStorageEXT = true;
+ extensions->textureFilterAnisotropicEXT = true;
+ extensions->occlusionQueryBooleanEXT = GetOcclusionQuerySupport(featureLevel);
+ extensions->fenceNV = GetEventQuerySupport(featureLevel);
+ extensions->disjointTimerQueryEXT = true;
+ extensions->robustnessEXT = true;
+ // Direct3D guarantees to return zero for any resource that is accessed out of bounds.
+ // See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476332(v=vs.85).aspx
+ // and https://msdn.microsoft.com/en-us/library/windows/desktop/ff476900(v=vs.85).aspx
+ extensions->robustBufferAccessBehaviorKHR = true;
+ extensions->blendMinmaxEXT = true;
+ // https://docs.microsoft.com/en-us/windows/desktop/direct3ddxgi/format-support-for-direct3d-11-0-feature-level-hardware
+ extensions->floatBlendEXT = true;
+ extensions->framebufferBlitANGLE = GetFramebufferBlitSupport(featureLevel);
+ extensions->framebufferBlitNV = extensions->framebufferBlitANGLE;
+ extensions->framebufferMultisampleANGLE = GetFramebufferMultisampleSupport(featureLevel);
+ extensions->instancedArraysANGLE = GetInstancingSupport(featureLevel);
+ extensions->instancedArraysEXT = GetInstancingSupport(featureLevel);
+ extensions->packReverseRowOrderANGLE = true;
+ extensions->standardDerivativesOES = GetDerivativeInstructionSupport(featureLevel);
+ extensions->shaderTextureLodEXT = GetShaderTextureLODSupport(featureLevel);
+ extensions->fragDepthEXT = true;
+ extensions->multiviewOVR = IsMultiviewSupported(featureLevel);
+ extensions->multiview2OVR = IsMultiviewSupported(featureLevel);
+ if (extensions->multiviewOVR || extensions->multiview2OVR)
+ {
+ caps->maxViews = std::min(static_cast<GLuint>(GetMaximum2DTextureArraySize(featureLevel)),
+ GetMaxViewportAndScissorRectanglesPerPipeline(featureLevel));
+ }
+ extensions->textureUsageANGLE = true; // This could be false since it has no effect in D3D11
+ extensions->discardFramebufferEXT = true;
+ extensions->translatedShaderSourceANGLE = true;
+ extensions->fboRenderMipmapOES = true;
+ extensions->debugMarkerEXT = true;
+ extensions->EGLImageOES = true;
+ extensions->EGLImageExternalOES = true;
+ extensions->EGLImageExternalWrapModesEXT = true;
+ extensions->EGLImageExternalEssl3OES = true;
+ extensions->EGLStreamConsumerExternalNV = true;
+ extensions->unpackSubimageEXT = true;
+ extensions->packSubimageNV = true;
+ extensions->lossyEtcDecodeANGLE = true;
+ extensions->syncQueryCHROMIUM = GetEventQuerySupport(featureLevel);
+ extensions->copyTextureCHROMIUM = true;
+ extensions->copyCompressedTextureCHROMIUM = true;
+ extensions->textureStorageMultisample2dArrayOES = true;
+ extensions->multiviewMultisampleANGLE =
+ ((extensions->multiviewOVR || extensions->multiview2OVR) &&
+ extensions->textureStorageMultisample2dArrayOES);
+ extensions->copyTexture3dANGLE = true;
+ extensions->textureBorderClampOES = true;
+ extensions->multiDrawIndirectEXT = true;
+ extensions->textureMultisampleANGLE = true;
+ extensions->provokingVertexANGLE = true;
+ extensions->blendFuncExtendedEXT = true;
+ // http://anglebug.com/4926
+ extensions->texture3DOES = false;
+ extensions->baseInstanceEXT = true;
+ extensions->baseVertexBaseInstanceANGLE = true;
+ extensions->baseVertexBaseInstanceShaderBuiltinANGLE = true;
+ extensions->drawElementsBaseVertexOES = true;
+ extensions->drawElementsBaseVertexEXT = true;
+ if (!strstr(description, "Adreno"))
+ {
+ extensions->multisampledRenderToTextureEXT = true;
+ }
+ extensions->videoTextureWEBGL = true;
+
+ // D3D11 cannot support reading depth texture as a luminance texture.
+ // It treats it as a red-channel-only texture.
+ extensions->depthTextureOES = false;
+
+ // readPixels on depth & stencil not working with D3D11 backend.
+ extensions->readDepthNV = false;
+ extensions->readStencilNV = false;
+ extensions->depthBufferFloat2NV = false;
+
+ // GL_EXT_clip_control
+ extensions->clipControlEXT = (renderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_9_3);
+
+ // GL_KHR_parallel_shader_compile
+ extensions->parallelShaderCompileKHR = true;
+
+ // GL_EXT_texture_buffer
+ extensions->textureBufferEXT = HasTextureBufferSupport(device, renderer11DeviceCaps);
+
+ // GL_OES_texture_buffer
+ extensions->textureBufferOES = extensions->textureBufferEXT;
+
+ // ANGLE_shader_pixel_local_storage -- fragment shader UAVs appear in D3D 11.0.
+ extensions->shaderPixelLocalStorageANGLE = (featureLevel >= D3D_FEATURE_LEVEL_11_0);
+ extensions->shaderPixelLocalStorageCoherentANGLE =
+ renderer11DeviceCaps.supportsRasterizerOrderViews;
+
+ // D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing.
+ // D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't
+ // support gl_FrontFacing.
+ limitations->noFrontFacingSupport =
+ (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
+
+ // D3D11 Feature Level 9_3 doesn't support alpha-to-coverage
+ limitations->noSampleAlphaToCoverageSupport =
+ (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
+
+ // D3D11 Feature Levels 9_3 and below do not support non-constant loop indexing and require
+ // additional
+ // pre-validation of the shader at compile time to produce a better error message.
+ limitations->shadersRequireIndexedLoopValidation =
+ (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
+
+ // D3D11 has no concept of separate masks and refs for front and back faces in the depth stencil
+ // state.
+ limitations->noSeparateStencilRefsAndMasks = true;
+
+ // D3D11 cannot support constant color and alpha blend funcs together
+ limitations->noSimultaneousConstantColorAndAlphaBlendFunc = true;
+
+ // D3D11 does not support multiple transform feedback outputs writing to the same buffer.
+ limitations->noDoubleBoundTransformFeedbackBuffers = true;
+
+ // D3D11 does not support vertex attribute aliasing
+ limitations->noVertexAttributeAliasing = true;
+
+ // D3D11 does not support compressed textures where the base mip level is not a multiple of 4
+ limitations->compressedBaseMipLevelMultipleOfFour = true;
+
+ if (extensions->textureBufferAny())
+ {
+ caps->maxTextureBufferSize = 1 << D3D11_REQ_BUFFER_RESOURCE_TEXEL_COUNT_2_TO_EXP;
+ // this maybe touble for RGB32 format.
+ caps->textureBufferOffsetAlignment = 16;
+ }
+
+#ifdef ANGLE_ENABLE_WINDOWS_UWP
+ // Setting a non-zero divisor on attribute zero doesn't work on certain Windows Phone 8-era
+ // devices. We should prevent developers from doing this on ALL Windows Store devices. This will
+ // maintain consistency across all Windows devices. We allow non-zero divisors on attribute zero
+ // if the Client Version >= 3, since devices affected by this issue don't support ES3+.
+ limitations->attributeZeroRequiresZeroDivisorInEXT = true;
+#endif
+}
+
+} // namespace d3d11_gl
+
+namespace gl_d3d11
+{
+
+D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha)
+{
+ D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO;
+
+ switch (glBlend)
+ {
+ case GL_ZERO:
+ d3dBlend = D3D11_BLEND_ZERO;
+ break;
+ case GL_ONE:
+ d3dBlend = D3D11_BLEND_ONE;
+ break;
+ case GL_SRC_COLOR:
+ d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR);
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR);
+ break;
+ case GL_DST_COLOR:
+ d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR);
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR);
+ break;
+ case GL_SRC_ALPHA:
+ d3dBlend = D3D11_BLEND_SRC_ALPHA;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ d3dBlend = D3D11_BLEND_INV_SRC_ALPHA;
+ break;
+ case GL_DST_ALPHA:
+ d3dBlend = D3D11_BLEND_DEST_ALPHA;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ d3dBlend = D3D11_BLEND_INV_DEST_ALPHA;
+ break;
+ case GL_CONSTANT_COLOR:
+ d3dBlend = D3D11_BLEND_BLEND_FACTOR;
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;
+ break;
+ case GL_CONSTANT_ALPHA:
+ d3dBlend = D3D11_BLEND_BLEND_FACTOR;
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT;
+ break;
+ case GL_SRC1_COLOR_EXT:
+ d3dBlend = (isAlpha ? D3D11_BLEND_SRC1_ALPHA : D3D11_BLEND_SRC1_COLOR);
+ break;
+ case GL_SRC1_ALPHA_EXT:
+ d3dBlend = D3D11_BLEND_SRC1_ALPHA;
+ break;
+ case GL_ONE_MINUS_SRC1_COLOR_EXT:
+ d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC1_ALPHA : D3D11_BLEND_INV_SRC1_COLOR);
+ break;
+ case GL_ONE_MINUS_SRC1_ALPHA_EXT:
+ d3dBlend = D3D11_BLEND_INV_SRC1_ALPHA;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return d3dBlend;
+}
+
+D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp)
+{
+ D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD;
+
+ switch (glBlendOp)
+ {
+ case GL_FUNC_ADD:
+ d3dBlendOp = D3D11_BLEND_OP_ADD;
+ break;
+ case GL_FUNC_SUBTRACT:
+ d3dBlendOp = D3D11_BLEND_OP_SUBTRACT;
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT;
+ break;
+ case GL_MIN:
+ d3dBlendOp = D3D11_BLEND_OP_MIN;
+ break;
+ case GL_MAX:
+ d3dBlendOp = D3D11_BLEND_OP_MAX;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return d3dBlendOp;
+}
+
+UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha)
+{
+ UINT8 mask = 0;
+ if (red)
+ {
+ mask |= D3D11_COLOR_WRITE_ENABLE_RED;
+ }
+ if (green)
+ {
+ mask |= D3D11_COLOR_WRITE_ENABLE_GREEN;
+ }
+ if (blue)
+ {
+ mask |= D3D11_COLOR_WRITE_ENABLE_BLUE;
+ }
+ if (alpha)
+ {
+ mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA;
+ }
+ return mask;
+}
+
+D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, gl::CullFaceMode cullMode)
+{
+ D3D11_CULL_MODE cull = D3D11_CULL_NONE;
+
+ if (cullEnabled)
+ {
+ switch (cullMode)
+ {
+ case gl::CullFaceMode::Front:
+ cull = D3D11_CULL_FRONT;
+ break;
+ case gl::CullFaceMode::Back:
+ cull = D3D11_CULL_BACK;
+ break;
+ case gl::CullFaceMode::FrontAndBack:
+ cull = D3D11_CULL_NONE;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ else
+ {
+ cull = D3D11_CULL_NONE;
+ }
+
+ return cull;
+}
+
+D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison)
+{
+ D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER;
+ switch (comparison)
+ {
+ case GL_NEVER:
+ d3dComp = D3D11_COMPARISON_NEVER;
+ break;
+ case GL_ALWAYS:
+ d3dComp = D3D11_COMPARISON_ALWAYS;
+ break;
+ case GL_LESS:
+ d3dComp = D3D11_COMPARISON_LESS;
+ break;
+ case GL_LEQUAL:
+ d3dComp = D3D11_COMPARISON_LESS_EQUAL;
+ break;
+ case GL_EQUAL:
+ d3dComp = D3D11_COMPARISON_EQUAL;
+ break;
+ case GL_GREATER:
+ d3dComp = D3D11_COMPARISON_GREATER;
+ break;
+ case GL_GEQUAL:
+ d3dComp = D3D11_COMPARISON_GREATER_EQUAL;
+ break;
+ case GL_NOTEQUAL:
+ d3dComp = D3D11_COMPARISON_NOT_EQUAL;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return d3dComp;
+}
+
+D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled)
+{
+ return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO;
+}
+
+UINT8 ConvertStencilMask(GLuint stencilmask)
+{
+ return static_cast<UINT8>(stencilmask);
+}
+
+D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp)
+{
+ D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP;
+
+ switch (stencilOp)
+ {
+ case GL_ZERO:
+ d3dStencilOp = D3D11_STENCIL_OP_ZERO;
+ break;
+ case GL_KEEP:
+ d3dStencilOp = D3D11_STENCIL_OP_KEEP;
+ break;
+ case GL_REPLACE:
+ d3dStencilOp = D3D11_STENCIL_OP_REPLACE;
+ break;
+ case GL_INCR:
+ d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT;
+ break;
+ case GL_DECR:
+ d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT;
+ break;
+ case GL_INVERT:
+ d3dStencilOp = D3D11_STENCIL_OP_INVERT;
+ break;
+ case GL_INCR_WRAP:
+ d3dStencilOp = D3D11_STENCIL_OP_INCR;
+ break;
+ case GL_DECR_WRAP:
+ d3dStencilOp = D3D11_STENCIL_OP_DECR;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return d3dStencilOp;
+}
+
+D3D11_FILTER ConvertFilter(GLenum minFilter,
+ GLenum magFilter,
+ float maxAnisotropy,
+ GLenum comparisonMode)
+{
+ bool comparison = comparisonMode != GL_NONE;
+
+ if (maxAnisotropy > 1.0f)
+ {
+ return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast<D3D11_COMPARISON_FUNC>(comparison));
+ }
+ else
+ {
+ D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT;
+ D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT;
+ switch (minFilter)
+ {
+ case GL_NEAREST:
+ dxMin = D3D11_FILTER_TYPE_POINT;
+ dxMip = D3D11_FILTER_TYPE_POINT;
+ break;
+ case GL_LINEAR:
+ dxMin = D3D11_FILTER_TYPE_LINEAR;
+ dxMip = D3D11_FILTER_TYPE_POINT;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ dxMin = D3D11_FILTER_TYPE_POINT;
+ dxMip = D3D11_FILTER_TYPE_POINT;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ dxMin = D3D11_FILTER_TYPE_LINEAR;
+ dxMip = D3D11_FILTER_TYPE_POINT;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ dxMin = D3D11_FILTER_TYPE_POINT;
+ dxMip = D3D11_FILTER_TYPE_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ dxMin = D3D11_FILTER_TYPE_LINEAR;
+ dxMip = D3D11_FILTER_TYPE_LINEAR;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT;
+ switch (magFilter)
+ {
+ case GL_NEAREST:
+ dxMag = D3D11_FILTER_TYPE_POINT;
+ break;
+ case GL_LINEAR:
+ dxMag = D3D11_FILTER_TYPE_LINEAR;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip,
+ static_cast<D3D11_COMPARISON_FUNC>(comparison));
+ }
+}
+
+D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap)
+{
+ switch (wrap)
+ {
+ case GL_REPEAT:
+ return D3D11_TEXTURE_ADDRESS_WRAP;
+ case GL_CLAMP_TO_EDGE:
+ return D3D11_TEXTURE_ADDRESS_CLAMP;
+ case GL_CLAMP_TO_BORDER:
+ return D3D11_TEXTURE_ADDRESS_BORDER;
+ case GL_MIRRORED_REPEAT:
+ return D3D11_TEXTURE_ADDRESS_MIRROR;
+ default:
+ UNREACHABLE();
+ }
+
+ return D3D11_TEXTURE_ADDRESS_WRAP;
+}
+
+UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel)
+{
+ return static_cast<UINT>(std::min(maxAnisotropy, d3d11_gl::GetMaximumAnisotropy(featureLevel)));
+}
+
+D3D11_QUERY ConvertQueryType(gl::QueryType type)
+{
+ switch (type)
+ {
+ case gl::QueryType::AnySamples:
+ case gl::QueryType::AnySamplesConservative:
+ return D3D11_QUERY_OCCLUSION;
+ case gl::QueryType::TransformFeedbackPrimitivesWritten:
+ return D3D11_QUERY_SO_STATISTICS;
+ case gl::QueryType::TimeElapsed:
+ // Two internal queries are also created for begin/end timestamps
+ return D3D11_QUERY_TIMESTAMP_DISJOINT;
+ case gl::QueryType::CommandsCompleted:
+ return D3D11_QUERY_EVENT;
+ default:
+ UNREACHABLE();
+ return D3D11_QUERY_EVENT;
+ }
+}
+
+// Get the D3D11 write mask covering all color channels of a given format
+UINT8 GetColorMask(const gl::InternalFormat &format)
+{
+ return ConvertColorMask(format.redBits > 0, format.greenBits > 0, format.blueBits > 0,
+ format.alphaBits > 0);
+}
+
+} // namespace gl_d3d11
+
+namespace d3d11
+{
+
+ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device)
+{
+ // Note that this function returns an ANGLED3D11DeviceType rather than a D3D_DRIVER_TYPE value,
+ // since it is difficult to tell Software and Reference devices apart
+
+ IDXGIDevice *dxgiDevice = nullptr;
+ IDXGIAdapter *dxgiAdapter = nullptr;
+ IDXGIAdapter2 *dxgiAdapter2 = nullptr;
+
+ ANGLED3D11DeviceType retDeviceType = ANGLE_D3D11_DEVICE_TYPE_UNKNOWN;
+
+ HRESULT hr = device->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
+ if (SUCCEEDED(hr))
+ {
+ hr = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&dxgiAdapter);
+ if (SUCCEEDED(hr))
+ {
+ std::wstring adapterString;
+ HRESULT adapter2hr =
+ dxgiAdapter->QueryInterface(__uuidof(dxgiAdapter2), (void **)&dxgiAdapter2);
+ if (SUCCEEDED(adapter2hr))
+ {
+ // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter"
+ // for the description string. Try to use IDXGIAdapter2::GetDesc2 to get the
+ // actual hardware values if possible.
+ DXGI_ADAPTER_DESC2 adapterDesc2;
+ dxgiAdapter2->GetDesc2(&adapterDesc2);
+ adapterString = std::wstring(adapterDesc2.Description);
+ }
+ else
+ {
+ DXGI_ADAPTER_DESC adapterDesc;
+ dxgiAdapter->GetDesc(&adapterDesc);
+ adapterString = std::wstring(adapterDesc.Description);
+ }
+
+ // Both Reference and Software adapters will be 'Software Adapter'
+ const bool isSoftwareDevice =
+ (adapterString.find(std::wstring(L"Software Adapter")) != std::string::npos);
+ const bool isNullDevice = (adapterString == L"");
+ const bool isWARPDevice =
+ (adapterString.find(std::wstring(L"Basic Render")) != std::string::npos);
+
+ if (isSoftwareDevice || isNullDevice)
+ {
+ ASSERT(!isWARPDevice);
+ retDeviceType = ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL;
+ }
+ else if (isWARPDevice)
+ {
+ retDeviceType = ANGLE_D3D11_DEVICE_TYPE_WARP;
+ }
+ else
+ {
+ retDeviceType = ANGLE_D3D11_DEVICE_TYPE_HARDWARE;
+ }
+ }
+ }
+
+ SafeRelease(dxgiDevice);
+ SafeRelease(dxgiAdapter);
+ SafeRelease(dxgiAdapter2);
+
+ return retDeviceType;
+}
+
+void MakeValidSize(bool isImage,
+ DXGI_FORMAT format,
+ GLsizei *requestWidth,
+ GLsizei *requestHeight,
+ int *levelOffset)
+{
+ const DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(format);
+ bool validFormat = format != DXGI_FORMAT_UNKNOWN;
+ bool validImage = isImage && validFormat;
+
+ int upsampleCount = 0;
+ // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already.
+ if (validImage || *requestWidth < static_cast<GLsizei>(dxgiFormatInfo.blockWidth) ||
+ *requestHeight < static_cast<GLsizei>(dxgiFormatInfo.blockHeight))
+ {
+ while (*requestWidth % dxgiFormatInfo.blockWidth != 0 ||
+ *requestHeight % dxgiFormatInfo.blockHeight != 0)
+ {
+ *requestWidth <<= 1;
+ *requestHeight <<= 1;
+ upsampleCount++;
+ }
+ }
+ else if (validFormat)
+ {
+ if (*requestWidth % dxgiFormatInfo.blockWidth != 0)
+ {
+ *requestWidth = roundUp(*requestWidth, static_cast<GLsizei>(dxgiFormatInfo.blockWidth));
+ }
+
+ if (*requestHeight % dxgiFormatInfo.blockHeight != 0)
+ {
+ *requestHeight =
+ roundUp(*requestHeight, static_cast<GLsizei>(dxgiFormatInfo.blockHeight));
+ }
+ }
+
+ if (levelOffset)
+ {
+ *levelOffset = upsampleCount;
+ }
+}
+
+angle::Result GenerateInitialTextureData(
+ const gl::Context *context,
+ GLint internalFormat,
+ const Renderer11DeviceCaps &renderer11DeviceCaps,
+ GLuint width,
+ GLuint height,
+ GLuint depth,
+ GLuint mipLevels,
+ gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> *outSubresourceData)
+{
+ const d3d11::Format &d3dFormatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps);
+ ASSERT(d3dFormatInfo.dataInitializerFunction != nullptr);
+
+ const d3d11::DXGIFormatSize &dxgiFormatInfo =
+ d3d11::GetDXGIFormatSizeInfo(d3dFormatInfo.texFormat);
+
+ using CheckedSize = angle::CheckedNumeric<size_t>;
+ CheckedSize rowPitch = CheckedSize(dxgiFormatInfo.pixelBytes) * CheckedSize(width);
+ CheckedSize depthPitch = rowPitch * CheckedSize(height);
+ CheckedSize maxImageSize = depthPitch * CheckedSize(depth);
+
+ Context11 *context11 = GetImplAs<Context11>(context);
+ ANGLE_CHECK_GL_ALLOC(context11, maxImageSize.IsValid());
+
+ angle::MemoryBuffer *scratchBuffer = nullptr;
+ ANGLE_CHECK_GL_ALLOC(context11,
+ context->getScratchBuffer(maxImageSize.ValueOrDie(), &scratchBuffer));
+
+ d3dFormatInfo.dataInitializerFunction(width, height, depth, scratchBuffer->data(),
+ rowPitch.ValueOrDie(), depthPitch.ValueOrDie());
+
+ for (unsigned int i = 0; i < mipLevels; i++)
+ {
+ unsigned int mipWidth = std::max(width >> i, 1U);
+ unsigned int mipHeight = std::max(height >> i, 1U);
+
+ using CheckedUINT = angle::CheckedNumeric<UINT>;
+ CheckedUINT mipRowPitch = CheckedUINT(dxgiFormatInfo.pixelBytes) * CheckedUINT(mipWidth);
+ CheckedUINT mipDepthPitch = mipRowPitch * CheckedUINT(mipHeight);
+
+ ANGLE_CHECK_GL_ALLOC(context11, mipRowPitch.IsValid() && mipDepthPitch.IsValid());
+
+ outSubresourceData->at(i).pSysMem = scratchBuffer->data();
+ outSubresourceData->at(i).SysMemPitch = mipRowPitch.ValueOrDie();
+ outSubresourceData->at(i).SysMemSlicePitch = mipDepthPitch.ValueOrDie();
+ }
+
+ return angle::Result::Continue;
+}
+
+UINT GetPrimitiveRestartIndex()
+{
+ return std::numeric_limits<UINT>::max();
+}
+
+void SetPositionTexCoordVertex(PositionTexCoordVertex *vertex, float x, float y, float u, float v)
+{
+ vertex->x = x;
+ vertex->y = y;
+ vertex->u = u;
+ vertex->v = v;
+}
+
+void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex *vertex,
+ float x,
+ float y,
+ unsigned int layer,
+ float u,
+ float v,
+ float s)
+{
+ vertex->x = x;
+ vertex->y = y;
+ vertex->l = layer;
+ vertex->u = u;
+ vertex->v = v;
+ vertex->s = s;
+}
+
+BlendStateKey::BlendStateKey()
+{
+ memset(this, 0, sizeof(BlendStateKey));
+ blendStateExt = gl::BlendStateExt();
+}
+
+BlendStateKey::BlendStateKey(const BlendStateKey &other)
+{
+ memcpy(this, &other, sizeof(BlendStateKey));
+}
+
+bool operator==(const BlendStateKey &a, const BlendStateKey &b)
+{
+ return memcmp(&a, &b, sizeof(BlendStateKey)) == 0;
+}
+
+bool operator!=(const BlendStateKey &a, const BlendStateKey &b)
+{
+ return !(a == b);
+}
+
+RasterizerStateKey::RasterizerStateKey()
+{
+ memset(this, 0, sizeof(RasterizerStateKey));
+}
+
+bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b)
+{
+ return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0;
+}
+
+bool operator!=(const RasterizerStateKey &a, const RasterizerStateKey &b)
+{
+ return !(a == b);
+}
+
+HRESULT SetDebugName(ID3D11DeviceChild *resource,
+ const char *internalName,
+ const std::string *khrDebugName)
+{
+ // Prepend ANGLE to separate names from other components in the same process.
+ std::string d3dName = "ANGLE";
+ bool sendNameToD3D = false;
+ if (internalName && internalName[0] != '\0')
+ {
+ d3dName += std::string("_") + internalName;
+ sendNameToD3D = true;
+ }
+ if (khrDebugName && !khrDebugName->empty())
+ {
+ d3dName += std::string("_") + *khrDebugName;
+ sendNameToD3D = true;
+ }
+ // If both internalName and khrDebugName are empty, avoid sending the string to d3d.
+ if (sendNameToD3D)
+ {
+ return resource->SetPrivateData(WKPDID_D3DDebugObjectName,
+ static_cast<UINT>(d3dName.size()), d3dName.c_str());
+ }
+ return S_OK;
+}
+
+// Keep this in cpp file where it has visibility of Renderer11.h, otherwise calling
+// allocateResource is only compatible with Clang and MSVS, which support calling a
+// method on a forward declared class in a template.
+template <ResourceType ResourceT>
+angle::Result LazyResource<ResourceT>::resolveImpl(d3d::Context *context,
+ Renderer11 *renderer,
+ const GetDescType<ResourceT> &desc,
+ GetInitDataType<ResourceT> *initData,
+ const char *name)
+{
+ if (!mResource.valid())
+ {
+ ANGLE_TRY(renderer->allocateResource(context, desc, initData, &mResource));
+ mResource.setInternalName(name);
+ }
+ return angle::Result::Continue;
+}
+
+template angle::Result LazyResource<ResourceType::BlendState>::resolveImpl(
+ d3d::Context *context,
+ Renderer11 *renderer,
+ const D3D11_BLEND_DESC &desc,
+ void *initData,
+ const char *name);
+template angle::Result LazyResource<ResourceType::ComputeShader>::resolveImpl(
+ d3d::Context *context,
+ Renderer11 *renderer,
+ const ShaderData &desc,
+ void *initData,
+ const char *name);
+template angle::Result LazyResource<ResourceType::GeometryShader>::resolveImpl(
+ d3d::Context *context,
+ Renderer11 *renderer,
+ const ShaderData &desc,
+ const std::vector<D3D11_SO_DECLARATION_ENTRY> *initData,
+ const char *name);
+template angle::Result LazyResource<ResourceType::InputLayout>::resolveImpl(
+ d3d::Context *context,
+ Renderer11 *renderer,
+ const InputElementArray &desc,
+ const ShaderData *initData,
+ const char *name);
+template angle::Result LazyResource<ResourceType::PixelShader>::resolveImpl(d3d::Context *context,
+ Renderer11 *renderer,
+ const ShaderData &desc,
+ void *initData,
+ const char *name);
+template angle::Result LazyResource<ResourceType::VertexShader>::resolveImpl(d3d::Context *context,
+ Renderer11 *renderer,
+ const ShaderData &desc,
+ void *initData,
+ const char *name);
+
+LazyInputLayout::LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
+ size_t inputDescLen,
+ const BYTE *byteCode,
+ size_t byteCodeLen,
+ const char *debugName)
+ : mInputDesc(inputDesc, inputDescLen), mByteCode(byteCode, byteCodeLen), mDebugName(debugName)
+{}
+
+LazyInputLayout::~LazyInputLayout() {}
+
+angle::Result LazyInputLayout::resolve(d3d::Context *context, Renderer11 *renderer)
+{
+ return resolveImpl(context, renderer, mInputDesc, &mByteCode, mDebugName);
+}
+
+LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName)
+ : mDesc(desc), mDebugName(debugName)
+{}
+
+angle::Result LazyBlendState::resolve(d3d::Context *context, Renderer11 *renderer)
+{
+ return resolveImpl(context, renderer, mDesc, nullptr, mDebugName);
+}
+
+void InitializeFeatures(const Renderer11DeviceCaps &deviceCaps,
+ const DXGI_ADAPTER_DESC &adapterDesc,
+ angle::FeaturesD3D *features)
+{
+ bool isNvidia = IsNvidia(adapterDesc.VendorId);
+ bool isIntel = IsIntel(adapterDesc.VendorId);
+ bool isSkylake = false;
+ bool isBroadwell = false;
+ bool isHaswell = false;
+ bool isIvyBridge = false;
+ bool isSandyBridge = false;
+ bool isAMD = IsAMD(adapterDesc.VendorId);
+ bool isFeatureLevel9_3 = (deviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3);
+
+ IntelDriverVersion capsVersion = IntelDriverVersion(0);
+ if (isIntel)
+ {
+ capsVersion = d3d11_gl::GetIntelDriverVersion(deviceCaps.driverVersion);
+
+ isSkylake = IsSkylake(adapterDesc.DeviceId);
+ isBroadwell = IsBroadwell(adapterDesc.DeviceId);
+ isHaswell = IsHaswell(adapterDesc.DeviceId);
+ isIvyBridge = IsIvyBridge(adapterDesc.DeviceId);
+ isSandyBridge = IsSandyBridge(adapterDesc.DeviceId);
+ }
+
+ if (isNvidia)
+ {
+ // TODO(jmadill): Narrow problematic driver range.
+ bool driverVersionValid = deviceCaps.driverVersion.valid();
+ if (driverVersionValid)
+ {
+ WORD part1 = HIWORD(deviceCaps.driverVersion.value().LowPart);
+ WORD part2 = LOWORD(deviceCaps.driverVersion.value().LowPart);
+
+ // Disable the workaround to fix a second driver bug on newer NVIDIA.
+ ANGLE_FEATURE_CONDITION(
+ features, depthStencilBlitExtraCopy,
+ (part1 <= 13u && part2 < 6881) && isNvidia && driverVersionValid);
+ }
+ else
+ {
+ ANGLE_FEATURE_CONDITION(features, depthStencilBlitExtraCopy,
+ isNvidia && !driverVersionValid);
+ }
+ }
+
+ ANGLE_FEATURE_CONDITION(features, mrtPerfWorkaround, true);
+ ANGLE_FEATURE_CONDITION(features, zeroMaxLodWorkaround, isFeatureLevel9_3);
+ ANGLE_FEATURE_CONDITION(features, useInstancedPointSpriteEmulation, isFeatureLevel9_3);
+ ANGLE_FEATURE_CONDITION(features, allowES3OnFL100, false);
+
+ // TODO(jmadill): Disable workaround when we have a fixed compiler DLL.
+ ANGLE_FEATURE_CONDITION(features, expandIntegerPowExpressions, true);
+
+ ANGLE_FEATURE_CONDITION(features, flushAfterEndingTransformFeedback, isNvidia);
+ ANGLE_FEATURE_CONDITION(features, getDimensionsIgnoresBaseLevel, isNvidia);
+ ANGLE_FEATURE_CONDITION(features, skipVSConstantRegisterZero, isNvidia);
+ ANGLE_FEATURE_CONDITION(features, forceAtomicValueResolution, isNvidia);
+
+ ANGLE_FEATURE_CONDITION(features, preAddTexelFetchOffsets, isIntel);
+ ANGLE_FEATURE_CONDITION(features, useSystemMemoryForConstantBuffers, isIntel);
+
+ // ClearView on Skylake seems to incorrectly clear with unaligned rects (edge has saw tooth
+ // pattern instead of straight).
+ ANGLE_FEATURE_CONDITION(features, scissoredClearArtifacts, isIntel && isSkylake);
+
+ ANGLE_FEATURE_CONDITION(features, callClearTwice,
+ isIntel && isSkylake && capsVersion >= IntelDriverVersion(160000) &&
+ capsVersion < IntelDriverVersion(164771));
+ ANGLE_FEATURE_CONDITION(features, emulateIsnanFloat,
+ isIntel && isSkylake && capsVersion >= IntelDriverVersion(160000) &&
+ capsVersion < IntelDriverVersion(164542));
+ ANGLE_FEATURE_CONDITION(features, rewriteUnaryMinusOperator,
+ isIntel && (isBroadwell || isHaswell) &&
+ capsVersion >= IntelDriverVersion(150000) &&
+ capsVersion < IntelDriverVersion(154624));
+
+ ANGLE_FEATURE_CONDITION(features, addMockTextureNoRenderTarget,
+ isIntel && capsVersion >= IntelDriverVersion(160000) &&
+ capsVersion < IntelDriverVersion(164815));
+
+ // Haswell drivers occasionally corrupt (small?) (vertex?) texture data uploads for 128bit
+ // formats.
+ ANGLE_FEATURE_CONDITION(features, setDataFasterThanImageUpload, true);
+ ANGLE_FEATURE_CONDITION(features, setDataFasterThanImageUploadOn128bitFormats,
+ !(isIvyBridge || isBroadwell || isHaswell));
+
+ ANGLE_FEATURE_CONDITION(features, emulateClearViewAfterDualSourceBlending, isSandyBridge);
+
+ ANGLE_FEATURE_CONDITION(features, disableB5G6R5Support,
+ (isIntel && capsVersion >= IntelDriverVersion(150000) &&
+ capsVersion < IntelDriverVersion(154539)) ||
+ isAMD);
+
+ // TODO(jmadill): Disable when we have a fixed driver version.
+ // The tiny stencil texture workaround involves using CopySubresource or UpdateSubresource on a
+ // depth stencil texture. This is not allowed until feature level 10.1 but since it is not
+ // possible to support ES3 on these devices, there is no need for the workaround to begin with
+ // (anglebug.com/1572).
+ ANGLE_FEATURE_CONDITION(features, emulateTinyStencilTextures,
+ isAMD && !(deviceCaps.featureLevel < D3D_FEATURE_LEVEL_10_1));
+
+ // If the VPAndRTArrayIndexFromAnyShaderFeedingRasterizer feature is not available, we have to
+ // select the viewport / RT array index in the geometry shader.
+ ANGLE_FEATURE_CONDITION(features, selectViewInGeometryShader,
+ !deviceCaps.supportsVpRtIndexWriteFromVertexShader);
+
+ // NVidia drivers have no trouble clearing textures without showing corruption.
+ // Intel and AMD drivers that have trouble have been blocklisted by Chromium. In the case of
+ // Intel, they've been blocklisted to the DX9 runtime.
+ ANGLE_FEATURE_CONDITION(features, allowClearForRobustResourceInit, true);
+
+ // Allow translating uniform block to StructuredBuffer on Windows 10. This is targeted
+ // to work around a slow fxc compile performance issue with dynamic uniform indexing.
+ ANGLE_FEATURE_CONDITION(features, allowTranslateUniformBlockToStructuredBuffer,
+ IsWin10OrGreater());
+}
+
+void InitializeFrontendFeatures(const DXGI_ADAPTER_DESC &adapterDesc,
+ angle::FrontendFeatures *features)
+{
+ bool isAMD = IsAMD(adapterDesc.VendorId);
+
+ ANGLE_FEATURE_CONDITION(features, forceDepthAttachmentInitOnClear, isAMD);
+}
+
+void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth)
+{
+ constantBufferDescription->ByteWidth = static_cast<UINT>(byteWidth);
+ constantBufferDescription->Usage = D3D11_USAGE_DYNAMIC;
+ constantBufferDescription->BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ constantBufferDescription->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ constantBufferDescription->MiscFlags = 0;
+ constantBufferDescription->StructureByteStride = 0;
+}
+
+} // namespace d3d11
+
+// TextureHelper11 implementation.
+TextureHelper11::TextureHelper11() : mFormatSet(nullptr), mSampleCount(0) {}
+
+TextureHelper11::TextureHelper11(TextureHelper11 &&toCopy) : TextureHelper11()
+{
+ *this = std::move(toCopy);
+}
+
+TextureHelper11::TextureHelper11(const TextureHelper11 &other)
+ : mFormatSet(other.mFormatSet), mExtents(other.mExtents), mSampleCount(other.mSampleCount)
+{
+ mData = other.mData;
+}
+
+TextureHelper11::~TextureHelper11() {}
+
+void TextureHelper11::getDesc(D3D11_TEXTURE2D_DESC *desc) const
+{
+ static_cast<ID3D11Texture2D *>(mData->object)->GetDesc(desc);
+}
+
+void TextureHelper11::getDesc(D3D11_TEXTURE3D_DESC *desc) const
+{
+ static_cast<ID3D11Texture3D *>(mData->object)->GetDesc(desc);
+}
+
+void TextureHelper11::getDesc(D3D11_BUFFER_DESC *desc) const
+{
+ static_cast<ID3D11Buffer *>(mData->object)->GetDesc(desc);
+}
+
+void TextureHelper11::initDesc(const D3D11_TEXTURE2D_DESC &desc2D)
+{
+ mData->resourceType = ResourceType::Texture2D;
+ mExtents.width = static_cast<int>(desc2D.Width);
+ mExtents.height = static_cast<int>(desc2D.Height);
+ mExtents.depth = 1;
+ mSampleCount = desc2D.SampleDesc.Count;
+}
+
+void TextureHelper11::initDesc(const D3D11_TEXTURE3D_DESC &desc3D)
+{
+ mData->resourceType = ResourceType::Texture3D;
+ mExtents.width = static_cast<int>(desc3D.Width);
+ mExtents.height = static_cast<int>(desc3D.Height);
+ mExtents.depth = static_cast<int>(desc3D.Depth);
+ mSampleCount = 1;
+}
+
+void TextureHelper11::initDesc(const D3D11_BUFFER_DESC &descBuffer)
+{
+ mData->resourceType = ResourceType::Buffer;
+ mExtents.width = static_cast<int>(descBuffer.ByteWidth);
+ mExtents.height = 1;
+ mExtents.depth = 1;
+ mSampleCount = 1;
+}
+
+TextureHelper11 &TextureHelper11::operator=(TextureHelper11 &&other)
+{
+ std::swap(mData, other.mData);
+ std::swap(mExtents, other.mExtents);
+ std::swap(mFormatSet, other.mFormatSet);
+ std::swap(mSampleCount, other.mSampleCount);
+ return *this;
+}
+
+TextureHelper11 &TextureHelper11::operator=(const TextureHelper11 &other)
+{
+ mData = other.mData;
+ mExtents = other.mExtents;
+ mFormatSet = other.mFormatSet;
+ mSampleCount = other.mSampleCount;
+ return *this;
+}
+
+bool TextureHelper11::operator==(const TextureHelper11 &other) const
+{
+ return mData->object == other.mData->object;
+}
+
+bool TextureHelper11::operator!=(const TextureHelper11 &other) const
+{
+ return mData->object != other.mData->object;
+}
+
+bool UsePresentPathFast(const Renderer11 *renderer,
+ const gl::FramebufferAttachment *framebufferAttachment)
+{
+ if (framebufferAttachment == nullptr)
+ {
+ return false;
+ }
+
+ return (framebufferAttachment->type() == GL_FRAMEBUFFER_DEFAULT &&
+ renderer->presentPathFastEnabled());
+}
+
+bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,
+ gl::DrawElementsType type)
+{
+ // We should never have to deal with primitive restart workaround issue with GL_UNSIGNED_INT
+ // indices, since we restrict it via MAX_ELEMENT_INDEX.
+ return (!primitiveRestartFixedIndexEnabled && type == gl::DrawElementsType::UnsignedShort);
+}
+
+IndexStorageType ClassifyIndexStorage(const gl::State &glState,
+ const gl::Buffer *elementArrayBuffer,
+ gl::DrawElementsType elementType,
+ gl::DrawElementsType destElementType,
+ unsigned int offset)
+{
+ // No buffer bound means we are streaming from a client pointer.
+ if (!elementArrayBuffer || !IsOffsetAligned(elementType, offset))
+ {
+ return IndexStorageType::Dynamic;
+ }
+
+ // The buffer can be used directly if the storage supports it and no translation needed.
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(elementArrayBuffer);
+ if (bufferD3D->supportsDirectBinding() && destElementType == elementType)
+ {
+ return IndexStorageType::Direct;
+ }
+
+ // Use a static copy when available.
+ StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer();
+ if (staticBuffer != nullptr)
+ {
+ return IndexStorageType::Static;
+ }
+
+ // Static buffer not available, fall back to streaming.
+ return IndexStorageType::Dynamic;
+}
+
+bool SwizzleRequired(const gl::TextureState &textureState)
+{
+ // When sampling stencil, a swizzle is needed to move the stencil channel from G to R.
+ return textureState.swizzleRequired() || textureState.isStencilMode();
+}
+
+gl::SwizzleState GetEffectiveSwizzle(const gl::TextureState &textureState)
+{
+ const gl::SwizzleState &swizzle = textureState.getSwizzleState();
+ if (textureState.isStencilMode())
+ {
+ // Per GL semantics, the stencil value should be in the red channel, while D3D11 formats
+ // leave stencil in the green channel. So copy the stencil value from green to all
+ // components requesting red. Green and blue become zero; alpha becomes one.
+ std::unordered_map<GLenum, GLenum> map = {{GL_RED, GL_GREEN}, {GL_GREEN, GL_ZERO},
+ {GL_BLUE, GL_ZERO}, {GL_ALPHA, GL_ONE},
+ {GL_ZERO, GL_ZERO}, {GL_ONE, GL_ONE}};
+
+ return gl::SwizzleState(map[swizzle.swizzleRed], map[swizzle.swizzleGreen],
+ map[swizzle.swizzleBlue], map[swizzle.swizzleAlpha]);
+ }
+ return swizzle;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
new file mode 100644
index 0000000000..a8cd430bc6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
@@ -0,0 +1,478 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// renderer11_utils.h: Conversion functions and other utility routines
+// specific to the D3D11 renderer.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
+
+#include <array>
+#include <functional>
+#include <vector>
+
+#include "common/Color.h"
+
+#include "libANGLE/Caps.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+}
+
+namespace rx
+{
+class Context11;
+class Renderer11;
+class RenderTarget11;
+struct Renderer11DeviceCaps;
+
+using RTVArray = std::array<ID3D11RenderTargetView *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>;
+
+namespace gl_d3d11
+{
+
+D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha);
+D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp);
+UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha);
+
+D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, gl::CullFaceMode cullMode);
+
+D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison);
+D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled);
+UINT8 ConvertStencilMask(GLuint stencilmask);
+D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp);
+
+D3D11_FILTER ConvertFilter(GLenum minFilter,
+ GLenum magFilter,
+ float maxAnisotropy,
+ GLenum comparisonMode);
+D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap);
+UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel);
+
+D3D11_QUERY ConvertQueryType(gl::QueryType type);
+
+UINT8 GetColorMask(const gl::InternalFormat &formatInfo);
+
+} // namespace gl_d3d11
+
+namespace d3d11_gl
+{
+
+unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel);
+
+unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel);
+
+gl::Version GetMaximumClientVersion(const Renderer11DeviceCaps &caps);
+void GenerateCaps(ID3D11Device *device,
+ ID3D11DeviceContext *deviceContext,
+ const Renderer11DeviceCaps &renderer11DeviceCaps,
+ const angle::FeaturesD3D &features,
+ const char *description,
+ gl::Caps *caps,
+ gl::TextureCapsMap *textureCapsMap,
+ gl::Extensions *extensions,
+ gl::Limitations *limitations);
+
+D3D_FEATURE_LEVEL GetMinimumFeatureLevelForES31();
+
+} // namespace d3d11_gl
+
+namespace d3d11
+{
+
+enum ANGLED3D11DeviceType
+{
+ ANGLE_D3D11_DEVICE_TYPE_UNKNOWN,
+ ANGLE_D3D11_DEVICE_TYPE_HARDWARE,
+ ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL,
+ ANGLE_D3D11_DEVICE_TYPE_WARP,
+};
+
+ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device);
+
+void MakeValidSize(bool isImage,
+ DXGI_FORMAT format,
+ GLsizei *requestWidth,
+ GLsizei *requestHeight,
+ int *levelOffset);
+
+angle::Result GenerateInitialTextureData(
+ const gl::Context *context,
+ GLint internalFormat,
+ const Renderer11DeviceCaps &renderer11DeviceCaps,
+ GLuint width,
+ GLuint height,
+ GLuint depth,
+ GLuint mipLevels,
+ gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> *outSubresourceData);
+
+UINT GetPrimitiveRestartIndex();
+
+struct PositionTexCoordVertex
+{
+ float x, y;
+ float u, v;
+};
+void SetPositionTexCoordVertex(PositionTexCoordVertex *vertex, float x, float y, float u, float v);
+
+struct PositionLayerTexCoord3DVertex
+{
+ float x, y;
+ unsigned int l;
+ float u, v, s;
+};
+void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex *vertex,
+ float x,
+ float y,
+ unsigned int layer,
+ float u,
+ float v,
+ float s);
+
+struct PositionVertex
+{
+ float x, y, z, w;
+};
+
+struct BlendStateKey final
+{
+ // This will zero-initialize the struct, including padding.
+ BlendStateKey();
+ BlendStateKey(const BlendStateKey &other);
+
+ gl::BlendStateExt blendStateExt;
+
+ // Use two 16-bit ints to round the struct nicely.
+ uint16_t rtvMax;
+ uint16_t sampleAlphaToCoverage;
+};
+
+bool operator==(const BlendStateKey &a, const BlendStateKey &b);
+bool operator!=(const BlendStateKey &a, const BlendStateKey &b);
+
+struct RasterizerStateKey final
+{
+ // This will zero-initialize the struct, including padding.
+ RasterizerStateKey();
+
+ gl::RasterizerState rasterizerState;
+
+ // Use a 32-bit int to round the struct nicely.
+ uint32_t scissorEnabled;
+};
+
+bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b);
+bool operator!=(const RasterizerStateKey &a, const RasterizerStateKey &b);
+
+template <typename outType>
+outType *DynamicCastComObject(IUnknown *object)
+{
+ outType *outObject = nullptr;
+ HRESULT result =
+ object->QueryInterface(__uuidof(outType), reinterpret_cast<void **>(&outObject));
+ if (SUCCEEDED(result))
+ {
+ return outObject;
+ }
+ else
+ {
+ SafeRelease(outObject);
+ return nullptr;
+ }
+}
+
+template <typename outType>
+angle::ComPtr<outType> DynamicCastComObjectToComPtr(IUnknown *object)
+{
+ angle::ComPtr<outType> outObject;
+ const HRESULT hr = object->QueryInterface(IID_PPV_ARGS(&outObject));
+ if (SUCCEEDED(hr))
+ {
+ return outObject;
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+inline bool isDeviceLostError(HRESULT errorCode)
+{
+ switch (errorCode)
+ {
+ case DXGI_ERROR_DEVICE_HUNG:
+ case DXGI_ERROR_DEVICE_REMOVED:
+ case DXGI_ERROR_DEVICE_RESET:
+ case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
+ case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+template <ResourceType ResourceT>
+class LazyResource : angle::NonCopyable
+{
+ public:
+ constexpr LazyResource() : mResource() {}
+ virtual ~LazyResource() {}
+
+ virtual angle::Result resolve(d3d::Context *context, Renderer11 *renderer) = 0;
+ void reset() { mResource.reset(); }
+ GetD3D11Type<ResourceT> *get() const
+ {
+ ASSERT(mResource.valid());
+ return mResource.get();
+ }
+
+ const Resource11<GetD3D11Type<ResourceT>> &getObj() const { return mResource; }
+
+ protected:
+ LazyResource(LazyResource &&other) : mResource(std::move(other.mResource)) {}
+
+ // Specialized in the cpp file to avoid MSVS/Clang specific code.
+ angle::Result resolveImpl(d3d::Context *context,
+ Renderer11 *renderer,
+ const GetDescType<ResourceT> &desc,
+ GetInitDataType<ResourceT> *initData,
+ const char *name);
+
+ Resource11<GetD3D11Type<ResourceT>> mResource;
+};
+
+template <typename D3D11ShaderType>
+class LazyShader final : public LazyResource<GetResourceTypeFromD3D11<D3D11ShaderType>()>
+{
+ public:
+ // All parameters must be constexpr. Not supported in VS2013.
+ constexpr LazyShader(const BYTE *byteCode, size_t byteCodeSize, const char *name)
+ : mByteCode(byteCode, byteCodeSize), mName(name)
+ {}
+
+ constexpr LazyShader(LazyShader &&shader)
+ : LazyResource<GetResourceTypeFromD3D11<D3D11ShaderType>()>(std::move(shader)),
+ mByteCode(std::move(shader.mByteCode)),
+ mName(shader.mName)
+ {}
+
+ angle::Result resolve(d3d::Context *context, Renderer11 *renderer) override
+ {
+ return this->resolveImpl(context, renderer, mByteCode, nullptr, mName);
+ }
+
+ private:
+ ShaderData mByteCode;
+ const char *mName;
+};
+
+class LazyInputLayout final : public LazyResource<ResourceType::InputLayout>
+{
+ public:
+ LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
+ size_t inputDescLen,
+ const BYTE *byteCode,
+ size_t byteCodeLen,
+ const char *debugName);
+ ~LazyInputLayout() override;
+
+ angle::Result resolve(d3d::Context *context, Renderer11 *renderer) override;
+
+ private:
+ InputElementArray mInputDesc;
+ ShaderData mByteCode;
+ const char *mDebugName;
+};
+
+class LazyBlendState final : public LazyResource<ResourceType::BlendState>
+{
+ public:
+ LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName);
+
+ angle::Result resolve(d3d::Context *context, Renderer11 *renderer) override;
+
+ private:
+ D3D11_BLEND_DESC mDesc;
+ const char *mDebugName;
+};
+
+// Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to
+// represent an entire buffer.
+template <class T>
+void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, const T &value)
+{
+ D3D11_MAPPED_SUBRESOURCE mappedResource = {};
+ HRESULT result = context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ ASSERT(SUCCEEDED(result));
+ if (SUCCEEDED(result))
+ {
+ memcpy(mappedResource.pData, &value, sizeof(T));
+ context->Unmap(constantBuffer, 0);
+ }
+}
+
+void InitializeFeatures(const Renderer11DeviceCaps &deviceCaps,
+ const DXGI_ADAPTER_DESC &adapterDesc,
+ angle::FeaturesD3D *features);
+
+void InitializeFrontendFeatures(const DXGI_ADAPTER_DESC &adapterDesc,
+ angle::FrontendFeatures *features);
+
+enum ReservedConstantBufferSlot
+{
+ RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK = 0,
+ RESERVED_CONSTANT_BUFFER_SLOT_DRIVER = 1,
+
+ RESERVED_CONSTANT_BUFFER_SLOT_COUNT = 2
+};
+
+void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth);
+
+// Helper class for RAII patterning.
+template <typename T>
+class [[nodiscard]] ScopedUnmapper final : angle::NonCopyable
+{
+ public:
+ ScopedUnmapper(T *object) : mObject(object) {}
+ ~ScopedUnmapper() { mObject->unmap(); }
+
+ private:
+ T *mObject;
+};
+} // namespace d3d11
+
+struct GenericData
+{
+ GenericData() {}
+ ~GenericData()
+ {
+ if (object)
+ {
+ // We can have a nullptr factory when holding passed-in resources.
+ if (manager)
+ {
+ manager->onReleaseGeneric(resourceType, object);
+ manager = nullptr;
+ }
+ object->Release();
+ object = nullptr;
+ }
+ }
+
+ ResourceType resourceType = ResourceType::Last;
+ ID3D11Resource *object = nullptr;
+ ResourceManager11 *manager = nullptr;
+};
+
+// A helper class which wraps a 2D or 3D texture.
+class TextureHelper11 : public Resource11Base<ID3D11Resource, std::shared_ptr, GenericData>
+{
+ public:
+ TextureHelper11();
+ TextureHelper11(TextureHelper11 &&other);
+ TextureHelper11(const TextureHelper11 &other);
+ ~TextureHelper11() override;
+ TextureHelper11 &operator=(TextureHelper11 &&other);
+ TextureHelper11 &operator=(const TextureHelper11 &other);
+
+ bool isBuffer() const { return mData->resourceType == ResourceType::Buffer; }
+ bool is2D() const { return mData->resourceType == ResourceType::Texture2D; }
+ bool is3D() const { return mData->resourceType == ResourceType::Texture3D; }
+ ResourceType getTextureType() const { return mData->resourceType; }
+ gl::Extents getExtents() const { return mExtents; }
+ DXGI_FORMAT getFormat() const { return mFormatSet->texFormat; }
+ const d3d11::Format &getFormatSet() const { return *mFormatSet; }
+ int getSampleCount() const { return mSampleCount; }
+
+ template <typename DescT, typename ResourceT>
+ void init(Resource11<ResourceT> &&texture, const DescT &desc, const d3d11::Format &format)
+ {
+ std::swap(mData->manager, texture.mData->manager);
+
+ // Can't use std::swap because texture is typed, and here we use ID3D11Resource.
+ ID3D11Resource *temp = mData->object;
+ mData->object = texture.mData->object;
+ texture.mData->object = static_cast<ResourceT *>(temp);
+
+ mFormatSet = &format;
+ initDesc(desc);
+ }
+
+ template <typename ResourceT>
+ void set(ResourceT *object, const d3d11::Format &format)
+ {
+ ASSERT(!valid());
+
+ mFormatSet = &format;
+ mData->object = object;
+ mData->manager = nullptr;
+
+ GetDescFromD3D11<ResourceT> desc;
+ getDesc(&desc);
+ initDesc(desc);
+ }
+
+ bool operator==(const TextureHelper11 &other) const;
+ bool operator!=(const TextureHelper11 &other) const;
+
+ void getDesc(D3D11_TEXTURE2D_DESC *desc) const;
+ void getDesc(D3D11_TEXTURE3D_DESC *desc) const;
+ void getDesc(D3D11_BUFFER_DESC *desc) const;
+
+ private:
+ void initDesc(const D3D11_TEXTURE2D_DESC &desc2D);
+ void initDesc(const D3D11_TEXTURE3D_DESC &desc3D);
+ void initDesc(const D3D11_BUFFER_DESC &descBuffer);
+
+ const d3d11::Format *mFormatSet;
+ gl::Extents mExtents;
+ int mSampleCount;
+};
+
+enum class StagingAccess
+{
+ READ,
+ READ_WRITE,
+};
+
+bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachment *colorbuffer);
+bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,
+ gl::DrawElementsType type);
+
+enum class IndexStorageType
+{
+ // Dynamic indexes are re-streamed every frame. They come from a client data pointer or
+ // from buffers that are updated frequently.
+ Dynamic,
+
+ // Static indexes are translated from the original storage once, and re-used multiple times.
+ Static,
+
+ // Direct indexes are never transated and are used directly from the source buffer. They are
+ // the fastest available path.
+ Direct,
+
+ // Not a real storage type.
+ Invalid,
+};
+
+IndexStorageType ClassifyIndexStorage(const gl::State &glState,
+ const gl::Buffer *elementArrayBuffer,
+ gl::DrawElementsType elementType,
+ gl::DrawElementsType destElementType,
+ unsigned int offset);
+
+bool SwizzleRequired(const gl::TextureState &textureState);
+gl::SwizzleState GetEffectiveSwizzle(const gl::TextureState &textureState);
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h
new file mode 100644
index 0000000000..9bfc750765
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h
@@ -0,0 +1,80 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float xyzw
+// TEXCOORD 0 x 1 NONE uint x
+// LAYER 0 y 1 NONE uint y
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float xyzw
+// TEXCOORD 0 x 1 NONE uint x
+// SV_RenderTargetArrayIndex 0 y 1 RTINDEX uint y
+//
+gs_4_0
+dcl_input_siv v[1][0].xyzw, position
+dcl_input v[1][1].x
+dcl_input v[1][1].y
+dcl_inputprimitive point
+dcl_outputtopology pointlist
+dcl_output_siv o0.xyzw, position
+dcl_output o1.x
+dcl_output_siv o1.y, rendertarget_array_index
+dcl_maxout 1
+mov o0.xyzw, v[0][0].xyzw
+mov o1.x, v[0][1].x
+mov o1.y, v[0][1].y
+emit
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_GS_BufferToTexture[] = {
+ 68, 88, 66, 67, 181, 104, 45, 14, 26, 142, 216, 235, 63, 167, 110, 6, 1, 170, 134,
+ 100, 1, 0, 0, 0, 200, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 128, 0,
+ 0, 0, 244, 0, 0, 0, 124, 1, 0, 0, 76, 2, 0, 0, 82, 68, 69, 70, 68,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 83, 71, 0, 1, 0, 0, 28, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 108,
+ 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 15, 0, 0, 92, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1,
+ 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
+ 0, 0, 0, 2, 2, 0, 0, 83, 86, 95, 80, 111, 115, 105, 116, 105, 111, 110, 0,
+ 84, 69, 88, 67, 79, 79, 82, 68, 0, 76, 65, 89, 69, 82, 0, 171, 79, 83, 71,
+ 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 1, 14, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0, 2, 13, 0, 0, 83, 86, 95, 80, 111, 115, 105, 116, 105, 111,
+ 110, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 83, 86, 95, 82, 101, 110, 100, 101,
+ 114, 84, 97, 114, 103, 101, 116, 65, 114, 114, 97, 121, 73, 110, 100, 101, 120, 0, 171,
+ 83, 72, 68, 82, 200, 0, 0, 0, 64, 0, 2, 0, 50, 0, 0, 0, 97, 0, 0,
+ 5, 242, 16, 32, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 95, 0,
+ 0, 4, 18, 16, 32, 0, 1, 0, 0, 0, 1, 0, 0, 0, 95, 0, 0, 4, 34,
+ 16, 32, 0, 1, 0, 0, 0, 1, 0, 0, 0, 93, 8, 0, 1, 92, 8, 0, 1,
+ 103, 0, 0, 4, 242, 32, 16, 0, 0, 0, 0, 0, 1, 0, 0, 0, 101, 0, 0,
+ 3, 18, 32, 16, 0, 1, 0, 0, 0, 103, 0, 0, 4, 34, 32, 16, 0, 1, 0,
+ 0, 0, 4, 0, 0, 0, 94, 0, 0, 2, 1, 0, 0, 0, 54, 0, 0, 6, 242,
+ 32, 16, 0, 0, 0, 0, 0, 70, 30, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 32, 16, 0, 1, 0, 0, 0, 10, 16, 32, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 54, 0, 0, 6, 34, 32, 16, 0, 1, 0, 0, 0, 26, 16,
+ 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 19, 0, 0, 1, 62, 0, 0, 1, 83,
+ 84, 65, 84, 116, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h
new file mode 100644
index 0000000000..87730ffe5c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h
@@ -0,0 +1,65 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Buffer4F texture float4 buf t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float
+// TEXCOORD 0 x 1 NONE uint x
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_resource_buffer (float,float,float,float) t0
+dcl_input_ps constant v1.x
+dcl_output o0.xyzw
+ld o0.xyzw, v1.xxxx, t0.xyzw
+ret
+// Approximately 2 instruction slots used
+#endif
+
+const BYTE g_PS_BufferToTexture_4F[] = {
+ 68, 88, 66, 67, 156, 38, 137, 246, 11, 113, 21, 186, 20, 101, 47, 15, 216, 211, 176,
+ 224, 1, 0, 0, 0, 12, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 4, 1, 0, 0, 56, 1, 0, 0, 144, 1, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 5, 0, 0, 0, 1, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 66, 117, 102, 102, 101, 114, 52, 70, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171,
+ 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 1, 0, 0, 83, 86, 95, 80, 111, 115, 105, 116, 105, 111, 110,
+ 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84,
+ 97, 114, 103, 101, 116, 0, 171, 171, 83, 72, 68, 82, 80, 0, 0, 0, 64, 0, 0,
+ 0, 20, 0, 0, 0, 88, 8, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85,
+ 0, 0, 98, 8, 0, 3, 18, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 32, 16, 0, 0, 0, 0, 0,
+ 6, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 62, 0, 0,
+ 1, 83, 84, 65, 84, 116, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h
new file mode 100644
index 0000000000..64304f956d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h
@@ -0,0 +1,65 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Buffer4I texture sint4 buf t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float
+// TEXCOORD 0 x 1 NONE uint x
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_buffer (sint,sint,sint,sint) t0
+dcl_input_ps constant v1.x
+dcl_output o0.xyzw
+ld o0.xyzw, v1.xxxx, t0.xyzw
+ret
+// Approximately 2 instruction slots used
+#endif
+
+const BYTE g_PS_BufferToTexture_4I[] = {
+ 68, 88, 66, 67, 162, 203, 46, 4, 155, 72, 142, 126, 228, 80, 83, 117, 139, 11, 48,
+ 250, 1, 0, 0, 0, 12, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 4, 1, 0, 0, 56, 1, 0, 0, 144, 1, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 1, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 66, 117, 102, 102, 101, 114, 52, 73, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171,
+ 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 1, 0, 0, 83, 86, 95, 80, 111, 115, 105, 116, 105, 111, 110,
+ 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84,
+ 97, 114, 103, 101, 116, 0, 171, 171, 83, 72, 68, 82, 80, 0, 0, 0, 64, 0, 0,
+ 0, 20, 0, 0, 0, 88, 8, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 51, 51,
+ 0, 0, 98, 8, 0, 3, 18, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 32, 16, 0, 0, 0, 0, 0,
+ 6, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 62, 0, 0,
+ 1, 83, 84, 65, 84, 116, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h
new file mode 100644
index 0000000000..9504753bde
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h
@@ -0,0 +1,65 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Buffer4UI texture uint4 buf t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float
+// TEXCOORD 0 x 1 NONE uint x
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_buffer (uint,uint,uint,uint) t0
+dcl_input_ps constant v1.x
+dcl_output o0.xyzw
+ld o0.xyzw, v1.xxxx, t0.xyzw
+ret
+// Approximately 2 instruction slots used
+#endif
+
+const BYTE g_PS_BufferToTexture_4UI[] = {
+ 68, 88, 66, 67, 168, 39, 110, 5, 143, 0, 75, 136, 251, 25, 27, 24, 35, 191, 3,
+ 64, 1, 0, 0, 0, 12, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 4, 1, 0, 0, 56, 1, 0, 0, 144, 1, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 70, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 1, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 66, 117, 102, 102, 101, 114, 52, 85, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171,
+ 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 1, 0, 0, 83, 86, 95, 80, 111, 115, 105, 116, 105, 111, 110,
+ 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84,
+ 97, 114, 103, 101, 116, 0, 171, 171, 83, 72, 68, 82, 80, 0, 0, 0, 64, 0, 0,
+ 0, 20, 0, 0, 0, 88, 8, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 68, 68,
+ 0, 0, 98, 8, 0, 3, 18, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 32, 16, 0, 0, 0, 0, 0,
+ 6, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 62, 0, 0,
+ 1, 83, 84, 65, 84, 116, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h
new file mode 100644
index 0000000000..b9ce502123
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h
@@ -0,0 +1,145 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer BufferCopyParams
+// {
+//
+// uint FirstPixelOffset; // Offset: 0 Size: 4
+// uint PixelsPerRow; // Offset: 4 Size: 4
+// uint RowStride; // Offset: 8 Size: 4
+// uint RowsPerSlice; // Offset: 12 Size: 4
+// float2 PositionOffset; // Offset: 16 Size: 8
+// float2 PositionScale; // Offset: 24 Size: 8
+// int2 TexLocationOffset; // Offset: 32 Size: 8 [unused]
+// int2 TexLocationScale; // Offset: 40 Size: 8 [unused]
+// uint FirstSlice; // Offset: 48 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// BufferCopyParams cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_VertexID 0 x 0 VERTID uint x
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float xyzw
+// TEXCOORD 0 x 1 NONE uint x
+// LAYER 0 y 1 NONE uint y
+//
+vs_4_0
+dcl_constantbuffer CB0[4], immediateIndexed
+dcl_input_sgv v0.x, vertex_id
+dcl_output_siv o0.xyzw, position
+dcl_output o1.x
+dcl_output o1.y
+dcl_temps 2
+mov o0.zw, l(0,0,0,1.000000)
+imul null, r0.xy, cb0[0].wwww, cb0[0].yzyy
+udiv r0.z, null, v0.x, r0.x
+imad r0.x, -r0.z, r0.x, v0.x
+imad r0.y, r0.z, r0.y, cb0[0].x
+iadd o1.y, r0.z, cb0[3].x
+udiv r0.z, null, r0.x, cb0[0].y
+imad r0.x, -r0.z, cb0[0].y, r0.x
+utof r1.xy, r0.xzxx
+imad r0.y, r0.z, cb0[0].z, r0.y
+iadd o1.x, r0.x, r0.y
+mad o0.xy, cb0[1].zwzz, r1.xyxx, cb0[1].xyxx
+ret
+// Approximately 13 instruction slots used
+#endif
+
+const BYTE g_VS_BufferToTexture[] = {
+ 68, 88, 66, 67, 153, 33, 196, 57, 209, 115, 237, 17, 59, 231, 206, 105, 1, 81, 121,
+ 39, 1, 0, 0, 0, 140, 5, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 88, 2,
+ 0, 0, 140, 2, 0, 0, 0, 3, 0, 0, 16, 5, 0, 0, 82, 68, 69, 70, 28,
+ 2, 0, 0, 1, 0, 0, 0, 80, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 254, 255, 0, 1, 0, 0, 244, 1, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 66, 117, 102, 102, 101, 114, 67, 111, 112, 121, 80, 97, 114,
+ 97, 109, 115, 0, 171, 171, 171, 60, 0, 0, 0, 9, 0, 0, 0, 104, 0, 0, 0,
+ 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 0,
+ 0, 4, 0, 0, 0, 2, 0, 0, 0, 84, 1, 0, 0, 0, 0, 0, 0, 100, 1,
+ 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 84, 1, 0, 0, 0,
+ 0, 0, 0, 113, 1, 0, 0, 8, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0,
+ 84, 1, 0, 0, 0, 0, 0, 0, 123, 1, 0, 0, 12, 0, 0, 0, 4, 0, 0,
+ 0, 2, 0, 0, 0, 84, 1, 0, 0, 0, 0, 0, 0, 136, 1, 0, 0, 16, 0,
+ 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 152, 1, 0, 0, 0, 0, 0, 0, 168,
+ 1, 0, 0, 24, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 152, 1, 0, 0,
+ 0, 0, 0, 0, 182, 1, 0, 0, 32, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0,
+ 0, 200, 1, 0, 0, 0, 0, 0, 0, 216, 1, 0, 0, 40, 0, 0, 0, 8, 0,
+ 0, 0, 0, 0, 0, 0, 200, 1, 0, 0, 0, 0, 0, 0, 233, 1, 0, 0, 48,
+ 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 84, 1, 0, 0, 0, 0, 0, 0,
+ 70, 105, 114, 115, 116, 80, 105, 120, 101, 108, 79, 102, 102, 115, 101, 116, 0, 171, 171,
+ 171, 0, 0, 19, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 105,
+ 120, 101, 108, 115, 80, 101, 114, 82, 111, 119, 0, 82, 111, 119, 83, 116, 114, 105, 100,
+ 101, 0, 82, 111, 119, 115, 80, 101, 114, 83, 108, 105, 99, 101, 0, 80, 111, 115, 105,
+ 116, 105, 111, 110, 79, 102, 102, 115, 101, 116, 0, 171, 1, 0, 3, 0, 1, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 111, 115, 105, 116, 105, 111, 110, 83, 99,
+ 97, 108, 101, 0, 84, 101, 120, 76, 111, 99, 97, 116, 105, 111, 110, 79, 102, 102, 115,
+ 101, 116, 0, 1, 0, 2, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 84, 101, 120, 76, 111, 99, 97, 116, 105, 111, 110, 83, 99, 97, 108, 101, 0, 70, 105,
+ 114, 115, 116, 83, 108, 105, 99, 101, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32,
+ 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 83, 86, 95, 86, 101, 114,
+ 116, 101, 120, 73, 68, 0, 79, 83, 71, 78, 108, 0, 0, 0, 3, 0, 0, 0, 8,
+ 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 14, 0, 0, 101, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 13, 0, 0, 83,
+ 86, 95, 80, 111, 115, 105, 116, 105, 111, 110, 0, 84, 69, 88, 67, 79, 79, 82, 68,
+ 0, 76, 65, 89, 69, 82, 0, 171, 83, 72, 68, 82, 8, 2, 0, 0, 64, 0, 1,
+ 0, 130, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 4, 0,
+ 0, 0, 96, 0, 0, 4, 18, 16, 16, 0, 0, 0, 0, 0, 6, 0, 0, 0, 103,
+ 0, 0, 4, 242, 32, 16, 0, 0, 0, 0, 0, 1, 0, 0, 0, 101, 0, 0, 3,
+ 18, 32, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 34, 32, 16, 0, 1, 0, 0,
+ 0, 104, 0, 0, 2, 2, 0, 0, 0, 54, 0, 0, 8, 194, 32, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 128, 63, 38, 0, 0, 10, 0, 208, 0, 0, 50, 0, 16, 0, 0, 0, 0, 0,
+ 246, 143, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 133, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 78, 0, 0, 8, 66, 0, 16, 0, 0, 0, 0, 0, 0, 208,
+ 0, 0, 10, 16, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 35,
+ 0, 0, 10, 18, 0, 16, 0, 0, 0, 0, 0, 42, 0, 16, 128, 65, 0, 0, 0,
+ 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 0, 0, 0,
+ 0, 35, 0, 0, 10, 34, 0, 16, 0, 0, 0, 0, 0, 42, 0, 16, 0, 0, 0,
+ 0, 0, 26, 0, 16, 0, 0, 0, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 30, 0, 0, 8, 34, 32, 16, 0, 1, 0, 0, 0, 42, 0, 16, 0,
+ 0, 0, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 3, 0, 0, 0, 78, 0, 0,
+ 9, 66, 0, 16, 0, 0, 0, 0, 0, 0, 208, 0, 0, 10, 0, 16, 0, 0, 0,
+ 0, 0, 26, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 11, 18,
+ 0, 16, 0, 0, 0, 0, 0, 42, 0, 16, 128, 65, 0, 0, 0, 0, 0, 0, 0,
+ 26, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0,
+ 0, 86, 0, 0, 5, 50, 0, 16, 0, 1, 0, 0, 0, 134, 0, 16, 0, 0, 0,
+ 0, 0, 35, 0, 0, 10, 34, 0, 16, 0, 0, 0, 0, 0, 42, 0, 16, 0, 0,
+ 0, 0, 0, 42, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 16, 0,
+ 0, 0, 0, 0, 30, 0, 0, 7, 18, 32, 16, 0, 1, 0, 0, 0, 10, 0, 16,
+ 0, 0, 0, 0, 0, 26, 0, 16, 0, 0, 0, 0, 0, 50, 0, 0, 11, 50, 32,
+ 16, 0, 0, 0, 0, 0, 230, 138, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 70,
+ 0, 16, 0, 1, 0, 0, 0, 70, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 13, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 7, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11_fl9vs.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11_fl9vs.h
new file mode 100644
index 0000000000..9b4ccfb902
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11_fl9vs.h
@@ -0,0 +1,71 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION 0 xyzw 0 NONE float xyzw
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+//
+//
+// Runtime generated constant mappings:
+//
+// Target Reg Constant Description
+// ---------- --------------------------------------------------
+// c0 Vertex Shader position offset
+//
+//
+// Level9 shader bytecode:
+//
+ vs_2_x
+ dcl_texcoord v0
+ mad oPos.xy, v0.w, c0, v0
+ mov oPos.zw, v0
+
+// approximately 2 instruction slots used
+vs_4_0
+dcl_input v0.xyzw
+dcl_output_siv o0.xyzw, position
+mov o0.xyzw, v0.xyzw
+ret
+// Approximately 2 instruction slots used
+#endif
+
+const BYTE g_VS_Clear_FL9[] = {
+ 68, 88, 66, 67, 166, 109, 78, 113, 107, 98, 65, 70, 91, 88, 250, 161, 103, 22, 241, 76,
+ 1, 0, 0, 0, 16, 2, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 156, 0, 0, 0,
+ 224, 0, 0, 0, 92, 1, 0, 0, 168, 1, 0, 0, 220, 1, 0, 0, 65, 111, 110, 57,
+ 92, 0, 0, 0, 92, 0, 0, 0, 0, 2, 254, 255, 52, 0, 0, 0, 40, 0, 0, 0,
+ 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36, 0, 1, 0, 36, 0,
+ 0, 0, 0, 0, 1, 2, 254, 255, 31, 0, 0, 2, 5, 0, 0, 128, 0, 0, 15, 144,
+ 4, 0, 0, 4, 0, 0, 3, 192, 0, 0, 255, 144, 0, 0, 228, 160, 0, 0, 228, 144,
+ 1, 0, 0, 2, 0, 0, 12, 192, 0, 0, 228, 144, 255, 255, 0, 0, 83, 72, 68, 82,
+ 60, 0, 0, 0, 64, 0, 1, 0, 15, 0, 0, 0, 95, 0, 0, 3, 242, 16, 16, 0,
+ 0, 0, 0, 0, 103, 0, 0, 4, 242, 32, 16, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 54, 0, 0, 5, 242, 32, 16, 0, 0, 0, 0, 0, 70, 30, 16, 0, 0, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 82, 68, 69, 70, 68, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 4, 254, 255, 0, 1, 0, 0,
+ 28, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76,
+ 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49,
+ 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 15, 15, 0, 0, 80, 79, 83, 73, 84, 73, 79, 78, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewgs.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewgs.h
new file mode 100644
index 0000000000..92b192107b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewgs.h
@@ -0,0 +1,83 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float xyzw
+// TEXCOORD 0 x 1 NONE uint x
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float xyzw
+// SV_RenderTargetArrayIndex 0 x 1 RTINDEX uint x
+//
+gs_4_0
+dcl_input_siv v[3][0].xyzw, position
+dcl_input v[3][1].x
+dcl_temps 1
+dcl_inputprimitive triangle
+dcl_outputtopology trianglestrip
+dcl_output_siv o0.xyzw, position
+dcl_output_siv o1.x, rendertarget_array_index
+dcl_maxout 3
+mov r0.x, l(0)
+loop
+ ige r0.y, r0.x, l(3)
+ breakc_nz r0.y
+ mov o0.xyzw, v[r0.x + 0][0].xyzw
+ mov o1.x, v[r0.x + 0][1].x
+ emit
+ iadd r0.x, r0.x, l(1)
+endloop
+cut
+ret
+// Approximately 11 instruction slots used
+#endif
+
+const BYTE g_GS_Multiview_Clear[] = {
+ 68, 88, 66, 67, 110, 37, 141, 207, 15, 59, 27, 66, 207, 215, 205, 198, 147, 31, 42,
+ 22, 1, 0, 0, 0, 204, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 128, 0,
+ 0, 0, 216, 0, 0, 0, 64, 1, 0, 0, 80, 2, 0, 0, 82, 68, 69, 70, 68,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 83, 71, 0, 1, 0, 0, 28, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 80,
+ 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 15, 0, 0, 68, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1,
+ 0, 0, 83, 86, 95, 80, 111, 115, 105, 116, 105, 111, 110, 0, 84, 69, 88, 67, 79,
+ 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 96, 0, 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 4, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 14, 0, 0, 83, 86, 95, 80, 111,
+ 115, 105, 116, 105, 111, 110, 0, 83, 86, 95, 82, 101, 110, 100, 101, 114, 84, 97, 114,
+ 103, 101, 116, 65, 114, 114, 97, 121, 73, 110, 100, 101, 120, 0, 171, 171, 83, 72, 68,
+ 82, 8, 1, 0, 0, 64, 0, 2, 0, 66, 0, 0, 0, 97, 0, 0, 5, 242, 16,
+ 32, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 95, 0, 0, 4, 18,
+ 16, 32, 0, 3, 0, 0, 0, 1, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0,
+ 93, 24, 0, 1, 92, 40, 0, 1, 103, 0, 0, 4, 242, 32, 16, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 103, 0, 0, 4, 18, 32, 16, 0, 1, 0, 0, 0, 4, 0,
+ 0, 0, 94, 0, 0, 2, 3, 0, 0, 0, 54, 0, 0, 5, 18, 0, 16, 0, 0,
+ 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 48, 0, 0, 1, 33, 0, 0, 7,
+ 34, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0,
+ 0, 3, 0, 0, 0, 3, 0, 4, 3, 26, 0, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 7, 242, 32, 16, 0, 0, 0, 0, 0, 70, 30, 160, 0, 10, 0, 16, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 18, 32, 16, 0, 1, 0, 0, 0,
+ 10, 16, 160, 0, 10, 0, 16, 0, 0, 0, 0, 0, 1, 0, 0, 0, 19, 0, 0,
+ 1, 30, 0, 0, 7, 18, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0, 1, 0, 0, 0, 22, 0, 0, 1, 9, 0, 0, 1, 62,
+ 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 11, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewvs.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewvs.h
new file mode 100644
index 0000000000..ba1c5425e2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewvs.h
@@ -0,0 +1,80 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_VertexID 0 x 0 VERTID uint x
+// SV_InstanceID 0 x 1 INSTID uint x
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// TEXCOORD 0 x 1 NONE uint x
+//
+vs_4_0
+dcl_immediateConstantBuffer { { -1.000000, 1.000000, 0, 0},
+ { 1.000000, -1.000000, 0, 0},
+ { -1.000000, -1.000000, 0, 0},
+ { -1.000000, 1.000000, 0, 0},
+ { 1.000000, 1.000000, 0, 0},
+ { 1.000000, -1.000000, 0, 0} }
+dcl_input_sgv v0.x, vertex_id
+dcl_input_sgv v1.x, instance_id
+dcl_output_siv o0.xyzw, position
+dcl_output o1.x
+dcl_temps 1
+mov r0.x, v0.x
+mov o0.xy, icb[r0.x + 0].xyxx
+mov o0.zw, l(0,0,0,1.000000)
+mov o1.x, v1.x
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_VS_Multiview_Clear[] = {
+ 68, 88, 66, 67, 29, 63, 249, 196, 208, 130, 142, 190, 155, 101, 165, 213, 91, 14, 122,
+ 2, 1, 0, 0, 0, 208, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 128, 0,
+ 0, 0, 220, 0, 0, 0, 52, 1, 0, 0, 84, 2, 0, 0, 82, 68, 69, 70, 68,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 254, 255, 0, 1, 0, 0, 28, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 84,
+ 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 68, 0, 0,
+ 0, 0, 0, 0, 0, 8, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1,
+ 0, 0, 83, 86, 95, 86, 101, 114, 116, 101, 120, 73, 68, 0, 83, 86, 95, 73, 110,
+ 115, 116, 97, 110, 99, 101, 73, 68, 0, 171, 171, 79, 83, 71, 78, 80, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 14, 0, 0, 83,
+ 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68,
+ 0, 171, 171, 171, 83, 72, 68, 82, 24, 1, 0, 0, 64, 0, 1, 0, 70, 0, 0,
+ 0, 53, 24, 0, 0, 26, 0, 0, 0, 0, 0, 128, 191, 0, 0, 128, 63, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 128, 191, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 128, 191, 0, 0, 128, 191, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 128, 191, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128,
+ 63, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0,
+ 128, 191, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 4, 18, 16, 16, 0, 0,
+ 0, 0, 0, 6, 0, 0, 0, 96, 0, 0, 4, 18, 16, 16, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 103, 0, 0, 4, 242, 32, 16, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 101, 0, 0, 3, 18, 32, 16, 0, 1, 0, 0, 0, 104, 0, 0, 2, 1, 0,
+ 0, 0, 54, 0, 0, 5, 18, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 0,
+ 0, 0, 0, 54, 0, 0, 6, 50, 32, 16, 0, 0, 0, 0, 0, 70, 144, 144, 0,
+ 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 8, 194, 32, 16, 0, 0, 0, 0,
+ 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 128, 63, 54, 0, 0, 5, 18, 32, 16, 0, 1, 0, 0, 0, 10, 16, 16, 0, 1,
+ 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 5, 0, 0, 0,
+ 1, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11vs.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11vs.h
new file mode 100644
index 0000000000..035a1fdca0
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11vs.h
@@ -0,0 +1,69 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_VertexID 0 x 0 VERTID uint x
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+//
+vs_4_0
+dcl_immediateConstantBuffer { { -1.000000, 1.000000, 0, 0},
+ { 1.000000, -1.000000, 0, 0},
+ { -1.000000, -1.000000, 0, 0},
+ { -1.000000, 1.000000, 0, 0},
+ { 1.000000, 1.000000, 0, 0},
+ { 1.000000, -1.000000, 0, 0} }
+dcl_input_sgv v0.x, vertex_id
+dcl_output_siv o0.xyzw, position
+dcl_temps 1
+mov r0.x, v0.x
+mov o0.xy, icb[r0.x + 0].xyxx
+mov o0.zw, l(0,0,0,1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_VS_Clear[] = {
+ 68, 88, 66, 67, 142, 0, 156, 121, 128, 35, 189, 41, 14, 141, 59, 193, 158, 19, 28,
+ 184, 1, 0, 0, 0, 84, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 128, 0,
+ 0, 0, 180, 0, 0, 0, 232, 0, 0, 0, 216, 1, 0, 0, 82, 68, 69, 70, 68,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 254, 255, 0, 1, 0, 0, 28, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 83, 86, 95,
+ 86, 101, 114, 116, 101, 120, 73, 68, 0, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 83, 72, 68, 82, 232, 0, 0, 0, 64, 0, 1, 0, 58, 0, 0,
+ 0, 53, 24, 0, 0, 26, 0, 0, 0, 0, 0, 128, 191, 0, 0, 128, 63, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 128, 191, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 128, 191, 0, 0, 128, 191, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 128, 191, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128,
+ 63, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0,
+ 128, 191, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 4, 18, 16, 16, 0, 0,
+ 0, 0, 0, 6, 0, 0, 0, 103, 0, 0, 4, 242, 32, 16, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 54, 0, 0, 5, 18, 0, 16,
+ 0, 0, 0, 0, 0, 10, 16, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 50, 32,
+ 16, 0, 0, 0, 0, 0, 70, 144, 144, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 8, 194, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65,
+ 84, 116, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/cleardepth11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/cleardepth11ps.h
new file mode 100644
index 0000000000..41a39aead9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/cleardepth11ps.h
@@ -0,0 +1,74 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer DepthOnlyData
+// {
+//
+// float zValue_Depth; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// DepthOnlyData cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output oDepth
+mov oDepth, cb0[1].x
+ret
+// Approximately 2 instruction slots used
+#endif
+
+const BYTE g_PS_ClearDepth[] = {
+ 68, 88, 66, 67, 27, 164, 102, 59, 78, 154, 233, 127, 65, 17, 101, 9, 4, 119, 201,
+ 97, 1, 0, 0, 0, 36, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 0, 1,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 168, 1, 0, 0, 82, 68, 69, 70, 196,
+ 0, 0, 0, 1, 0, 0, 0, 76, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 156, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 68, 101, 112, 116, 104, 79, 110, 108, 121, 68, 97, 116, 97,
+ 0, 171, 171, 60, 0, 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 124, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0,
+ 0, 2, 0, 0, 0, 140, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97, 108, 117, 101,
+ 95, 68, 101, 112, 116, 104, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82,
+ 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105,
+ 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84,
+ 73, 79, 78, 0, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 255,
+ 255, 255, 1, 14, 0, 0, 83, 86, 95, 68, 69, 80, 84, 72, 0, 171, 171, 171, 83,
+ 72, 68, 82, 56, 0, 0, 0, 64, 0, 0, 0, 14, 0, 0, 0, 89, 0, 0, 4,
+ 70, 142, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 101, 0, 0, 2, 1, 192, 0,
+ 0, 54, 0, 0, 5, 1, 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h
new file mode 100644
index 0000000000..cebc263110
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h
@@ -0,0 +1,128 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataFloat
+// {
+//
+// float4 color_Float; // Offset: 0 Size: 16
+// float zValueF_Float; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataFloat cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+// SV_TARGET 1 xyzw 1 TARGET float xyzw
+// SV_TARGET 2 xyzw 2 TARGET float xyzw
+// SV_TARGET 3 xyzw 3 TARGET float xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+//
+// Constant buffer to DX9 shader constant mappings:
+//
+// Target Reg Buffer Start Reg # of Regs Data Conversion
+// ---------- ------- --------- --------- ----------------------
+// c0 cb0 0 2 ( FLT, FLT, FLT, FLT)
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ mov oC0, c0
+ mov oC1, c0
+ mov oC2, c0
+ mov oC3, c0
+ mov oDepth, c1.x
+
+// approximately 5 instruction slots used
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_ClearFloat_FL9[] = {
+ 68, 88, 66, 67, 85, 216, 43, 21, 188, 93, 222, 90, 179, 114, 11, 205, 194, 17, 203,
+ 168, 1, 0, 0, 0, 216, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 180, 0,
+ 0, 0, 132, 1, 0, 0, 0, 2, 0, 0, 8, 3, 0, 0, 60, 3, 0, 0, 65,
+ 111, 110, 57, 116, 0, 0, 0, 116, 0, 0, 0, 0, 2, 255, 255, 68, 0, 0, 0,
+ 48, 0, 0, 0, 1, 0, 36, 0, 0, 0, 48, 0, 0, 0, 48, 0, 0, 0, 36,
+ 0, 0, 0, 48, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 2,
+ 255, 255, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 160, 1, 0, 0, 2, 1,
+ 8, 15, 128, 0, 0, 228, 160, 1, 0, 0, 2, 2, 8, 15, 128, 0, 0, 228, 160,
+ 1, 0, 0, 2, 3, 8, 15, 128, 0, 0, 228, 160, 1, 0, 0, 2, 0, 8, 15,
+ 144, 1, 0, 0, 160, 255, 255, 0, 0, 83, 72, 68, 82, 200, 0, 0, 0, 64, 0,
+ 0, 0, 50, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 2, 0, 0,
+ 0, 101, 0, 0, 3, 242, 32, 16, 0, 3, 0, 0, 0, 101, 0, 0, 2, 1, 192,
+ 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0, 0, 0,
+ 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16,
+ 0, 2, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0,
+ 0, 6, 242, 32, 16, 0, 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 54, 0, 0, 5, 1, 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,
+ 68, 69, 70, 0, 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68,
+ 101, 112, 116, 104, 68, 97, 116, 97, 70, 108, 111, 97, 116, 0, 171, 60, 0, 0, 0,
+ 2, 0, 0, 0, 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 156, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0,
+ 0, 0, 0, 0, 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2,
+ 0, 0, 0, 200, 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 70, 108,
+ 111, 97, 116, 0, 1, 0, 3, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 122, 86, 97, 108, 117, 101, 70, 95, 70, 108, 111, 97, 116, 0, 171, 171, 0, 0,
+ 3, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71,
+ 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83,
+ 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 148, 0, 0, 0,
+ 5, 0, 0, 0, 8, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 128, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 128,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 15, 0, 0, 0, 128, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 3, 0, 0, 0, 15, 0, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 0, 83, 86, 95, 84, 65,
+ 82, 71, 69, 84, 0, 83, 86, 95, 68, 69, 80, 84, 72, 0, 171};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps1.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps1.h
new file mode 100644
index 0000000000..d2845b994b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps1.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataFloat
+// {
+//
+// float4 color_Float; // Offset: 0 Size: 16
+// float zValueF_Float; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataFloat cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 3 instruction slots used
+#endif
+
+const BYTE g_PS_ClearFloat1[] = {
+ 68, 88, 66, 67, 249, 37, 129, 249, 125, 252, 189, 145, 109, 207, 171, 136, 14, 159, 102,
+ 81, 1, 0, 0, 0, 164, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 196, 1, 0, 0, 40, 2, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 70, 108, 111, 97, 116, 0, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 70, 108, 111, 97, 116, 0,
+ 1, 0, 3, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 70, 108, 111, 97, 116, 0, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 76, 0, 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 0, 83, 86, 95, 84, 65,
+ 82, 71, 69, 84, 0, 83, 86, 95, 68, 69, 80, 84, 72, 0, 171, 83, 72, 68, 82,
+ 92, 0, 0, 0, 64, 0, 0, 0, 23, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32,
+ 0, 0, 0, 0, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 101, 0, 0, 2, 1, 192, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0,
+ 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 1, 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0,
+ 1, 83, 84, 65, 84, 116, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps2.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps2.h
new file mode 100644
index 0000000000..b1b3a4e441
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps2.h
@@ -0,0 +1,91 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataFloat
+// {
+//
+// float4 color_Float; // Offset: 0 Size: 16
+// float zValueF_Float; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataFloat cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+// SV_TARGET 1 xyzw 1 TARGET float xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_ClearFloat2[] = {
+ 68, 88, 66, 67, 47, 142, 59, 204, 239, 80, 8, 161, 169, 171, 199, 199, 129, 33, 42,
+ 115, 1, 0, 0, 0, 224, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 220, 1, 0, 0, 100, 2, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 70, 108, 111, 97, 116, 0, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 70, 108, 111, 97, 116, 0,
+ 1, 0, 3, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 70, 108, 111, 97, 116, 0, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 100, 0, 0, 0, 3, 0, 0, 0,
+ 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 80, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 90, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 0,
+ 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 83, 86, 95, 68, 69, 80, 84, 72, 0,
+ 171, 83, 72, 68, 82, 128, 0, 0, 0, 64, 0, 0, 0, 32, 0, 0, 0, 89, 0,
+ 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 0, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 1, 0, 0, 0,
+ 101, 0, 0, 2, 1, 192, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0,
+ 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32,
+ 16, 0, 1, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 5, 1, 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps3.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps3.h
new file mode 100644
index 0000000000..e84854ff68
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps3.h
@@ -0,0 +1,97 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataFloat
+// {
+//
+// float4 color_Float; // Offset: 0 Size: 16
+// float zValueF_Float; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataFloat cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+// SV_TARGET 1 xyzw 1 TARGET float xyzw
+// SV_TARGET 2 xyzw 2 TARGET float xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_PS_ClearFloat3[] = {
+ 68, 88, 66, 67, 98, 17, 13, 150, 202, 50, 172, 72, 101, 93, 116, 134, 154, 66, 233,
+ 63, 1, 0, 0, 0, 28, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 244, 1, 0, 0, 160, 2, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 70, 108, 111, 97, 116, 0, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 70, 108, 111, 97, 116, 0,
+ 1, 0, 3, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 70, 108, 111, 97, 116, 0, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 124, 0, 0, 0, 4, 0, 0, 0,
+ 8, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 104, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 104, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 255, 255,
+ 255, 1, 14, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 83, 86, 95, 68,
+ 69, 80, 84, 72, 0, 171, 83, 72, 68, 82, 164, 0, 0, 0, 64, 0, 0, 0, 41,
+ 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16,
+ 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 2, 0, 0, 0, 101, 0,
+ 0, 2, 1, 192, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70,
+ 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0,
+ 1, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0,
+ 6, 242, 32, 16, 0, 2, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5, 1, 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps4.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps4.h
new file mode 100644
index 0000000000..60584aceef
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps4.h
@@ -0,0 +1,104 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataFloat
+// {
+//
+// float4 color_Float; // Offset: 0 Size: 16
+// float zValueF_Float; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataFloat cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+// SV_TARGET 1 xyzw 1 TARGET float xyzw
+// SV_TARGET 2 xyzw 2 TARGET float xyzw
+// SV_TARGET 3 xyzw 3 TARGET float xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_ClearFloat4[] = {
+ 68, 88, 66, 67, 138, 36, 21, 91, 225, 8, 214, 250, 89, 152, 40, 168, 243, 126, 8,
+ 187, 1, 0, 0, 0, 88, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 12, 2, 0, 0, 220, 2, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 70, 108, 111, 97, 116, 0, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 70, 108, 111, 97, 116, 0,
+ 1, 0, 3, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 70, 108, 111, 97, 116, 0, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 148, 0, 0, 0, 5, 0, 0, 0,
+ 8, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 128, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 128, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 128, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0,
+ 0, 15, 0, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 255, 255, 255, 255, 1, 14, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84,
+ 0, 83, 86, 95, 68, 69, 80, 84, 72, 0, 171, 83, 72, 68, 82, 200, 0, 0, 0,
+ 64, 0, 0, 0, 50, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 2,
+ 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 3, 0, 0, 0, 101, 0, 0, 2,
+ 1, 192, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0,
+ 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242,
+ 32, 16, 0, 2, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 242, 32, 16, 0, 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 54, 0, 0, 5, 1, 192, 0, 0, 10, 128, 32, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps5.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps5.h
new file mode 100644
index 0000000000..15c0545fee
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps5.h
@@ -0,0 +1,110 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataFloat
+// {
+//
+// float4 color_Float; // Offset: 0 Size: 16
+// float zValueF_Float; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataFloat cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+// SV_TARGET 1 xyzw 1 TARGET float xyzw
+// SV_TARGET 2 xyzw 2 TARGET float xyzw
+// SV_TARGET 3 xyzw 3 TARGET float xyzw
+// SV_TARGET 4 xyzw 4 TARGET float xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov o4.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_ClearFloat5[] = {
+ 68, 88, 66, 67, 19, 82, 125, 81, 104, 222, 105, 50, 128, 46, 184, 118, 230, 154, 80,
+ 52, 1, 0, 0, 0, 148, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 36, 2, 0, 0, 24, 3, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 70, 108, 111, 97, 116, 0, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 70, 108, 111, 97, 116, 0,
+ 1, 0, 3, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 70, 108, 111, 97, 116, 0, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 172, 0, 0, 0, 6, 0, 0, 0,
+ 8, 0, 0, 0, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 152, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 152, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 152, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0,
+ 0, 15, 0, 0, 0, 152, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 162, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0, 83, 86, 95, 68, 69, 80, 84, 72, 0, 171, 83, 72, 68,
+ 82, 236, 0, 0, 0, 64, 0, 0, 0, 59, 0, 0, 0, 89, 0, 0, 4, 70, 142,
+ 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0,
+ 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 3, 0, 0,
+ 0, 101, 0, 0, 3, 242, 32, 16, 0, 4, 0, 0, 0, 101, 0, 0, 2, 1, 192,
+ 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0, 0, 0,
+ 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16,
+ 0, 2, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0,
+ 0, 6, 242, 32, 16, 0, 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 4, 0, 0, 0, 70, 142, 32, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 5, 1, 192, 0, 0, 10, 128, 32,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0,
+ 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps6.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps6.h
new file mode 100644
index 0000000000..7cd6a03188
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps6.h
@@ -0,0 +1,116 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataFloat
+// {
+//
+// float4 color_Float; // Offset: 0 Size: 16
+// float zValueF_Float; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataFloat cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+// SV_TARGET 1 xyzw 1 TARGET float xyzw
+// SV_TARGET 2 xyzw 2 TARGET float xyzw
+// SV_TARGET 3 xyzw 3 TARGET float xyzw
+// SV_TARGET 4 xyzw 4 TARGET float xyzw
+// SV_TARGET 5 xyzw 5 TARGET float xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output o5.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov o4.xyzw, cb0[0].xyzw
+mov o5.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_ClearFloat6[] = {
+ 68, 88, 66, 67, 115, 157, 164, 56, 254, 153, 37, 126, 220, 182, 131, 196, 87, 71, 44,
+ 30, 1, 0, 0, 0, 208, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 60, 2, 0, 0, 84, 3, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 70, 108, 111, 97, 116, 0, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 70, 108, 111, 97, 116, 0,
+ 1, 0, 3, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 70, 108, 111, 97, 116, 0, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 196, 0, 0, 0, 7, 0, 0, 0,
+ 8, 0, 0, 0, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 176, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 176, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 176, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0,
+ 0, 15, 0, 0, 0, 176, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 176, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 15, 0, 0, 0, 186, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 1, 14, 0,
+ 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 83, 86, 95, 68, 69, 80, 84, 72,
+ 0, 171, 83, 72, 68, 82, 16, 1, 0, 0, 64, 0, 0, 0, 68, 0, 0, 0, 89,
+ 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 1, 0, 0,
+ 0, 101, 0, 0, 3, 242, 32, 16, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32,
+ 16, 0, 3, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 4, 0, 0, 0, 101,
+ 0, 0, 3, 242, 32, 16, 0, 5, 0, 0, 0, 101, 0, 0, 2, 1, 192, 0, 0,
+ 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0, 0, 0, 70, 142,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 2,
+ 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6,
+ 242, 32, 16, 0, 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 54, 0, 0, 6, 242, 32, 16, 0, 4, 0, 0, 0, 70, 142, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 5, 0, 0, 0, 70,
+ 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 5, 1, 192, 0, 0,
+ 10, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65,
+ 84, 116, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps7.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps7.h
new file mode 100644
index 0000000000..048471ad6b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps7.h
@@ -0,0 +1,122 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataFloat
+// {
+//
+// float4 color_Float; // Offset: 0 Size: 16
+// float zValueF_Float; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataFloat cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+// SV_TARGET 1 xyzw 1 TARGET float xyzw
+// SV_TARGET 2 xyzw 2 TARGET float xyzw
+// SV_TARGET 3 xyzw 3 TARGET float xyzw
+// SV_TARGET 4 xyzw 4 TARGET float xyzw
+// SV_TARGET 5 xyzw 5 TARGET float xyzw
+// SV_TARGET 6 xyzw 6 TARGET float xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output o5.xyzw
+dcl_output o6.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov o4.xyzw, cb0[0].xyzw
+mov o5.xyzw, cb0[0].xyzw
+mov o6.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_ClearFloat7[] = {
+ 68, 88, 66, 67, 142, 12, 138, 6, 10, 107, 58, 43, 178, 14, 208, 224, 48, 233, 91,
+ 50, 1, 0, 0, 0, 12, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 84, 2, 0, 0, 144, 3, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 70, 108, 111, 97, 116, 0, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 70, 108, 111, 97, 116, 0,
+ 1, 0, 3, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 70, 108, 111, 97, 116, 0, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 220, 0, 0, 0, 8, 0, 0, 0,
+ 8, 0, 0, 0, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 200, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 200, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0,
+ 0, 15, 0, 0, 0, 200, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 200, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 15, 0, 0, 0, 200, 0, 0, 0,
+ 6, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 15, 0, 0,
+ 0, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 255,
+ 255, 255, 1, 14, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 83, 86, 95,
+ 68, 69, 80, 84, 72, 0, 171, 83, 72, 68, 82, 52, 1, 0, 0, 64, 0, 0, 0,
+ 77, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 101, 0, 0, 3, 242, 32,
+ 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 2, 0, 0, 0, 101,
+ 0, 0, 3, 242, 32, 16, 0, 3, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0,
+ 4, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 5, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 6, 0, 0, 0, 101, 0, 0, 2, 1, 192, 0, 0, 54, 0,
+ 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0, 0, 0, 70, 142, 32, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 2, 0, 0,
+ 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32,
+ 16, 0, 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 6, 242, 32, 16, 0, 4, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 5, 0, 0, 0, 70, 142, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 6, 0,
+ 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 5, 1,
+ 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps8.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps8.h
new file mode 100644
index 0000000000..b338868e18
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps8.h
@@ -0,0 +1,128 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataFloat
+// {
+//
+// float4 color_Float; // Offset: 0 Size: 16
+// float zValueF_Float; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataFloat cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+// SV_TARGET 1 xyzw 1 TARGET float xyzw
+// SV_TARGET 2 xyzw 2 TARGET float xyzw
+// SV_TARGET 3 xyzw 3 TARGET float xyzw
+// SV_TARGET 4 xyzw 4 TARGET float xyzw
+// SV_TARGET 5 xyzw 5 TARGET float xyzw
+// SV_TARGET 6 xyzw 6 TARGET float xyzw
+// SV_TARGET 7 xyzw 7 TARGET float xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output o5.xyzw
+dcl_output o6.xyzw
+dcl_output o7.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov o4.xyzw, cb0[0].xyzw
+mov o5.xyzw, cb0[0].xyzw
+mov o6.xyzw, cb0[0].xyzw
+mov o7.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_ClearFloat8[] = {
+ 68, 88, 66, 67, 228, 232, 153, 58, 173, 161, 124, 75, 45, 184, 173, 123, 62, 150, 36,
+ 145, 1, 0, 0, 0, 72, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 108, 2, 0, 0, 204, 3, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 70, 108, 111, 97, 116, 0, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 70, 108, 111, 97, 116, 0,
+ 1, 0, 3, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 70, 108, 111, 97, 116, 0, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 244, 0, 0, 0, 9, 0, 0, 0,
+ 8, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 224, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 224, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 224, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0,
+ 0, 15, 0, 0, 0, 224, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 224, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 15, 0, 0, 0, 224, 0, 0, 0,
+ 6, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 6, 0, 0, 0, 15, 0, 0,
+ 0, 224, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 7, 0,
+ 0, 0, 15, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69,
+ 84, 0, 83, 86, 95, 68, 69, 80, 84, 72, 0, 171, 83, 72, 68, 82, 88, 1, 0,
+ 0, 64, 0, 0, 0, 86, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 101,
+ 0, 0, 3, 242, 32, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0,
+ 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 3, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 4, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 5, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 6, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 7, 0, 0, 0, 101, 0, 0, 2, 1, 192, 0, 0, 54, 0, 0, 6,
+ 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0, 0, 0, 70, 142, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 2, 0, 0, 0, 70,
+ 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0,
+ 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0,
+ 6, 242, 32, 16, 0, 4, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 5, 0, 0, 0, 70, 142, 32, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 6, 0, 0, 0,
+ 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16,
+ 0, 7, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 1, 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62,
+ 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps1.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps1.h
new file mode 100644
index 0000000000..d6139430ee
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps1.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataSint
+// {
+//
+// int4 color_Sint; // Offset: 0 Size: 16
+// float zValueF_Sint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataSint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 3 instruction slots used
+#endif
+
+const BYTE g_PS_ClearSint1[] = {
+ 68, 88, 66, 67, 231, 188, 2, 59, 91, 73, 220, 119, 245, 143, 245, 143, 240, 202, 170,
+ 163, 1, 0, 0, 0, 164, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 196, 1, 0, 0, 40, 2, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 83, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 83, 105, 110, 116, 0, 171,
+ 1, 0, 2, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 83, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 76, 0, 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 0, 83, 86, 95, 84, 65,
+ 82, 71, 69, 84, 0, 83, 86, 95, 68, 69, 80, 84, 72, 0, 171, 83, 72, 68, 82,
+ 92, 0, 0, 0, 64, 0, 0, 0, 23, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32,
+ 0, 0, 0, 0, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 101, 0, 0, 2, 1, 192, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0,
+ 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 1, 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0,
+ 1, 83, 84, 65, 84, 116, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps2.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps2.h
new file mode 100644
index 0000000000..a7cc7221ce
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps2.h
@@ -0,0 +1,91 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataSint
+// {
+//
+// int4 color_Sint; // Offset: 0 Size: 16
+// float zValueF_Sint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataSint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+// SV_TARGET 1 xyzw 1 TARGET int xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_ClearSint2[] = {
+ 68, 88, 66, 67, 85, 225, 210, 35, 166, 97, 84, 193, 114, 210, 51, 82, 238, 19, 251,
+ 198, 1, 0, 0, 0, 224, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 220, 1, 0, 0, 100, 2, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 83, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 83, 105, 110, 116, 0, 171,
+ 1, 0, 2, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 83, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 100, 0, 0, 0, 3, 0, 0, 0,
+ 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 80, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 90, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 0,
+ 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 83, 86, 95, 68, 69, 80, 84, 72, 0,
+ 171, 83, 72, 68, 82, 128, 0, 0, 0, 64, 0, 0, 0, 32, 0, 0, 0, 89, 0,
+ 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 0, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 1, 0, 0, 0,
+ 101, 0, 0, 2, 1, 192, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0,
+ 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32,
+ 16, 0, 1, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 5, 1, 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps3.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps3.h
new file mode 100644
index 0000000000..053de6d738
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps3.h
@@ -0,0 +1,97 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataSint
+// {
+//
+// int4 color_Sint; // Offset: 0 Size: 16
+// float zValueF_Sint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataSint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+// SV_TARGET 1 xyzw 1 TARGET int xyzw
+// SV_TARGET 2 xyzw 2 TARGET int xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_PS_ClearSint3[] = {
+ 68, 88, 66, 67, 101, 236, 110, 148, 64, 148, 5, 108, 246, 70, 148, 1, 36, 90, 92,
+ 9, 1, 0, 0, 0, 28, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 244, 1, 0, 0, 160, 2, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 83, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 83, 105, 110, 116, 0, 171,
+ 1, 0, 2, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 83, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 124, 0, 0, 0, 4, 0, 0, 0,
+ 8, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 104, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 104, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 255, 255,
+ 255, 1, 14, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 83, 86, 95, 68,
+ 69, 80, 84, 72, 0, 171, 83, 72, 68, 82, 164, 0, 0, 0, 64, 0, 0, 0, 41,
+ 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16,
+ 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 2, 0, 0, 0, 101, 0,
+ 0, 2, 1, 192, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70,
+ 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0,
+ 1, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0,
+ 6, 242, 32, 16, 0, 2, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5, 1, 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps4.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps4.h
new file mode 100644
index 0000000000..134f6253ee
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps4.h
@@ -0,0 +1,104 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataSint
+// {
+//
+// int4 color_Sint; // Offset: 0 Size: 16
+// float zValueF_Sint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataSint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+// SV_TARGET 1 xyzw 1 TARGET int xyzw
+// SV_TARGET 2 xyzw 2 TARGET int xyzw
+// SV_TARGET 3 xyzw 3 TARGET int xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_ClearSint4[] = {
+ 68, 88, 66, 67, 206, 59, 157, 191, 139, 37, 109, 85, 193, 141, 185, 200, 81, 149, 0,
+ 246, 1, 0, 0, 0, 88, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 12, 2, 0, 0, 220, 2, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 83, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 83, 105, 110, 116, 0, 171,
+ 1, 0, 2, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 83, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 148, 0, 0, 0, 5, 0, 0, 0,
+ 8, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 128, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 128, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 128, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0,
+ 0, 15, 0, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 255, 255, 255, 255, 1, 14, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84,
+ 0, 83, 86, 95, 68, 69, 80, 84, 72, 0, 171, 83, 72, 68, 82, 200, 0, 0, 0,
+ 64, 0, 0, 0, 50, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 2,
+ 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 3, 0, 0, 0, 101, 0, 0, 2,
+ 1, 192, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0,
+ 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242,
+ 32, 16, 0, 2, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 242, 32, 16, 0, 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 54, 0, 0, 5, 1, 192, 0, 0, 10, 128, 32, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps5.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps5.h
new file mode 100644
index 0000000000..3466e72460
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps5.h
@@ -0,0 +1,110 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataSint
+// {
+//
+// int4 color_Sint; // Offset: 0 Size: 16
+// float zValueF_Sint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataSint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+// SV_TARGET 1 xyzw 1 TARGET int xyzw
+// SV_TARGET 2 xyzw 2 TARGET int xyzw
+// SV_TARGET 3 xyzw 3 TARGET int xyzw
+// SV_TARGET 4 xyzw 4 TARGET int xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov o4.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_ClearSint5[] = {
+ 68, 88, 66, 67, 91, 91, 66, 76, 160, 92, 0, 147, 5, 30, 128, 248, 1, 125, 140,
+ 124, 1, 0, 0, 0, 148, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 36, 2, 0, 0, 24, 3, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 83, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 83, 105, 110, 116, 0, 171,
+ 1, 0, 2, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 83, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 172, 0, 0, 0, 6, 0, 0, 0,
+ 8, 0, 0, 0, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 152, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 152, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 152, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0,
+ 0, 15, 0, 0, 0, 152, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 162, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0, 83, 86, 95, 68, 69, 80, 84, 72, 0, 171, 83, 72, 68,
+ 82, 236, 0, 0, 0, 64, 0, 0, 0, 59, 0, 0, 0, 89, 0, 0, 4, 70, 142,
+ 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0,
+ 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 3, 0, 0,
+ 0, 101, 0, 0, 3, 242, 32, 16, 0, 4, 0, 0, 0, 101, 0, 0, 2, 1, 192,
+ 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0, 0, 0,
+ 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16,
+ 0, 2, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0,
+ 0, 6, 242, 32, 16, 0, 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 4, 0, 0, 0, 70, 142, 32, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 5, 1, 192, 0, 0, 10, 128, 32,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0,
+ 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps6.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps6.h
new file mode 100644
index 0000000000..b54bcf1fea
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps6.h
@@ -0,0 +1,116 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataSint
+// {
+//
+// int4 color_Sint; // Offset: 0 Size: 16
+// float zValueF_Sint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataSint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+// SV_TARGET 1 xyzw 1 TARGET int xyzw
+// SV_TARGET 2 xyzw 2 TARGET int xyzw
+// SV_TARGET 3 xyzw 3 TARGET int xyzw
+// SV_TARGET 4 xyzw 4 TARGET int xyzw
+// SV_TARGET 5 xyzw 5 TARGET int xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output o5.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov o4.xyzw, cb0[0].xyzw
+mov o5.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_ClearSint6[] = {
+ 68, 88, 66, 67, 245, 94, 2, 129, 134, 247, 241, 8, 253, 220, 200, 172, 215, 17, 127,
+ 35, 1, 0, 0, 0, 208, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 60, 2, 0, 0, 84, 3, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 83, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 83, 105, 110, 116, 0, 171,
+ 1, 0, 2, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 83, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 196, 0, 0, 0, 7, 0, 0, 0,
+ 8, 0, 0, 0, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 176, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 176, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 176, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0,
+ 0, 15, 0, 0, 0, 176, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 176, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 15, 0, 0, 0, 186, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 1, 14, 0,
+ 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 83, 86, 95, 68, 69, 80, 84, 72,
+ 0, 171, 83, 72, 68, 82, 16, 1, 0, 0, 64, 0, 0, 0, 68, 0, 0, 0, 89,
+ 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 1, 0, 0,
+ 0, 101, 0, 0, 3, 242, 32, 16, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32,
+ 16, 0, 3, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 4, 0, 0, 0, 101,
+ 0, 0, 3, 242, 32, 16, 0, 5, 0, 0, 0, 101, 0, 0, 2, 1, 192, 0, 0,
+ 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0, 0, 0, 70, 142,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 2,
+ 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6,
+ 242, 32, 16, 0, 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 54, 0, 0, 6, 242, 32, 16, 0, 4, 0, 0, 0, 70, 142, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 5, 0, 0, 0, 70,
+ 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 5, 1, 192, 0, 0,
+ 10, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65,
+ 84, 116, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps7.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps7.h
new file mode 100644
index 0000000000..0c7755d295
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps7.h
@@ -0,0 +1,122 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataSint
+// {
+//
+// int4 color_Sint; // Offset: 0 Size: 16
+// float zValueF_Sint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataSint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+// SV_TARGET 1 xyzw 1 TARGET int xyzw
+// SV_TARGET 2 xyzw 2 TARGET int xyzw
+// SV_TARGET 3 xyzw 3 TARGET int xyzw
+// SV_TARGET 4 xyzw 4 TARGET int xyzw
+// SV_TARGET 5 xyzw 5 TARGET int xyzw
+// SV_TARGET 6 xyzw 6 TARGET int xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output o5.xyzw
+dcl_output o6.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov o4.xyzw, cb0[0].xyzw
+mov o5.xyzw, cb0[0].xyzw
+mov o6.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_ClearSint7[] = {
+ 68, 88, 66, 67, 203, 48, 20, 196, 108, 146, 109, 165, 143, 63, 145, 150, 29, 34, 214,
+ 22, 1, 0, 0, 0, 12, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 84, 2, 0, 0, 144, 3, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 83, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 83, 105, 110, 116, 0, 171,
+ 1, 0, 2, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 83, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 220, 0, 0, 0, 8, 0, 0, 0,
+ 8, 0, 0, 0, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 200, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 200, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0,
+ 0, 15, 0, 0, 0, 200, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 200, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 15, 0, 0, 0, 200, 0, 0, 0,
+ 6, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 15, 0, 0,
+ 0, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 255,
+ 255, 255, 1, 14, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 83, 86, 95,
+ 68, 69, 80, 84, 72, 0, 171, 83, 72, 68, 82, 52, 1, 0, 0, 64, 0, 0, 0,
+ 77, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 101, 0, 0, 3, 242, 32,
+ 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 2, 0, 0, 0, 101,
+ 0, 0, 3, 242, 32, 16, 0, 3, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0,
+ 4, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 5, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 6, 0, 0, 0, 101, 0, 0, 2, 1, 192, 0, 0, 54, 0,
+ 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0, 0, 0, 70, 142, 32, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 2, 0, 0,
+ 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32,
+ 16, 0, 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 6, 242, 32, 16, 0, 4, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 5, 0, 0, 0, 70, 142, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 6, 0,
+ 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 5, 1,
+ 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps8.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps8.h
new file mode 100644
index 0000000000..10e77dfcc3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps8.h
@@ -0,0 +1,128 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataSint
+// {
+//
+// int4 color_Sint; // Offset: 0 Size: 16
+// float zValueF_Sint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataSint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+// SV_TARGET 1 xyzw 1 TARGET int xyzw
+// SV_TARGET 2 xyzw 2 TARGET int xyzw
+// SV_TARGET 3 xyzw 3 TARGET int xyzw
+// SV_TARGET 4 xyzw 4 TARGET int xyzw
+// SV_TARGET 5 xyzw 5 TARGET int xyzw
+// SV_TARGET 6 xyzw 6 TARGET int xyzw
+// SV_TARGET 7 xyzw 7 TARGET int xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output o5.xyzw
+dcl_output o6.xyzw
+dcl_output o7.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov o4.xyzw, cb0[0].xyzw
+mov o5.xyzw, cb0[0].xyzw
+mov o6.xyzw, cb0[0].xyzw
+mov o7.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_ClearSint8[] = {
+ 68, 88, 66, 67, 199, 7, 207, 179, 143, 119, 139, 38, 92, 223, 215, 110, 33, 171, 222,
+ 186, 1, 0, 0, 0, 72, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 108, 2, 0, 0, 204, 3, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 83, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 83, 105, 110, 116, 0, 171,
+ 1, 0, 2, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 83, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 244, 0, 0, 0, 9, 0, 0, 0,
+ 8, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 224, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 224, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 224, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0,
+ 0, 15, 0, 0, 0, 224, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 224, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 15, 0, 0, 0, 224, 0, 0, 0,
+ 6, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 6, 0, 0, 0, 15, 0, 0,
+ 0, 224, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 7, 0,
+ 0, 0, 15, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69,
+ 84, 0, 83, 86, 95, 68, 69, 80, 84, 72, 0, 171, 83, 72, 68, 82, 88, 1, 0,
+ 0, 64, 0, 0, 0, 86, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 101,
+ 0, 0, 3, 242, 32, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0,
+ 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 3, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 4, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 5, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 6, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 7, 0, 0, 0, 101, 0, 0, 2, 1, 192, 0, 0, 54, 0, 0, 6,
+ 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0, 0, 0, 70, 142, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 2, 0, 0, 0, 70,
+ 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0,
+ 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0,
+ 6, 242, 32, 16, 0, 4, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 5, 0, 0, 0, 70, 142, 32, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 6, 0, 0, 0,
+ 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16,
+ 0, 7, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 1, 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62,
+ 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps1.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps1.h
new file mode 100644
index 0000000000..10f1a56e51
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps1.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataUint
+// {
+//
+// uint4 color_Uint; // Offset: 0 Size: 16
+// float zValueF_Uint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataUint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 3 instruction slots used
+#endif
+
+const BYTE g_PS_ClearUint1[] = {
+ 68, 88, 66, 67, 153, 3, 197, 234, 233, 241, 61, 147, 138, 167, 150, 193, 156, 181, 197,
+ 213, 1, 0, 0, 0, 164, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 196, 1, 0, 0, 40, 2, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 85, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 85, 105, 110, 116, 0, 171,
+ 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 85, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 76, 0, 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 0, 83, 86, 95, 84, 65,
+ 82, 71, 69, 84, 0, 83, 86, 95, 68, 69, 80, 84, 72, 0, 171, 83, 72, 68, 82,
+ 92, 0, 0, 0, 64, 0, 0, 0, 23, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32,
+ 0, 0, 0, 0, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 101, 0, 0, 2, 1, 192, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0,
+ 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 1, 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0,
+ 1, 83, 84, 65, 84, 116, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps2.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps2.h
new file mode 100644
index 0000000000..8c94b388f9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps2.h
@@ -0,0 +1,91 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataUint
+// {
+//
+// uint4 color_Uint; // Offset: 0 Size: 16
+// float zValueF_Uint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataUint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+// SV_TARGET 1 xyzw 1 TARGET uint xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_ClearUint2[] = {
+ 68, 88, 66, 67, 192, 246, 30, 248, 11, 186, 26, 252, 71, 98, 86, 143, 152, 241, 57,
+ 66, 1, 0, 0, 0, 224, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 220, 1, 0, 0, 100, 2, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 85, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 85, 105, 110, 116, 0, 171,
+ 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 85, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 100, 0, 0, 0, 3, 0, 0, 0,
+ 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 80, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 90, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 0,
+ 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 83, 86, 95, 68, 69, 80, 84, 72, 0,
+ 171, 83, 72, 68, 82, 128, 0, 0, 0, 64, 0, 0, 0, 32, 0, 0, 0, 89, 0,
+ 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 0, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 1, 0, 0, 0,
+ 101, 0, 0, 2, 1, 192, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0,
+ 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32,
+ 16, 0, 1, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 5, 1, 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps3.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps3.h
new file mode 100644
index 0000000000..3c31a85656
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps3.h
@@ -0,0 +1,97 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataUint
+// {
+//
+// uint4 color_Uint; // Offset: 0 Size: 16
+// float zValueF_Uint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataUint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+// SV_TARGET 1 xyzw 1 TARGET uint xyzw
+// SV_TARGET 2 xyzw 2 TARGET uint xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_PS_ClearUint3[] = {
+ 68, 88, 66, 67, 122, 152, 146, 15, 20, 60, 207, 219, 181, 233, 35, 208, 96, 171, 60,
+ 29, 1, 0, 0, 0, 28, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 244, 1, 0, 0, 160, 2, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 85, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 85, 105, 110, 116, 0, 171,
+ 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 85, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 124, 0, 0, 0, 4, 0, 0, 0,
+ 8, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 104, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 104, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 114, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 255, 255,
+ 255, 1, 14, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 83, 86, 95, 68,
+ 69, 80, 84, 72, 0, 171, 83, 72, 68, 82, 164, 0, 0, 0, 64, 0, 0, 0, 41,
+ 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16,
+ 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 2, 0, 0, 0, 101, 0,
+ 0, 2, 1, 192, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70,
+ 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0,
+ 1, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0,
+ 6, 242, 32, 16, 0, 2, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5, 1, 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps4.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps4.h
new file mode 100644
index 0000000000..722f1f0acc
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps4.h
@@ -0,0 +1,104 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataUint
+// {
+//
+// uint4 color_Uint; // Offset: 0 Size: 16
+// float zValueF_Uint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataUint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+// SV_TARGET 1 xyzw 1 TARGET uint xyzw
+// SV_TARGET 2 xyzw 2 TARGET uint xyzw
+// SV_TARGET 3 xyzw 3 TARGET uint xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_ClearUint4[] = {
+ 68, 88, 66, 67, 255, 94, 158, 125, 94, 174, 68, 246, 120, 231, 8, 70, 114, 202, 111,
+ 31, 1, 0, 0, 0, 88, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 12, 2, 0, 0, 220, 2, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 85, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 85, 105, 110, 116, 0, 171,
+ 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 85, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 148, 0, 0, 0, 5, 0, 0, 0,
+ 8, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 128, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 128, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 128, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0,
+ 0, 15, 0, 0, 0, 138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 255, 255, 255, 255, 1, 14, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84,
+ 0, 83, 86, 95, 68, 69, 80, 84, 72, 0, 171, 83, 72, 68, 82, 200, 0, 0, 0,
+ 64, 0, 0, 0, 50, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 2,
+ 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 3, 0, 0, 0, 101, 0, 0, 2,
+ 1, 192, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0,
+ 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242,
+ 32, 16, 0, 2, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 242, 32, 16, 0, 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 54, 0, 0, 5, 1, 192, 0, 0, 10, 128, 32, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps5.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps5.h
new file mode 100644
index 0000000000..d387a76848
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps5.h
@@ -0,0 +1,110 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataUint
+// {
+//
+// uint4 color_Uint; // Offset: 0 Size: 16
+// float zValueF_Uint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataUint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+// SV_TARGET 1 xyzw 1 TARGET uint xyzw
+// SV_TARGET 2 xyzw 2 TARGET uint xyzw
+// SV_TARGET 3 xyzw 3 TARGET uint xyzw
+// SV_TARGET 4 xyzw 4 TARGET uint xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov o4.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_ClearUint5[] = {
+ 68, 88, 66, 67, 208, 22, 91, 140, 204, 34, 72, 161, 50, 27, 2, 156, 220, 29, 44,
+ 80, 1, 0, 0, 0, 148, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 36, 2, 0, 0, 24, 3, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 85, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 85, 105, 110, 116, 0, 171,
+ 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 85, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 172, 0, 0, 0, 6, 0, 0, 0,
+ 8, 0, 0, 0, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 152, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 152, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 152, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0,
+ 0, 15, 0, 0, 0, 152, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 162, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0, 83, 86, 95, 68, 69, 80, 84, 72, 0, 171, 83, 72, 68,
+ 82, 236, 0, 0, 0, 64, 0, 0, 0, 59, 0, 0, 0, 89, 0, 0, 4, 70, 142,
+ 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0,
+ 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 3, 0, 0,
+ 0, 101, 0, 0, 3, 242, 32, 16, 0, 4, 0, 0, 0, 101, 0, 0, 2, 1, 192,
+ 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0, 0, 0,
+ 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16,
+ 0, 2, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0,
+ 0, 6, 242, 32, 16, 0, 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 4, 0, 0, 0, 70, 142, 32, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 5, 1, 192, 0, 0, 10, 128, 32,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0,
+ 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps6.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps6.h
new file mode 100644
index 0000000000..b3dce8228d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps6.h
@@ -0,0 +1,116 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataUint
+// {
+//
+// uint4 color_Uint; // Offset: 0 Size: 16
+// float zValueF_Uint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataUint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+// SV_TARGET 1 xyzw 1 TARGET uint xyzw
+// SV_TARGET 2 xyzw 2 TARGET uint xyzw
+// SV_TARGET 3 xyzw 3 TARGET uint xyzw
+// SV_TARGET 4 xyzw 4 TARGET uint xyzw
+// SV_TARGET 5 xyzw 5 TARGET uint xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output o5.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov o4.xyzw, cb0[0].xyzw
+mov o5.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_ClearUint6[] = {
+ 68, 88, 66, 67, 78, 113, 96, 10, 75, 203, 142, 20, 121, 52, 202, 19, 182, 137, 113,
+ 117, 1, 0, 0, 0, 208, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 60, 2, 0, 0, 84, 3, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 85, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 85, 105, 110, 116, 0, 171,
+ 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 85, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 196, 0, 0, 0, 7, 0, 0, 0,
+ 8, 0, 0, 0, 176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 176, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 176, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 176, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0,
+ 0, 15, 0, 0, 0, 176, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 176, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 15, 0, 0, 0, 186, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 1, 14, 0,
+ 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 83, 86, 95, 68, 69, 80, 84, 72,
+ 0, 171, 83, 72, 68, 82, 16, 1, 0, 0, 64, 0, 0, 0, 68, 0, 0, 0, 89,
+ 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 1, 0, 0,
+ 0, 101, 0, 0, 3, 242, 32, 16, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32,
+ 16, 0, 3, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 4, 0, 0, 0, 101,
+ 0, 0, 3, 242, 32, 16, 0, 5, 0, 0, 0, 101, 0, 0, 2, 1, 192, 0, 0,
+ 54, 0, 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0, 0, 0, 70, 142,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 2,
+ 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6,
+ 242, 32, 16, 0, 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 54, 0, 0, 6, 242, 32, 16, 0, 4, 0, 0, 0, 70, 142, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 5, 0, 0, 0, 70,
+ 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 5, 1, 192, 0, 0,
+ 10, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65,
+ 84, 116, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps7.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps7.h
new file mode 100644
index 0000000000..95987043f2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps7.h
@@ -0,0 +1,122 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataUint
+// {
+//
+// uint4 color_Uint; // Offset: 0 Size: 16
+// float zValueF_Uint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataUint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+// SV_TARGET 1 xyzw 1 TARGET uint xyzw
+// SV_TARGET 2 xyzw 2 TARGET uint xyzw
+// SV_TARGET 3 xyzw 3 TARGET uint xyzw
+// SV_TARGET 4 xyzw 4 TARGET uint xyzw
+// SV_TARGET 5 xyzw 5 TARGET uint xyzw
+// SV_TARGET 6 xyzw 6 TARGET uint xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output o5.xyzw
+dcl_output o6.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov o4.xyzw, cb0[0].xyzw
+mov o5.xyzw, cb0[0].xyzw
+mov o6.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_ClearUint7[] = {
+ 68, 88, 66, 67, 187, 93, 194, 62, 133, 16, 185, 196, 51, 199, 55, 8, 8, 169, 14,
+ 118, 1, 0, 0, 0, 12, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 84, 2, 0, 0, 144, 3, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 85, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 85, 105, 110, 116, 0, 171,
+ 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 85, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 220, 0, 0, 0, 8, 0, 0, 0,
+ 8, 0, 0, 0, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 200, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 200, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 200, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0,
+ 0, 15, 0, 0, 0, 200, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 200, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 15, 0, 0, 0, 200, 0, 0, 0,
+ 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 15, 0, 0,
+ 0, 210, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 255,
+ 255, 255, 1, 14, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 83, 86, 95,
+ 68, 69, 80, 84, 72, 0, 171, 83, 72, 68, 82, 52, 1, 0, 0, 64, 0, 0, 0,
+ 77, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 101, 0, 0, 3, 242, 32,
+ 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 2, 0, 0, 0, 101,
+ 0, 0, 3, 242, 32, 16, 0, 3, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0,
+ 4, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 5, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 6, 0, 0, 0, 101, 0, 0, 2, 1, 192, 0, 0, 54, 0,
+ 0, 6, 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0, 0, 0, 70, 142, 32, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 2, 0, 0,
+ 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32,
+ 16, 0, 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 6, 242, 32, 16, 0, 4, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 5, 0, 0, 0, 70, 142, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 6, 0,
+ 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 5, 1,
+ 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps8.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps8.h
new file mode 100644
index 0000000000..c470ab47bf
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps8.h
@@ -0,0 +1,128 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer ColorAndDepthDataUint
+// {
+//
+// uint4 color_Uint; // Offset: 0 Size: 16
+// float zValueF_Uint; // Offset: 16 Size: 4
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// ColorAndDepthDataUint cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+// SV_TARGET 1 xyzw 1 TARGET uint xyzw
+// SV_TARGET 2 xyzw 2 TARGET uint xyzw
+// SV_TARGET 3 xyzw 3 TARGET uint xyzw
+// SV_TARGET 4 xyzw 4 TARGET uint xyzw
+// SV_TARGET 5 xyzw 5 TARGET uint xyzw
+// SV_TARGET 6 xyzw 6 TARGET uint xyzw
+// SV_TARGET 7 xyzw 7 TARGET uint xyzw
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_constantbuffer CB0[2], immediateIndexed
+dcl_output o0.xyzw
+dcl_output o1.xyzw
+dcl_output o2.xyzw
+dcl_output o3.xyzw
+dcl_output o4.xyzw
+dcl_output o5.xyzw
+dcl_output o6.xyzw
+dcl_output o7.xyzw
+dcl_output oDepth
+mov o0.xyzw, cb0[0].xyzw
+mov o1.xyzw, cb0[0].xyzw
+mov o2.xyzw, cb0[0].xyzw
+mov o3.xyzw, cb0[0].xyzw
+mov o4.xyzw, cb0[0].xyzw
+mov o5.xyzw, cb0[0].xyzw
+mov o6.xyzw, cb0[0].xyzw
+mov o7.xyzw, cb0[0].xyzw
+mov oDepth, cb0[1].x
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_ClearUint8[] = {
+ 68, 88, 66, 67, 206, 106, 135, 121, 179, 175, 105, 51, 32, 41, 211, 246, 201, 25, 75,
+ 237, 1, 0, 0, 0, 72, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 60, 1,
+ 0, 0, 112, 1, 0, 0, 108, 2, 0, 0, 204, 3, 0, 0, 82, 68, 69, 70, 0,
+ 1, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 216, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 67, 111, 108, 111, 114, 65, 110, 100, 68, 101, 112, 116, 104,
+ 68, 97, 116, 97, 85, 105, 110, 116, 0, 171, 171, 60, 0, 0, 0, 2, 0, 0, 0,
+ 108, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 156, 0, 0,
+ 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 168, 0, 0, 0, 0, 0,
+ 0, 0, 184, 0, 0, 0, 16, 0, 0, 0, 4, 0, 0, 0, 2, 0, 0, 0, 200,
+ 0, 0, 0, 0, 0, 0, 0, 99, 111, 108, 111, 114, 95, 85, 105, 110, 116, 0, 171,
+ 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 122, 86, 97,
+ 108, 117, 101, 70, 95, 85, 105, 110, 116, 0, 171, 171, 171, 0, 0, 3, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 79, 83, 71, 78, 244, 0, 0, 0, 9, 0, 0, 0,
+ 8, 0, 0, 0, 224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 224, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 15, 0, 0, 0, 224, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 15, 0, 0, 0,
+ 224, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0,
+ 0, 15, 0, 0, 0, 224, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 4, 0, 0, 0, 15, 0, 0, 0, 224, 0, 0, 0, 5, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0, 15, 0, 0, 0, 224, 0, 0, 0,
+ 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 6, 0, 0, 0, 15, 0, 0,
+ 0, 224, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 7, 0,
+ 0, 0, 15, 0, 0, 0, 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69,
+ 84, 0, 83, 86, 95, 68, 69, 80, 84, 72, 0, 171, 83, 72, 68, 82, 88, 1, 0,
+ 0, 64, 0, 0, 0, 86, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 101,
+ 0, 0, 3, 242, 32, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0,
+ 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 3, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 4, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 5, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 6, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 7, 0, 0, 0, 101, 0, 0, 2, 1, 192, 0, 0, 54, 0, 0, 6,
+ 242, 32, 16, 0, 0, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 54, 0, 0, 6, 242, 32, 16, 0, 1, 0, 0, 0, 70, 142, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 2, 0, 0, 0, 70,
+ 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0,
+ 3, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0,
+ 6, 242, 32, 16, 0, 4, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 5, 0, 0, 0, 70, 142, 32, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16, 0, 6, 0, 0, 0,
+ 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 242, 32, 16,
+ 0, 7, 0, 0, 0, 70, 142, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 1, 192, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62,
+ 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_2d_ps.h
new file mode 100644
index 0000000000..215c315abf
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_2d_ps.h
@@ -0,0 +1,76 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul o0.xyz, r0.wwww, r0.xxxx
+mov o0.w, l(1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_LUMA_2D[] = {
+ 68, 88, 66, 67, 196, 88, 192, 127, 243, 30, 81, 182, 148, 19, 99, 57, 115, 181, 138,
+ 146, 1, 0, 0, 0, 128, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 4, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 156, 0, 0, 0, 64,
+ 0, 0, 0, 39, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 32, 16, 0, 0, 0, 0,
+ 0, 246, 15, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 62,
+ 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_2darray_ps.h
new file mode 100644
index 0000000000..6918bb1bb3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_2darray_ps.h
@@ -0,0 +1,86 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul o0.xyz, r0.wwww, r0.xxxx
+mov o0.w, l(1.000000)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_LUMA_2DArray[] = {
+ 68, 88, 66, 67, 96, 91, 207, 234, 31, 106, 235, 231, 220, 198, 196, 200, 17, 9, 209,
+ 197, 1, 0, 0, 0, 240, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 116, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 212, 0, 0, 0, 64, 0,
+ 0, 0, 53, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 32, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 62, 0, 0,
+ 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_3d_ps.h
new file mode 100644
index 0000000000..0c5f9d3b26
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_3d_ps.h
@@ -0,0 +1,80 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul o0.xyz, r0.wwww, r0.xxxx
+mov o0.w, l(1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_LUMA_3D[] = {
+ 68, 88, 66, 67, 241, 186, 22, 7, 74, 156, 103, 227, 226, 7, 140, 127, 65, 83, 2,
+ 111, 1, 0, 0, 0, 176, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 52, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 156, 0, 0, 0, 64, 0, 0, 0, 39, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 7, 114, 32, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0,
+ 6, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_2d_ps.h
new file mode 100644
index 0000000000..5904f217e3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_2d_ps.h
@@ -0,0 +1,76 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul o0.xyz, r0.wwww, r0.xxxx
+mov o0.w, r0.w
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_LUMAALPHA_2D[] = {
+ 68, 88, 66, 67, 101, 29, 108, 117, 250, 233, 255, 220, 65, 43, 102, 162, 164, 247, 189,
+ 112, 1, 0, 0, 0, 128, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 4, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 156, 0, 0, 0, 64,
+ 0, 0, 0, 39, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 32, 16, 0, 0, 0, 0,
+ 0, 246, 15, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62,
+ 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_2darray_ps.h
new file mode 100644
index 0000000000..09d9bad5c0
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_2darray_ps.h
@@ -0,0 +1,86 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul o0.xyz, r0.wwww, r0.xxxx
+mov o0.w, r0.w
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_LUMAALPHA_2DArray[] = {
+ 68, 88, 66, 67, 16, 148, 215, 158, 112, 164, 42, 84, 33, 70, 148, 190, 238, 94, 245,
+ 128, 1, 0, 0, 0, 240, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 116, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 212, 0, 0, 0, 64, 0,
+ 0, 0, 53, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 32, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62, 0, 0,
+ 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_3d_ps.h
new file mode 100644
index 0000000000..d8ca1c845a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_3d_ps.h
@@ -0,0 +1,80 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul o0.xyz, r0.wwww, r0.xxxx
+mov o0.w, r0.w
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_LUMAALPHA_3D[] = {
+ 68, 88, 66, 67, 9, 39, 6, 28, 108, 109, 23, 108, 237, 131, 58, 1, 102, 159, 191,
+ 61, 1, 0, 0, 0, 176, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 52, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 156, 0, 0, 0, 64, 0, 0, 0, 39, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 7, 114, 32, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0,
+ 6, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0,
+ 0, 58, 0, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_2d_ps.h
new file mode 100644
index 0000000000..be18a987f8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_2d_ps.h
@@ -0,0 +1,76 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul o0.xyz, r0.wwww, r0.xyzx
+mov o0.w, l(1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_RGB_2D[] = {
+ 68, 88, 66, 67, 87, 204, 158, 94, 75, 152, 102, 217, 0, 88, 222, 29, 232, 182, 2,
+ 132, 1, 0, 0, 0, 128, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 4, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 156, 0, 0, 0, 64,
+ 0, 0, 0, 39, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 32, 16, 0, 0, 0, 0,
+ 0, 246, 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 62,
+ 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_2darray_ps.h
new file mode 100644
index 0000000000..7f18036816
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_2darray_ps.h
@@ -0,0 +1,86 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul o0.xyz, r0.wwww, r0.xyzx
+mov o0.w, l(1.000000)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_RGB_2DArray[] = {
+ 68, 88, 66, 67, 73, 224, 127, 95, 171, 173, 116, 230, 242, 111, 205, 239, 210, 69, 91,
+ 238, 1, 0, 0, 0, 240, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 116, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 212, 0, 0, 0, 64, 0,
+ 0, 0, 53, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 32, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 62, 0, 0,
+ 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_3d_ps.h
new file mode 100644
index 0000000000..78ed86a6cf
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_3d_ps.h
@@ -0,0 +1,80 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul o0.xyz, r0.wwww, r0.xyzx
+mov o0.w, l(1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_RGB_3D[] = {
+ 68, 88, 66, 67, 188, 235, 5, 90, 236, 180, 172, 101, 155, 220, 117, 214, 110, 8, 67,
+ 121, 1, 0, 0, 0, 176, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 52, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 156, 0, 0, 0, 64, 0, 0, 0, 39, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 7, 114, 32, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_565_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_565_2d_ps.h
new file mode 100644
index 0000000000..05af034cf3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_565_2d_ps.h
@@ -0,0 +1,84 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyz, r0.xyzx, l(31.000000, 63.000000, 31.000000, 0.000000)
+round_ne r0.xyz, r0.xyzx
+mul o0.xyz, r0.xyzx, l(0.032258, 0.015873, 0.032258, 0.000000)
+mov o0.w, l(1.000000)
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_RGB_565_2D[] = {
+ 68, 88, 66, 67, 107, 29, 4, 204, 154, 16, 239, 118, 140, 65, 255, 118, 32, 171, 247,
+ 239, 1, 0, 0, 0, 228, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 104, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 0, 1, 0, 0, 64,
+ 0, 0, 0, 64, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 0, 16, 0, 0, 0, 0,
+ 0, 246, 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0,
+ 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2,
+ 64, 0, 0, 0, 0, 248, 65, 0, 0, 124, 66, 0, 0, 248, 65, 0, 0, 0, 0,
+ 64, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0,
+ 0, 56, 0, 0, 10, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0, 8, 33, 4, 61, 33, 8, 130, 60, 8, 33, 4, 61, 0,
+ 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0,
+ 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 7, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_565_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_565_2darray_ps.h
new file mode 100644
index 0000000000..af5eb349ba
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_565_2darray_ps.h
@@ -0,0 +1,94 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyz, r0.xyzx, l(31.000000, 63.000000, 31.000000, 0.000000)
+round_ne r0.xyz, r0.xyzx
+mul o0.xyz, r0.xyzx, l(0.032258, 0.015873, 0.032258, 0.000000)
+mov o0.w, l(1.000000)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_RGB_565_2DArray[] = {
+ 68, 88, 66, 67, 45, 176, 85, 221, 234, 218, 205, 113, 163, 153, 221, 15, 166, 157, 230,
+ 200, 1, 0, 0, 0, 84, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 216, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 56, 1, 0, 0, 64, 0,
+ 0, 0, 78, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 0, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10,
+ 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0,
+ 0, 0, 0, 248, 65, 0, 0, 124, 66, 0, 0, 248, 65, 0, 0, 0, 0, 64, 0,
+ 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 8, 33, 4, 61, 33, 8, 130, 60, 8, 33, 4, 61, 0, 0, 0,
+ 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0,
+ 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_565_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_565_3d_ps.h
new file mode 100644
index 0000000000..bf02050d89
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_565_3d_ps.h
@@ -0,0 +1,88 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyz, r0.xyzx, l(31.000000, 63.000000, 31.000000, 0.000000)
+round_ne r0.xyz, r0.xyzx
+mul o0.xyz, r0.xyzx, l(0.032258, 0.015873, 0.032258, 0.000000)
+mov o0.w, l(1.000000)
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_RGB_565_3D[] = {
+ 68, 88, 66, 67, 72, 210, 100, 140, 147, 53, 29, 56, 170, 112, 233, 37, 175, 201, 198,
+ 250, 1, 0, 0, 0, 20, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 152, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 0, 1, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 7, 114, 0, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 248, 65, 0, 0,
+ 124, 66, 0, 0, 248, 65, 0, 0, 0, 0, 64, 0, 0, 5, 114, 0, 16, 0, 0,
+ 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 32, 16, 0,
+ 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 8, 33, 4,
+ 61, 33, 8, 130, 60, 8, 33, 4, 61, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32,
+ 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 62, 0, 0, 1, 83,
+ 84, 65, 84, 116, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_2d_ps.h
new file mode 100644
index 0000000000..68712ef7f5
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_2d_ps.h
@@ -0,0 +1,76 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul o0.xyz, r0.wwww, r0.xyzx
+mov o0.w, r0.w
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_RGBA_2D[] = {
+ 68, 88, 66, 67, 132, 105, 208, 138, 186, 182, 112, 82, 173, 16, 240, 222, 116, 72, 178,
+ 126, 1, 0, 0, 0, 128, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 4, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 156, 0, 0, 0, 64,
+ 0, 0, 0, 39, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 32, 16, 0, 0, 0, 0,
+ 0, 246, 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62,
+ 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_2darray_ps.h
new file mode 100644
index 0000000000..2f0b59abe0
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_2darray_ps.h
@@ -0,0 +1,86 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul o0.xyz, r0.wwww, r0.xyzx
+mov o0.w, r0.w
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_RGBA_2DArray[] = {
+ 68, 88, 66, 67, 61, 17, 53, 94, 235, 123, 58, 146, 86, 204, 96, 4, 97, 221, 95,
+ 134, 1, 0, 0, 0, 240, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 116, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 212, 0, 0, 0, 64, 0,
+ 0, 0, 53, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 32, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62, 0, 0,
+ 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_3d_ps.h
new file mode 100644
index 0000000000..62d18d62db
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_3d_ps.h
@@ -0,0 +1,80 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul o0.xyz, r0.wwww, r0.xyzx
+mov o0.w, r0.w
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_RGBA_3D[] = {
+ 68, 88, 66, 67, 80, 173, 64, 240, 1, 143, 85, 115, 221, 254, 89, 145, 213, 191, 49,
+ 141, 1, 0, 0, 0, 176, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 52, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 156, 0, 0, 0, 64, 0, 0, 0, 39, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 7, 114, 32, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0,
+ 0, 58, 0, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_4444_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_4444_2d_ps.h
new file mode 100644
index 0000000000..62e59d2e4e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_4444_2d_ps.h
@@ -0,0 +1,82 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(15.000000, 15.000000, 15.000000, 15.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.066667, 0.066667, 0.066667, 0.066667)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_RGBA_4444_2D[] = {
+ 68, 88, 66, 67, 52, 89, 222, 242, 25, 197, 40, 54, 79, 232, 156, 234, 251, 41, 41,
+ 226, 1, 0, 0, 0, 208, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 84, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 236, 0, 0, 0, 64,
+ 0, 0, 0, 59, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 0, 16, 0, 0, 0, 0,
+ 0, 246, 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0,
+ 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2,
+ 64, 0, 0, 0, 0, 112, 65, 0, 0, 112, 65, 0, 0, 112, 65, 0, 0, 112, 65,
+ 64, 0, 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0,
+ 0, 56, 0, 0, 10, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0, 137, 136, 136, 61, 137, 136, 136, 61, 137, 136, 136, 61, 137,
+ 136, 136, 61, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_4444_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_4444_2darray_ps.h
new file mode 100644
index 0000000000..ebfce59f6a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_4444_2darray_ps.h
@@ -0,0 +1,92 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(15.000000, 15.000000, 15.000000, 15.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.066667, 0.066667, 0.066667, 0.066667)
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_RGBA_4444_2DArray[] = {
+ 68, 88, 66, 67, 119, 1, 180, 34, 213, 167, 228, 86, 205, 242, 230, 17, 87, 32, 74,
+ 6, 1, 0, 0, 0, 64, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 196, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 36, 1, 0, 0, 64, 0,
+ 0, 0, 73, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 0, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10,
+ 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0,
+ 0, 0, 0, 112, 65, 0, 0, 112, 65, 0, 0, 112, 65, 0, 0, 112, 65, 64, 0,
+ 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 137, 136, 136, 61, 137, 136, 136, 61, 137, 136, 136, 61, 137, 136, 136,
+ 61, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_4444_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_4444_3d_ps.h
new file mode 100644
index 0000000000..a5dd42a2a7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_4444_3d_ps.h
@@ -0,0 +1,86 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(15.000000, 15.000000, 15.000000, 15.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.066667, 0.066667, 0.066667, 0.066667)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_RGBA_4444_3D[] = {
+ 68, 88, 66, 67, 233, 160, 206, 221, 201, 110, 121, 251, 163, 213, 234, 30, 171, 187, 79,
+ 242, 1, 0, 0, 0, 0, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 132, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 236, 0, 0, 0, 64, 0, 0, 0, 59, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 7, 114, 0, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 112, 65, 0, 0,
+ 112, 65, 0, 0, 112, 65, 0, 0, 112, 65, 64, 0, 0, 5, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 137, 136, 136,
+ 61, 137, 136, 136, 61, 137, 136, 136, 61, 137, 136, 136, 61, 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_5551_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_5551_2d_ps.h
new file mode 100644
index 0000000000..fca424ebc2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_5551_2d_ps.h
@@ -0,0 +1,82 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(31.000000, 31.000000, 31.000000, 1.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.032258, 0.032258, 0.032258, 1.000000)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_RGBA_5551_2D[] = {
+ 68, 88, 66, 67, 157, 187, 40, 209, 230, 225, 190, 246, 40, 140, 167, 190, 61, 115, 94,
+ 70, 1, 0, 0, 0, 208, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 84, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 236, 0, 0, 0, 64,
+ 0, 0, 0, 59, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 0, 16, 0, 0, 0, 0,
+ 0, 246, 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0,
+ 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2,
+ 64, 0, 0, 0, 0, 248, 65, 0, 0, 248, 65, 0, 0, 248, 65, 0, 0, 128, 63,
+ 64, 0, 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0,
+ 0, 56, 0, 0, 10, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0, 8, 33, 4, 61, 8, 33, 4, 61, 8, 33, 4, 61, 0,
+ 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_5551_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_5551_2darray_ps.h
new file mode 100644
index 0000000000..ee5c7d6e27
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_5551_2darray_ps.h
@@ -0,0 +1,92 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(31.000000, 31.000000, 31.000000, 1.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.032258, 0.032258, 0.032258, 1.000000)
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_RGBA_5551_2DArray[] = {
+ 68, 88, 66, 67, 66, 21, 128, 163, 11, 21, 65, 137, 107, 224, 148, 78, 244, 169, 148,
+ 247, 1, 0, 0, 0, 64, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 196, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 36, 1, 0, 0, 64, 0,
+ 0, 0, 73, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 0, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10,
+ 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0,
+ 0, 0, 0, 248, 65, 0, 0, 248, 65, 0, 0, 248, 65, 0, 0, 128, 63, 64, 0,
+ 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 8, 33, 4, 61, 8, 33, 4, 61, 8, 33, 4, 61, 0, 0, 128,
+ 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_5551_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_5551_3d_ps.h
new file mode 100644
index 0000000000..f4b47c002f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_5551_3d_ps.h
@@ -0,0 +1,86 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(31.000000, 31.000000, 31.000000, 1.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.032258, 0.032258, 0.032258, 1.000000)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_PM_RGBA_5551_3D[] = {
+ 68, 88, 66, 67, 74, 0, 199, 89, 200, 147, 93, 64, 244, 239, 156, 102, 110, 132, 22,
+ 10, 1, 0, 0, 0, 0, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 132, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 236, 0, 0, 0, 64, 0, 0, 0, 59, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 7, 114, 0, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 248, 65, 0, 0,
+ 248, 65, 0, 0, 248, 65, 0, 0, 128, 63, 64, 0, 0, 5, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 8, 33, 4,
+ 61, 8, 33, 4, 61, 8, 33, 4, 61, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_2d_ps.h
new file mode 100644
index 0000000000..a0023c0013
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_2d_ps.h
@@ -0,0 +1,82 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r0.w, r0.x, r0.w
+movc o0.xyz, r1.xxxx, r0.wwww, r0.xyzx
+mov o0.w, l(1.000000)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_LUMA_2D[] = {
+ 68, 88, 66, 67, 75, 92, 229, 222, 23, 169, 5, 92, 146, 12, 107, 229, 137, 155, 179,
+ 250, 1, 0, 0, 0, 192, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 68, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 220, 0, 0, 0, 64,
+ 0, 0, 0, 55, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0,
+ 0, 7, 130, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 58,
+ 0, 16, 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 32, 16, 0, 0, 0, 0, 0,
+ 6, 0, 16, 0, 1, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0, 70, 2, 16,
+ 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_2darray_ps.h
new file mode 100644
index 0000000000..4ad691bef4
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_2darray_ps.h
@@ -0,0 +1,91 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 2
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r0.w, r0.x, r0.w
+movc o0.xyz, r1.xxxx, r0.wwww, r0.xyzx
+mov o0.w, l(1.000000)
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_LUMA_2DArray[] = {
+ 68, 88, 66, 67, 2, 234, 137, 29, 211, 208, 186, 172, 235, 8, 55, 155, 195, 91, 134,
+ 133, 1, 0, 0, 0, 48, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 180, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 20, 1, 0, 0, 64, 0,
+ 0, 0, 69, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 2, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7,
+ 130, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 58, 0, 16,
+ 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 32, 16, 0, 0, 0, 0, 0, 6, 0,
+ 16, 0, 1, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0,
+ 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0,
+ 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_3d_ps.h
new file mode 100644
index 0000000000..4eed8c15ba
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_3d_ps.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r0.w, r0.x, r0.w
+movc o0.xyz, r1.xxxx, r0.wwww, r0.xyzx
+mov o0.w, l(1.000000)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_LUMA_3D[] = {
+ 68, 88, 66, 67, 120, 214, 14, 47, 69, 88, 46, 178, 8, 214, 190, 124, 42, 131, 170,
+ 151, 1, 0, 0, 0, 240, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 116, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 220, 0, 0, 0, 64, 0, 0, 0, 55, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 2, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 49,
+ 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0,
+ 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7, 130, 0, 16, 0, 0, 0, 0,
+ 0, 10, 0, 16, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 55, 0,
+ 0, 9, 114, 32, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 62, 0, 0,
+ 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_2d_ps.h
new file mode 100644
index 0000000000..7501fae643
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_2d_ps.h
@@ -0,0 +1,82 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.y, r0.x, r0.w
+movc o0.xyz, r1.xxxx, r1.yyyy, r0.xyzx
+mov o0.w, r0.w
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_LUMAALPHA_2D[] = {
+ 68, 88, 66, 67, 190, 69, 123, 211, 19, 130, 132, 1, 132, 116, 62, 1, 233, 115, 38,
+ 22, 1, 0, 0, 0, 192, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 68, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 220, 0, 0, 0, 64,
+ 0, 0, 0, 55, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0,
+ 0, 7, 34, 0, 16, 0, 1, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 58,
+ 0, 16, 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 32, 16, 0, 0, 0, 0, 0,
+ 6, 0, 16, 0, 1, 0, 0, 0, 86, 5, 16, 0, 1, 0, 0, 0, 70, 2, 16,
+ 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 58, 0,
+ 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_2darray_ps.h
new file mode 100644
index 0000000000..40eb1f480c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_2darray_ps.h
@@ -0,0 +1,91 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 2
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.y, r0.x, r0.w
+movc o0.xyz, r1.xxxx, r1.yyyy, r0.xyzx
+mov o0.w, r0.w
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_LUMAALPHA_2DArray[] = {
+ 68, 88, 66, 67, 222, 131, 31, 168, 174, 145, 73, 243, 164, 132, 216, 2, 103, 0, 142,
+ 101, 1, 0, 0, 0, 48, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 180, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 20, 1, 0, 0, 64, 0,
+ 0, 0, 69, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 2, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7,
+ 34, 0, 16, 0, 1, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 58, 0, 16,
+ 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 32, 16, 0, 0, 0, 0, 0, 6, 0,
+ 16, 0, 1, 0, 0, 0, 86, 5, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0,
+ 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 58, 0, 16, 0,
+ 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_3d_ps.h
new file mode 100644
index 0000000000..f6bbc8cc01
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_3d_ps.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.y, r0.x, r0.w
+movc o0.xyz, r1.xxxx, r1.yyyy, r0.xyzx
+mov o0.w, r0.w
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_LUMAALPHA_3D[] = {
+ 68, 88, 66, 67, 160, 196, 1, 185, 15, 156, 153, 67, 85, 102, 198, 128, 138, 216, 238,
+ 143, 1, 0, 0, 0, 240, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 116, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 220, 0, 0, 0, 64, 0, 0, 0, 55, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 2, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 49,
+ 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0,
+ 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7, 34, 0, 16, 0, 1, 0, 0,
+ 0, 10, 0, 16, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 55, 0,
+ 0, 9, 114, 32, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, 86,
+ 5, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62, 0, 0,
+ 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_2d_ps.h
new file mode 100644
index 0000000000..ce44a394d7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_2d_ps.h
@@ -0,0 +1,82 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc o0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mov o0.w, l(1.000000)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_RGB_2D[] = {
+ 68, 88, 66, 67, 93, 55, 14, 204, 55, 114, 238, 111, 6, 213, 4, 64, 58, 99, 168,
+ 104, 1, 0, 0, 0, 192, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 68, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 220, 0, 0, 0, 64,
+ 0, 0, 0, 55, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0,
+ 0, 7, 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 32, 16, 0, 0, 0, 0, 0,
+ 6, 0, 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16,
+ 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_2darray_ps.h
new file mode 100644
index 0000000000..ea38e2e559
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_2darray_ps.h
@@ -0,0 +1,91 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 2
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc o0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mov o0.w, l(1.000000)
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_RGB_2DArray[] = {
+ 68, 88, 66, 67, 224, 13, 199, 125, 145, 168, 88, 56, 242, 2, 144, 118, 87, 186, 241,
+ 248, 1, 0, 0, 0, 48, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 180, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 20, 1, 0, 0, 64, 0,
+ 0, 0, 69, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 2, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7,
+ 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16,
+ 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 32, 16, 0, 0, 0, 0, 0, 6, 0,
+ 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0,
+ 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0,
+ 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_3d_ps.h
new file mode 100644
index 0000000000..da862eb119
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_3d_ps.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc o0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mov o0.w, l(1.000000)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_RGB_3D[] = {
+ 68, 88, 66, 67, 200, 37, 175, 150, 106, 41, 102, 69, 21, 246, 40, 148, 142, 99, 101,
+ 71, 1, 0, 0, 0, 240, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 116, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 220, 0, 0, 0, 64, 0, 0, 0, 55, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 2, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 49,
+ 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0,
+ 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7, 226, 0, 16, 0, 1, 0, 0,
+ 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0, 55, 0,
+ 0, 9, 114, 32, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, 150,
+ 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 62, 0, 0,
+ 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_565_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_565_2d_ps.h
new file mode 100644
index 0000000000..5996ba335e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_565_2d_ps.h
@@ -0,0 +1,90 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyz, r0.xyzx, l(31.000000, 63.000000, 31.000000, 0.000000)
+round_ne r0.xyz, r0.xyzx
+mul o0.xyz, r0.xyzx, l(0.032258, 0.015873, 0.032258, 0.000000)
+mov o0.w, l(1.000000)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_RGB_565_2D[] = {
+ 68, 88, 66, 67, 120, 138, 72, 172, 147, 159, 222, 80, 129, 231, 133, 236, 125, 211, 201,
+ 82, 1, 0, 0, 0, 36, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 168, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 64, 1, 0, 0, 64,
+ 0, 0, 0, 80, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0,
+ 0, 7, 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 0, 16, 0, 0, 0, 0, 0,
+ 6, 0, 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16,
+ 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 248, 65, 0, 0, 124, 66, 0,
+ 0, 248, 65, 0, 0, 0, 0, 64, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 32, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 8, 33, 4, 61, 33, 8,
+ 130, 60, 8, 33, 4, 61, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0,
+ 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 9, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_565_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_565_2darray_ps.h
new file mode 100644
index 0000000000..b36c06adb0
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_565_2darray_ps.h
@@ -0,0 +1,100 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 2
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyz, r0.xyzx, l(31.000000, 63.000000, 31.000000, 0.000000)
+round_ne r0.xyz, r0.xyzx
+mul o0.xyz, r0.xyzx, l(0.032258, 0.015873, 0.032258, 0.000000)
+mov o0.w, l(1.000000)
+ret
+// Approximately 11 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_RGB_565_2DArray[] = {
+ 68, 88, 66, 67, 44, 2, 174, 208, 118, 237, 233, 207, 57, 29, 178, 223, 138, 140, 88,
+ 102, 1, 0, 0, 0, 148, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 24, 3, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 120, 1, 0, 0, 64, 0,
+ 0, 0, 94, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 2, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7,
+ 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16,
+ 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0,
+ 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0,
+ 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0,
+ 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 248, 65, 0, 0, 124, 66, 0, 0, 248,
+ 65, 0, 0, 0, 0, 64, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 32, 16, 0, 0, 0, 0, 0, 70,
+ 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 8, 33, 4, 61, 33, 8, 130, 60,
+ 8, 33, 4, 61, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0,
+ 0, 0, 11, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_565_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_565_3d_ps.h
new file mode 100644
index 0000000000..8de8d85d37
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_565_3d_ps.h
@@ -0,0 +1,93 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyz, r0.xyzx, l(31.000000, 63.000000, 31.000000, 0.000000)
+round_ne r0.xyz, r0.xyzx
+mul o0.xyz, r0.xyzx, l(0.032258, 0.015873, 0.032258, 0.000000)
+mov o0.w, l(1.000000)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_RGB_565_3D[] = {
+ 68, 88, 66, 67, 250, 168, 68, 191, 15, 51, 156, 108, 63, 18, 251, 133, 207, 174, 26,
+ 44, 1, 0, 0, 0, 84, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 216, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 64, 1, 0, 0, 64, 0, 0, 0, 80, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 2, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 49,
+ 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0,
+ 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7, 226, 0, 16, 0, 1, 0, 0,
+ 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0, 55, 0,
+ 0, 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, 150,
+ 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10,
+ 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0,
+ 0, 0, 0, 248, 65, 0, 0, 124, 66, 0, 0, 248, 65, 0, 0, 0, 0, 64, 0,
+ 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 8, 33, 4, 61, 33, 8, 130, 60, 8, 33, 4, 61, 0, 0, 0,
+ 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0,
+ 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_2d_ps.h
new file mode 100644
index 0000000000..764b560d78
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_2d_ps.h
@@ -0,0 +1,82 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc o0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mov o0.w, r0.w
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_RGBA_2D[] = {
+ 68, 88, 66, 67, 43, 116, 27, 96, 239, 39, 33, 81, 44, 127, 180, 166, 1, 156, 105,
+ 167, 1, 0, 0, 0, 192, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 68, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 220, 0, 0, 0, 64,
+ 0, 0, 0, 55, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0,
+ 0, 7, 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 32, 16, 0, 0, 0, 0, 0,
+ 6, 0, 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16,
+ 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 58, 0,
+ 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_2darray_ps.h
new file mode 100644
index 0000000000..84cf6ebefa
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_2darray_ps.h
@@ -0,0 +1,91 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 2
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc o0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mov o0.w, r0.w
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_RGBA_2DArray[] = {
+ 68, 88, 66, 67, 226, 210, 183, 205, 237, 244, 131, 11, 158, 229, 134, 100, 181, 52, 86,
+ 124, 1, 0, 0, 0, 48, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 180, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 20, 1, 0, 0, 64, 0,
+ 0, 0, 69, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 2, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7,
+ 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16,
+ 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 32, 16, 0, 0, 0, 0, 0, 6, 0,
+ 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0,
+ 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 58, 0, 16, 0,
+ 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_3d_ps.h
new file mode 100644
index 0000000000..d0725735e4
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_3d_ps.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc o0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mov o0.w, r0.w
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_RGBA_3D[] = {
+ 68, 88, 66, 67, 47, 35, 68, 46, 230, 212, 160, 221, 21, 19, 140, 22, 115, 9, 100,
+ 58, 1, 0, 0, 0, 240, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 116, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 220, 0, 0, 0, 64, 0, 0, 0, 55, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 2, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 49,
+ 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0,
+ 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7, 226, 0, 16, 0, 1, 0, 0,
+ 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0, 55, 0,
+ 0, 9, 114, 32, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, 150,
+ 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 130, 32, 16, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 62, 0, 0,
+ 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_4444_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_4444_2d_ps.h
new file mode 100644
index 0000000000..cfa23a7bf9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_4444_2d_ps.h
@@ -0,0 +1,88 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(15.000000, 15.000000, 15.000000, 15.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.066667, 0.066667, 0.066667, 0.066667)
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_RGBA_4444_2D[] = {
+ 68, 88, 66, 67, 233, 41, 159, 52, 49, 178, 50, 48, 148, 28, 18, 200, 140, 164, 4,
+ 13, 1, 0, 0, 0, 16, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 148, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 44, 1, 0, 0, 64,
+ 0, 0, 0, 75, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0,
+ 0, 7, 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 0, 16, 0, 0, 0, 0, 0,
+ 6, 0, 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16,
+ 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 112, 65, 0, 0, 112, 65, 0,
+ 0, 112, 65, 0, 0, 112, 65, 64, 0, 0, 5, 242, 0, 16, 0, 0, 0, 0, 0,
+ 70, 14, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 32, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 137, 136, 136, 61, 137, 136,
+ 136, 61, 137, 136, 136, 61, 137, 136, 136, 61, 62, 0, 0, 1, 83, 84, 65, 84, 116,
+ 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_4444_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_4444_2darray_ps.h
new file mode 100644
index 0000000000..1a08e60147
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_4444_2darray_ps.h
@@ -0,0 +1,98 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 2
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(15.000000, 15.000000, 15.000000, 15.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.066667, 0.066667, 0.066667, 0.066667)
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_RGBA_4444_2DArray[] = {
+ 68, 88, 66, 67, 51, 224, 15, 241, 219, 215, 90, 241, 40, 140, 3, 53, 152, 74, 169,
+ 200, 1, 0, 0, 0, 128, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 4, 3, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 100, 1, 0, 0, 64, 0,
+ 0, 0, 89, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 2, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7,
+ 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16,
+ 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0,
+ 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0,
+ 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 112, 65, 0, 0, 112, 65, 0, 0, 112,
+ 65, 0, 0, 112, 65, 64, 0, 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 32, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 137, 136, 136, 61, 137, 136, 136, 61,
+ 137, 136, 136, 61, 137, 136, 136, 61, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0,
+ 0, 10, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_4444_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_4444_3d_ps.h
new file mode 100644
index 0000000000..ef493e3f4b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_4444_3d_ps.h
@@ -0,0 +1,91 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(15.000000, 15.000000, 15.000000, 15.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.066667, 0.066667, 0.066667, 0.066667)
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_RGBA_4444_3D[] = {
+ 68, 88, 66, 67, 210, 247, 48, 228, 222, 252, 207, 191, 86, 78, 158, 63, 239, 245, 179,
+ 7, 1, 0, 0, 0, 64, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 196, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 44, 1, 0, 0, 64, 0, 0, 0, 75, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 2, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 49,
+ 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0,
+ 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7, 226, 0, 16, 0, 1, 0, 0,
+ 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0, 55, 0,
+ 0, 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, 150,
+ 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10,
+ 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0,
+ 0, 0, 0, 112, 65, 0, 0, 112, 65, 0, 0, 112, 65, 0, 0, 112, 65, 64, 0,
+ 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 137, 136, 136, 61, 137, 136, 136, 61, 137, 136, 136, 61, 137, 136, 136,
+ 61, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_5551_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_5551_2d_ps.h
new file mode 100644
index 0000000000..42829c90c9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_5551_2d_ps.h
@@ -0,0 +1,88 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(31.000000, 31.000000, 31.000000, 1.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.032258, 0.032258, 0.032258, 1.000000)
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_RGBA_5551_2D[] = {
+ 68, 88, 66, 67, 140, 39, 186, 158, 51, 211, 162, 56, 171, 90, 89, 241, 42, 247, 30,
+ 222, 1, 0, 0, 0, 16, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 148, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 44, 1, 0, 0, 64,
+ 0, 0, 0, 75, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0,
+ 0, 7, 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 0, 16, 0, 0, 0, 0, 0,
+ 6, 0, 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16,
+ 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 248, 65, 0, 0, 248, 65, 0,
+ 0, 248, 65, 0, 0, 128, 63, 64, 0, 0, 5, 242, 0, 16, 0, 0, 0, 0, 0,
+ 70, 14, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 32, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 8, 33, 4, 61, 8, 33,
+ 4, 61, 8, 33, 4, 61, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116,
+ 0, 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_5551_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_5551_2darray_ps.h
new file mode 100644
index 0000000000..22389cfa5d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_5551_2darray_ps.h
@@ -0,0 +1,98 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 2
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(31.000000, 31.000000, 31.000000, 1.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.032258, 0.032258, 0.032258, 1.000000)
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_RGBA_5551_2DArray[] = {
+ 68, 88, 66, 67, 17, 161, 17, 46, 139, 141, 231, 172, 21, 139, 205, 213, 78, 192, 111,
+ 150, 1, 0, 0, 0, 128, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 4, 3, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 100, 1, 0, 0, 64, 0,
+ 0, 0, 89, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 2, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7,
+ 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16,
+ 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0,
+ 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0,
+ 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 248, 65, 0, 0, 248, 65, 0, 0, 248,
+ 65, 0, 0, 128, 63, 64, 0, 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 32, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 8, 33, 4, 61, 8, 33, 4, 61,
+ 8, 33, 4, 61, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0,
+ 0, 10, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 5, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_5551_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_5551_3d_ps.h
new file mode 100644
index 0000000000..a97e54f1d2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_5551_3d_ps.h
@@ -0,0 +1,91 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(31.000000, 31.000000, 31.000000, 1.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.032258, 0.032258, 0.032258, 1.000000)
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_FtoF_UM_RGBA_5551_3D[] = {
+ 68, 88, 66, 67, 95, 144, 206, 44, 123, 213, 142, 219, 42, 152, 39, 211, 195, 66, 184,
+ 29, 1, 0, 0, 0, 64, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 196, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 44, 1, 0, 0, 64, 0, 0, 0, 75, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 2, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 49,
+ 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0,
+ 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7, 226, 0, 16, 0, 1, 0, 0,
+ 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0, 55, 0,
+ 0, 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, 150,
+ 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10,
+ 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0,
+ 0, 0, 0, 248, 65, 0, 0, 248, 65, 0, 0, 248, 65, 0, 0, 128, 63, 64, 0,
+ 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 8, 33, 4, 61, 8, 33, 4, 61, 8, 33, 4, 61, 0, 0, 128,
+ 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0, 0, 2, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgb_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgb_2darray_ps.h
new file mode 100644
index 0000000000..2921c17e7d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgb_2darray_ps.h
@@ -0,0 +1,96 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyz, r0.xyzx, l(127.000000, 127.000000, 127.000000, 0.000000)
+round_ne r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, l(1.000000, 1.000000, 1.000000, 0.000000)
+ftoi o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_FtoI_PM_RGB_2DArray[] = {
+ 68, 88, 66, 67, 214, 86, 133, 76, 36, 73, 187, 120, 120, 177, 199, 23, 161, 34, 44,
+ 41, 1, 0, 0, 0, 104, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 236, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 76, 1, 0, 0, 64, 0,
+ 0, 0, 83, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 0, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10,
+ 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0,
+ 0, 0, 0, 254, 66, 0, 0, 254, 66, 0, 0, 254, 66, 0, 0, 0, 0, 64, 0,
+ 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 0,
+ 0, 27, 0, 0, 5, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 1,
+ 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 10, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgb_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgb_3d_ps.h
new file mode 100644
index 0000000000..18741678e1
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgb_3d_ps.h
@@ -0,0 +1,90 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyz, r0.xyzx, l(127.000000, 127.000000, 127.000000, 0.000000)
+round_ne r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, l(1.000000, 1.000000, 1.000000, 0.000000)
+ftoi o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_FtoI_PM_RGB_3D[] = {
+ 68, 88, 66, 67, 233, 244, 68, 31, 244, 75, 174, 119, 157, 230, 155, 216, 124, 72, 238,
+ 41, 1, 0, 0, 0, 40, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 172, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 20, 1, 0, 0, 64, 0, 0, 0, 69, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 7, 114, 0, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 254, 66, 0, 0,
+ 254, 66, 0, 0, 254, 66, 0, 0, 0, 0, 64, 0, 0, 5, 114, 0, 16, 0, 0,
+ 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 128,
+ 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 0, 0, 27, 0, 0, 5, 114, 32,
+ 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130,
+ 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgba_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgba_2darray_ps.h
new file mode 100644
index 0000000000..f877df2d74
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgba_2darray_ps.h
@@ -0,0 +1,94 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(127.000000, 127.000000, 127.000000, 127.000000)
+round_ne r0.xyzw, r0.xyzw
+mul r0.xyzw, r0.xyzw, l(1.000000, 1.000000, 1.000000, 1.000000)
+ftoi o0.xyzw, r0.xyzw
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_FtoI_PM_RGBA_2DArray[] = {
+ 68, 88, 66, 67, 6, 46, 120, 27, 94, 101, 87, 132, 53, 181, 154, 63, 109, 237, 51,
+ 143, 1, 0, 0, 0, 84, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 216, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 56, 1, 0, 0, 64, 0,
+ 0, 0, 78, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 0, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10,
+ 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0,
+ 0, 0, 0, 254, 66, 0, 0, 254, 66, 0, 0, 254, 66, 0, 0, 254, 66, 64, 0,
+ 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128,
+ 63, 27, 0, 0, 5, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgba_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgba_3d_ps.h
new file mode 100644
index 0000000000..e4b96a279b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pm_rgba_3d_ps.h
@@ -0,0 +1,88 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(127.000000, 127.000000, 127.000000, 127.000000)
+round_ne r0.xyzw, r0.xyzw
+mul r0.xyzw, r0.xyzw, l(1.000000, 1.000000, 1.000000, 1.000000)
+ftoi o0.xyzw, r0.xyzw
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_FtoI_PM_RGBA_3D[] = {
+ 68, 88, 66, 67, 249, 90, 79, 118, 112, 44, 159, 0, 189, 165, 140, 198, 201, 78, 213,
+ 100, 1, 0, 0, 0, 20, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 152, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 0, 1, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 7, 114, 0, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 254, 66, 0, 0,
+ 254, 66, 0, 0, 254, 66, 0, 0, 254, 66, 64, 0, 0, 5, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0,
+ 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 128,
+ 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 27, 0, 0, 5, 242, 32,
+ 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83,
+ 84, 65, 84, 116, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgb_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgb_2darray_ps.h
new file mode 100644
index 0000000000..8970316b3d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgb_2darray_ps.h
@@ -0,0 +1,94 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.xyzx, l(127.000000, 127.000000, 127.000000, 0.000000)
+round_ne r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, l(1.000000, 1.000000, 1.000000, 0.000000)
+ftoi o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_FtoI_PT_RGB_2DArray[] = {
+ 68, 88, 66, 67, 168, 185, 143, 219, 147, 147, 203, 58, 217, 196, 122, 65, 228, 189, 209,
+ 238, 1, 0, 0, 0, 76, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 208, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 48, 1, 0, 0, 64, 0,
+ 0, 0, 76, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70,
+ 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 254, 66, 0, 0, 254, 66,
+ 0, 0, 254, 66, 0, 0, 0, 0, 64, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0,
+ 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 128, 63, 0,
+ 0, 128, 63, 0, 0, 128, 63, 0, 0, 0, 0, 27, 0, 0, 5, 114, 32, 16, 0,
+ 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16,
+ 0, 0, 0, 0, 0, 1, 64, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgb_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgb_3d_ps.h
new file mode 100644
index 0000000000..3f93541ea7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgb_3d_ps.h
@@ -0,0 +1,88 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.xyzx, l(127.000000, 127.000000, 127.000000, 0.000000)
+round_ne r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, l(1.000000, 1.000000, 1.000000, 0.000000)
+ftoi o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_FtoI_PT_RGB_3D[] = {
+ 68, 88, 66, 67, 65, 66, 171, 227, 204, 106, 7, 188, 141, 169, 26, 209, 77, 251, 140,
+ 247, 1, 0, 0, 0, 12, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 144, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 248, 0, 0, 0, 64, 0, 0, 0, 62, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0, 254, 66, 0, 0, 254, 66, 0, 0, 254, 66, 0, 0, 0,
+ 0, 64, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0,
+ 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0,
+ 0, 0, 0, 2, 64, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63,
+ 0, 0, 0, 0, 27, 0, 0, 5, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16,
+ 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64,
+ 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 7,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgba_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgba_2darray_ps.h
new file mode 100644
index 0000000000..493fc2292b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgba_2darray_ps.h
@@ -0,0 +1,92 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul r0.xyzw, r0.xyzw, l(127.000000, 127.000000, 127.000000, 127.000000)
+round_ne r0.xyzw, r0.xyzw
+mul r0.xyzw, r0.xyzw, l(1.000000, 1.000000, 1.000000, 1.000000)
+ftoi o0.xyzw, r0.xyzw
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_FtoI_PT_RGBA_2DArray[] = {
+ 68, 88, 66, 67, 157, 78, 228, 79, 217, 28, 225, 96, 83, 195, 47, 176, 240, 168, 229,
+ 128, 1, 0, 0, 0, 56, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 188, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 28, 1, 0, 0, 64, 0,
+ 0, 0, 71, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 254, 66, 0, 0, 254, 66,
+ 0, 0, 254, 66, 0, 0, 254, 66, 64, 0, 0, 5, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 128, 63, 0,
+ 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 27, 0, 0, 5, 242, 32, 16, 0,
+ 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65,
+ 84, 116, 0, 0, 0, 8, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgba_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgba_3d_ps.h
new file mode 100644
index 0000000000..c602d2fb2e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_pt_rgba_3d_ps.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul r0.xyzw, r0.xyzw, l(127.000000, 127.000000, 127.000000, 127.000000)
+round_ne r0.xyzw, r0.xyzw
+mul r0.xyzw, r0.xyzw, l(1.000000, 1.000000, 1.000000, 1.000000)
+ftoi o0.xyzw, r0.xyzw
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoI_PT_RGBA_3D[] = {
+ 68, 88, 66, 67, 73, 236, 106, 44, 249, 119, 115, 91, 94, 156, 145, 139, 146, 47, 33,
+ 36, 1, 0, 0, 0, 248, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 124, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 228, 0, 0, 0, 64, 0, 0, 0, 57, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0, 254, 66, 0, 0, 254, 66, 0, 0, 254, 66, 0, 0, 254,
+ 66, 64, 0, 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0,
+ 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0,
+ 0, 0, 0, 2, 64, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63,
+ 0, 0, 128, 63, 27, 0, 0, 5, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16,
+ 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgb_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgb_2darray_ps.h
new file mode 100644
index 0000000000..8335a149c6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgb_2darray_ps.h
@@ -0,0 +1,102 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 2
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyz, r0.xyzx, l(127.000000, 127.000000, 127.000000, 0.000000)
+round_ne r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, l(1.000000, 1.000000, 1.000000, 0.000000)
+ftoi o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 12 instruction slots used
+#endif
+
+const BYTE g_PS_FtoI_UM_RGB_2DArray[] = {
+ 68, 88, 66, 67, 229, 156, 153, 172, 30, 111, 168, 172, 47, 75, 227, 206, 198, 78, 62,
+ 42, 1, 0, 0, 0, 168, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 44, 3, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 140, 1, 0, 0, 64, 0,
+ 0, 0, 99, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 2, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7,
+ 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16,
+ 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0,
+ 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0,
+ 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0,
+ 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 254, 66, 0, 0, 254, 66, 0, 0, 254,
+ 66, 0, 0, 0, 0, 64, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70,
+ 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63,
+ 0, 0, 128, 63, 0, 0, 0, 0, 27, 0, 0, 5, 114, 32, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116,
+ 0, 0, 0, 12, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgb_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgb_3d_ps.h
new file mode 100644
index 0000000000..2df877322f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgb_3d_ps.h
@@ -0,0 +1,95 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyz, r0.xyzx, l(127.000000, 127.000000, 127.000000, 0.000000)
+round_ne r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, l(1.000000, 1.000000, 1.000000, 0.000000)
+ftoi o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_FtoI_UM_RGB_3D[] = {
+ 68, 88, 66, 67, 23, 5, 101, 80, 190, 217, 192, 233, 141, 228, 109, 126, 239, 211, 129,
+ 244, 1, 0, 0, 0, 104, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 236, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 84, 1, 0, 0, 64, 0, 0, 0, 85, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 2, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 49,
+ 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0,
+ 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7, 226, 0, 16, 0, 1, 0, 0,
+ 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0, 55, 0,
+ 0, 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, 150,
+ 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10,
+ 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0,
+ 0, 0, 0, 254, 66, 0, 0, 254, 66, 0, 0, 254, 66, 0, 0, 0, 0, 64, 0,
+ 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 0,
+ 0, 27, 0, 0, 5, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 1,
+ 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 10, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgba_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgba_2darray_ps.h
new file mode 100644
index 0000000000..3d4dfa2bb9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgba_2darray_ps.h
@@ -0,0 +1,100 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 2
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(127.000000, 127.000000, 127.000000, 127.000000)
+round_ne r0.xyzw, r0.xyzw
+mul r0.xyzw, r0.xyzw, l(1.000000, 1.000000, 1.000000, 1.000000)
+ftoi o0.xyzw, r0.xyzw
+ret
+// Approximately 11 instruction slots used
+#endif
+
+const BYTE g_PS_FtoI_UM_RGBA_2DArray[] = {
+ 68, 88, 66, 67, 131, 143, 223, 155, 139, 202, 127, 87, 193, 203, 100, 239, 91, 19, 167,
+ 10, 1, 0, 0, 0, 148, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 24, 3, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 120, 1, 0, 0, 64, 0,
+ 0, 0, 94, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 2, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7,
+ 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16,
+ 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0,
+ 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0,
+ 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 254, 66, 0, 0, 254, 66, 0, 0, 254,
+ 66, 0, 0, 254, 66, 64, 0, 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63,
+ 0, 0, 128, 63, 0, 0, 128, 63, 27, 0, 0, 5, 242, 32, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0,
+ 0, 0, 11, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 5,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgba_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgba_3d_ps.h
new file mode 100644
index 0000000000..89b06059e3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftoi_um_rgba_3d_ps.h
@@ -0,0 +1,93 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(127.000000, 127.000000, 127.000000, 127.000000)
+round_ne r0.xyzw, r0.xyzw
+mul r0.xyzw, r0.xyzw, l(1.000000, 1.000000, 1.000000, 1.000000)
+ftoi o0.xyzw, r0.xyzw
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_FtoI_UM_RGBA_3D[] = {
+ 68, 88, 66, 67, 221, 247, 207, 180, 133, 35, 246, 152, 57, 87, 23, 116, 186, 51, 233,
+ 199, 1, 0, 0, 0, 84, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 216, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 64, 1, 0, 0, 64, 0, 0, 0, 80, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 2, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 49,
+ 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0,
+ 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7, 226, 0, 16, 0, 1, 0, 0,
+ 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0, 55, 0,
+ 0, 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, 150,
+ 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10,
+ 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0,
+ 0, 0, 0, 254, 66, 0, 0, 254, 66, 0, 0, 254, 66, 0, 0, 254, 66, 64, 0,
+ 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128, 63, 0, 0, 128,
+ 63, 27, 0, 0, 5, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_2d_ps.h
new file mode 100644
index 0000000000..29a60b7f93
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_2d_ps.h
@@ -0,0 +1,81 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyz, r0.xyzx, l(255.000000, 255.000000, 255.000000, 0.000000)
+ftou o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_PM_RGB_2D[] = {
+ 68, 88, 66, 67, 157, 10, 67, 137, 249, 135, 12, 161, 255, 107, 225, 32, 54, 65, 72,
+ 121, 1, 0, 0, 0, 188, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 64, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 216, 0, 0, 0, 64,
+ 0, 0, 0, 54, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 0, 16, 0, 0, 0, 0,
+ 0, 246, 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0,
+ 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2,
+ 64, 0, 0, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 0, 0,
+ 28, 0, 0, 5, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0,
+ 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 1, 0,
+ 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_2darray_ps.h
new file mode 100644
index 0000000000..f5937d6336
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_2darray_ps.h
@@ -0,0 +1,91 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyz, r0.xyzx, l(255.000000, 255.000000, 255.000000, 0.000000)
+ftou o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_PM_RGB_2DArray[] = {
+ 68, 88, 66, 67, 42, 230, 32, 82, 5, 44, 80, 225, 105, 151, 142, 19, 19, 183, 76,
+ 193, 1, 0, 0, 0, 44, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 176, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 16, 1, 0, 0, 64, 0,
+ 0, 0, 68, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 0, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10,
+ 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0,
+ 0, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 0, 0, 28, 0,
+ 0, 5, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 1, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_3d_ps.h
new file mode 100644
index 0000000000..1e074f9236
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_3d_ps.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyz, r0.xyzx, l(255.000000, 255.000000, 255.000000, 0.000000)
+ftou o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_PM_RGB_3D[] = {
+ 68, 88, 66, 67, 181, 194, 196, 252, 71, 44, 79, 110, 172, 188, 24, 27, 37, 220, 16,
+ 181, 1, 0, 0, 0, 236, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 112, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 216, 0, 0, 0, 64, 0, 0, 0, 54, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 7, 114, 0, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 127, 67, 0, 0,
+ 127, 67, 0, 0, 127, 67, 0, 0, 0, 0, 28, 0, 0, 5, 114, 32, 16, 0, 0,
+ 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0,
+ 0, 0, 0, 0, 1, 64, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65,
+ 84, 116, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_2d_ps.h
new file mode 100644
index 0000000000..f33e4d5bac
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_2d_ps.h
@@ -0,0 +1,79 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(255.000000, 255.000000, 255.000000, 255.000000)
+ftou o0.xyzw, r0.xyzw
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_PM_RGBA_2D[] = {
+ 68, 88, 66, 67, 40, 207, 117, 251, 196, 95, 200, 222, 47, 24, 239, 143, 252, 25, 140,
+ 25, 1, 0, 0, 0, 168, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 44, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 196, 0, 0, 0, 64,
+ 0, 0, 0, 49, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 0, 16, 0, 0, 0, 0,
+ 0, 246, 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0,
+ 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2,
+ 64, 0, 0, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 127, 67,
+ 28, 0, 0, 5, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0,
+ 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 5, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_2darray_ps.h
new file mode 100644
index 0000000000..42ceb4a597
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_2darray_ps.h
@@ -0,0 +1,89 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(255.000000, 255.000000, 255.000000, 255.000000)
+ftou o0.xyzw, r0.xyzw
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_PM_RGBA_2DArray[] = {
+ 68, 88, 66, 67, 72, 177, 176, 126, 150, 61, 34, 127, 37, 128, 200, 148, 82, 84, 84,
+ 63, 1, 0, 0, 0, 24, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 156, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 252, 0, 0, 0, 64, 0,
+ 0, 0, 63, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 0, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10,
+ 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0,
+ 0, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 127, 67, 28, 0,
+ 0, 5, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 62,
+ 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_3d_ps.h
new file mode 100644
index 0000000000..1e91151b5a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_3d_ps.h
@@ -0,0 +1,83 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.wwww, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(255.000000, 255.000000, 255.000000, 255.000000)
+ftou o0.xyzw, r0.xyzw
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_PM_RGBA_3D[] = {
+ 68, 88, 66, 67, 108, 177, 182, 169, 224, 190, 112, 68, 155, 228, 67, 226, 65, 238, 217,
+ 116, 1, 0, 0, 0, 216, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 92, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 196, 0, 0, 0, 64, 0, 0, 0, 49, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 7, 114, 0, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 127, 67, 0, 0,
+ 127, 67, 0, 0, 127, 67, 0, 0, 127, 67, 28, 0, 0, 5, 242, 32, 16, 0, 0,
+ 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_2d_ps.h
new file mode 100644
index 0000000000..c74a48f769
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_2d_ps.h
@@ -0,0 +1,79 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul r0.xyz, r0.xyzx, l(255.000000, 255.000000, 255.000000, 0.000000)
+ftou o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_PT_RGB_2D[] = {
+ 68, 88, 66, 67, 21, 43, 226, 215, 164, 244, 10, 22, 123, 34, 48, 235, 95, 92, 229,
+ 201, 1, 0, 0, 0, 160, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 36, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 188, 0, 0, 0, 64,
+ 0, 0, 0, 47, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 127, 67, 0, 0,
+ 127, 67, 0, 0, 127, 67, 0, 0, 0, 0, 28, 0, 0, 5, 114, 32, 16, 0, 0,
+ 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0,
+ 0, 0, 0, 0, 1, 64, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65,
+ 84, 116, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_2darray_ps.h
new file mode 100644
index 0000000000..dd66bae38b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_2darray_ps.h
@@ -0,0 +1,89 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.xyzx, l(255.000000, 255.000000, 255.000000, 0.000000)
+ftou o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_PT_RGB_2DArray[] = {
+ 68, 88, 66, 67, 135, 27, 134, 107, 134, 245, 87, 208, 181, 1, 171, 9, 139, 65, 67,
+ 42, 1, 0, 0, 0, 16, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 148, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 244, 0, 0, 0, 64, 0,
+ 0, 0, 61, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70,
+ 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 127, 67, 0, 0, 127, 67,
+ 0, 0, 127, 67, 0, 0, 0, 0, 28, 0, 0, 5, 114, 32, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116,
+ 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_3d_ps.h
new file mode 100644
index 0000000000..cedb2554e8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_3d_ps.h
@@ -0,0 +1,80 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.xyzx, l(255.000000, 255.000000, 255.000000, 0.000000)
+ftou o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_PT_RGB_3D[] = {
+ 68, 88, 66, 67, 198, 108, 113, 77, 139, 67, 45, 18, 83, 139, 168, 237, 165, 209, 182, 76,
+ 1, 0, 0, 0, 208, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0, 0, 0,
+ 92, 1, 0, 0, 144, 1, 0, 0, 84, 2, 0, 0, 82, 68, 69, 70, 152, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0, 0, 4, 255, 255,
+ 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8, 0, 0, 0, 255, 255, 255, 255,
+ 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 83, 97, 109, 112, 108, 101, 114, 0,
+ 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68, 0, 77, 105, 99, 114, 111, 115, 111, 102,
+ 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0,
+ 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69,
+ 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69,
+ 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 188, 0, 0, 0, 64, 0, 0, 0, 47, 0, 0, 0, 90, 0, 0, 3,
+ 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0,
+ 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69, 0, 0, 9,
+ 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0, 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0,
+ 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 127, 67,
+ 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 0, 0, 28, 0, 0, 5, 114, 32, 16, 0,
+ 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0,
+ 0, 0, 0, 0, 1, 64, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_2d_ps.h
new file mode 100644
index 0000000000..22bce837e4
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_2d_ps.h
@@ -0,0 +1,77 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul r0.xyzw, r0.xyzw, l(255.000000, 255.000000, 255.000000, 255.000000)
+ftou o0.xyzw, r0.xyzw
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_PT_RGBA_2D[] = {
+ 68, 88, 66, 67, 15, 203, 215, 26, 226, 132, 179, 250, 218, 76, 219, 205, 201, 184, 211,
+ 22, 1, 0, 0, 0, 140, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 16, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 168, 0, 0, 0, 64,
+ 0, 0, 0, 42, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 127, 67, 0, 0,
+ 127, 67, 0, 0, 127, 67, 0, 0, 127, 67, 28, 0, 0, 5, 242, 32, 16, 0, 0,
+ 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_2darray_ps.h
new file mode 100644
index 0000000000..3fffb1c2d3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_2darray_ps.h
@@ -0,0 +1,87 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul r0.xyzw, r0.xyzw, l(255.000000, 255.000000, 255.000000, 255.000000)
+ftou o0.xyzw, r0.xyzw
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_PT_RGBA_2DArray[] = {
+ 68, 88, 66, 67, 141, 122, 224, 133, 227, 61, 69, 44, 172, 221, 157, 131, 76, 235, 81,
+ 130, 1, 0, 0, 0, 252, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 128, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 224, 0, 0, 0, 64, 0,
+ 0, 0, 56, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 127, 67, 0, 0, 127, 67,
+ 0, 0, 127, 67, 0, 0, 127, 67, 28, 0, 0, 5, 242, 32, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0,
+ 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_3d_ps.h
new file mode 100644
index 0000000000..bd50542b5d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_3d_ps.h
@@ -0,0 +1,80 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul r0.xyzw, r0.xyzw, l(255.000000, 255.000000, 255.000000, 255.000000)
+ftou o0.xyzw, r0.xyzw
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_PT_RGBA_3D[] = {
+ 68, 88, 66, 67, 60, 29, 156, 198, 163, 110, 141, 222, 219, 229, 175, 1, 103, 9, 217,
+ 156, 1, 0, 0, 0, 188, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 64, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 168, 0, 0, 0, 64, 0, 0, 0, 42, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 127,
+ 67, 28, 0, 0, 5, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_2d_ps.h
new file mode 100644
index 0000000000..25149b232d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_2d_ps.h
@@ -0,0 +1,87 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyz, r0.xyzx, l(255.000000, 255.000000, 255.000000, 0.000000)
+ftou o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_UM_RGB_2D[] = {
+ 68, 88, 66, 67, 104, 222, 184, 218, 135, 243, 133, 232, 177, 236, 20, 60, 64, 9, 17,
+ 90, 1, 0, 0, 0, 252, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 128, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 24, 1, 0, 0, 64,
+ 0, 0, 0, 70, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0,
+ 0, 7, 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 0, 16, 0, 0, 0, 0, 0,
+ 6, 0, 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16,
+ 0, 0, 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 127, 67, 0, 0, 127, 67, 0,
+ 0, 127, 67, 0, 0, 0, 0, 28, 0, 0, 5, 114, 32, 16, 0, 0, 0, 0, 0,
+ 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0,
+ 0, 1, 64, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0,
+ 0, 0, 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_2darray_ps.h
new file mode 100644
index 0000000000..8b8d1d3b7f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_2darray_ps.h
@@ -0,0 +1,97 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 2
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyz, r0.xyzx, l(255.000000, 255.000000, 255.000000, 0.000000)
+ftou o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_UM_RGB_2DArray[] = {
+ 68, 88, 66, 67, 211, 11, 247, 147, 13, 61, 188, 52, 49, 20, 122, 213, 216, 130, 203,
+ 211, 1, 0, 0, 0, 108, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 240, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 80, 1, 0, 0, 64, 0,
+ 0, 0, 84, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 2, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7,
+ 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16,
+ 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0,
+ 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0,
+ 0, 0, 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0,
+ 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 127,
+ 67, 0, 0, 0, 0, 28, 0, 0, 5, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2,
+ 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1,
+ 64, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0,
+ 10, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_3d_ps.h
new file mode 100644
index 0000000000..f7746e87ee
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_3d_ps.h
@@ -0,0 +1,90 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyz, r0.xyzx, l(255.000000, 255.000000, 255.000000, 0.000000)
+ftou o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_UM_RGB_3D[] = {
+ 68, 88, 66, 67, 211, 77, 171, 115, 172, 101, 224, 185, 62, 127, 82, 90, 150, 163, 227,
+ 209, 1, 0, 0, 0, 44, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 176, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 24, 1, 0, 0, 64, 0, 0, 0, 70, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 2, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 49,
+ 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0,
+ 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7, 226, 0, 16, 0, 1, 0, 0,
+ 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0, 55, 0,
+ 0, 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, 150,
+ 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10,
+ 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2, 64, 0,
+ 0, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 0, 0, 28, 0,
+ 0, 5, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 1, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_2d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_2d_ps.h
new file mode 100644
index 0000000000..71530637ef
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_2d_ps.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(255.000000, 255.000000, 255.000000, 255.000000)
+ftou o0.xyzw, r0.xyzw
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_UM_RGBA_2D[] = {
+ 68, 88, 66, 67, 79, 47, 172, 229, 63, 231, 120, 201, 52, 133, 90, 84, 23, 233, 153,
+ 100, 1, 0, 0, 0, 232, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 108, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86,
+ 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 4, 1, 0, 0, 64,
+ 0, 0, 0, 65, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0,
+ 0, 0, 104, 0, 0, 2, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 0, 96, 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0,
+ 0, 7, 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246,
+ 15, 16, 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 0, 16, 0, 0, 0, 0, 0,
+ 6, 0, 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16,
+ 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 127, 67, 0, 0, 127, 67, 0,
+ 0, 127, 67, 0, 0, 127, 67, 28, 0, 0, 5, 242, 32, 16, 0, 0, 0, 0, 0,
+ 70, 14, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0,
+ 0, 7, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_2darray_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_2darray_ps.h
new file mode 100644
index 0000000000..5d75b8df6d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_2darray_ps.h
@@ -0,0 +1,95 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_2DArray texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 2
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(255.000000, 255.000000, 255.000000, 255.000000)
+ftou o0.xyzw, r0.xyzw
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_UM_RGBA_2DArray[] = {
+ 68, 88, 66, 67, 237, 98, 226, 3, 103, 212, 163, 240, 153, 59, 189, 19, 100, 209, 34,
+ 202, 1, 0, 0, 0, 88, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 220, 0,
+ 0, 0, 100, 1, 0, 0, 152, 1, 0, 0, 220, 2, 0, 0, 82, 68, 69, 70, 160,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 117, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 50, 68,
+ 65, 114, 114, 97, 121, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0,
+ 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0,
+ 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0,
+ 7, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95,
+ 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78,
+ 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 60, 1, 0, 0, 64, 0,
+ 0, 0, 79, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88,
+ 64, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4,
+ 18, 16, 16, 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 2, 0, 0, 0, 86, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96,
+ 16, 0, 0, 0, 0, 0, 49, 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7,
+ 226, 0, 16, 0, 1, 0, 0, 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16,
+ 0, 0, 0, 0, 0, 55, 0, 0, 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0,
+ 16, 0, 1, 0, 0, 0, 150, 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0,
+ 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 127,
+ 67, 0, 0, 127, 67, 28, 0, 0, 5, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 9,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_3d_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_3d_ps.h
new file mode 100644
index 0000000000..7d98511943
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_3d_ps.h
@@ -0,0 +1,88 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF_3D texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 2
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+lt r1.x, l(0.000000), r0.w
+div r1.yzw, r0.xxyz, r0.wwww
+movc r0.xyz, r1.xxxx, r1.yzwy, r0.xyzx
+mul r0.xyzw, r0.xyzw, l(255.000000, 255.000000, 255.000000, 255.000000)
+ftou o0.xyzw, r0.xyzw
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_FtoU_UM_RGBA_3D[] = {
+ 68, 88, 66, 67, 9, 246, 142, 132, 23, 145, 144, 223, 33, 247, 146, 14, 116, 28, 69,
+ 175, 1, 0, 0, 0, 24, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 156, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 112, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 51, 68,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48,
+ 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 4, 1, 0, 0, 64, 0, 0, 0, 65, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 2, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 49,
+ 0, 0, 7, 18, 0, 16, 0, 1, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0,
+ 58, 0, 16, 0, 0, 0, 0, 0, 14, 0, 0, 7, 226, 0, 16, 0, 1, 0, 0,
+ 0, 6, 9, 16, 0, 0, 0, 0, 0, 246, 15, 16, 0, 0, 0, 0, 0, 55, 0,
+ 0, 9, 114, 0, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 1, 0, 0, 0, 150,
+ 7, 16, 0, 1, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 10,
+ 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2, 64, 0,
+ 0, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 127, 67, 0, 0, 127, 67, 28, 0,
+ 0, 5, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 62,
+ 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 7, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h
new file mode 100644
index 0000000000..fdeae67ad9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h
@@ -0,0 +1,91 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION 0 xy 0 NONE float xy
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Runtime generated constant mappings:
+//
+// Target Reg Constant Description
+// ---------- --------------------------------------------------
+// c0 Vertex Shader position offset
+//
+//
+// Level9 shader bytecode:
+//
+ vs_2_x
+ def c1, 0, 1, 0, 0
+ dcl_texcoord v0
+ dcl_texcoord1 v1
+ add oPos.xy, v0, c0
+ mov oPos.zw, c1.xyxy
+ mov oT0.xy, v1
+
+// approximately 3 instruction slots used
+vs_4_0
+dcl_input v0.xy
+dcl_input v1.xy
+dcl_output_siv o0.xyzw, position
+dcl_output o1.xy
+mov o0.xy, v0.xyxx
+mov o0.zw, l(0,0,0,1.000000)
+mov o1.xy, v1.xyxx
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_VS_Passthrough2D[] = {
+ 68, 88, 66, 67, 157, 119, 222, 216, 39, 186, 195, 24, 174, 138, 22, 73, 223, 185, 107,
+ 36, 1, 0, 0, 0, 204, 2, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 200, 0,
+ 0, 0, 88, 1, 0, 0, 212, 1, 0, 0, 32, 2, 0, 0, 116, 2, 0, 0, 65,
+ 111, 110, 57, 136, 0, 0, 0, 136, 0, 0, 0, 0, 2, 254, 255, 96, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36, 0, 0, 0, 36,
+ 0, 1, 0, 36, 0, 0, 0, 0, 0, 1, 2, 254, 255, 81, 0, 0, 5, 1, 0,
+ 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 31,
+ 0, 0, 2, 5, 0, 0, 128, 0, 0, 15, 144, 31, 0, 0, 2, 5, 0, 1, 128,
+ 1, 0, 15, 144, 2, 0, 0, 3, 0, 0, 3, 192, 0, 0, 228, 144, 0, 0, 228,
+ 160, 1, 0, 0, 2, 0, 0, 12, 192, 1, 0, 68, 160, 1, 0, 0, 2, 0, 0,
+ 3, 224, 1, 0, 228, 144, 255, 255, 0, 0, 83, 72, 68, 82, 136, 0, 0, 0, 64,
+ 0, 1, 0, 34, 0, 0, 0, 95, 0, 0, 3, 50, 16, 16, 0, 0, 0, 0, 0,
+ 95, 0, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 103, 0, 0, 4, 242, 32, 16,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 101, 0, 0, 3, 50, 32, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5, 50, 32, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 0,
+ 0, 0, 0, 54, 0, 0, 8, 194, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 54, 0, 0,
+ 5, 50, 32, 16, 0, 1, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 68, 69, 70, 68, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 4,
+ 254, 255, 0, 1, 0, 0, 28, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116,
+ 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111,
+ 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 76, 0, 0,
+ 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 65, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 0,
+ 80, 79, 83, 73, 84, 73, 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171,
+ 171, 79, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 12, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78,
+ 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h
new file mode 100644
index 0000000000..23fc7f99ea
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h
@@ -0,0 +1,93 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// LAYER 0 x 1 NONE uint x
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+gs_4_0
+dcl_input_siv v[3][0].xyzw, position
+dcl_input v[3][1].x
+dcl_input v[3][2].xyz
+dcl_temps 1
+dcl_inputprimitive triangle
+dcl_outputtopology trianglestrip
+dcl_output_siv o0.xyzw, position
+dcl_output_siv o1.x, rendertarget_array_index
+dcl_output o2.xyz
+dcl_maxout 3
+mov r0.x, l(0)
+loop
+ ige r0.y, r0.x, l(3)
+ breakc_nz r0.y
+ mov o0.xyzw, v[r0.x + 0][0].xyzw
+ mov o1.x, v[r0.x + 0][1].x
+ mov o2.xyz, v[r0.x + 0][2].xyzx
+ emit
+ iadd r0.x, r0.x, l(1)
+endloop
+ret
+// Approximately 11 instruction slots used
+#endif
+
+const BYTE g_GS_Passthrough3D[] = {
+ 68, 88, 66, 67, 226, 188, 145, 36, 193, 19, 254, 1, 249, 51, 174, 53, 33, 65, 233,
+ 89, 1, 0, 0, 0, 60, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 128, 0,
+ 0, 0, 244, 0, 0, 0, 124, 1, 0, 0, 192, 2, 0, 0, 82, 68, 69, 70, 68,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 83, 71, 0, 1, 0, 0, 28, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 108,
+ 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 15, 0, 0, 92, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1,
+ 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2,
+ 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0,
+ 76, 65, 89, 69, 82, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71,
+ 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92,
+ 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 1, 14, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 2, 0, 0, 0, 7, 8, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79,
+ 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69, 84, 65, 82,
+ 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171,
+ 83, 72, 68, 82, 60, 1, 0, 0, 64, 0, 2, 0, 79, 0, 0, 0, 97, 0, 0,
+ 5, 242, 16, 32, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 95, 0,
+ 0, 4, 18, 16, 32, 0, 3, 0, 0, 0, 1, 0, 0, 0, 95, 0, 0, 4, 114,
+ 16, 32, 0, 3, 0, 0, 0, 2, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0,
+ 93, 24, 0, 1, 92, 40, 0, 1, 103, 0, 0, 4, 242, 32, 16, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 103, 0, 0, 4, 18, 32, 16, 0, 1, 0, 0, 0, 4, 0,
+ 0, 0, 101, 0, 0, 3, 114, 32, 16, 0, 2, 0, 0, 0, 94, 0, 0, 2, 3,
+ 0, 0, 0, 54, 0, 0, 5, 18, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 48, 0, 0, 1, 33, 0, 0, 7, 34, 0, 16, 0, 0, 0, 0,
+ 0, 10, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 3, 0, 0, 0, 3, 0,
+ 4, 3, 26, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 7, 242, 32, 16, 0, 0,
+ 0, 0, 0, 70, 30, 160, 0, 10, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 54, 0, 0, 7, 18, 32, 16, 0, 1, 0, 0, 0, 10, 16, 160, 0, 10, 0, 16,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 54, 0, 0, 7, 114, 32, 16, 0, 2, 0,
+ 0, 0, 70, 18, 160, 0, 10, 0, 16, 0, 0, 0, 0, 0, 2, 0, 0, 0, 19,
+ 0, 0, 1, 30, 0, 0, 7, 18, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0,
+ 0, 0, 0, 0, 1, 64, 0, 0, 1, 0, 0, 0, 22, 0, 0, 1, 62, 0, 0,
+ 1, 83, 84, 65, 84, 116, 0, 0, 0, 11, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 5, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h
new file mode 100644
index 0000000000..3c833f79a8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h
@@ -0,0 +1,75 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// POSITION 0 xy 0 NONE float xy
+// LAYER 0 x 1 NONE uint x
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float xyzw
+// LAYER 0 x 1 NONE uint x
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+vs_4_0
+dcl_input v0.xy
+dcl_input v1.x
+dcl_input v2.xyz
+dcl_output_siv o0.xyzw, position
+dcl_output o1.x
+dcl_output o2.xyz
+mov o0.xy, v0.xyxx
+mov o0.zw, l(0,0,0,1.000000)
+mov o1.x, v1.x
+mov o2.xyz, v2.xyzx
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_VS_Passthrough3D[] = {
+ 68, 88, 66, 67, 136, 150, 103, 162, 167, 195, 182, 112, 150, 17, 18, 65, 73, 164, 12,
+ 142, 1, 0, 0, 0, 156, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 128, 0,
+ 0, 0, 240, 0, 0, 0, 100, 1, 0, 0, 32, 2, 0, 0, 82, 68, 69, 70, 68,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 254, 255, 0, 1, 0, 0, 28, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 104,
+ 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 89, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1,
+ 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2,
+ 0, 0, 0, 7, 7, 0, 0, 80, 79, 83, 73, 84, 73, 79, 78, 0, 76, 65, 89,
+ 69, 82, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 79, 83, 71, 78, 108, 0, 0,
+ 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 14, 0, 0,
+ 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0,
+ 0, 7, 8, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 76, 65,
+ 89, 69, 82, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 83, 72, 68, 82, 180,
+ 0, 0, 0, 64, 0, 1, 0, 45, 0, 0, 0, 95, 0, 0, 3, 50, 16, 16, 0,
+ 0, 0, 0, 0, 95, 0, 0, 3, 18, 16, 16, 0, 1, 0, 0, 0, 95, 0, 0,
+ 3, 114, 16, 16, 0, 2, 0, 0, 0, 103, 0, 0, 4, 242, 32, 16, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 101, 0, 0, 3, 18, 32, 16, 0, 1, 0, 0, 0, 101,
+ 0, 0, 3, 114, 32, 16, 0, 2, 0, 0, 0, 54, 0, 0, 5, 50, 32, 16, 0,
+ 0, 0, 0, 0, 70, 16, 16, 0, 0, 0, 0, 0, 54, 0, 0, 8, 194, 32, 16,
+ 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 128, 63, 54, 0, 0, 5, 18, 32, 16, 0, 1, 0, 0, 0, 10,
+ 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5, 114, 32, 16, 0, 2, 0, 0, 0,
+ 70, 18, 16, 0, 2, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0,
+ 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrougha2d11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrougha2d11ps.h
new file mode 100644
index 0000000000..a338628659
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrougha2d11ps.h
@@ -0,0 +1,103 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ def c0, 0, 1, 0, 0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mul r0, r0.w, c0.xxxy
+ mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov o0.w, r0.w
+mov o0.xyz, l(0,0,0,0)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughA2D[] = {
+ 68, 88, 66, 67, 194, 169, 124, 165, 14, 7, 97, 151, 180, 238, 123, 252, 63, 248, 162,
+ 165, 1, 0, 0, 0, 28, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 204, 0,
+ 0, 0, 116, 1, 0, 0, 240, 1, 0, 0, 144, 2, 0, 0, 232, 2, 0, 0, 65,
+ 111, 110, 57, 140, 0, 0, 0, 140, 0, 0, 0, 0, 2, 255, 255, 100, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36,
+ 0, 0, 0, 40, 0, 0, 0, 0, 0, 1, 2, 255, 255, 81, 0, 0, 5, 0, 0,
+ 15, 160, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 31,
+ 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228,
+ 160, 5, 0, 0, 3, 0, 0, 15, 128, 0, 0, 255, 128, 0, 0, 64, 160, 1, 0,
+ 0, 2, 0, 8, 15, 128, 0, 0, 228, 128, 255, 255, 0, 0, 83, 72, 68, 82, 160,
+ 0, 0, 0, 64, 0, 0, 0, 40, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0,
+ 0, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0,
+ 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32,
+ 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69, 0, 0, 9, 242,
+ 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16,
+ 0, 0, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 8, 114, 32,
+ 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 82, 68, 69, 70, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 28, 0, 0, 0, 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0,
+ 92, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1,
+ 0, 0, 0, 13, 0, 0, 0, 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116,
+ 117, 114, 101, 70, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101,
+ 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2,
+ 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0,
+ 171, 171, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h
new file mode 100644
index 0000000000..e8790cade6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h
@@ -0,0 +1,73 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_DEPTH 0 N/A oDepth DEPTH float YES
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output oDepth
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov oDepth, r0.x
+ret
+// Approximately 3 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughDepth2D[] = {
+ 68, 88, 66, 67, 215, 216, 149, 20, 177, 67, 115, 222, 9, 179, 226, 21, 58, 197, 172,
+ 136, 1, 0, 0, 0, 92, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 44, 1, 0, 0, 96, 1, 0, 0, 224, 1, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0,
+ 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73,
+ 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78,
+ 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 0, 83, 86,
+ 95, 68, 69, 80, 84, 72, 0, 171, 171, 171, 83, 72, 68, 82, 120, 0, 0, 0, 64,
+ 0, 0, 0, 30, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0,
+ 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0,
+ 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 2, 1, 192, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70,
+ 16, 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0,
+ 0, 0, 0, 0, 54, 0, 0, 4, 1, 192, 0, 0, 10, 0, 16, 0, 0, 0, 0,
+ 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 3, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h
new file mode 100644
index 0000000000..c8a472e9b6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h
@@ -0,0 +1,103 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ def c0, 1, 0, 0, 0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mad r0, r0.x, c0.xxxy, c0.yyyx
+ mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov o0.xyz, r0.xxxx
+mov o0.w, l(1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughLum2D[] = {
+ 68, 88, 66, 67, 241, 199, 66, 51, 118, 205, 236, 165, 244, 231, 234, 126, 203, 25, 231,
+ 134, 1, 0, 0, 0, 20, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 208, 0,
+ 0, 0, 108, 1, 0, 0, 232, 1, 0, 0, 136, 2, 0, 0, 224, 2, 0, 0, 65,
+ 111, 110, 57, 144, 0, 0, 0, 144, 0, 0, 0, 0, 2, 255, 255, 104, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36,
+ 0, 0, 0, 40, 0, 0, 0, 0, 0, 1, 2, 255, 255, 81, 0, 0, 5, 0, 0,
+ 15, 160, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31,
+ 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228,
+ 160, 4, 0, 0, 4, 0, 0, 15, 128, 0, 0, 0, 128, 0, 0, 64, 160, 0, 0,
+ 21, 160, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 128, 255, 255, 0, 0, 83,
+ 72, 68, 82, 148, 0, 0, 0, 64, 0, 0, 0, 37, 0, 0, 0, 90, 0, 0, 3,
+ 0, 96, 16, 0, 0, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0,
+ 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69,
+ 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 5, 114, 32, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 62,
+ 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 68, 69, 70, 152, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0, 0,
+ 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 83,
+ 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171,
+ 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79,
+ 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2darray11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2darray11ps.h
new file mode 100644
index 0000000000..4741497d93
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2darray11ps.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mov o0.xyz, r0.xxxx
+mov o0.w, l(1.000000)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughLum2DArray[] = {
+ 68, 88, 66, 67, 84, 131, 205, 28, 3, 168, 120, 6, 89, 75, 169, 140, 154, 126, 61,
+ 31, 1, 0, 0, 0, 224, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 100, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 204, 0, 0, 0, 64, 0, 0, 0, 51, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 64, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4, 18, 16, 16, 0, 1, 0, 0, 0,
+ 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 86, 0,
+ 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 1, 0, 0, 0, 54,
+ 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2, 0, 0, 0,
+ 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0,
+ 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 114, 32, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63,
+ 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h
new file mode 100644
index 0000000000..5c9ffc039a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h
@@ -0,0 +1,79 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mov o0.xyz, r0.xxxx
+mov o0.w, l(1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughLum3D[] = {
+ 68, 88, 66, 67, 15, 80, 145, 76, 93, 127, 194, 208, 106, 29, 26, 87, 147, 62, 128,
+ 143, 1, 0, 0, 0, 168, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 44, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 148, 0, 0, 0, 64, 0, 0, 0, 37, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 5, 114, 32, 16, 0, 0, 0, 0, 0, 6, 0, 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128,
+ 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h
new file mode 100644
index 0000000000..6229e57ea2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h
@@ -0,0 +1,98 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mov r0, r0.xxxw
+ mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov o0.xyzw, r0.xxxw
+ret
+// Approximately 3 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughLumAlpha2D[] = {
+ 68, 88, 66, 67, 19, 109, 76, 235, 225, 193, 54, 241, 78, 207, 77, 62, 148, 127, 172,
+ 73, 1, 0, 0, 0, 224, 2, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 176, 0,
+ 0, 0, 56, 1, 0, 0, 180, 1, 0, 0, 84, 2, 0, 0, 172, 2, 0, 0, 65,
+ 111, 110, 57, 112, 0, 0, 0, 112, 0, 0, 0, 0, 2, 255, 255, 72, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36,
+ 0, 0, 0, 40, 0, 0, 0, 0, 0, 1, 2, 255, 255, 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144, 0, 8, 15, 160, 66,
+ 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228, 160, 1, 0, 0, 2,
+ 0, 0, 15, 128, 0, 0, 192, 128, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228,
+ 128, 255, 255, 0, 0, 83, 72, 68, 82, 128, 0, 0, 0, 64, 0, 0, 0, 32, 0,
+ 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 24, 0, 4, 0,
+ 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0,
+ 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 16,
+ 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0,
+ 0, 0, 0, 54, 0, 0, 5, 242, 32, 16, 0, 0, 0, 0, 0, 6, 12, 16, 0,
+ 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 3, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82,
+ 68, 69, 70, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 28, 0, 0, 0, 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5,
+ 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0,
+ 13, 0, 0, 0, 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101,
+ 70, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49,
+ 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0,
+ 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171,
+ 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0,
+ 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2darray11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2darray11ps.h
new file mode 100644
index 0000000000..cdc91561bc
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2darray11ps.h
@@ -0,0 +1,83 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mov o0.xyzw, r0.xxxw
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughLumAlpha2DArray[] = {
+ 68, 88, 66, 67, 117, 33, 119, 91, 15, 156, 83, 232, 200, 231, 183, 116, 40, 238, 79,
+ 163, 1, 0, 0, 0, 204, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 80, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 184, 0, 0, 0, 64, 0, 0, 0, 46, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 64, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4, 18, 16, 16, 0, 1, 0, 0, 0,
+ 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 86, 0,
+ 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 1, 0, 0, 0, 54,
+ 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2, 0, 0, 0,
+ 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0,
+ 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 242, 32, 16, 0, 0, 0, 0, 0, 6, 12, 16, 0, 0, 0, 0, 0, 62,
+ 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h
new file mode 100644
index 0000000000..941b5b2b86
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h
@@ -0,0 +1,77 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mov o0.xyzw, r0.xxxw
+ret
+// Approximately 3 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughLumAlpha3D[] = {
+ 68, 88, 66, 67, 158, 22, 231, 90, 211, 81, 99, 1, 181, 209, 159, 145, 140, 162, 254,
+ 17, 1, 0, 0, 0, 148, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 24, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 128, 0, 0, 0, 64, 0, 0, 0, 32, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 5, 242, 32, 16, 0, 0, 0, 0, 0, 6, 12, 16, 0, 0, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h
new file mode 100644
index 0000000000..1b41ed1602
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h
@@ -0,0 +1,104 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ def c0, 1, 0, 0, 0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mad r0, r0.x, c0.xyyy, c0.yyyx
+ mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov o0.x, r0.x
+mov o0.yzw, l(0,0,0,1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughR2D[] = {
+ 68, 88, 66, 67, 14, 165, 206, 90, 117, 2, 221, 45, 225, 30, 128, 173, 62, 238, 39,
+ 64, 1, 0, 0, 0, 32, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 208, 0,
+ 0, 0, 120, 1, 0, 0, 244, 1, 0, 0, 148, 2, 0, 0, 236, 2, 0, 0, 65,
+ 111, 110, 57, 144, 0, 0, 0, 144, 0, 0, 0, 0, 2, 255, 255, 104, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36,
+ 0, 0, 0, 40, 0, 0, 0, 0, 0, 1, 2, 255, 255, 81, 0, 0, 5, 0, 0,
+ 15, 160, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31,
+ 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228,
+ 160, 4, 0, 0, 4, 0, 0, 15, 128, 0, 0, 0, 128, 0, 0, 84, 160, 0, 0,
+ 21, 160, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 128, 255, 255, 0, 0, 83,
+ 72, 68, 82, 160, 0, 0, 0, 64, 0, 0, 0, 40, 0, 0, 0, 90, 0, 0, 3,
+ 0, 96, 16, 0, 0, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0,
+ 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69,
+ 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 5, 18, 32, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 8, 226, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 82, 68, 69, 70, 152, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0, 0, 4, 255, 255, 0, 1, 0, 0,
+ 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 100, 0,
+ 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0,
+ 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 83, 97, 109, 112, 108, 101, 114, 0,
+ 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32,
+ 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 80,
+ 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 3,
+ 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 84, 69, 88, 67, 79,
+ 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0,
+ 171, 171};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2darray11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2darray11ps.h
new file mode 100644
index 0000000000..a5e3d5e52e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2darray11ps.h
@@ -0,0 +1,86 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mov o0.x, r0.x
+mov o0.yzw, l(0,0,0,1.000000)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughR2DArray[] = {
+ 68, 88, 66, 67, 67, 125, 115, 154, 244, 73, 25, 207, 88, 140, 76, 46, 206, 166, 161,
+ 193, 1, 0, 0, 0, 236, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 112, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 216, 0, 0, 0, 64, 0, 0, 0, 54, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 64, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4, 18, 16, 16, 0, 1, 0, 0, 0,
+ 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 86, 0,
+ 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 1, 0, 0, 0, 54,
+ 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2, 0, 0, 0,
+ 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0,
+ 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 18, 32, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 8, 226, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65,
+ 84, 116, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2darrayi11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2darrayi11ps.h
new file mode 100644
index 0000000000..eb41a93e37
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2darrayi11ps.h
@@ -0,0 +1,90 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureI texture sint4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture2darray (sint,sint,sint,sint) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v2.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.z, v1.x
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.x, r0.x
+mov o0.yzw, l(0,0,0,1)
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughR2DArrayI[] = {
+ 68, 88, 66, 67, 200, 92, 148, 185, 17, 79, 183, 61, 19, 121, 215, 3, 144, 133, 210,
+ 72, 1, 0, 0, 0, 16, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 148, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 5, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 73, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 36, 1, 0, 0, 64, 0, 0, 0, 73, 0, 0, 0, 88, 64, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 51, 51, 0, 0, 100, 8, 0, 4, 18, 16, 16,
+ 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1,
+ 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16,
+ 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2,
+ 0, 0, 0, 27, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16,
+ 0, 1, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 18, 32, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 8, 226, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116,
+ 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2darrayui11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2darrayui11ps.h
new file mode 100644
index 0000000000..12825c89e6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2darrayui11ps.h
@@ -0,0 +1,90 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureUI texture uint4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture2darray (uint,uint,uint,uint) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v2.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.z, v1.x
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.x, r0.x
+mov o0.yzw, l(0,0,0,1)
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughR2DArrayUI[] = {
+ 68, 88, 66, 67, 201, 224, 137, 9, 164, 198, 146, 11, 60, 99, 27, 27, 235, 209, 108,
+ 242, 1, 0, 0, 0, 16, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 148, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 70, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 5, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 85, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 36, 1, 0, 0, 64, 0, 0, 0, 73, 0, 0, 0, 88, 64, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 68, 68, 0, 0, 100, 8, 0, 4, 18, 16, 16,
+ 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1,
+ 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16,
+ 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2,
+ 0, 0, 0, 27, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16,
+ 0, 1, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 18, 32, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 8, 226, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116,
+ 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h
new file mode 100644
index 0000000000..ea6bbcd460
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h
@@ -0,0 +1,83 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureI texture sint4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture2d (sint,sint,sint,sint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.x, r0.x
+mov o0.yzw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughR2DI[] = {
+ 68, 88, 66, 67, 8, 16, 169, 157, 145, 179, 119, 85, 36, 37, 85, 107, 44, 112, 158,
+ 100, 1, 0, 0, 0, 200, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 4, 1, 0, 0, 56, 1, 0, 0, 76, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 73, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171,
+ 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78,
+ 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 12, 1, 0, 0, 64, 0, 0,
+ 0, 67, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 51, 51,
+ 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 61, 16, 0, 7,
+ 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 70, 126, 16,
+ 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 70,
+ 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 27, 0, 0, 5,
+ 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 8, 194, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 18, 32, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0,
+ 0, 54, 0, 0, 8, 226, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83,
+ 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h
new file mode 100644
index 0000000000..bc034faaf6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h
@@ -0,0 +1,83 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureUI texture uint4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture2d (uint,uint,uint,uint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.x, r0.x
+mov o0.yzw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughR2DUI[] = {
+ 68, 88, 66, 67, 6, 47, 175, 167, 62, 144, 171, 206, 77, 165, 245, 226, 135, 124, 142,
+ 188, 1, 0, 0, 0, 200, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 4, 1, 0, 0, 56, 1, 0, 0, 76, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 70, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 85, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171,
+ 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78,
+ 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 12, 1, 0, 0, 64, 0, 0,
+ 0, 67, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 68, 68,
+ 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 61, 16, 0, 7,
+ 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 70, 126, 16,
+ 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 70,
+ 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 27, 0, 0, 5,
+ 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 8, 194, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 18, 32, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0,
+ 0, 54, 0, 0, 8, 226, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83,
+ 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h
new file mode 100644
index 0000000000..010e3eae14
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h
@@ -0,0 +1,80 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mov o0.x, r0.x
+mov o0.yzw, l(0,0,0,1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughR3D[] = {
+ 68, 88, 66, 67, 134, 101, 76, 73, 205, 199, 65, 249, 170, 201, 40, 128, 129, 87, 93,
+ 148, 1, 0, 0, 0, 180, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 56, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 160, 0, 0, 0, 64, 0, 0, 0, 40, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 5, 18, 32, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 226, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h
new file mode 100644
index 0000000000..447690e35e
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h
@@ -0,0 +1,86 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureI texture sint4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture3d (sint,sint,sint,sint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.x, r0.x
+mov o0.yzw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughR3DI[] = {
+ 68, 88, 66, 67, 250, 224, 56, 242, 8, 157, 92, 236, 205, 252, 68, 242, 80, 46, 223,
+ 98, 1, 0, 0, 0, 236, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 112, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 8, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 73, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 0, 1, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 88, 40, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 51, 51, 0, 0, 98, 16, 0, 3, 114, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5,
+ 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0,
+ 7, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 18,
+ 16, 0, 2, 0, 0, 0, 27, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70,
+ 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 18, 32, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 8, 226, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65,
+ 84, 116, 0, 0, 0, 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h
new file mode 100644
index 0000000000..040b333116
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h
@@ -0,0 +1,86 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureUI texture uint4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture3d (uint,uint,uint,uint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.x, r0.x
+mov o0.yzw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughR3DUI[] = {
+ 68, 88, 66, 67, 125, 15, 246, 192, 16, 228, 182, 55, 2, 24, 75, 71, 132, 253, 233,
+ 61, 1, 0, 0, 0, 236, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 112, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 70, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 8, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 85, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 0, 1, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 88, 40, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 68, 68, 0, 0, 98, 16, 0, 3, 114, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5,
+ 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0,
+ 7, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 18,
+ 16, 0, 2, 0, 0, 0, 27, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70,
+ 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 18, 32, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 8, 226, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65,
+ 84, 116, 0, 0, 0, 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h
new file mode 100644
index 0000000000..a9373f69ab
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h
@@ -0,0 +1,104 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ def c0, 1, 0, 0, 0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mad r0, r0.xyxx, c0.xxyy, c0.yyyx
+ mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov o0.xy, r0.xyxx
+mov o0.zw, l(0,0,0,1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRG2D[] = {
+ 68, 88, 66, 67, 151, 54, 111, 200, 187, 200, 177, 214, 12, 69, 246, 113, 254, 31, 23,
+ 45, 1, 0, 0, 0, 32, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 208, 0,
+ 0, 0, 120, 1, 0, 0, 244, 1, 0, 0, 148, 2, 0, 0, 236, 2, 0, 0, 65,
+ 111, 110, 57, 144, 0, 0, 0, 144, 0, 0, 0, 0, 2, 255, 255, 104, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36,
+ 0, 0, 0, 40, 0, 0, 0, 0, 0, 1, 2, 255, 255, 81, 0, 0, 5, 0, 0,
+ 15, 160, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31,
+ 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228,
+ 160, 4, 0, 0, 4, 0, 0, 15, 128, 0, 0, 4, 128, 0, 0, 80, 160, 0, 0,
+ 21, 160, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 128, 255, 255, 0, 0, 83,
+ 72, 68, 82, 160, 0, 0, 0, 64, 0, 0, 0, 40, 0, 0, 0, 90, 0, 0, 3,
+ 0, 96, 16, 0, 0, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0,
+ 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69,
+ 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 5, 50, 32, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 8, 194, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 82, 68, 69, 70, 152, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0, 0, 4, 255, 255, 0, 1, 0, 0,
+ 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 100, 0,
+ 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0,
+ 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 83, 97, 109, 112, 108, 101, 114, 0,
+ 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32,
+ 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109,
+ 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 80,
+ 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 3,
+ 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 84, 69, 88, 67, 79,
+ 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0,
+ 171, 171};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2darray11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2darray11ps.h
new file mode 100644
index 0000000000..e97f66a770
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2darray11ps.h
@@ -0,0 +1,86 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mov o0.xy, r0.xyxx
+mov o0.zw, l(0,0,0,1.000000)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRG2DArray[] = {
+ 68, 88, 66, 67, 20, 85, 120, 206, 181, 139, 167, 245, 44, 89, 37, 135, 242, 39, 108,
+ 150, 1, 0, 0, 0, 236, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 112, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 216, 0, 0, 0, 64, 0, 0, 0, 54, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 64, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4, 18, 16, 16, 0, 1, 0, 0, 0,
+ 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 86, 0,
+ 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 1, 0, 0, 0, 54,
+ 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2, 0, 0, 0,
+ 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0,
+ 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 50, 32, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 8, 194, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65,
+ 84, 116, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2darrayi11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2darrayi11ps.h
new file mode 100644
index 0000000000..f7ac20960d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2darrayi11ps.h
@@ -0,0 +1,90 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureI texture sint4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture2darray (sint,sint,sint,sint) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v2.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.z, v1.x
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xy, r0.xyxx
+mov o0.zw, l(0,0,0,1)
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRG2DArrayI[] = {
+ 68, 88, 66, 67, 221, 150, 25, 83, 110, 171, 138, 218, 81, 94, 8, 224, 63, 191, 253,
+ 25, 1, 0, 0, 0, 16, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 148, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 5, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 73, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 36, 1, 0, 0, 64, 0, 0, 0, 73, 0, 0, 0, 88, 64, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 51, 51, 0, 0, 100, 8, 0, 4, 18, 16, 16,
+ 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1,
+ 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16,
+ 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2,
+ 0, 0, 0, 27, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16,
+ 0, 1, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 50, 32, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 8, 194, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116,
+ 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2darrayui11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2darrayui11ps.h
new file mode 100644
index 0000000000..2caa7b3b80
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2darrayui11ps.h
@@ -0,0 +1,90 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureUI texture uint4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture2darray (uint,uint,uint,uint) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v2.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.z, v1.x
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xy, r0.xyxx
+mov o0.zw, l(0,0,0,1)
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRG2DArrayUI[] = {
+ 68, 88, 66, 67, 120, 173, 124, 47, 122, 95, 175, 210, 44, 74, 36, 182, 242, 25, 225,
+ 20, 1, 0, 0, 0, 16, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 148, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 70, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 5, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 85, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 36, 1, 0, 0, 64, 0, 0, 0, 73, 0, 0, 0, 88, 64, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 68, 68, 0, 0, 100, 8, 0, 4, 18, 16, 16,
+ 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1,
+ 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16,
+ 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2,
+ 0, 0, 0, 27, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16,
+ 0, 1, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 50, 32, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 8, 194, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116,
+ 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h
new file mode 100644
index 0000000000..25f0638e82
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h
@@ -0,0 +1,83 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureI texture sint4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture2d (sint,sint,sint,sint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xy, r0.xyxx
+mov o0.zw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRG2DI[] = {
+ 68, 88, 66, 67, 161, 76, 0, 115, 100, 69, 2, 128, 179, 140, 112, 55, 172, 151, 175,
+ 231, 1, 0, 0, 0, 200, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 4, 1, 0, 0, 56, 1, 0, 0, 76, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 73, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171,
+ 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78,
+ 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 12, 1, 0, 0, 64, 0, 0,
+ 0, 67, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 51, 51,
+ 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 61, 16, 0, 7,
+ 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 70, 126, 16,
+ 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 70,
+ 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 27, 0, 0, 5,
+ 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 8, 194, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 50, 32, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0,
+ 0, 54, 0, 0, 8, 194, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83,
+ 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h
new file mode 100644
index 0000000000..cf9f8c793b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h
@@ -0,0 +1,83 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureUI texture uint4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture2d (uint,uint,uint,uint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xy, r0.xyxx
+mov o0.zw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRG2DUI[] = {
+ 68, 88, 66, 67, 161, 19, 0, 215, 231, 88, 50, 183, 124, 43, 107, 122, 144, 150, 193,
+ 168, 1, 0, 0, 0, 200, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 4, 1, 0, 0, 56, 1, 0, 0, 76, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 70, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 85, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171,
+ 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78,
+ 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 12, 1, 0, 0, 64, 0, 0,
+ 0, 67, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 68, 68,
+ 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 61, 16, 0, 7,
+ 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 70, 126, 16,
+ 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 70,
+ 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 27, 0, 0, 5,
+ 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 8, 194, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 50, 32, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0,
+ 0, 54, 0, 0, 8, 194, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83,
+ 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h
new file mode 100644
index 0000000000..f9d91f7bd7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h
@@ -0,0 +1,80 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mov o0.xy, r0.xyxx
+mov o0.zw, l(0,0,0,1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRG3D[] = {
+ 68, 88, 66, 67, 234, 174, 205, 77, 197, 154, 113, 172, 235, 131, 32, 212, 121, 65, 136,
+ 164, 1, 0, 0, 0, 180, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 56, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 160, 0, 0, 0, 64, 0, 0, 0, 40, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 5, 50, 32, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 8, 194, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84,
+ 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h
new file mode 100644
index 0000000000..53b5685cd6
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h
@@ -0,0 +1,86 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureI texture sint4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture3d (sint,sint,sint,sint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xy, r0.xyxx
+mov o0.zw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRG3DI[] = {
+ 68, 88, 66, 67, 215, 62, 152, 236, 50, 188, 41, 213, 133, 37, 41, 228, 13, 20, 9,
+ 166, 1, 0, 0, 0, 236, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 112, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 8, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 73, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 0, 1, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 88, 40, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 51, 51, 0, 0, 98, 16, 0, 3, 114, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5,
+ 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0,
+ 7, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 18,
+ 16, 0, 2, 0, 0, 0, 27, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70,
+ 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 50, 32, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 8, 194, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65,
+ 84, 116, 0, 0, 0, 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h
new file mode 100644
index 0000000000..de7c00b8cb
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h
@@ -0,0 +1,86 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureUI texture uint4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture3d (uint,uint,uint,uint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xy, r0.xyxx
+mov o0.zw, l(0,0,0,0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRG3DUI[] = {
+ 68, 88, 66, 67, 136, 113, 120, 69, 210, 200, 206, 216, 193, 132, 168, 220, 72, 141, 170,
+ 116, 1, 0, 0, 0, 236, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 112, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 70, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 8, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 85, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 0, 1, 0, 0, 64, 0, 0, 0, 64, 0, 0, 0, 88, 40, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 68, 68, 0, 0, 98, 16, 0, 3, 114, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5,
+ 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0,
+ 7, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 18,
+ 16, 0, 2, 0, 0, 0, 27, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70,
+ 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 50, 32, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 8, 194, 32, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65,
+ 84, 116, 0, 0, 0, 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h
new file mode 100644
index 0000000000..7187de985f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h
@@ -0,0 +1,103 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ def c0, 1, 0, 0, 0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mad r0, r0.xyzx, c0.xxxy, c0.yyyx
+ mov oC0, r0
+
+// approximately 3 instruction slots used (1 texture, 2 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov o0.xyz, r0.xyzx
+mov o0.w, l(1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB2D[] = {
+ 68, 88, 66, 67, 250, 48, 137, 17, 146, 199, 249, 10, 198, 141, 227, 123, 246, 248, 120,
+ 90, 1, 0, 0, 0, 20, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 208, 0,
+ 0, 0, 108, 1, 0, 0, 232, 1, 0, 0, 136, 2, 0, 0, 224, 2, 0, 0, 65,
+ 111, 110, 57, 144, 0, 0, 0, 144, 0, 0, 0, 0, 2, 255, 255, 104, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36,
+ 0, 0, 0, 40, 0, 0, 0, 0, 0, 1, 2, 255, 255, 81, 0, 0, 5, 0, 0,
+ 15, 160, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31,
+ 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228,
+ 160, 4, 0, 0, 4, 0, 0, 15, 128, 0, 0, 36, 128, 0, 0, 64, 160, 0, 0,
+ 21, 160, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 128, 255, 255, 0, 0, 83,
+ 72, 68, 82, 148, 0, 0, 0, 64, 0, 0, 0, 37, 0, 0, 0, 90, 0, 0, 3,
+ 0, 96, 16, 0, 0, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0,
+ 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0,
+ 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 69,
+ 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 5, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 62,
+ 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 68, 69, 70, 152, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0, 0,
+ 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4, 0,
+ 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0, 83,
+ 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171,
+ 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79,
+ 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d_565_11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d_565_11ps.h
new file mode 100644
index 0000000000..7807225fa7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d_565_11ps.h
@@ -0,0 +1,118 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ def c0, 31, 63, 0.5, 1
+ def c1, 0.0322580636, 0.0158730168, 0, 0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mad r0.xyz, r0, c0.xyxw, c0.z
+ frc r1.xyz, r0
+ add r0.xyz, r0, -r1
+ mul r0.xyz, r0, c1.xyxw
+ mov r0.w, c0.w
+ mov oC0, r0
+
+// approximately 7 instruction slots used (1 texture, 6 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul r0.xyz, r0.xyzx, l(31.000000, 63.000000, 31.000000, 0.000000)
+round_ne r0.xyz, r0.xyzx
+mul o0.xyz, r0.xyzx, l(0.032258, 0.015873, 0.032258, 0.000000)
+mov o0.w, l(1.000000)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB2D_565[] = {
+ 68, 88, 66, 67, 120, 69, 206, 120, 97, 29, 104, 168, 87, 8, 112, 9, 57, 119, 88,
+ 99, 1, 0, 0, 0, 180, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 32, 1,
+ 0, 0, 12, 2, 0, 0, 136, 2, 0, 0, 40, 3, 0, 0, 128, 3, 0, 0, 65,
+ 111, 110, 57, 224, 0, 0, 0, 224, 0, 0, 0, 0, 2, 255, 255, 184, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36,
+ 0, 0, 0, 40, 0, 0, 0, 0, 0, 1, 2, 255, 255, 81, 0, 0, 5, 0, 0,
+ 15, 160, 0, 0, 248, 65, 0, 0, 124, 66, 0, 0, 0, 63, 0, 0, 128, 63, 81,
+ 0, 0, 5, 1, 0, 15, 160, 8, 33, 4, 61, 33, 8, 130, 60, 0, 0, 0, 0,
+ 0, 0, 0, 0, 31, 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0,
+ 2, 0, 0, 0, 144, 0, 8, 15, 160, 66, 0, 0, 3, 0, 0, 15, 128, 0, 0,
+ 228, 176, 0, 8, 228, 160, 4, 0, 0, 4, 0, 0, 7, 128, 0, 0, 228, 128, 0,
+ 0, 196, 160, 0, 0, 170, 160, 19, 0, 0, 2, 1, 0, 7, 128, 0, 0, 228, 128,
+ 2, 0, 0, 3, 0, 0, 7, 128, 0, 0, 228, 128, 1, 0, 228, 129, 5, 0, 0,
+ 3, 0, 0, 7, 128, 0, 0, 228, 128, 1, 0, 196, 160, 1, 0, 0, 2, 0, 0,
+ 8, 128, 0, 0, 255, 160, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 128, 255,
+ 255, 0, 0, 83, 72, 68, 82, 228, 0, 0, 0, 64, 0, 0, 0, 57, 0, 0, 0,
+ 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16,
+ 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1,
+ 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0,
+ 0, 56, 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0, 0, 0, 248, 65, 0, 0, 124, 66, 0, 0, 248, 65, 0,
+ 0, 0, 0, 64, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0,
+ 0, 0, 0, 0, 56, 0, 0, 10, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16,
+ 0, 0, 0, 0, 0, 2, 64, 0, 0, 8, 33, 4, 61, 33, 8, 130, 60, 8, 33,
+ 4, 61, 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0,
+ 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 82, 68, 69, 70, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 28, 0, 0, 0, 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0,
+ 92, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0,
+ 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1,
+ 0, 0, 0, 13, 0, 0, 0, 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116,
+ 117, 114, 101, 70, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32,
+ 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101,
+ 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2,
+ 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86,
+ 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0,
+ 171, 171, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darray11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darray11ps.h
new file mode 100644
index 0000000000..22fc48b370
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darray11ps.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mov o0.xyz, r0.xyzx
+mov o0.w, l(1.000000)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB2DArray[] = {
+ 68, 88, 66, 67, 26, 40, 103, 223, 174, 169, 46, 176, 180, 125, 61, 98, 234, 113, 13,
+ 48, 1, 0, 0, 0, 224, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 100, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 204, 0, 0, 0, 64, 0, 0, 0, 51, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 64, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4, 18, 16, 16, 0, 1, 0, 0, 0,
+ 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 86, 0,
+ 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 1, 0, 0, 0, 54,
+ 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2, 0, 0, 0,
+ 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0,
+ 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63,
+ 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darray_565_11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darray_565_11ps.h
new file mode 100644
index 0000000000..93c8675762
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darray_565_11ps.h
@@ -0,0 +1,91 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.xyzx, l(31.000000, 63.000000, 31.000000, 0.000000)
+round_ne r0.xyz, r0.xyzx
+mul o0.xyz, r0.xyzx, l(0.032258, 0.015873, 0.032258, 0.000000)
+mov o0.w, l(1.000000)
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB2DArray_565[] = {
+ 68, 88, 66, 67, 185, 16, 51, 115, 29, 189, 183, 180, 27, 245, 224, 140, 177, 41, 213,
+ 79, 1, 0, 0, 0, 48, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 180, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 28, 1, 0, 0, 64, 0, 0, 0, 71, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 64, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4, 18, 16, 16, 0, 1, 0, 0, 0,
+ 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 86, 0,
+ 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 1, 0, 0, 0, 54,
+ 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2, 0, 0, 0,
+ 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0,
+ 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56, 0,
+ 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 2,
+ 64, 0, 0, 0, 0, 248, 65, 0, 0, 124, 66, 0, 0, 248, 65, 0, 0, 0, 0,
+ 64, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0,
+ 0, 56, 0, 0, 10, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0, 8, 33, 4, 61, 33, 8, 130, 60, 8, 33, 4, 61, 0,
+ 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0,
+ 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darrayi11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darrayi11ps.h
new file mode 100644
index 0000000000..da517dedc7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darrayi11ps.h
@@ -0,0 +1,89 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureI texture sint4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture2darray (sint,sint,sint,sint) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v2.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.z, v1.x
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB2DArrayI[] = {
+ 68, 88, 66, 67, 176, 173, 178, 89, 17, 53, 136, 1, 253, 33, 56, 172, 20, 106, 131,
+ 127, 1, 0, 0, 0, 4, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 136, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 5, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 73, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 24, 1, 0, 0, 64, 0, 0, 0, 70, 0, 0, 0, 88, 64, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 51, 51, 0, 0, 100, 8, 0, 4, 18, 16, 16,
+ 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1,
+ 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16,
+ 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2,
+ 0, 0, 0, 27, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16,
+ 0, 1, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 1, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darrayui11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darrayui11ps.h
new file mode 100644
index 0000000000..3b33754c28
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2darrayui11ps.h
@@ -0,0 +1,89 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureUI texture uint4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture2darray (uint,uint,uint,uint) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v2.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.z, v1.x
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xyz, r0.xyzx
+mov o0.w, l(1)
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB2DArrayUI[] = {
+ 68, 88, 66, 67, 239, 124, 234, 46, 158, 116, 212, 164, 152, 122, 22, 86, 114, 177, 255,
+ 160, 1, 0, 0, 0, 4, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 136, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 70, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 5, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 85, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 24, 1, 0, 0, 64, 0, 0, 0, 70, 0, 0, 0, 88, 64, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 68, 68, 0, 0, 100, 8, 0, 4, 18, 16, 16,
+ 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1,
+ 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16,
+ 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2,
+ 0, 0, 0, 27, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16,
+ 0, 1, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5,
+ 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 1, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 10, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h
new file mode 100644
index 0000000000..79ff3c4168
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h
@@ -0,0 +1,82 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureI texture sint4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture2d (sint,sint,sint,sint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xyz, r0.xyzx
+mov o0.w, l(0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB2DI[] = {
+ 68, 88, 66, 67, 190, 234, 127, 190, 151, 71, 156, 183, 160, 74, 156, 153, 91, 12, 95,
+ 85, 1, 0, 0, 0, 188, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 4, 1, 0, 0, 56, 1, 0, 0, 64, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 73, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171,
+ 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78,
+ 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 0, 1, 0, 0, 64, 0, 0,
+ 0, 64, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 51, 51,
+ 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 61, 16, 0, 7,
+ 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 70, 126, 16,
+ 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 70,
+ 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 27, 0, 0, 5,
+ 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 8, 194, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0,
+ 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h
new file mode 100644
index 0000000000..74ef0a2236
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h
@@ -0,0 +1,82 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureUI texture uint4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture2d (uint,uint,uint,uint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xyz, r0.xyzx
+mov o0.w, l(0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB2DUI[] = {
+ 68, 88, 66, 67, 240, 47, 31, 84, 32, 155, 233, 36, 235, 43, 92, 251, 152, 13, 113,
+ 169, 1, 0, 0, 0, 188, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 4, 1, 0, 0, 56, 1, 0, 0, 64, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 70, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 85, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171,
+ 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78,
+ 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 0, 1, 0, 0, 64, 0, 0,
+ 0, 64, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 68, 68,
+ 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 61, 16, 0, 7,
+ 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 70, 126, 16,
+ 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 70,
+ 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 27, 0, 0, 5,
+ 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 8, 194, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0,
+ 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0,
+ 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h
new file mode 100644
index 0000000000..b533c74d77
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h
@@ -0,0 +1,79 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mov o0.xyz, r0.xyzx
+mov o0.w, l(1.000000)
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB3D[] = {
+ 68, 88, 66, 67, 121, 178, 78, 177, 99, 144, 108, 81, 39, 245, 135, 91, 55, 31, 56,
+ 111, 1, 0, 0, 0, 168, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 44, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 148, 0, 0, 0, 64, 0, 0, 0, 37, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 5, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128,
+ 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d_565_11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d_565_11ps.h
new file mode 100644
index 0000000000..5222d51cc3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d_565_11ps.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul r0.xyz, r0.xyzx, l(31.000000, 63.000000, 31.000000, 0.000000)
+round_ne r0.xyz, r0.xyzx
+mul o0.xyz, r0.xyzx, l(0.032258, 0.015873, 0.032258, 0.000000)
+mov o0.w, l(1.000000)
+ret
+// Approximately 6 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB3D_565[] = {
+ 68, 88, 66, 67, 190, 139, 108, 54, 112, 70, 128, 98, 155, 40, 89, 132, 48, 127, 91,
+ 244, 1, 0, 0, 0, 248, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 124, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 228, 0, 0, 0, 64, 0, 0, 0, 57, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0, 248, 65, 0, 0, 124, 66, 0, 0, 248, 65, 0, 0, 0,
+ 0, 64, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0,
+ 0, 0, 56, 0, 0, 10, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0,
+ 0, 0, 0, 2, 64, 0, 0, 8, 33, 4, 61, 33, 8, 130, 60, 8, 33, 4, 61,
+ 0, 0, 0, 0, 54, 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0,
+ 0, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 6, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h
new file mode 100644
index 0000000000..9e590b3ebb
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureI texture sint4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture3d (sint,sint,sint,sint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xyz, r0.xyzx
+mov o0.w, l(0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB3DI[] = {
+ 68, 88, 66, 67, 122, 80, 149, 91, 225, 62, 16, 173, 12, 194, 248, 74, 159, 33, 217,
+ 135, 1, 0, 0, 0, 224, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 100, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 8, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 73, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 244, 0, 0, 0, 64, 0, 0, 0, 61, 0, 0, 0, 88, 40, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 51, 51, 0, 0, 98, 16, 0, 3, 114, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5,
+ 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0,
+ 7, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 18,
+ 16, 0, 2, 0, 0, 0, 27, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70,
+ 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h
new file mode 100644
index 0000000000..534b9d9faa
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureUI texture uint4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture3d (uint,uint,uint,uint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov o0.xyz, r0.xyzx
+mov o0.w, l(0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGB3DUI[] = {
+ 68, 88, 66, 67, 177, 156, 23, 109, 67, 253, 176, 134, 182, 213, 173, 70, 148, 235, 60,
+ 205, 1, 0, 0, 0, 224, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 100, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 70, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 8, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 85, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 244, 0, 0, 0, 64, 0, 0, 0, 61, 0, 0, 0, 88, 40, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 68, 68, 0, 0, 98, 16, 0, 3, 114, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5,
+ 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0,
+ 7, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 18,
+ 16, 0, 2, 0, 0, 0, 27, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70,
+ 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 5, 114, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 5, 130, 32, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 9, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h
new file mode 100644
index 0000000000..f8b36063f2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h
@@ -0,0 +1,93 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mov oC0, r0
+
+// approximately 2 instruction slots used (1 texture, 1 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+sample o0.xyzw, v1.xyxx, t0.xyzw, s0
+ret
+// Approximately 2 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA2D[] = {
+ 68, 88, 66, 67, 23, 65, 12, 167, 50, 71, 137, 250, 170, 67, 18, 134, 110, 213, 196,
+ 219, 1, 0, 0, 0, 184, 2, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 164, 0,
+ 0, 0, 16, 1, 0, 0, 140, 1, 0, 0, 44, 2, 0, 0, 132, 2, 0, 0, 65,
+ 111, 110, 57, 100, 0, 0, 0, 100, 0, 0, 0, 0, 2, 255, 255, 60, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36,
+ 0, 0, 0, 40, 0, 0, 0, 0, 0, 1, 2, 255, 255, 31, 0, 0, 2, 0, 0,
+ 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144, 0, 8, 15, 160, 66,
+ 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228, 160, 1, 0, 0, 2,
+ 0, 8, 15, 128, 0, 0, 228, 128, 255, 255, 0, 0, 83, 72, 68, 82, 100, 0, 0,
+ 0, 64, 0, 0, 0, 25, 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0,
+ 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98,
+ 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0,
+ 0, 0, 0, 0, 69, 0, 0, 9, 242, 32, 16, 0, 0, 0, 0, 0, 70, 16, 16,
+ 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 2, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 82, 68, 69,
+ 70, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0,
+ 0, 0, 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0,
+ 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0,
+ 0, 0, 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0,
+ 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46,
+ 49, 0, 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0,
+ 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73,
+ 84, 73, 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83,
+ 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0,
+ 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d_4444_11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d_4444_11ps.h
new file mode 100644
index 0000000000..2f94f13c12
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d_4444_11ps.h
@@ -0,0 +1,112 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ def c0, 15, 0.5, 0.0666666701, 0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mad r0, r0, c0.x, c0.y
+ frc r1, r0
+ add r0, r0, -r1
+ mul r0, r0, c0.z
+ mov oC0, r0
+
+// approximately 6 instruction slots used (1 texture, 5 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul r0.xyzw, r0.xyzw, l(15.000000, 15.000000, 15.000000, 15.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.066667, 0.066667, 0.066667, 0.066667)
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA2D_4444[] = {
+ 68, 88, 66, 67, 188, 56, 0, 47, 220, 85, 24, 210, 59, 166, 131, 1, 131, 90, 227,
+ 171, 1, 0, 0, 0, 124, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 252, 0,
+ 0, 0, 212, 1, 0, 0, 80, 2, 0, 0, 240, 2, 0, 0, 72, 3, 0, 0, 65,
+ 111, 110, 57, 188, 0, 0, 0, 188, 0, 0, 0, 0, 2, 255, 255, 148, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36,
+ 0, 0, 0, 40, 0, 0, 0, 0, 0, 1, 2, 255, 255, 81, 0, 0, 5, 0, 0,
+ 15, 160, 0, 0, 112, 65, 0, 0, 0, 63, 137, 136, 136, 61, 0, 0, 0, 0, 31,
+ 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228,
+ 160, 4, 0, 0, 4, 0, 0, 15, 128, 0, 0, 228, 128, 0, 0, 0, 160, 0, 0,
+ 85, 160, 19, 0, 0, 2, 1, 0, 15, 128, 0, 0, 228, 128, 2, 0, 0, 3, 0,
+ 0, 15, 128, 0, 0, 228, 128, 1, 0, 228, 129, 5, 0, 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 128, 0, 0, 170, 160, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228,
+ 128, 255, 255, 0, 0, 83, 72, 68, 82, 208, 0, 0, 0, 64, 0, 0, 0, 52, 0,
+ 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 24, 0, 4, 0,
+ 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0,
+ 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 16,
+ 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0,
+ 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 112, 65, 0, 0, 112, 65, 0, 0, 112,
+ 65, 0, 0, 112, 65, 64, 0, 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 32, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 137, 136, 136, 61, 137, 136, 136, 61,
+ 137, 136, 136, 61, 137, 136, 136, 61, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0,
+ 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 82, 68, 69, 70, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 28, 0, 0, 0, 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0,
+ 0, 92, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2,
+ 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0, 0, 0, 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120,
+ 116, 117, 114, 101, 70, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83,
+ 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68,
+ 0, 171, 171, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d_5551_11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d_5551_11ps.h
new file mode 100644
index 0000000000..44966d6a9b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d_5551_11ps.h
@@ -0,0 +1,112 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+//
+// Sampler/Resource to DX9 shader sampler mappings:
+//
+// Target Sampler Source Sampler Source Resource
+// -------------- --------------- ----------------
+// s0 s0 t0
+//
+//
+// Level9 shader bytecode:
+//
+ ps_2_x
+ def c0, 31, 1, 0.5, 0.0322580636
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mad r0, r0, c0.xxxy, c0.z
+ frc r1, r0
+ add r0, r0, -r1
+ mul r0, r0, c0.wwwy
+ mov oC0, r0
+
+// approximately 6 instruction slots used (1 texture, 5 arithmetic)
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mul r0.xyzw, r0.xyzw, l(31.000000, 31.000000, 31.000000, 1.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.032258, 0.032258, 0.032258, 1.000000)
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA2D_5551[] = {
+ 68, 88, 66, 67, 202, 32, 204, 89, 54, 13, 5, 203, 247, 109, 207, 183, 162, 90, 24,
+ 32, 1, 0, 0, 0, 124, 3, 0, 0, 6, 0, 0, 0, 56, 0, 0, 0, 252, 0,
+ 0, 0, 212, 1, 0, 0, 80, 2, 0, 0, 240, 2, 0, 0, 72, 3, 0, 0, 65,
+ 111, 110, 57, 188, 0, 0, 0, 188, 0, 0, 0, 0, 2, 255, 255, 148, 0, 0, 0,
+ 40, 0, 0, 0, 0, 0, 40, 0, 0, 0, 40, 0, 0, 0, 40, 0, 1, 0, 36,
+ 0, 0, 0, 40, 0, 0, 0, 0, 0, 1, 2, 255, 255, 81, 0, 0, 5, 0, 0,
+ 15, 160, 0, 0, 248, 65, 0, 0, 128, 63, 0, 0, 0, 63, 8, 33, 4, 61, 31,
+ 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228,
+ 160, 4, 0, 0, 4, 0, 0, 15, 128, 0, 0, 228, 128, 0, 0, 64, 160, 0, 0,
+ 170, 160, 19, 0, 0, 2, 1, 0, 15, 128, 0, 0, 228, 128, 2, 0, 0, 3, 0,
+ 0, 15, 128, 0, 0, 228, 128, 1, 0, 228, 129, 5, 0, 0, 3, 0, 0, 15, 128,
+ 0, 0, 228, 128, 0, 0, 127, 160, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228,
+ 128, 255, 255, 0, 0, 83, 72, 68, 82, 208, 0, 0, 0, 64, 0, 0, 0, 52, 0,
+ 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 24, 0, 4, 0,
+ 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0,
+ 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0,
+ 2, 1, 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 16,
+ 16, 0, 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0,
+ 0, 0, 0, 56, 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 248, 65, 0, 0, 248, 65, 0, 0, 248,
+ 65, 0, 0, 128, 63, 64, 0, 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 10, 242, 32, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 8, 33, 4, 61, 8, 33, 4, 61,
+ 8, 33, 4, 61, 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0,
+ 0, 5, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 82, 68, 69, 70, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 28, 0, 0, 0, 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0,
+ 0, 92, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2,
+ 0, 0, 0, 5, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0,
+ 1, 0, 0, 0, 13, 0, 0, 0, 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120,
+ 116, 117, 114, 101, 70, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41,
+ 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108,
+ 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 171, 73, 83, 71, 78, 80, 0, 0, 0,
+ 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 3, 0, 0, 83,
+ 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68,
+ 0, 171, 171, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darray11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darray11ps.h
new file mode 100644
index 0000000000..227aab3bf9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darray11ps.h
@@ -0,0 +1,81 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample o0.xyzw, r0.xyzx, t0.xyzw, s0
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA2DArray[] = {
+ 68, 88, 66, 67, 200, 215, 233, 151, 66, 46, 221, 224, 83, 242, 34, 162, 166, 5, 137,
+ 148, 1, 0, 0, 0, 184, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 60, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 164, 0, 0, 0, 64, 0, 0, 0, 41, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 64, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4, 18, 16, 16, 0, 1, 0, 0, 0,
+ 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 86, 0,
+ 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 1, 0, 0, 0, 54,
+ 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2, 0, 0, 0,
+ 69, 0, 0, 9, 242, 32, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0,
+ 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darray_4444_11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darray_4444_11ps.h
new file mode 100644
index 0000000000..24011717c7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darray_4444_11ps.h
@@ -0,0 +1,89 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul r0.xyzw, r0.xyzw, l(15.000000, 15.000000, 15.000000, 15.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.066667, 0.066667, 0.066667, 0.066667)
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA2DArray_4444[] = {
+ 68, 88, 66, 67, 88, 17, 60, 194, 201, 5, 168, 96, 74, 117, 234, 137, 214, 224, 224,
+ 134, 1, 0, 0, 0, 28, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 160, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 8, 1, 0, 0, 64, 0, 0, 0, 66, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 64, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4, 18, 16, 16, 0, 1, 0, 0, 0,
+ 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 86, 0,
+ 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 1, 0, 0, 0, 54,
+ 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2, 0, 0, 0,
+ 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0,
+ 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56, 0,
+ 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2,
+ 64, 0, 0, 0, 0, 112, 65, 0, 0, 112, 65, 0, 0, 112, 65, 0, 0, 112, 65,
+ 64, 0, 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0,
+ 0, 56, 0, 0, 10, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0, 137, 136, 136, 61, 137, 136, 136, 61, 137, 136, 136, 61, 137,
+ 136, 136, 61, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 7, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darray_5551_11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darray_5551_11ps.h
new file mode 100644
index 0000000000..f6335bccef
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darray_5551_11ps.h
@@ -0,0 +1,89 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mul r0.xyzw, r0.xyzw, l(31.000000, 31.000000, 31.000000, 1.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.032258, 0.032258, 0.032258, 1.000000)
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA2DArray_5551[] = {
+ 68, 88, 66, 67, 68, 140, 194, 251, 165, 142, 204, 154, 232, 236, 200, 233, 255, 120, 4,
+ 27, 1, 0, 0, 0, 28, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 160, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 8, 1, 0, 0, 64, 0, 0, 0, 66, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 64, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4, 18, 16, 16, 0, 1, 0, 0, 0,
+ 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 86, 0,
+ 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 1, 0, 0, 0, 54,
+ 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2, 0, 0, 0,
+ 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0,
+ 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56, 0,
+ 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 2,
+ 64, 0, 0, 0, 0, 248, 65, 0, 0, 248, 65, 0, 0, 248, 65, 0, 0, 128, 63,
+ 64, 0, 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0,
+ 0, 56, 0, 0, 10, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0, 8, 33, 4, 61, 8, 33, 4, 61, 8, 33, 4, 61, 0,
+ 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 7, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darrayi11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darrayi11ps.h
new file mode 100644
index 0000000000..457935a252
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darrayi11ps.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureI texture sint4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture2darray (sint,sint,sint,sint) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v2.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.z, v1.x
+mov r0.w, l(0)
+ld o0.xyzw, r0.xyzw, t0.xyzw
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA2DArrayI[] = {
+ 68, 88, 66, 67, 215, 68, 211, 98, 73, 229, 148, 22, 136, 6, 112, 36, 206, 148, 145,
+ 188, 1, 0, 0, 0, 220, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 96, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 5, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 73, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 240, 0, 0, 0, 64, 0, 0, 0, 60, 0, 0, 0, 88, 64, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 51, 51, 0, 0, 100, 8, 0, 4, 18, 16, 16,
+ 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1,
+ 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16,
+ 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2,
+ 0, 0, 0, 27, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16,
+ 0, 1, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 32, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darrayui11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darrayui11ps.h
new file mode 100644
index 0000000000..58b67ac728
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2darrayui11ps.h
@@ -0,0 +1,85 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureUI texture uint4 2darray t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture2darray (uint,uint,uint,uint) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v2.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.z, v1.x
+mov r0.w, l(0)
+ld o0.xyzw, r0.xyzw, t0.xyzw
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA2DArrayUI[] = {
+ 68, 88, 66, 67, 31, 32, 146, 134, 107, 181, 50, 167, 97, 108, 64, 57, 238, 167, 69,
+ 217, 1, 0, 0, 0, 220, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 96, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 70, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 5, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 85, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 240, 0, 0, 0, 64, 0, 0, 0, 60, 0, 0, 0, 88, 64, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 68, 68, 0, 0, 100, 8, 0, 4, 18, 16, 16,
+ 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1,
+ 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16,
+ 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0,
+ 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2,
+ 0, 0, 0, 27, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0,
+ 0, 0, 0, 0, 54, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16,
+ 0, 1, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 32, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1,
+ 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h
new file mode 100644
index 0000000000..eb0ebbd6ea
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h
@@ -0,0 +1,78 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureI texture sint4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture2d (sint,sint,sint,sint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld o0.xyzw, r0.xyzw, t0.xyzw
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA2DI[] = {
+ 68, 88, 66, 67, 11, 194, 121, 174, 53, 241, 53, 229, 116, 76, 99, 226, 54, 79, 165,
+ 216, 1, 0, 0, 0, 148, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 4, 1, 0, 0, 56, 1, 0, 0, 24, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 73, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171,
+ 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78,
+ 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 216, 0, 0, 0, 64, 0, 0,
+ 0, 54, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 51, 51,
+ 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 61, 16, 0, 7,
+ 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 70, 126, 16,
+ 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 70,
+ 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 27, 0, 0, 5,
+ 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 8, 194, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 32, 16, 0, 0,
+ 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h
new file mode 100644
index 0000000000..76361532d2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h
@@ -0,0 +1,80 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureF_MS texture float4 2dMS t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+// SV_SAMPLEINDEX 0 x 2 SAMPLE uint x
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+// Pixel Shader runs at sample frequency
+//
+ps_4_1
+dcl_globalFlags refactoringAllowed
+dcl_resource_texture2dms(0) (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_input_ps_sgv constant v2.x, sampleIndex
+dcl_output o0.xyzw
+dcl_temps 1
+ftou r0.xy, v1.xyxx
+mov r0.zw, l(0,0,0,0)
+ldms o0.xyzw, r0.xyzw, t0.xyzw, v2.x
+ret
+// Approximately 4 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA2DMS[] = {
+ 68, 88, 66, 67, 49, 75, 69, 135, 188, 202, 223, 102, 144, 42, 4, 30, 173, 255, 143,
+ 210, 1, 0, 0, 0, 136, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 40, 1, 0, 0, 92, 1, 0, 0, 12, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 1, 4, 255, 255, 0, 1, 0, 0, 72, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 77, 83, 0, 77,
+ 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49,
+ 0, 73, 83, 71, 78, 116, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3, 0, 0, 101, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0,
+ 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 1, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 83, 86, 95, 83,
+ 65, 77, 80, 76, 69, 73, 78, 68, 69, 88, 0, 79, 83, 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82,
+ 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 168, 0, 0, 0, 65, 0, 0, 0, 42,
+ 0, 0, 0, 106, 8, 0, 1, 88, 32, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0,
+ 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 99, 8, 0,
+ 4, 18, 16, 16, 0, 2, 0, 0, 0, 10, 0, 0, 0, 101, 0, 0, 3, 242, 32,
+ 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 28, 0, 0, 5, 50,
+ 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 8,
+ 194, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 9, 242, 32, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 10,
+ 16, 16, 0, 2, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0,
+ 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h
new file mode 100644
index 0000000000..31f84d0d74
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h
@@ -0,0 +1,78 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureUI texture uint4 2d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture2d (uint,uint,uint,uint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld o0.xyzw, r0.xyzw, t0.xyzw
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA2DUI[] = {
+ 68, 88, 66, 67, 116, 109, 92, 124, 46, 28, 237, 165, 173, 42, 6, 53, 183, 101, 128,
+ 93, 1, 0, 0, 0, 148, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 4, 1, 0, 0, 56, 1, 0, 0, 24, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 70, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 85, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171,
+ 171, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78,
+ 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 216, 0, 0, 0, 64, 0, 0,
+ 0, 54, 0, 0, 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 68, 68,
+ 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242,
+ 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 61, 16, 0, 7,
+ 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 70, 126, 16,
+ 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 70,
+ 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 27, 0, 0, 5,
+ 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 8, 194, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 32, 16, 0, 0,
+ 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0,
+ 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h
new file mode 100644
index 0000000000..4aef441bcd
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h
@@ -0,0 +1,74 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+sample o0.xyzw, v2.xyzx, t0.xyzw, s0
+ret
+// Approximately 2 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA3D[] = {
+ 68, 88, 66, 67, 68, 93, 216, 66, 165, 49, 226, 52, 230, 199, 150, 143, 253, 53, 233,
+ 213, 1, 0, 0, 0, 120, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 252, 1, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 100, 0, 0, 0, 64, 0, 0, 0, 25, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 69, 0, 0, 9, 242, 32, 16,
+ 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0, 0, 0, 70, 126, 16, 0, 0, 0,
+ 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d_4444_11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d_4444_11ps.h
new file mode 100644
index 0000000000..d6c7a28333
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d_4444_11ps.h
@@ -0,0 +1,83 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul r0.xyzw, r0.xyzw, l(15.000000, 15.000000, 15.000000, 15.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.066667, 0.066667, 0.066667, 0.066667)
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA3D_4444[] = {
+ 68, 88, 66, 67, 244, 22, 101, 89, 172, 184, 153, 143, 94, 198, 255, 75, 136, 76, 172,
+ 69, 1, 0, 0, 0, 228, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 104, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 208, 0, 0, 0, 64, 0, 0, 0, 52, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0, 112, 65, 0, 0, 112, 65, 0, 0, 112, 65, 0, 0, 112,
+ 65, 64, 0, 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0,
+ 0, 0, 56, 0, 0, 10, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0,
+ 0, 0, 0, 2, 64, 0, 0, 137, 136, 136, 61, 137, 136, 136, 61, 137, 136, 136, 61,
+ 137, 136, 136, 61, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 5, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d_5551_11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d_5551_11ps.h
new file mode 100644
index 0000000000..3329c4d2ce
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d_5551_11ps.h
@@ -0,0 +1,83 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF texture float4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mul r0.xyzw, r0.xyzw, l(31.000000, 31.000000, 31.000000, 1.000000)
+round_ne r0.xyzw, r0.xyzw
+mul o0.xyzw, r0.xyzw, l(0.032258, 0.032258, 0.032258, 1.000000)
+ret
+// Approximately 5 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA3D_5551[] = {
+ 68, 88, 66, 67, 84, 84, 9, 48, 70, 52, 100, 237, 108, 219, 183, 20, 215, 148, 144,
+ 173, 1, 0, 0, 0, 228, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 212, 0,
+ 0, 0, 92, 1, 0, 0, 144, 1, 0, 0, 104, 2, 0, 0, 82, 68, 69, 70, 152,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 109, 0, 0, 0, 92, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 83, 97, 109, 112, 108, 101, 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 171, 171, 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0,
+ 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80,
+ 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65,
+ 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67,
+ 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8,
+ 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171,
+ 171, 83, 72, 68, 82, 208, 0, 0, 0, 64, 0, 0, 0, 52, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0,
+ 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0,
+ 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0, 248, 65, 0, 0, 248, 65, 0, 0, 248, 65, 0, 0, 128,
+ 63, 64, 0, 0, 5, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0,
+ 0, 0, 56, 0, 0, 10, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0,
+ 0, 0, 0, 2, 64, 0, 0, 8, 33, 4, 61, 8, 33, 4, 61, 8, 33, 4, 61,
+ 0, 0, 128, 63, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 5, 0, 0,
+ 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h
new file mode 100644
index 0000000000..81adb14ca9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h
@@ -0,0 +1,81 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureI texture sint4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_resource_texture3d (sint,sint,sint,sint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld o0.xyzw, r0.xyzw, t0.xyzw
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA3DI[] = {
+ 68, 88, 66, 67, 112, 154, 25, 211, 170, 223, 11, 97, 14, 10, 139, 203, 225, 190, 33,
+ 158, 1, 0, 0, 0, 184, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 60, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 69, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 8, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 73, 0, 77, 105, 99, 114,
+ 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100,
+ 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 204, 0, 0, 0, 64, 0, 0, 0, 51, 0, 0, 0, 88, 40, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 51, 51, 0, 0, 98, 16, 0, 3, 114, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5,
+ 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0,
+ 7, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 18,
+ 16, 0, 2, 0, 0, 0, 27, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70,
+ 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 32, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h
new file mode 100644
index 0000000000..31bc39204d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h
@@ -0,0 +1,81 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureUI texture uint4 3d t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_resource_texture3d (uint,uint,uint,uint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld o0.xyzw, r0.xyzw, t0.xyzw
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_PS_PassthroughRGBA3DUI[] = {
+ 68, 88, 66, 67, 136, 72, 192, 109, 253, 59, 232, 36, 69, 34, 127, 153, 17, 12, 205,
+ 209, 1, 0, 0, 0, 184, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 52, 1, 0, 0, 104, 1, 0, 0, 60, 2, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 70, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 8, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 85, 73, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97,
+ 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171,
+ 171, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80, 79, 83,
+ 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71,
+ 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79,
+ 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0,
+ 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83,
+ 72, 68, 82, 204, 0, 0, 0, 64, 0, 0, 0, 51, 0, 0, 0, 88, 40, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 68, 68, 0, 0, 98, 16, 0, 3, 114, 16, 16,
+ 0, 2, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5,
+ 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0,
+ 7, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 18,
+ 16, 0, 2, 0, 0, 0, 27, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70,
+ 2, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0, 0, 0, 45, 0, 0, 7, 242, 32, 16, 0, 0, 0, 0,
+ 0, 70, 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 62, 0,
+ 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvecolor2dps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvecolor2dps.h
new file mode 100644
index 0000000000..8283ea9c4c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvecolor2dps.h
@@ -0,0 +1,103 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureF_MS texture float4 2dMS t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_1
+dcl_globalFlags refactoringAllowed
+dcl_resource_texture2dms(0) (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 4
+resinfo_uint r0.xy, l(0), t0.xyzw
+sampleinfo_uint r0.z, t0.x
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftou r1.xy, r0.xyxx
+mov r1.zw, l(0,0,0,0)
+mov r2.xyzw, l(0,0,0,0)
+mov r0.x, l(0)
+loop
+ uge r0.y, r0.x, r0.z
+ breakc_nz r0.y
+ ldms r3.xyzw, r1.xyzw, t0.xyzw, r0.x
+ add r2.xyzw, r2.xyzw, r3.xyzw
+ iadd r0.x, r0.x, l(1)
+endloop
+sampleinfo r0.x, t0.x
+div o0.xyzw, r2.xyzw, r0.xxxx
+ret
+// Approximately 18 instruction slots used
+#endif
+
+const BYTE g_PS_ResolveColor2D[] = {
+ 68, 88, 66, 67, 93, 61, 55, 147, 13, 181, 1, 129, 207, 120, 176, 100, 210, 126, 243,
+ 242, 1, 0, 0, 0, 128, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 172, 0,
+ 0, 0, 4, 1, 0, 0, 56, 1, 0, 0, 4, 3, 0, 0, 82, 68, 69, 70, 112,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 1, 4, 255, 255, 0, 1, 0, 0, 72, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 84, 101, 120, 116, 117, 114, 101, 70, 95, 77, 83, 0, 77,
+ 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83,
+ 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49,
+ 0, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15,
+ 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
+ 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78,
+ 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0,
+ 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84,
+ 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 196, 1, 0, 0, 65, 0, 0,
+ 0, 113, 0, 0, 0, 106, 8, 0, 1, 88, 32, 0, 4, 0, 112, 16, 0, 0, 0,
+ 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101,
+ 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 4, 0, 0, 0,
+ 61, 16, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0,
+ 0, 70, 126, 16, 0, 0, 0, 0, 0, 111, 8, 0, 5, 66, 0, 16, 0, 0, 0,
+ 0, 0, 10, 112, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16, 0, 0,
+ 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0,
+ 0, 28, 0, 0, 5, 50, 0, 16, 0, 1, 0, 0, 0, 70, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 8, 194, 0, 16, 0, 1, 0, 0, 0, 2, 64, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 8,
+ 242, 0, 16, 0, 2, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 5, 18, 0, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 48, 0, 0, 1, 80, 0, 0, 7, 34,
+ 0, 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 42, 0, 16, 0,
+ 0, 0, 0, 0, 3, 0, 4, 3, 26, 0, 16, 0, 0, 0, 0, 0, 46, 0, 0,
+ 9, 242, 0, 16, 0, 3, 0, 0, 0, 70, 14, 16, 0, 1, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 7, 242,
+ 0, 16, 0, 2, 0, 0, 0, 70, 14, 16, 0, 2, 0, 0, 0, 70, 14, 16, 0,
+ 3, 0, 0, 0, 30, 0, 0, 7, 18, 0, 16, 0, 0, 0, 0, 0, 10, 0, 16,
+ 0, 0, 0, 0, 0, 1, 64, 0, 0, 1, 0, 0, 0, 22, 0, 0, 1, 111, 0,
+ 0, 5, 18, 0, 16, 0, 0, 0, 0, 0, 10, 112, 16, 0, 0, 0, 0, 0, 14,
+ 0, 0, 7, 242, 32, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 2, 0, 0, 0,
+ 6, 0, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0,
+ 0, 18, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0,
+ 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h
new file mode 100644
index 0000000000..0f986c7843
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h
@@ -0,0 +1,81 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Depth texture float 2dMS t0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Depth 0 N/A oDepth DEPTH float YES
+//
+ps_4_1
+dcl_globalFlags refactoringAllowed
+dcl_resource_texture2dms(0) (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output oDepth
+dcl_temps 1
+resinfo_uint r0.xy, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftou r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ldms r0.x, r0.xyzw, t0.xyzw, l(0)
+mov oDepth, r0.x
+ret
+// Approximately 8 instruction slots used
+#endif
+
+const BYTE g_PS_ResolveDepth[] = {
+ 68, 88, 66, 67, 133, 15, 63, 40, 192, 212, 199, 79, 7, 253, 243, 47, 246, 158, 13,
+ 45, 1, 0, 0, 0, 168, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 168, 0,
+ 0, 0, 0, 1, 0, 0, 52, 1, 0, 0, 44, 2, 0, 0, 82, 68, 69, 70, 108,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 1, 4, 255, 255, 0, 1, 0, 0, 66, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 68, 101, 112, 116, 104, 0, 77, 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 73, 83, 71,
+ 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 68,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0,
+ 3, 3, 0, 0, 83, 86, 95, 80, 111, 115, 105, 116, 105, 111, 110, 0, 84, 69, 88,
+ 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0, 255, 255, 255, 255, 1, 14, 0, 0, 83, 86, 95, 68, 101, 112, 116, 104,
+ 0, 171, 171, 171, 83, 72, 68, 82, 240, 0, 0, 0, 65, 0, 0, 0, 60, 0, 0,
+ 0, 106, 8, 0, 1, 88, 32, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85, 85,
+ 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 2, 1,
+ 192, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 61, 16, 0, 7, 50, 0, 16, 0,
+ 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0,
+ 0, 86, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0,
+ 0, 0, 56, 0, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0,
+ 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 28, 0, 0, 5, 50, 0, 16, 0,
+ 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 8, 194, 0, 16,
+ 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 46, 0, 0, 9, 18, 0, 16, 0, 0, 0, 0, 0, 70,
+ 14, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0,
+ 0, 0, 0, 0, 54, 0, 0, 4, 1, 192, 0, 0, 10, 0, 16, 0, 0, 0, 0,
+ 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 8, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h
new file mode 100644
index 0000000000..449fbdbed9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h
@@ -0,0 +1,92 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Depth texture float 2dMS t0 1
+// Stencil texture uint2 2dMS t1 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target 0 xy 0 TARGET float xy
+//
+ps_4_1
+dcl_globalFlags refactoringAllowed
+dcl_resource_texture2dms(0) (float,float,float,float) t0
+dcl_resource_texture2dms(0) (uint,uint,uint,uint) t1
+dcl_input_ps linear v1.xy
+dcl_output o0.xy
+dcl_temps 1
+resinfo_uint r0.xy, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftou r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ldms r0.z, r0.xyzw, t1.xzyw, l(0)
+ldms r0.x, r0.xyww, t0.xyzw, l(0)
+mov o0.x, r0.x
+utof o0.y, r0.z
+ret
+// Approximately 10 instruction slots used
+#endif
+
+const BYTE g_PS_ResolveDepthStencil[] = {
+ 68, 88, 66, 67, 89, 136, 221, 180, 85, 229, 18, 205, 242, 112, 176, 35, 107, 34, 5,
+ 254, 1, 0, 0, 0, 32, 3, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 208, 0,
+ 0, 0, 40, 1, 0, 0, 92, 1, 0, 0, 164, 2, 0, 0, 82, 68, 69, 70, 148,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 1, 4, 255, 255, 0, 1, 0, 0, 106, 0, 0, 0, 92, 0, 0, 0, 2, 0, 0,
+ 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 98, 0, 0, 0, 2, 0, 0, 0, 4, 0, 0, 0, 6,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 5, 0, 0, 0,
+ 68, 101, 112, 116, 104, 0, 83, 116, 101, 110, 99, 105, 108, 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 171, 171, 73,
+ 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0,
+ 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0,
+ 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 111, 115, 105, 116, 105, 111, 110, 0, 84,
+ 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0, 0, 0,
+ 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 12, 0, 0, 83, 86, 95, 84, 97, 114,
+ 103, 101, 116, 0, 171, 171, 83, 72, 68, 82, 64, 1, 0, 0, 65, 0, 0, 0, 80,
+ 0, 0, 0, 106, 8, 0, 1, 88, 32, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0,
+ 85, 85, 0, 0, 88, 32, 0, 4, 0, 112, 16, 0, 1, 0, 0, 0, 68, 68, 0,
+ 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 50, 32,
+ 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 61, 16, 0, 7, 50,
+ 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 70, 126, 16, 0,
+ 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16,
+ 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 28, 0, 0, 5, 50,
+ 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 8,
+ 194, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 9, 66, 0, 16, 0, 0, 0,
+ 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 134, 125, 16, 0, 1, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 46, 0, 0, 9, 18, 0, 16, 0, 0, 0, 0, 0,
+ 70, 15, 16, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 1, 64, 0,
+ 0, 0, 0, 0, 0, 54, 0, 0, 5, 18, 32, 16, 0, 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 34, 32, 16, 0, 0, 0, 0, 0, 42,
+ 0, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0,
+ 10, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h
new file mode 100644
index 0000000000..162168be33
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h
@@ -0,0 +1,83 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_VertexID 0 x 0 VERTID uint x
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float xyzw
+// TEXCOORD 0 xy 1 NONE float xy
+//
+vs_4_1
+dcl_globalFlags refactoringAllowed
+dcl_immediateConstantBuffer { { -1.000000, 1.000000, 0, 0},
+ { 1.000000, -1.000000, 0, 0},
+ { -1.000000, -1.000000, 0, 0},
+ { -1.000000, 1.000000, 0, 0},
+ { 1.000000, 1.000000, 0, 0},
+ { 1.000000, -1.000000, 0, 0} }
+dcl_input_sgv v0.x, vertex_id
+dcl_output_siv o0.xyzw, position
+dcl_output o1.xy
+dcl_temps 1
+mov o0.zw, l(0,0,0,1.000000)
+mov r0.x, v0.x
+mov o0.xy, icb[r0.x + 0].xyxx
+add r0.y, l(1.000000), icb[r0.x + 0].x
+add r0.x, l(1.000000), -icb[r0.x + 0].y
+mul o1.xy, r0.yxyy, l(0.500000, 0.500000, 0.000000, 0.000000)
+ret
+// Approximately 7 instruction slots used
+#endif
+
+const BYTE g_VS_ResolveDepthStencil[] = {
+ 68, 88, 66, 67, 151, 71, 251, 149, 26, 9, 107, 111, 231, 137, 148, 94, 92, 2, 252,
+ 182, 1, 0, 0, 0, 244, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 128, 0,
+ 0, 0, 180, 0, 0, 0, 12, 1, 0, 0, 120, 2, 0, 0, 82, 68, 69, 70, 68,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0,
+ 1, 4, 254, 255, 0, 1, 0, 0, 28, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111,
+ 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32,
+ 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 83, 86, 95,
+ 86, 101, 114, 116, 101, 120, 73, 68, 0, 79, 83, 71, 78, 80, 0, 0, 0, 2, 0,
+ 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 3, 12, 0, 0, 83, 86, 95,
+ 80, 111, 115, 105, 116, 105, 111, 110, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171,
+ 171, 171, 83, 72, 68, 82, 100, 1, 0, 0, 65, 0, 1, 0, 89, 0, 0, 0, 106,
+ 8, 0, 1, 53, 24, 0, 0, 26, 0, 0, 0, 0, 0, 128, 191, 0, 0, 128, 63,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 128, 191, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 128, 191, 0, 0, 128, 191, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 128, 191, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 128, 63, 0, 0, 128, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 63,
+ 0, 0, 128, 191, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 4, 18, 16, 16,
+ 0, 0, 0, 0, 0, 6, 0, 0, 0, 103, 0, 0, 4, 242, 32, 16, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 101, 0, 0, 3, 50, 32, 16, 0, 1, 0, 0, 0, 104,
+ 0, 0, 2, 1, 0, 0, 0, 54, 0, 0, 8, 194, 32, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128,
+ 63, 54, 0, 0, 5, 18, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6, 50, 32, 16, 0, 0, 0, 0, 0, 70, 144, 144, 0, 10,
+ 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 8, 34, 0, 16, 0, 0, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0, 128, 63, 10, 144, 144, 0, 10, 0, 16, 0, 0, 0, 0,
+ 0, 0, 0, 0, 9, 18, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0,
+ 128, 63, 26, 144, 144, 128, 65, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 10, 50, 32, 16, 0, 1, 0, 0, 0, 22, 5, 16, 0, 0, 0, 0, 0,
+ 2, 64, 0, 0, 0, 0, 0, 63, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0,
+ 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 7, 0, 0, 0, 1, 0,
+ 0, 0, 6, 0, 0, 0, 3, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h
new file mode 100644
index 0000000000..0f96154858
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h
@@ -0,0 +1,84 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Stencil texture uint2 2dMS t1 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Position 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_Target 0 xy 0 TARGET float xy
+//
+ps_4_1
+dcl_globalFlags refactoringAllowed
+dcl_resource_texture2dms(0) (uint,uint,uint,uint) t1
+dcl_input_ps linear v1.xy
+dcl_output o0.xy
+dcl_temps 1
+resinfo_uint r0.xy, l(0), t1.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftou r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ldms r0.x, r0.xyzw, t1.yxzw, l(0)
+utof o0.y, r0.x
+mov o0.x, l(0)
+ret
+// Approximately 9 instruction slots used
+#endif
+
+const BYTE g_PS_ResolveStencil[] = {
+ 68, 88, 66, 67, 123, 66, 135, 11, 171, 75, 198, 85, 15, 70, 47, 122, 95, 167, 34,
+ 235, 1, 0, 0, 0, 196, 2, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 168, 0,
+ 0, 0, 0, 1, 0, 0, 52, 1, 0, 0, 72, 2, 0, 0, 82, 68, 69, 70, 108,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 28, 0, 0, 0,
+ 1, 4, 255, 255, 0, 1, 0, 0, 68, 0, 0, 0, 60, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0,
+ 0, 0, 5, 0, 0, 0, 83, 116, 101, 110, 99, 105, 108, 0, 77, 105, 99, 114, 111,
+ 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104, 97, 100, 101,
+ 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0, 73, 83, 71,
+ 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 68,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0,
+ 3, 3, 0, 0, 83, 86, 95, 80, 111, 115, 105, 116, 105, 111, 110, 0, 84, 69, 88,
+ 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 3, 12, 0, 0, 83, 86, 95, 84, 97, 114, 103, 101,
+ 116, 0, 171, 171, 83, 72, 68, 82, 12, 1, 0, 0, 65, 0, 0, 0, 67, 0, 0,
+ 0, 106, 8, 0, 1, 88, 32, 0, 4, 0, 112, 16, 0, 1, 0, 0, 0, 68, 68,
+ 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 50,
+ 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 61, 16, 0, 7,
+ 50, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 70, 126, 16,
+ 0, 1, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0,
+ 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 70,
+ 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 1, 0, 0, 0, 28, 0, 0, 5,
+ 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 8, 194, 0, 16, 0, 0, 0, 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46, 0, 0, 9, 18, 0, 16, 0, 0,
+ 0, 0, 0, 70, 14, 16, 0, 0, 0, 0, 0, 22, 126, 16, 0, 1, 0, 0, 0,
+ 1, 64, 0, 0, 0, 0, 0, 0, 86, 0, 0, 5, 34, 32, 16, 0, 0, 0, 0,
+ 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 5, 18, 32, 16, 0, 0, 0,
+ 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116,
+ 0, 0, 0, 9, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h
new file mode 100644
index 0000000000..d3d5c0f0e3
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h
@@ -0,0 +1,135 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF2DArray texture float4 2darray t0 1
+// SwizzleProperties cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_constantbuffer CB0[1], immediateIndexed
+dcl_sampler s0, mode_default
+dcl_resource_texture2darray (float,float,float,float) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+utof r0.z, v1.x
+mov r0.xy, v2.xyxx
+sample r0.xyzw, r0.xyzx, t0.xyzw, s0
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1.000000)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 18 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleF2DArray[] = {
+ 68, 88, 66, 67, 43, 191, 227, 129, 77, 88, 223, 209, 64, 17, 168, 91, 78, 216, 210,
+ 134, 1, 0, 0, 0, 192, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 92, 1,
+ 0, 0, 228, 1, 0, 0, 24, 2, 0, 0, 68, 4, 0, 0, 82, 68, 69, 70, 32,
+ 1, 0, 0, 1, 0, 0, 0, 168, 0, 0, 0, 3, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 248, 0, 0, 0, 124, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 132, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 5,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 148, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 83, 97, 109, 112, 108, 101,
+ 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 50, 68, 65, 114, 114, 97, 121, 0, 83,
+ 119, 105, 122, 122, 108, 101, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 0, 171, 171,
+ 148, 0, 0, 0, 1, 0, 0, 0, 192, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 216, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0,
+ 0, 0, 232, 0, 0, 0, 0, 0, 0, 0, 83, 119, 105, 122, 122, 108, 101, 73, 110,
+ 100, 105, 99, 101, 115, 0, 171, 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72,
+ 76, 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114,
+ 32, 49, 48, 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8,
+ 0, 0, 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0,
+ 0, 0, 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0,
+ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83,
+ 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69,
+ 82, 84, 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84,
+ 69, 88, 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0,
+ 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69,
+ 84, 0, 171, 171, 83, 72, 68, 82, 36, 2, 0, 0, 64, 0, 0, 0, 137, 0, 0,
+ 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 90, 0,
+ 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 64, 0, 4, 0, 112, 16, 0, 0,
+ 0, 0, 0, 85, 85, 0, 0, 100, 8, 0, 4, 18, 16, 16, 0, 1, 0, 0, 0,
+ 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0, 0, 0, 101, 0, 0,
+ 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 105, 0,
+ 0, 4, 0, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 86, 0, 0, 5, 66,
+ 0, 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 1, 0, 0, 0, 54, 0, 0, 5,
+ 50, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2, 0, 0, 0, 69, 0, 0,
+ 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 126,
+ 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18,
+ 48, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 26, 0, 16,
+ 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 2, 0,
+ 0, 0, 42, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0,
+ 0, 0, 0, 3, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6,
+ 18, 48, 32, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0,
+ 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 64,
+ 0, 0, 0, 0, 128, 63, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 10,
+ 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 18, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0,
+ 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 26, 128, 32, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 34, 32, 16, 0, 0, 0, 0, 0, 10,
+ 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6,
+ 18, 0, 16, 0, 0, 0, 0, 0, 42, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 54, 0, 0, 7, 66, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0,
+ 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0,
+ 0, 0, 0, 58, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7,
+ 130, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16,
+ 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 18, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 6, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h
new file mode 100644
index 0000000000..091c3e29ea
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h
@@ -0,0 +1,126 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF2D texture float4 2d t0 1
+// SwizzleProperties cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_constantbuffer CB0[1], immediateIndexed
+dcl_sampler s0, mode_default
+dcl_resource_texture2d (float,float,float,float) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+sample r0.xyzw, v1.xyxx, t0.xyzw, s0
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1.000000)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 16 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleF2D[] = {
+ 68, 88, 66, 67, 221, 55, 186, 66, 171, 208, 86, 211, 37, 150, 98, 209, 236, 60, 108,
+ 41, 1, 0, 0, 0, 84, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 88, 1,
+ 0, 0, 176, 1, 0, 0, 228, 1, 0, 0, 216, 3, 0, 0, 82, 68, 69, 70, 28,
+ 1, 0, 0, 1, 0, 0, 0, 164, 0, 0, 0, 3, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 244, 0, 0, 0, 124, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 132, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 4,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 83, 97, 109, 112, 108, 101,
+ 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 50, 68, 0, 83, 119, 105, 122, 122, 108,
+ 101, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 0, 171, 171, 171, 143, 0, 0, 0,
+ 1, 0, 0, 0, 188, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 212, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 228, 0,
+ 0, 0, 0, 0, 0, 0, 83, 119, 105, 122, 122, 108, 101, 73, 110, 100, 105, 99, 101,
+ 115, 0, 171, 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46,
+ 49, 0, 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0,
+ 0, 1, 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79,
+ 78, 0, 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44,
+ 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95,
+ 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 236, 1, 0, 0, 64, 0,
+ 0, 0, 123, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 90, 0, 0, 3, 0, 96, 16, 0, 0, 0, 0, 0, 88, 24, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 85, 85, 0, 0, 98, 16, 0, 3, 50, 16, 16,
+ 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0,
+ 0, 2, 1, 0, 0, 0, 105, 0, 0, 4, 0, 0, 0, 0, 6, 0, 0, 0, 4,
+ 0, 0, 0, 69, 0, 0, 9, 242, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0,
+ 1, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 0, 96, 16, 0, 0, 0, 0,
+ 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 26, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 42, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 6, 18, 48, 32, 0, 0, 0, 0, 0, 3, 0, 0, 0, 58, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1,
+ 64, 0, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0,
+ 5, 0, 0, 0, 1, 64, 0, 0, 0, 0, 128, 63, 54, 0, 0, 6, 18, 0, 16,
+ 0, 0, 0, 0, 0, 10, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0,
+ 0, 7, 18, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10,
+ 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0,
+ 26, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 34, 32, 16,
+ 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 42, 128, 32, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 66, 32, 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 6, 18, 0, 16, 0, 0, 0, 0, 0, 58, 128, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 7, 130, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0,
+ 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84,
+ 116, 0, 0, 0, 16, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h
new file mode 100644
index 0000000000..042cd18005
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h
@@ -0,0 +1,129 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// Sampler sampler NA NA s0 1
+// TextureF3D texture float4 3d t0 1
+// SwizzleProperties cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET float xyzw
+//
+ps_4_0
+dcl_constantbuffer CB0[1], immediateIndexed
+dcl_sampler s0, mode_default
+dcl_resource_texture3d (float,float,float,float) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+sample r0.xyzw, v2.xyzx, t0.xyzw, s0
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1.000000)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 16 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleF3D[] = {
+ 68, 88, 66, 67, 73, 214, 47, 221, 178, 220, 225, 86, 113, 45, 198, 41, 129, 110, 186,
+ 79, 1, 0, 0, 0, 132, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 88, 1,
+ 0, 0, 224, 1, 0, 0, 20, 2, 0, 0, 8, 4, 0, 0, 82, 68, 69, 70, 28,
+ 1, 0, 0, 1, 0, 0, 0, 164, 0, 0, 0, 3, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 244, 0, 0, 0, 124, 0, 0, 0, 3, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 0, 0, 132, 0, 0, 0, 2, 0, 0, 0, 5, 0, 0, 0, 8,
+ 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0, 0, 0, 13, 0, 0, 0,
+ 143, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 83, 97, 109, 112, 108, 101,
+ 114, 0, 84, 101, 120, 116, 117, 114, 101, 70, 51, 68, 0, 83, 119, 105, 122, 122, 108,
+ 101, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 0, 171, 171, 171, 143, 0, 0, 0,
+ 1, 0, 0, 0, 188, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 212, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 228, 0,
+ 0, 0, 0, 0, 0, 0, 83, 119, 105, 122, 122, 108, 101, 73, 110, 100, 105, 99, 101,
+ 115, 0, 171, 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32,
+ 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46,
+ 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
+ 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0,
+ 0, 1, 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80, 79,
+ 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82,
+ 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79,
+ 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0,
+ 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0,
+ 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171,
+ 83, 72, 68, 82, 236, 1, 0, 0, 64, 0, 0, 0, 123, 0, 0, 0, 89, 0, 0,
+ 4, 70, 142, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 90, 0, 0, 3, 0, 96,
+ 16, 0, 0, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 85,
+ 85, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0, 0, 101, 0, 0, 3,
+ 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 105, 0, 0,
+ 4, 0, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 69, 0, 0, 9, 242, 0,
+ 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0, 0, 0, 70, 126, 16, 0, 0,
+ 0, 0, 0, 0, 96, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 6, 18, 48, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 26, 0, 16, 0, 0, 0,
+ 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 42,
+ 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32,
+ 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 64, 0, 0, 0,
+ 0, 128, 63, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 10, 128, 32, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 18, 32, 16, 0, 0, 0, 0,
+ 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 26, 128, 32, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 54, 0, 0, 7, 34, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32, 4,
+ 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16,
+ 0, 0, 0, 0, 0, 42, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0,
+ 0, 7, 66, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10,
+ 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0,
+ 58, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 130, 32, 16,
+ 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0,
+ 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 16, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0,
+ 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h
new file mode 100644
index 0000000000..08c48427e2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h
@@ -0,0 +1,139 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureI2DArray texture sint4 2darray t0 1
+// SwizzleProperties cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_constantbuffer CB0[1], immediateIndexed
+dcl_resource_texture2darray (sint,sint,sint,sint) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v2.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.z, v1.x
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 22 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleI2DArray[] = {
+ 68, 88, 66, 67, 212, 163, 121, 141, 10, 113, 132, 178, 58, 176, 145, 98, 43, 111, 211,
+ 61, 1, 0, 0, 0, 228, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 52, 1,
+ 0, 0, 188, 1, 0, 0, 240, 1, 0, 0, 104, 4, 0, 0, 82, 68, 69, 70, 248,
+ 0, 0, 0, 1, 0, 0, 0, 128, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 208, 0, 0, 0, 92, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 5, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114, 101, 73, 50, 68, 65, 114, 114, 97, 121, 0, 83, 119, 105,
+ 122, 122, 108, 101, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 0, 171, 171, 108, 0,
+ 0, 0, 1, 0, 0, 0, 152, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 176, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0,
+ 192, 0, 0, 0, 0, 0, 0, 0, 83, 119, 105, 122, 122, 108, 101, 73, 110, 100, 105,
+ 99, 101, 115, 0, 171, 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49,
+ 48, 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0,
+ 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1,
+ 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95,
+ 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84,
+ 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88,
+ 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82, 112, 2, 0, 0, 64, 0, 0, 0, 156, 0, 0, 0, 89,
+ 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 88, 64, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 51, 51, 0, 0, 100, 8, 0, 4, 18, 16, 16,
+ 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1,
+ 0, 0, 0, 105, 0, 0, 4, 0, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0,
+ 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16, 0, 0, 0,
+ 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0, 16, 0, 0,
+ 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2, 0, 0, 0,
+ 27, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0,
+ 0, 54, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0,
+ 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 26, 0, 16, 0, 0,
+ 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 42, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 64, 0, 0,
+ 1, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 10, 128, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 18, 32, 16, 0, 0, 0,
+ 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 26, 128, 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0, 0, 7, 34, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32,
+ 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0, 42, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 7, 66, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0,
+ 0, 58, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 130, 32,
+ 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0,
+ 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 22, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0,
+ 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h
new file mode 100644
index 0000000000..fbce5942df
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h
@@ -0,0 +1,132 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureI2D texture sint4 2d t0 1
+// SwizzleProperties cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_constantbuffer CB0[1], immediateIndexed
+dcl_resource_texture2d (sint,sint,sint,sint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 21 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleI2D[] = {
+ 68, 88, 66, 67, 177, 45, 190, 185, 217, 208, 59, 28, 232, 250, 124, 179, 32, 246, 26,
+ 206, 1, 0, 0, 0, 152, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 48, 1,
+ 0, 0, 136, 1, 0, 0, 188, 1, 0, 0, 28, 4, 0, 0, 82, 68, 69, 70, 244,
+ 0, 0, 0, 1, 0, 0, 0, 124, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 204, 0, 0, 0, 92, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114, 101, 73, 50, 68, 0, 83, 119, 105, 122, 122, 108, 101, 80,
+ 114, 111, 112, 101, 114, 116, 105, 101, 115, 0, 171, 171, 171, 103, 0, 0, 0, 1, 0,
+ 0, 0, 148, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172,
+ 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0,
+ 0, 0, 0, 0, 83, 119, 105, 122, 122, 108, 101, 73, 110, 100, 105, 99, 101, 115, 0,
+ 171, 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0,
+ 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1,
+ 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0,
+ 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65,
+ 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 88, 2, 0, 0, 64, 0, 0, 0,
+ 150, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 51, 51, 0, 0, 98, 16,
+ 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0,
+ 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 105, 0, 0, 4, 0, 0, 0, 0,
+ 6, 0, 0, 0, 4, 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0,
+ 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 1, 0, 0, 0, 27, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0,
+ 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 8, 194, 0, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 26, 0, 16, 0, 0,
+ 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 42, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 64, 0, 0,
+ 1, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 10, 128, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 18, 32, 16, 0, 0, 0,
+ 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 26, 128, 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0, 0, 7, 34, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32,
+ 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0, 42, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 7, 66, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0,
+ 0, 58, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 130, 32,
+ 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0,
+ 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 21, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0,
+ 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h
new file mode 100644
index 0000000000..1ce3ce47c8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h
@@ -0,0 +1,135 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureI3D texture sint4 3d t0 1
+// SwizzleProperties cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET int xyzw
+//
+ps_4_0
+dcl_constantbuffer CB0[1], immediateIndexed
+dcl_resource_texture3d (sint,sint,sint,sint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 21 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleI3D[] = {
+ 68, 88, 66, 67, 239, 203, 72, 66, 58, 92, 169, 191, 239, 77, 187, 21, 109, 161, 64,
+ 95, 1, 0, 0, 0, 188, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 48, 1,
+ 0, 0, 184, 1, 0, 0, 236, 1, 0, 0, 64, 4, 0, 0, 82, 68, 69, 70, 244,
+ 0, 0, 0, 1, 0, 0, 0, 124, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 204, 0, 0, 0, 92, 0, 0, 0, 2, 0, 0,
+ 0, 3, 0, 0, 0, 8, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114, 101, 73, 51, 68, 0, 83, 119, 105, 122, 122, 108, 101, 80,
+ 114, 111, 112, 101, 114, 116, 105, 101, 115, 0, 171, 171, 171, 103, 0, 0, 0, 1, 0,
+ 0, 0, 148, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172,
+ 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0,
+ 0, 0, 0, 0, 83, 119, 105, 122, 122, 108, 101, 73, 110, 100, 105, 99, 101, 115, 0,
+ 171, 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0,
+ 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1,
+ 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80, 79, 83, 73,
+ 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69,
+ 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82,
+ 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72,
+ 68, 82, 76, 2, 0, 0, 64, 0, 0, 0, 147, 0, 0, 0, 89, 0, 0, 4, 70,
+ 142, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0,
+ 0, 0, 0, 0, 51, 51, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0,
+ 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0,
+ 0, 0, 105, 0, 0, 4, 0, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 61,
+ 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 0, 16, 0, 0, 0,
+ 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0, 0, 0, 27,
+ 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0,
+ 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6,
+ 18, 48, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 26, 0, 16, 0, 0, 0, 0,
+ 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 42, 0,
+ 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 4, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 54, 0, 0,
+ 6, 18, 48, 32, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 64, 0, 0, 1, 0,
+ 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 10, 128, 32, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 18, 32, 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 6, 18, 0, 16, 0, 0, 0, 0, 0, 26, 128, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 7, 34, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0,
+ 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 42, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0,
+ 7, 66, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 58,
+ 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 130, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0,
+ 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 21, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0,
+ 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h
new file mode 100644
index 0000000000..d3d479f7b0
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h
@@ -0,0 +1,139 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureUI2DArray texture uint4 2darray t0 1
+// SwizzleProperties cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint x
+// TEXCOORD 0 xyz 2 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_constantbuffer CB0[1], immediateIndexed
+dcl_resource_texture2darray (uint,uint,uint,uint) t0
+dcl_input_ps_siv constant v1.x, rendertarget_array_index
+dcl_input_ps linear v2.xy
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v2.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.z, v1.x
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 22 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleUI2DArray[] = {
+ 68, 88, 66, 67, 116, 247, 215, 129, 4, 49, 47, 120, 164, 87, 225, 112, 75, 76, 233,
+ 53, 1, 0, 0, 0, 228, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 52, 1,
+ 0, 0, 188, 1, 0, 0, 240, 1, 0, 0, 104, 4, 0, 0, 82, 68, 69, 70, 248,
+ 0, 0, 0, 1, 0, 0, 0, 128, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 208, 0, 0, 0, 92, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 5, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 109, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114, 101, 85, 73, 50, 68, 65, 114, 114, 97, 121, 0, 83, 119,
+ 105, 122, 122, 108, 101, 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 0, 171, 109, 0,
+ 0, 0, 1, 0, 0, 0, 152, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 176, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0,
+ 192, 0, 0, 0, 0, 0, 0, 0, 83, 119, 105, 122, 122, 108, 101, 73, 110, 100, 105,
+ 99, 101, 115, 0, 171, 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83,
+ 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49,
+ 48, 46, 49, 0, 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0,
+ 0, 80, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0,
+ 0, 0, 15, 0, 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1,
+ 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 3, 0, 0, 0, 2, 0, 0, 0, 7, 3, 0, 0, 83, 86, 95,
+ 80, 79, 83, 73, 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84,
+ 65, 82, 71, 69, 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88,
+ 67, 79, 79, 82, 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0,
+ 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0,
+ 171, 171, 83, 72, 68, 82, 112, 2, 0, 0, 64, 0, 0, 0, 156, 0, 0, 0, 89,
+ 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 88, 64, 0, 4,
+ 0, 112, 16, 0, 0, 0, 0, 0, 68, 68, 0, 0, 100, 8, 0, 4, 18, 16, 16,
+ 0, 1, 0, 0, 0, 4, 0, 0, 0, 98, 16, 0, 3, 50, 16, 16, 0, 2, 0,
+ 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1,
+ 0, 0, 0, 105, 0, 0, 4, 0, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0,
+ 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0,
+ 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 50, 0, 16, 0, 0, 0,
+ 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 50, 0, 16, 0, 0,
+ 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 70, 16, 16, 0, 2, 0, 0, 0,
+ 27, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0,
+ 0, 54, 0, 0, 5, 66, 0, 16, 0, 0, 0, 0, 0, 10, 16, 16, 0, 1, 0,
+ 0, 0, 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0,
+ 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 26, 0, 16, 0, 0,
+ 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 42, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 64, 0, 0,
+ 1, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 10, 128, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 18, 32, 16, 0, 0, 0,
+ 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 26, 128, 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0, 0, 7, 34, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32,
+ 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0, 42, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 7, 66, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0,
+ 0, 58, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 130, 32,
+ 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0,
+ 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 22, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0,
+ 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h
new file mode 100644
index 0000000000..b83bd117be
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h
@@ -0,0 +1,132 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureUI2D texture uint4 2d t0 1
+// SwizzleProperties cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// TEXCOORD 0 xy 1 NONE float xy
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_constantbuffer CB0[1], immediateIndexed
+dcl_resource_texture2d (uint,uint,uint,uint) t0
+dcl_input_ps linear v1.xy
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xy, r0.xyxx
+mul r0.xy, r0.xyxx, v1.xyxx
+ftoi r0.xy, r0.xyxx
+mov r0.zw, l(0,0,0,0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 21 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleUI2D[] = {
+ 68, 88, 66, 67, 5, 230, 100, 22, 104, 28, 143, 55, 98, 102, 32, 210, 129, 6, 68,
+ 183, 1, 0, 0, 0, 152, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 48, 1,
+ 0, 0, 136, 1, 0, 0, 188, 1, 0, 0, 28, 4, 0, 0, 82, 68, 69, 70, 244,
+ 0, 0, 0, 1, 0, 0, 0, 124, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 204, 0, 0, 0, 92, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 4, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114, 101, 85, 73, 50, 68, 0, 83, 119, 105, 122, 122, 108, 101,
+ 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 0, 171, 171, 104, 0, 0, 0, 1, 0,
+ 0, 0, 148, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172,
+ 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0,
+ 0, 0, 0, 0, 83, 119, 105, 122, 122, 108, 101, 73, 110, 100, 105, 99, 101, 115, 0,
+ 171, 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 73, 83, 71, 78, 80, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 56, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0,
+ 0, 0, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 1,
+ 0, 0, 0, 3, 3, 0, 0, 83, 86, 95, 80, 79, 83, 73, 84, 73, 79, 78, 0,
+ 84, 69, 88, 67, 79, 79, 82, 68, 0, 171, 171, 171, 79, 83, 71, 78, 44, 0, 0,
+ 0, 1, 0, 0, 0, 8, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 83, 86, 95, 84, 65,
+ 82, 71, 69, 84, 0, 171, 171, 83, 72, 68, 82, 88, 2, 0, 0, 64, 0, 0, 0,
+ 150, 0, 0, 0, 89, 0, 0, 4, 70, 142, 32, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 88, 24, 0, 4, 0, 112, 16, 0, 0, 0, 0, 0, 68, 68, 0, 0, 98, 16,
+ 0, 3, 50, 16, 16, 0, 1, 0, 0, 0, 101, 0, 0, 3, 242, 32, 16, 0, 0,
+ 0, 0, 0, 104, 0, 0, 2, 1, 0, 0, 0, 105, 0, 0, 4, 0, 0, 0, 0,
+ 6, 0, 0, 0, 4, 0, 0, 0, 61, 16, 0, 7, 242, 0, 16, 0, 0, 0, 0,
+ 0, 1, 64, 0, 0, 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 86, 0,
+ 0, 5, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0, 56,
+ 0, 0, 7, 50, 0, 16, 0, 0, 0, 0, 0, 70, 0, 16, 0, 0, 0, 0, 0,
+ 70, 16, 16, 0, 1, 0, 0, 0, 27, 0, 0, 5, 50, 0, 16, 0, 0, 0, 0,
+ 0, 70, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 8, 194, 0, 16, 0, 0, 0,
+ 0, 0, 2, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0,
+ 0, 0, 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0,
+ 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 26, 0, 16, 0, 0,
+ 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+ 42, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0,
+ 0, 3, 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48,
+ 32, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 64, 0, 0,
+ 1, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 10, 128, 32,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 18, 32, 16, 0, 0, 0,
+ 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54,
+ 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 26, 128, 32, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 54, 0, 0, 7, 34, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32,
+ 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0,
+ 16, 0, 0, 0, 0, 0, 42, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54,
+ 0, 0, 7, 66, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0,
+ 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0,
+ 0, 58, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 130, 32,
+ 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0,
+ 0, 0, 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 21, 0, 0, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0,
+ 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0,
+ 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h
new file mode 100644
index 0000000000..a7024e22db
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h
@@ -0,0 +1,135 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 10.1
+//
+//
+// Buffer Definitions:
+//
+// cbuffer SwizzleProperties
+// {
+//
+// uint4 SwizzleIndices; // Offset: 0 Size: 16
+//
+// }
+//
+//
+// Resource Bindings:
+//
+// Name Type Format Dim HLSL Bind Count
+// ------------------------------ ---------- ------- ----------- -------------- ------
+// TextureUI3D texture uint4 3d t0 1
+// SwizzleProperties cbuffer NA NA cb0 1
+//
+//
+//
+// Input signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_POSITION 0 xyzw 0 POS float
+// SV_RENDERTARGETARRAYINDEX 0 x 1 RTINDEX uint
+// TEXCOORD 0 xyz 2 NONE float xyz
+//
+//
+// Output signature:
+//
+// Name Index Mask Register SysValue Format Used
+// -------------------- ----- ------ -------- -------- ------- ------
+// SV_TARGET 0 xyzw 0 TARGET uint xyzw
+//
+ps_4_0
+dcl_constantbuffer CB0[1], immediateIndexed
+dcl_resource_texture3d (uint,uint,uint,uint) t0
+dcl_input_ps linear v2.xyz
+dcl_output o0.xyzw
+dcl_temps 1
+dcl_indexableTemp x0[6], 4
+resinfo_uint r0.xyzw, l(0), t0.xyzw
+utof r0.xyz, r0.xyzx
+mul r0.xyz, r0.xyzx, v2.xyzx
+ftoi r0.xyz, r0.xyzx
+mov r0.w, l(0)
+ld r0.xyzw, r0.xyzw, t0.xyzw
+mov x0[0].x, r0.x
+mov x0[1].x, r0.y
+mov x0[2].x, r0.z
+mov x0[3].x, r0.w
+mov x0[4].x, l(0)
+mov x0[5].x, l(1)
+mov r0.x, cb0[0].x
+mov o0.x, x0[r0.x + 0].x
+mov r0.x, cb0[0].y
+mov o0.y, x0[r0.x + 0].x
+mov r0.x, cb0[0].z
+mov o0.z, x0[r0.x + 0].x
+mov r0.x, cb0[0].w
+mov o0.w, x0[r0.x + 0].x
+ret
+// Approximately 21 instruction slots used
+#endif
+
+const BYTE g_PS_SwizzleUI3D[] = {
+ 68, 88, 66, 67, 234, 128, 119, 252, 97, 217, 113, 192, 202, 15, 92, 121, 106, 82, 46,
+ 102, 1, 0, 0, 0, 188, 4, 0, 0, 5, 0, 0, 0, 52, 0, 0, 0, 48, 1,
+ 0, 0, 184, 1, 0, 0, 236, 1, 0, 0, 64, 4, 0, 0, 82, 68, 69, 70, 244,
+ 0, 0, 0, 1, 0, 0, 0, 124, 0, 0, 0, 2, 0, 0, 0, 28, 0, 0, 0,
+ 0, 4, 255, 255, 0, 1, 0, 0, 204, 0, 0, 0, 92, 0, 0, 0, 2, 0, 0,
+ 0, 4, 0, 0, 0, 8, 0, 0, 0, 255, 255, 255, 255, 0, 0, 0, 0, 1, 0,
+ 0, 0, 13, 0, 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
+ 84, 101, 120, 116, 117, 114, 101, 85, 73, 51, 68, 0, 83, 119, 105, 122, 122, 108, 101,
+ 80, 114, 111, 112, 101, 114, 116, 105, 101, 115, 0, 171, 171, 104, 0, 0, 0, 1, 0,
+ 0, 0, 148, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 172,
+ 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 2, 0, 0, 0, 188, 0, 0, 0,
+ 0, 0, 0, 0, 83, 119, 105, 122, 122, 108, 101, 73, 110, 100, 105, 99, 101, 115, 0,
+ 171, 1, 0, 19, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 77, 105,
+ 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 49, 48, 46, 49, 0,
+ 73, 83, 71, 78, 128, 0, 0, 0, 3, 0, 0, 0, 8, 0, 0, 0, 80, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 15, 0,
+ 0, 0, 92, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 1, 0, 0, 0, 1,
+ 0, 0, 0, 1, 0, 0, 0, 118, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 3, 0, 0, 0, 2, 0, 0, 0, 7, 7, 0, 0, 83, 86, 95, 80, 79, 83, 73,
+ 84, 73, 79, 78, 0, 83, 86, 95, 82, 69, 78, 68, 69, 82, 84, 65, 82, 71, 69,
+ 84, 65, 82, 82, 65, 89, 73, 78, 68, 69, 88, 0, 84, 69, 88, 67, 79, 79, 82,
+ 68, 0, 171, 79, 83, 71, 78, 44, 0, 0, 0, 1, 0, 0, 0, 8, 0, 0, 0,
+ 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 15, 0, 0, 0, 83, 86, 95, 84, 65, 82, 71, 69, 84, 0, 171, 171, 83, 72,
+ 68, 82, 76, 2, 0, 0, 64, 0, 0, 0, 147, 0, 0, 0, 89, 0, 0, 4, 70,
+ 142, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 88, 40, 0, 4, 0, 112, 16, 0,
+ 0, 0, 0, 0, 68, 68, 0, 0, 98, 16, 0, 3, 114, 16, 16, 0, 2, 0, 0,
+ 0, 101, 0, 0, 3, 242, 32, 16, 0, 0, 0, 0, 0, 104, 0, 0, 2, 1, 0,
+ 0, 0, 105, 0, 0, 4, 0, 0, 0, 0, 6, 0, 0, 0, 4, 0, 0, 0, 61,
+ 16, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0,
+ 70, 126, 16, 0, 0, 0, 0, 0, 86, 0, 0, 5, 114, 0, 16, 0, 0, 0, 0,
+ 0, 70, 2, 16, 0, 0, 0, 0, 0, 56, 0, 0, 7, 114, 0, 16, 0, 0, 0,
+ 0, 0, 70, 2, 16, 0, 0, 0, 0, 0, 70, 18, 16, 0, 2, 0, 0, 0, 27,
+ 0, 0, 5, 114, 0, 16, 0, 0, 0, 0, 0, 70, 2, 16, 0, 0, 0, 0, 0,
+ 54, 0, 0, 5, 130, 0, 16, 0, 0, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0,
+ 0, 45, 0, 0, 7, 242, 0, 16, 0, 0, 0, 0, 0, 70, 14, 16, 0, 0, 0,
+ 0, 0, 70, 126, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6,
+ 18, 48, 32, 0, 0, 0, 0, 0, 1, 0, 0, 0, 26, 0, 16, 0, 0, 0, 0,
+ 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 2, 0, 0, 0, 42, 0,
+ 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0, 0, 0, 0, 0, 3,
+ 0, 0, 0, 58, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 48, 32, 0,
+ 0, 0, 0, 0, 4, 0, 0, 0, 1, 64, 0, 0, 0, 0, 0, 0, 54, 0, 0,
+ 6, 18, 48, 32, 0, 0, 0, 0, 0, 5, 0, 0, 0, 1, 64, 0, 0, 1, 0,
+ 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 10, 128, 32, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 18, 32, 16, 0, 0, 0, 0, 0,
+ 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0,
+ 6, 18, 0, 16, 0, 0, 0, 0, 0, 26, 128, 32, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 54, 0, 0, 7, 34, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0,
+ 0, 0, 0, 10, 0, 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16, 0,
+ 0, 0, 0, 0, 42, 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0,
+ 7, 66, 32, 16, 0, 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0,
+ 16, 0, 0, 0, 0, 0, 54, 0, 0, 6, 18, 0, 16, 0, 0, 0, 0, 0, 58,
+ 128, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 7, 130, 32, 16, 0,
+ 0, 0, 0, 0, 10, 48, 32, 4, 0, 0, 0, 0, 10, 0, 16, 0, 0, 0, 0,
+ 0, 62, 0, 0, 1, 83, 84, 65, 84, 116, 0, 0, 0, 21, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0,
+ 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
+ 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp
new file mode 100644
index 0000000000..a9dfec56b8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp
@@ -0,0 +1,35 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Helper routines for the D3D11 texture format table.
+
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+#include "libANGLE/renderer/load_functions_table.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+const Format &Format::getSwizzleFormat(const Renderer11DeviceCaps &deviceCaps) const
+{
+ return (swizzleFormat == internalFormat ? *this : Format::Get(swizzleFormat, deviceCaps));
+}
+
+LoadFunctionMap Format::getLoadFunctions() const
+{
+ return GetLoadFunctionsMap(internalFormat, formatID);
+}
+
+const angle::Format &Format::format() const
+{
+ return angle::Format::Get(formatID);
+}
+
+} // namespace d3d11
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h
new file mode 100644
index 0000000000..1797476f62
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h
@@ -0,0 +1,118 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// texture_format_table:
+// Queries for full textureFormat information based on internalFormat
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_
+
+#include <map>
+
+#include "common/angleutils.h"
+#include "common/platform.h"
+#include "libANGLE/renderer/Format.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.h"
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace rx
+{
+
+struct Renderer11DeviceCaps;
+
+namespace d3d11
+{
+
+// For sized GL internal formats, there are several possible corresponding D3D11 formats depending
+// on device capabilities.
+// This structure allows querying for the DXGI texture formats to use for textures, SRVs, RTVs and
+// DSVs given a GL internal format.
+struct Format final : private angle::NonCopyable
+{
+ inline constexpr Format();
+ inline constexpr Format(GLenum internalFormat,
+ angle::FormatID formatID,
+ DXGI_FORMAT texFormat,
+ DXGI_FORMAT srvFormat,
+ DXGI_FORMAT uavFormat,
+ DXGI_FORMAT rtvFormat,
+ DXGI_FORMAT dsvFormat,
+ DXGI_FORMAT blitSRVFormat,
+ DXGI_FORMAT stencilSRVFormat,
+ DXGI_FORMAT typelessFormat,
+ GLenum swizzleFormat,
+ InitializeTextureDataFunction internalFormatInitializer);
+
+ static const Format &Get(GLenum internalFormat, const Renderer11DeviceCaps &deviceCaps);
+
+ const Format &getSwizzleFormat(const Renderer11DeviceCaps &deviceCaps) const;
+ LoadFunctionMap getLoadFunctions() const;
+ const angle::Format &format() const;
+
+ GLenum internalFormat;
+ angle::FormatID formatID;
+
+ DXGI_FORMAT texFormat;
+ DXGI_FORMAT srvFormat;
+ DXGI_FORMAT uavFormat;
+ DXGI_FORMAT rtvFormat;
+ DXGI_FORMAT dsvFormat;
+
+ DXGI_FORMAT blitSRVFormat;
+ DXGI_FORMAT stencilSRVFormat;
+ DXGI_FORMAT typelessFormat;
+
+ GLenum swizzleFormat;
+
+ InitializeTextureDataFunction dataInitializerFunction;
+};
+
+constexpr Format::Format()
+ : internalFormat(GL_NONE),
+ formatID(angle::FormatID::NONE),
+ texFormat(DXGI_FORMAT_UNKNOWN),
+ srvFormat(DXGI_FORMAT_UNKNOWN),
+ uavFormat(DXGI_FORMAT_UNKNOWN),
+ rtvFormat(DXGI_FORMAT_UNKNOWN),
+ dsvFormat(DXGI_FORMAT_UNKNOWN),
+ blitSRVFormat(DXGI_FORMAT_UNKNOWN),
+ stencilSRVFormat(DXGI_FORMAT_UNKNOWN),
+ typelessFormat(DXGI_FORMAT_UNKNOWN),
+ swizzleFormat(GL_NONE),
+ dataInitializerFunction(nullptr)
+{}
+
+constexpr Format::Format(GLenum internalFormat,
+ angle::FormatID formatID,
+ DXGI_FORMAT texFormat,
+ DXGI_FORMAT srvFormat,
+ DXGI_FORMAT uavFormat,
+ DXGI_FORMAT rtvFormat,
+ DXGI_FORMAT dsvFormat,
+ DXGI_FORMAT blitSRVFormat,
+ DXGI_FORMAT stencilSRVFormat,
+ DXGI_FORMAT typelessFormat,
+ GLenum swizzleFormat,
+ InitializeTextureDataFunction internalFormatInitializer)
+ : internalFormat(internalFormat),
+ formatID(formatID),
+ texFormat(texFormat),
+ srvFormat(srvFormat),
+ uavFormat(uavFormat),
+ rtvFormat(rtvFormat),
+ dsvFormat(dsvFormat),
+ blitSRVFormat(blitSRVFormat),
+ stencilSRVFormat(stencilSRVFormat),
+ typelessFormat(typelessFormat),
+ swizzleFormat(swizzleFormat),
+ dataInitializerFunction(internalFormatInitializer)
+{}
+
+} // namespace d3d11
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
new file mode 100644
index 0000000000..39d03a93fd
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
@@ -0,0 +1,3269 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_texture_format_table.py using data from texture_format_data.json
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// texture_format_table:
+// Queries for full textureFormat information based in internalFormat
+//
+
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+// static
+const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &deviceCaps)
+{
+ // clang-format off
+ switch (internalFormat)
+ {
+ case GL_ALPHA16F_EXT:
+ {
+ static constexpr Format info(GL_ALPHA16F_EXT,
+ angle::FormatID::R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS,
+ GL_RGBA16F,
+ nullptr);
+ return info;
+ }
+ case GL_ALPHA32F_EXT:
+ {
+ static constexpr Format info(GL_ALPHA32F_EXT,
+ angle::FormatID::R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_TYPELESS,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_ALPHA8_EXT:
+ {
+ if (OnlyFL10Plus(deviceCaps))
+ {
+ static constexpr Format info(GL_ALPHA8_EXT,
+ angle::FormatID::A8_UNORM,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_ALPHA8_EXT,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_BGR10_A2_ANGLEX:
+ {
+ static constexpr Format info(GL_BGR10_A2_ANGLEX,
+ angle::FormatID::B10G10R10A2_UNORM,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_TYPELESS,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_BGR565_ANGLEX:
+ {
+ if (SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps))
+ {
+ static constexpr Format info(GL_BGR565_ANGLEX,
+ angle::FormatID::B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_BGR565_ANGLEX,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_BGR5_A1_ANGLEX:
+ {
+ static constexpr Format info(GL_BGR5_A1_ANGLEX,
+ angle::FormatID::B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_TYPELESS,
+ GL_BGRA8_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_BGRA4_ANGLEX:
+ {
+ static constexpr Format info(GL_BGRA4_ANGLEX,
+ angle::FormatID::B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_TYPELESS,
+ GL_BGRA8_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_BGRA8_EXT:
+ {
+ static constexpr Format info(GL_BGRA8_EXT,
+ angle::FormatID::B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_TYPELESS,
+ GL_BGRA8_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_BGRA8_SRGB_ANGLEX:
+ {
+ static constexpr Format info(GL_BGRA8_SRGB_ANGLEX,
+ angle::FormatID::B8G8R8A8_UNORM_SRGB,
+ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
+ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8A8_TYPELESS,
+ GL_BGRA8_SRGB_ANGLEX,
+ nullptr);
+ return info;
+ }
+ case GL_BGRX8_ANGLEX:
+ {
+ if (OnlyFL11_1Plus(deviceCaps))
+ {
+ static constexpr Format info(GL_BGRX8_ANGLEX,
+ angle::FormatID::B8G8R8X8_UNORM,
+ DXGI_FORMAT_B8G8R8X8_UNORM,
+ DXGI_FORMAT_B8G8R8X8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8X8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8X8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8X8_TYPELESS,
+ GL_BGRX8_ANGLEX,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_BGRX8_ANGLEX,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_COMPRESSED_R11_EAC:
+ {
+ static constexpr Format info(GL_COMPRESSED_R11_EAC,
+ angle::FormatID::R16_UNORM,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_TYPELESS,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_RED_GREEN_RGTC2_EXT,
+ angle::FormatID::BC5_RG_UNORM_BLOCK,
+ DXGI_FORMAT_BC5_UNORM,
+ DXGI_FORMAT_BC5_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC5_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RED_RGTC1_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_RED_RGTC1_EXT,
+ angle::FormatID::BC4_RED_UNORM_BLOCK,
+ DXGI_FORMAT_BC4_UNORM,
+ DXGI_FORMAT_BC4_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC4_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RG11_EAC:
+ {
+ static constexpr Format info(GL_COMPRESSED_RG11_EAC,
+ angle::FormatID::R16G16_UNORM,
+ DXGI_FORMAT_R16G16_UNORM,
+ DXGI_FORMAT_R16G16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_TYPELESS,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGB8_ETC2:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGB8_ETC2,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE,
+ angle::FormatID::BC1_RGB_UNORM_BLOCK,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE,
+ angle::FormatID::BC1_RGBA_UNORM_BLOCK,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA8_ETC2_EAC:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA8_ETC2_EAC,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x10_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x5_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x6_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x8_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_12x10_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_12x12_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_3x3x3_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_3x3x3_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_4x3x3_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_4x3x3_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_4x4_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_4x4x3_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_4x4x3_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_4x4x4_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_4x4x4_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x4_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_5x4x4_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x4x4_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x5_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_5x5x4_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x5x4_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_5x5x5_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x5x5_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x5_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_6x5x5_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x5x5_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x6_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_6x6x5_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x6x5_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_6x6x6_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x6x6_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x5_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x6_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x8_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_BPTC_UNORM_EXT,
+ angle::FormatID::BC7_RGBA_UNORM_BLOCK,
+ DXGI_FORMAT_BC7_UNORM,
+ DXGI_FORMAT_BC7_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC7_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
+ angle::FormatID::BC1_RGBA_UNORM_BLOCK,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,
+ angle::FormatID::BC2_RGBA_UNORM_BLOCK,
+ DXGI_FORMAT_BC2_UNORM,
+ DXGI_FORMAT_BC2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,
+ angle::FormatID::BC3_RGBA_UNORM_BLOCK,
+ DXGI_FORMAT_BC3_UNORM,
+ DXGI_FORMAT_BC3_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC3_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT,
+ angle::FormatID::BC6H_RGB_SFLOAT_BLOCK,
+ DXGI_FORMAT_BC6H_SF16,
+ DXGI_FORMAT_BC6H_SF16,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC6H_SF16,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT,
+ angle::FormatID::BC6H_RGB_UFLOAT_BLOCK,
+ DXGI_FORMAT_BC6H_UF16,
+ DXGI_FORMAT_BC6H_UF16,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC6H_UF16,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
+ angle::FormatID::BC1_RGB_UNORM_BLOCK,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SIGNED_R11_EAC:
+ {
+ static constexpr Format info(GL_COMPRESSED_SIGNED_R11_EAC,
+ angle::FormatID::R16_SNORM,
+ DXGI_FORMAT_R16_SNORM,
+ DXGI_FORMAT_R16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_TYPELESS,
+ GL_RGBA16_SNORM_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT,
+ angle::FormatID::BC5_RG_SNORM_BLOCK,
+ DXGI_FORMAT_BC5_SNORM,
+ DXGI_FORMAT_BC5_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC5_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8_SNORM,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT,
+ angle::FormatID::BC4_RED_SNORM_BLOCK,
+ DXGI_FORMAT_BC4_SNORM,
+ DXGI_FORMAT_BC4_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC4_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8_SNORM,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SIGNED_RG11_EAC:
+ {
+ static constexpr Format info(GL_COMPRESSED_SIGNED_RG11_EAC,
+ angle::FormatID::R16G16_SNORM,
+ DXGI_FORMAT_R16G16_SNORM,
+ DXGI_FORMAT_R16G16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_TYPELESS,
+ GL_RGBA16_SNORM_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,
+ angle::FormatID::R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_SRGB8_ALPHA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_ETC2:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_ETC2,
+ angle::FormatID::R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_SRGB8_ALPHA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE,
+ angle::FormatID::BC1_RGB_UNORM_SRGB_BLOCK,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,
+ angle::FormatID::R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_SRGB8_ALPHA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE,
+ angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT,
+ angle::FormatID::BC7_RGBA_UNORM_SRGB_BLOCK,
+ DXGI_FORMAT_BC7_UNORM_SRGB,
+ DXGI_FORMAT_BC7_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC7_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_SRGB8_ALPHA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,
+ angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT,
+ angle::FormatID::BC2_RGBA_UNORM_SRGB_BLOCK,
+ DXGI_FORMAT_BC2_UNORM_SRGB,
+ DXGI_FORMAT_BC2_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC2_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT,
+ angle::FormatID::BC3_RGBA_UNORM_SRGB_BLOCK,
+ DXGI_FORMAT_BC3_UNORM_SRGB,
+ DXGI_FORMAT_BC3_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC3_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ {
+ static constexpr Format info(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,
+ angle::FormatID::BC1_RGB_UNORM_SRGB_BLOCK,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_DEPTH24_STENCIL8:
+ {
+ if (OnlyFL10Plus(deviceCaps))
+ {
+ static constexpr Format info(GL_DEPTH24_STENCIL8,
+ angle::FormatID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_X24_TYPELESS_G8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_DEPTH24_STENCIL8,
+ angle::FormatID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_DEPTH32F_STENCIL8:
+ {
+ static constexpr Format info(GL_DEPTH32F_STENCIL8,
+ angle::FormatID::D32_FLOAT_S8X24_UINT,
+ DXGI_FORMAT_R32G8X24_TYPELESS,
+ DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
+ DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS,
+ DXGI_FORMAT_X32_TYPELESS_G8X24_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_DEPTH_COMPONENT16:
+ {
+ if (OnlyFL10Plus(deviceCaps))
+ {
+ static constexpr Format info(GL_DEPTH_COMPONENT16,
+ angle::FormatID::D16_UNORM,
+ DXGI_FORMAT_R16_TYPELESS,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D16_UNORM,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_DEPTH_COMPONENT16,
+ angle::FormatID::D16_UNORM,
+ DXGI_FORMAT_D16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_DEPTH_COMPONENT24:
+ {
+ if (OnlyFL10Plus(deviceCaps))
+ {
+ static constexpr Format info(GL_DEPTH_COMPONENT24,
+ angle::FormatID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_X24_TYPELESS_G8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_DEPTH_COMPONENT24,
+ angle::FormatID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_DEPTH_COMPONENT32F:
+ {
+ static constexpr Format info(GL_DEPTH_COMPONENT32F,
+ angle::FormatID::D32_FLOAT,
+ DXGI_FORMAT_R32_TYPELESS,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_DEPTH_COMPONENT32_OES:
+ {
+ if (OnlyFL10Plus(deviceCaps))
+ {
+ static constexpr Format info(GL_DEPTH_COMPONENT32_OES,
+ angle::FormatID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_X24_TYPELESS_G8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_DEPTH_COMPONENT32_OES,
+ angle::FormatID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ {
+ static constexpr Format info(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE,
+ angle::FormatID::BC1_RGB_UNORM_BLOCK,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_BC1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_ETC1_RGB8_OES:
+ {
+ static constexpr Format info(GL_ETC1_RGB8_OES,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE:
+ {
+ static constexpr Format info(GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE:
+ {
+ static constexpr Format info(GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_LUMINANCE16F_EXT:
+ {
+ static constexpr Format info(GL_LUMINANCE16F_EXT,
+ angle::FormatID::R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS,
+ GL_RGBA16F,
+ Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>);
+ return info;
+ }
+ case GL_LUMINANCE32F_EXT:
+ {
+ static constexpr Format info(GL_LUMINANCE32F_EXT,
+ angle::FormatID::R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_TYPELESS,
+ GL_RGBA32F,
+ Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>);
+ return info;
+ }
+ case GL_LUMINANCE8_ALPHA8_EXT:
+ {
+ static constexpr Format info(GL_LUMINANCE8_ALPHA8_EXT,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_LUMINANCE8_EXT:
+ {
+ static constexpr Format info(GL_LUMINANCE8_EXT,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ {
+ static constexpr Format info(GL_LUMINANCE_ALPHA16F_EXT,
+ angle::FormatID::R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS,
+ GL_RGBA16F,
+ nullptr);
+ return info;
+ }
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ {
+ static constexpr Format info(GL_LUMINANCE_ALPHA32F_EXT,
+ angle::FormatID::R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_TYPELESS,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_NONE:
+ {
+ static constexpr Format info(GL_NONE,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_PALETTE4_R5_G6_B5_OES:
+ {
+ static constexpr Format info(GL_PALETTE4_R5_G6_B5_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_PALETTE4_RGB5_A1_OES:
+ {
+ static constexpr Format info(GL_PALETTE4_RGB5_A1_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_PALETTE4_RGB8_OES:
+ {
+ static constexpr Format info(GL_PALETTE4_RGB8_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_PALETTE4_RGBA4_OES:
+ {
+ static constexpr Format info(GL_PALETTE4_RGBA4_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_PALETTE4_RGBA8_OES:
+ {
+ static constexpr Format info(GL_PALETTE4_RGBA8_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_PALETTE8_R5_G6_B5_OES:
+ {
+ static constexpr Format info(GL_PALETTE8_R5_G6_B5_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_PALETTE8_RGB5_A1_OES:
+ {
+ static constexpr Format info(GL_PALETTE8_RGB5_A1_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_PALETTE8_RGB8_OES:
+ {
+ static constexpr Format info(GL_PALETTE8_RGB8_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_PALETTE8_RGBA4_OES:
+ {
+ static constexpr Format info(GL_PALETTE8_RGBA4_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_PALETTE8_RGBA8_OES:
+ {
+ static constexpr Format info(GL_PALETTE8_RGBA8_OES,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_R11F_G11F_B10F:
+ {
+ static constexpr Format info(GL_R11F_G11F_B10F,
+ angle::FormatID::R11G11B10_FLOAT,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R11G11B10_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA16F_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_R16F:
+ {
+ static constexpr Format info(GL_R16F,
+ angle::FormatID::R16_FLOAT,
+ DXGI_FORMAT_R16_FLOAT,
+ DXGI_FORMAT_R16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_TYPELESS,
+ GL_RGBA16F_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_R16I:
+ {
+ static constexpr Format info(GL_R16I,
+ angle::FormatID::R16_SINT,
+ DXGI_FORMAT_R16_SINT,
+ DXGI_FORMAT_R16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_TYPELESS,
+ GL_RGBA16I,
+ nullptr);
+ return info;
+ }
+ case GL_R16UI:
+ {
+ static constexpr Format info(GL_R16UI,
+ angle::FormatID::R16_UINT,
+ DXGI_FORMAT_R16_UINT,
+ DXGI_FORMAT_R16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_TYPELESS,
+ GL_RGBA16I,
+ nullptr);
+ return info;
+ }
+ case GL_R16_EXT:
+ {
+ static constexpr Format info(GL_R16_EXT,
+ angle::FormatID::R16_UNORM,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_TYPELESS,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_R16_SNORM_EXT:
+ {
+ static constexpr Format info(GL_R16_SNORM_EXT,
+ angle::FormatID::R16_SNORM,
+ DXGI_FORMAT_R16_SNORM,
+ DXGI_FORMAT_R16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16_TYPELESS,
+ GL_RGBA16_SNORM_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_R32F:
+ {
+ static constexpr Format info(GL_R32F,
+ angle::FormatID::R32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32_TYPELESS,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_R32I:
+ {
+ static constexpr Format info(GL_R32I,
+ angle::FormatID::R32_SINT,
+ DXGI_FORMAT_R32_SINT,
+ DXGI_FORMAT_R32_SINT,
+ DXGI_FORMAT_R32_SINT,
+ DXGI_FORMAT_R32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32_TYPELESS,
+ GL_RGBA32I,
+ nullptr);
+ return info;
+ }
+ case GL_R32UI:
+ {
+ static constexpr Format info(GL_R32UI,
+ angle::FormatID::R32_UINT,
+ DXGI_FORMAT_R32_UINT,
+ DXGI_FORMAT_R32_UINT,
+ DXGI_FORMAT_R32_UINT,
+ DXGI_FORMAT_R32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32_TYPELESS,
+ GL_RGBA32I,
+ nullptr);
+ return info;
+ }
+ case GL_R8:
+ {
+ static constexpr Format info(GL_R8,
+ angle::FormatID::R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_TYPELESS,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_R8I:
+ {
+ static constexpr Format info(GL_R8I,
+ angle::FormatID::R8_SINT,
+ DXGI_FORMAT_R8_SINT,
+ DXGI_FORMAT_R8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_TYPELESS,
+ GL_RGBA8I,
+ nullptr);
+ return info;
+ }
+ case GL_R8UI:
+ {
+ static constexpr Format info(GL_R8UI,
+ angle::FormatID::R8_UINT,
+ DXGI_FORMAT_R8_UINT,
+ DXGI_FORMAT_R8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_TYPELESS,
+ GL_RGBA8I,
+ nullptr);
+ return info;
+ }
+ case GL_R8_SNORM:
+ {
+ static constexpr Format info(GL_R8_SNORM,
+ angle::FormatID::R8_SNORM,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8_TYPELESS,
+ GL_RGBA8_SNORM,
+ nullptr);
+ return info;
+ }
+ case GL_RG16F:
+ {
+ static constexpr Format info(GL_RG16F,
+ angle::FormatID::R16G16_FLOAT,
+ DXGI_FORMAT_R16G16_FLOAT,
+ DXGI_FORMAT_R16G16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_TYPELESS,
+ GL_RGBA16F_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RG16I:
+ {
+ static constexpr Format info(GL_RG16I,
+ angle::FormatID::R16G16_SINT,
+ DXGI_FORMAT_R16G16_SINT,
+ DXGI_FORMAT_R16G16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_TYPELESS,
+ GL_RGBA16I,
+ nullptr);
+ return info;
+ }
+ case GL_RG16UI:
+ {
+ static constexpr Format info(GL_RG16UI,
+ angle::FormatID::R16G16_UINT,
+ DXGI_FORMAT_R16G16_UINT,
+ DXGI_FORMAT_R16G16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_TYPELESS,
+ GL_RGBA16I,
+ nullptr);
+ return info;
+ }
+ case GL_RG16_EXT:
+ {
+ static constexpr Format info(GL_RG16_EXT,
+ angle::FormatID::R16G16_UNORM,
+ DXGI_FORMAT_R16G16_UNORM,
+ DXGI_FORMAT_R16G16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_TYPELESS,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RG16_SNORM_EXT:
+ {
+ static constexpr Format info(GL_RG16_SNORM_EXT,
+ angle::FormatID::R16G16_SNORM,
+ DXGI_FORMAT_R16G16_SNORM,
+ DXGI_FORMAT_R16G16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16_TYPELESS,
+ GL_RGBA16_SNORM_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RG32F:
+ {
+ static constexpr Format info(GL_RG32F,
+ angle::FormatID::R32G32_FLOAT,
+ DXGI_FORMAT_R32G32_FLOAT,
+ DXGI_FORMAT_R32G32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32_TYPELESS,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_RG32I:
+ {
+ static constexpr Format info(GL_RG32I,
+ angle::FormatID::R32G32_SINT,
+ DXGI_FORMAT_R32G32_SINT,
+ DXGI_FORMAT_R32G32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32_TYPELESS,
+ GL_RGBA32I,
+ nullptr);
+ return info;
+ }
+ case GL_RG32UI:
+ {
+ static constexpr Format info(GL_RG32UI,
+ angle::FormatID::R32G32_UINT,
+ DXGI_FORMAT_R32G32_UINT,
+ DXGI_FORMAT_R32G32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32_TYPELESS,
+ GL_RGBA32I,
+ nullptr);
+ return info;
+ }
+ case GL_RG8:
+ {
+ static constexpr Format info(GL_RG8,
+ angle::FormatID::R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_TYPELESS,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_RG8I:
+ {
+ static constexpr Format info(GL_RG8I,
+ angle::FormatID::R8G8_SINT,
+ DXGI_FORMAT_R8G8_SINT,
+ DXGI_FORMAT_R8G8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_TYPELESS,
+ GL_RGBA8I,
+ nullptr);
+ return info;
+ }
+ case GL_RG8UI:
+ {
+ static constexpr Format info(GL_RG8UI,
+ angle::FormatID::R8G8_UINT,
+ DXGI_FORMAT_R8G8_UINT,
+ DXGI_FORMAT_R8G8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_TYPELESS,
+ GL_RGBA8I,
+ nullptr);
+ return info;
+ }
+ case GL_RG8_SNORM:
+ {
+ static constexpr Format info(GL_RG8_SNORM,
+ angle::FormatID::R8G8_SNORM,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8_TYPELESS,
+ GL_RGBA8_SNORM,
+ nullptr);
+ return info;
+ }
+ case GL_RGB:
+ {
+ static constexpr Format info(GL_RGB,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_RGB10_A2:
+ {
+ static constexpr Format info(GL_RGB10_A2,
+ angle::FormatID::R10G10B10A2_UNORM,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_TYPELESS,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RGB10_A2UI:
+ {
+ static constexpr Format info(GL_RGB10_A2UI,
+ angle::FormatID::R10G10B10A2_UINT,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_TYPELESS,
+ GL_RGBA16I,
+ nullptr);
+ return info;
+ }
+ case GL_RGB10_UNORM_ANGLEX:
+ {
+ static constexpr Format info(GL_RGB10_UNORM_ANGLEX,
+ angle::FormatID::R10G10B10X2_UNORM,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R10G10B10A2_TYPELESS,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RGB16F:
+ {
+ static constexpr Format info(GL_RGB16F,
+ angle::FormatID::R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS,
+ GL_RGBA16F,
+ Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>);
+ return info;
+ }
+ case GL_RGB16I:
+ {
+ static constexpr Format info(GL_RGB16I,
+ angle::FormatID::R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS,
+ GL_RGBA16I,
+ Initialize4ComponentData<GLshort, 0x0000, 0x0000, 0x0000, 0x0001>);
+ return info;
+ }
+ case GL_RGB16UI:
+ {
+ static constexpr Format info(GL_RGB16UI,
+ angle::FormatID::R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS,
+ GL_RGBA16UI,
+ Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x0001>);
+ return info;
+ }
+ case GL_RGB16_EXT:
+ {
+ static constexpr Format info(GL_RGB16_EXT,
+ angle::FormatID::R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS,
+ GL_RGBA16_EXT,
+ Initialize4ComponentData<GLubyte, 0x0000, 0x0000, 0x0000, 0xFFFF>);
+ return info;
+ }
+ case GL_RGB16_SNORM_EXT:
+ {
+ static constexpr Format info(GL_RGB16_SNORM_EXT,
+ angle::FormatID::R16G16B16A16_SNORM,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS,
+ GL_RGBA16_SNORM_EXT,
+ Initialize4ComponentData<GLushort, 0x0000, 0x0000, 0x0000, 0x7FFF>);
+ return info;
+ }
+ case GL_RGB32F:
+ {
+ static constexpr Format info(GL_RGB32F,
+ angle::FormatID::R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_TYPELESS,
+ GL_RGBA32F,
+ Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>);
+ return info;
+ }
+ case GL_RGB32I:
+ {
+ static constexpr Format info(GL_RGB32I,
+ angle::FormatID::R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_TYPELESS,
+ GL_RGBA32I,
+ Initialize4ComponentData<GLint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>);
+ return info;
+ }
+ case GL_RGB32UI:
+ {
+ static constexpr Format info(GL_RGB32UI,
+ angle::FormatID::R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_TYPELESS,
+ GL_RGBA32UI,
+ Initialize4ComponentData<GLuint, 0x00000000, 0x00000000, 0x00000000, 0x00000001>);
+ return info;
+ }
+ case GL_RGB565:
+ {
+ if (SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps))
+ {
+ static constexpr Format info(GL_RGB565,
+ angle::FormatID::B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B5G6R5_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_RGB565,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ }
+ case GL_RGB5_A1:
+ {
+ if (SupportsFormat(DXGI_FORMAT_B5G5R5A1_UNORM, deviceCaps))
+ {
+ static constexpr Format info(GL_RGB5_A1,
+ angle::FormatID::B5G5R5A1_UNORM,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B5G5R5A1_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_RGB5_A1,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_RGB8:
+ {
+ static constexpr Format info(GL_RGB8,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_RGB8I:
+ {
+ static constexpr Format info(GL_RGB8I,
+ angle::FormatID::R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8I,
+ Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x01>);
+ return info;
+ }
+ case GL_RGB8UI:
+ {
+ static constexpr Format info(GL_RGB8UI,
+ angle::FormatID::R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8UI,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0x01>);
+ return info;
+ }
+ case GL_RGB8_SNORM:
+ {
+ static constexpr Format info(GL_RGB8_SNORM,
+ angle::FormatID::R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8_SNORM,
+ Initialize4ComponentData<GLbyte, 0x00, 0x00, 0x00, 0x7F>);
+ return info;
+ }
+ case GL_RGB9_E5:
+ {
+ static constexpr Format info(GL_RGB9_E5,
+ angle::FormatID::R9G9B9E5_SHAREDEXP,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA16F_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA:
+ {
+ static constexpr Format info(GL_RGBA,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA16F:
+ {
+ static constexpr Format info(GL_RGBA16F,
+ angle::FormatID::R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS,
+ GL_RGBA16F,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA16I:
+ {
+ static constexpr Format info(GL_RGBA16I,
+ angle::FormatID::R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS,
+ GL_RGBA16I,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA16UI:
+ {
+ static constexpr Format info(GL_RGBA16UI,
+ angle::FormatID::R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS,
+ GL_RGBA16UI,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA16_EXT:
+ {
+ static constexpr Format info(GL_RGBA16_EXT,
+ angle::FormatID::R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS,
+ GL_RGBA16_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA16_SNORM_EXT:
+ {
+ static constexpr Format info(GL_RGBA16_SNORM_EXT,
+ angle::FormatID::R16G16B16A16_SNORM,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS,
+ GL_RGBA16_SNORM_EXT,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA32F:
+ {
+ static constexpr Format info(GL_RGBA32F,
+ angle::FormatID::R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_FLOAT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_TYPELESS,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA32I:
+ {
+ static constexpr Format info(GL_RGBA32I,
+ angle::FormatID::R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_TYPELESS,
+ GL_RGBA32I,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA32UI:
+ {
+ static constexpr Format info(GL_RGBA32UI,
+ angle::FormatID::R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R32G32B32A32_TYPELESS,
+ GL_RGBA32UI,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA4:
+ {
+ if (SupportsFormat(DXGI_FORMAT_B4G4R4A4_UNORM, deviceCaps))
+ {
+ static constexpr Format info(GL_RGBA4,
+ angle::FormatID::B4G4R4A4_UNORM,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B4G4R4A4_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA4,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_RGBA4,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_RGBA8:
+ {
+ static constexpr Format info(GL_RGBA8,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA8I:
+ {
+ static constexpr Format info(GL_RGBA8I,
+ angle::FormatID::R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_SINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8I,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA8UI:
+ {
+ static constexpr Format info(GL_RGBA8UI,
+ angle::FormatID::R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8UI,
+ nullptr);
+ return info;
+ }
+ case GL_RGBA8_SNORM:
+ {
+ static constexpr Format info(GL_RGBA8_SNORM,
+ angle::FormatID::R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_SNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8_SNORM,
+ nullptr);
+ return info;
+ }
+ case GL_RGBX8_ANGLE:
+ {
+ if (OnlyFL11_1Plus(deviceCaps))
+ {
+ static constexpr Format info(GL_RGBX8_ANGLE,
+ angle::FormatID::R8G8B8X8_UNORM,
+ DXGI_FORMAT_B8G8R8X8_UNORM,
+ DXGI_FORMAT_B8G8R8X8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8X8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_B8G8R8X8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBX8_ANGLE,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_RGBX8_ANGLE,
+ angle::FormatID::R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_RGBA8,
+ nullptr);
+ return info;
+ }
+ }
+ case GL_SR8_EXT:
+ {
+ static constexpr Format info(GL_SR8_EXT,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_SRG8_EXT:
+ {
+ static constexpr Format info(GL_SRG8_EXT,
+ angle::FormatID::NONE,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_NONE,
+ nullptr);
+ return info;
+ }
+ case GL_SRGB8:
+ {
+ static constexpr Format info(GL_SRGB8,
+ angle::FormatID::R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_SRGB8_ALPHA8,
+ Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>);
+ return info;
+ }
+ case GL_SRGB8_ALPHA8:
+ {
+ static constexpr Format info(GL_SRGB8_ALPHA8,
+ angle::FormatID::R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS,
+ GL_SRGB8_ALPHA8,
+ nullptr);
+ return info;
+ }
+ case GL_STENCIL_INDEX8:
+ {
+ if (OnlyFL10Plus(deviceCaps))
+ {
+ static constexpr Format info(GL_STENCIL_INDEX8,
+ angle::FormatID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24G8_TYPELESS,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
+ DXGI_FORMAT_X24_TYPELESS_G8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ else
+ {
+ static constexpr Format info(GL_STENCIL_INDEX8,
+ angle::FormatID::D24_UNORM_S8_UINT,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_D24_UNORM_S8_UINT,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ DXGI_FORMAT_UNKNOWN,
+ GL_RGBA32F,
+ nullptr);
+ return info;
+ }
+ }
+
+ default:
+ break;
+ }
+ // clang-format on
+
+ UNREACHABLE();
+ static constexpr Format defaultInfo;
+ return defaultInfo;
+}
+
+} // namespace d3d11
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h
new file mode 100644
index 0000000000..f46f769182
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h
@@ -0,0 +1,90 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Helper routines for the D3D11 texture format table.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTURE_FORMAT_TABLE_UTILS_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TEXTURE_FORMAT_TABLE_UTILS_H_
+
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+using FormatSupportFunction = bool (*)(const Renderer11DeviceCaps &);
+
+inline bool OnlyFL11_1Plus(const Renderer11DeviceCaps &deviceCaps)
+{
+ return (deviceCaps.featureLevel >= D3D_FEATURE_LEVEL_11_1);
+}
+
+inline bool OnlyFL10Plus(const Renderer11DeviceCaps &deviceCaps)
+{
+ return (deviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0);
+}
+
+inline bool OnlyFL9_3(const Renderer11DeviceCaps &deviceCaps)
+{
+ return (deviceCaps.featureLevel == D3D_FEATURE_LEVEL_9_3);
+}
+
+inline bool SupportsFormat(DXGI_FORMAT format, const Renderer11DeviceCaps &deviceCaps)
+{
+ // Must support texture, SRV and RTV support
+ UINT mustSupport = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE |
+ D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | D3D11_FORMAT_SUPPORT_MIP |
+ D3D11_FORMAT_SUPPORT_RENDER_TARGET;
+ UINT minimumRequiredSamples = 0;
+
+ if (d3d11_gl::GetMaximumClientVersion(deviceCaps).major > 2)
+ {
+ mustSupport |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
+
+ // RGBA4, RGB5A1 and RGB565 are all required multisampled renderbuffer formats in ES3 and
+ // need to support a minimum of 4 samples.
+ minimumRequiredSamples = 4;
+ }
+
+ bool fullSupport = false;
+ if (format == DXGI_FORMAT_B5G6R5_UNORM)
+ {
+ // All hardware that supports DXGI_FORMAT_B5G6R5_UNORM should support autogen mipmaps, but
+ // check anyway.
+ mustSupport |= D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
+ fullSupport = ((deviceCaps.B5G6R5support & mustSupport) == mustSupport) &&
+ deviceCaps.B5G6R5maxSamples >= minimumRequiredSamples;
+ }
+ else if (format == DXGI_FORMAT_B4G4R4A4_UNORM)
+ {
+ fullSupport = ((deviceCaps.B4G4R4A4support & mustSupport) == mustSupport) &&
+ deviceCaps.B4G4R4A4maxSamples >= minimumRequiredSamples;
+ }
+ else if (format == DXGI_FORMAT_B5G5R5A1_UNORM)
+ {
+ fullSupport = ((deviceCaps.B5G5R5A1support & mustSupport) == mustSupport) &&
+ deviceCaps.B5G5R5A1maxSamples >= minimumRequiredSamples;
+ }
+ else
+ {
+ UNREACHABLE();
+ return false;
+ }
+
+ // This means that ANGLE would like to use the entry in the map if the inputted DXGI format
+ // *IS* supported.
+ // e.g. the entry might map GL_RGB5_A1 to DXGI_FORMAT_B5G5R5A1, which should only be used if
+ // DXGI_FORMAT_B5G5R5A1 is supported.
+ // In this case, we should only return 'true' if the format *IS* supported.
+ return fullSupport;
+}
+
+} // namespace d3d11
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURE_FORMAT_TABLE_UTILS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp
new file mode 100644
index 0000000000..722510a482
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp
@@ -0,0 +1,218 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow11Win32.cpp: Implementation of NativeWindow11 using win32 window APIs.
+
+#include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#include "common/debug.h"
+
+// This header must be included before dcomp.h.
+#include <initguid.h>
+
+#include <dcomp.h>
+
+namespace rx
+{
+
+NativeWindow11Win32::NativeWindow11Win32(EGLNativeWindowType window,
+ bool hasAlpha,
+ bool directComposition)
+ : NativeWindow11(window),
+ mDirectComposition(directComposition),
+ mHasAlpha(hasAlpha),
+ mDevice(nullptr),
+ mCompositionTarget(nullptr),
+ mVisual(nullptr)
+{}
+
+NativeWindow11Win32::~NativeWindow11Win32()
+{
+ SafeRelease(mCompositionTarget);
+ SafeRelease(mDevice);
+ SafeRelease(mVisual);
+}
+
+bool NativeWindow11Win32::initialize()
+{
+ return true;
+}
+
+bool NativeWindow11Win32::getClientRect(LPRECT rect) const
+{
+ return GetClientRect(getNativeWindow(), rect) == TRUE;
+}
+
+bool NativeWindow11Win32::isIconic() const
+{
+ return IsIconic(getNativeWindow()) == TRUE;
+}
+
+HRESULT NativeWindow11Win32::createSwapChain(ID3D11Device *device,
+ IDXGIFactory *factory,
+ DXGI_FORMAT format,
+ UINT width,
+ UINT height,
+ UINT samples,
+ IDXGISwapChain **swapChain)
+{
+ if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 ||
+ height == 0)
+ {
+ return E_INVALIDARG;
+ }
+
+ if (mDirectComposition)
+ {
+ HMODULE dcomp = ::GetModuleHandle(TEXT("dcomp.dll"));
+ if (!dcomp)
+ {
+ return E_INVALIDARG;
+ }
+
+ typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE)(
+ IDXGIDevice * dxgiDevice, REFIID iid, void **dcompositionDevice);
+ PFN_DCOMPOSITION_CREATE_DEVICE createDComp =
+ reinterpret_cast<PFN_DCOMPOSITION_CREATE_DEVICE>(
+ GetProcAddress(dcomp, "DCompositionCreateDevice"));
+ if (!createDComp)
+ {
+ return E_INVALIDARG;
+ }
+
+ if (!mDevice)
+ {
+ IDXGIDevice *dxgiDevice = d3d11::DynamicCastComObject<IDXGIDevice>(device);
+ HRESULT result = createDComp(dxgiDevice, __uuidof(IDCompositionDevice),
+ reinterpret_cast<void **>(&mDevice));
+ SafeRelease(dxgiDevice);
+
+ if (FAILED(result))
+ {
+ return result;
+ }
+ }
+
+ if (!mCompositionTarget)
+ {
+ HRESULT result =
+ mDevice->CreateTargetForHwnd(getNativeWindow(), TRUE, &mCompositionTarget);
+ if (FAILED(result))
+ {
+ return result;
+ }
+ }
+
+ if (!mVisual)
+ {
+ HRESULT result = mDevice->CreateVisual(&mVisual);
+ if (FAILED(result))
+ {
+ return result;
+ }
+ }
+
+ IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
+ swapChainDesc.Width = width;
+ swapChainDesc.Height = height;
+ swapChainDesc.Format = format;
+ swapChainDesc.Stereo = FALSE;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage =
+ DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_SHADER_INPUT;
+ swapChainDesc.BufferCount = 2;
+ swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ swapChainDesc.AlphaMode =
+ mHasAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE;
+ swapChainDesc.Flags = 0;
+ IDXGISwapChain1 *swapChain1 = nullptr;
+ HRESULT result =
+ factory2->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, &swapChain1);
+ if (SUCCEEDED(result))
+ {
+ *swapChain = static_cast<IDXGISwapChain *>(swapChain1);
+ }
+ mVisual->SetContent(swapChain1);
+ mCompositionTarget->SetRoot(mVisual);
+ SafeRelease(factory2);
+ return result;
+ }
+
+ // Use IDXGIFactory2::CreateSwapChainForHwnd if DXGI 1.2 is available to create a
+ // DXGI_SWAP_EFFECT_SEQUENTIAL swap chain.
+ IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject<IDXGIFactory2>(factory);
+ if (factory2 != nullptr)
+ {
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
+ swapChainDesc.Width = width;
+ swapChainDesc.Height = height;
+ swapChainDesc.Format = format;
+ swapChainDesc.Stereo = FALSE;
+ swapChainDesc.SampleDesc.Count = samples;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage =
+ DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
+ swapChainDesc.BufferCount = 1;
+ swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
+ swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
+ swapChainDesc.Flags = 0;
+ IDXGISwapChain1 *swapChain1 = nullptr;
+ HRESULT result = factory2->CreateSwapChainForHwnd(device, getNativeWindow(), &swapChainDesc,
+ nullptr, nullptr, &swapChain1);
+ if (SUCCEEDED(result))
+ {
+ factory2->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER);
+ *swapChain = static_cast<IDXGISwapChain *>(swapChain1);
+ }
+ SafeRelease(factory2);
+ return result;
+ }
+
+ DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
+ swapChainDesc.BufferCount = 1;
+ swapChainDesc.BufferDesc.Format = format;
+ swapChainDesc.BufferDesc.Width = width;
+ swapChainDesc.BufferDesc.Height = height;
+ swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
+ swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
+ swapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
+ swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
+ swapChainDesc.BufferUsage =
+ DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER;
+ swapChainDesc.Flags = 0;
+ swapChainDesc.OutputWindow = getNativeWindow();
+ swapChainDesc.SampleDesc.Count = samples;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.Windowed = TRUE;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+
+ HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, swapChain);
+ if (SUCCEEDED(result))
+ {
+ factory->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER);
+ }
+ return result;
+}
+
+void NativeWindow11Win32::commitChange()
+{
+ if (mDevice)
+ {
+ mDevice->Commit();
+ }
+}
+
+// static
+bool NativeWindow11Win32::IsValidNativeWindow(EGLNativeWindowType window)
+{
+ return IsWindow(window) == TRUE;
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h
new file mode 100644
index 0000000000..f67cfc73a8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h
@@ -0,0 +1,53 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow11Win32.h: Implementation of NativeWindow11 using win32 window APIs.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_WIN32_NATIVEWINDOW11WIN32_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_WIN32_NATIVEWINDOW11WIN32_H_
+
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h"
+
+typedef interface IDCompositionDevice IDCompositionDevice;
+typedef interface IDCompositionTarget IDCompositionTarget;
+typedef interface IDCompositionVisual IDCompositionVisual;
+
+namespace rx
+{
+
+class NativeWindow11Win32 : public NativeWindow11
+{
+ public:
+ NativeWindow11Win32(EGLNativeWindowType window, bool hasAlpha, bool directComposition);
+ ~NativeWindow11Win32() override;
+
+ bool initialize() override;
+ bool getClientRect(LPRECT rect) const override;
+ bool isIconic() const override;
+
+ HRESULT createSwapChain(ID3D11Device *device,
+ IDXGIFactory *factory,
+ DXGI_FORMAT format,
+ UINT width,
+ UINT height,
+ UINT samples,
+ IDXGISwapChain **swapChain) override;
+
+ void commitChange() override;
+
+ static bool IsValidNativeWindow(EGLNativeWindowType window);
+
+ private:
+ bool mDirectComposition;
+ bool mHasAlpha;
+ IDCompositionDevice *mDevice;
+ IDCompositionTarget *mCompositionTarget;
+ IDCompositionVisual *mVisual;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_WIN32_NATIVEWINDOW11WIN32_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp
new file mode 100644
index 0000000000..429159b4cb
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp
@@ -0,0 +1,760 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Blit9.cpp: Surface copy utility class.
+
+#include "libANGLE/renderer/d3d/d3d9/Blit9.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+
+namespace
+{
+// Precompiled shaders
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskpremultps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskunmultps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminancepremultps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceunmultps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h"
+
+const BYTE *const g_shaderCode[] = {
+ g_vs20_standardvs,
+ g_ps20_passthroughps,
+ g_ps20_luminanceps,
+ g_ps20_luminancepremultps,
+ g_ps20_luminanceunmultps,
+ g_ps20_componentmaskps,
+ g_ps20_componentmaskpremultps,
+ g_ps20_componentmaskunmultps,
+};
+
+const size_t g_shaderSize[] = {
+ sizeof(g_vs20_standardvs),
+ sizeof(g_ps20_passthroughps),
+ sizeof(g_ps20_luminanceps),
+ sizeof(g_ps20_luminancepremultps),
+ sizeof(g_ps20_luminanceunmultps),
+ sizeof(g_ps20_componentmaskps),
+ sizeof(g_ps20_componentmaskpremultps),
+ sizeof(g_ps20_componentmaskunmultps),
+};
+} // namespace
+
+namespace rx
+{
+
+Blit9::Blit9(Renderer9 *renderer)
+ : mRenderer(renderer),
+ mGeometryLoaded(false),
+ mQuadVertexBuffer(nullptr),
+ mQuadVertexDeclaration(nullptr),
+ mSavedStateBlock(nullptr),
+ mSavedRenderTarget(nullptr),
+ mSavedDepthStencil(nullptr)
+{
+ memset(mCompiledShaders, 0, sizeof(mCompiledShaders));
+}
+
+Blit9::~Blit9()
+{
+ SafeRelease(mSavedStateBlock);
+ SafeRelease(mQuadVertexBuffer);
+ SafeRelease(mQuadVertexDeclaration);
+
+ for (int i = 0; i < SHADER_COUNT; i++)
+ {
+ SafeRelease(mCompiledShaders[i]);
+ }
+}
+
+angle::Result Blit9::initialize(Context9 *context9)
+{
+ if (mGeometryLoaded)
+ {
+ return angle::Result::Continue;
+ }
+
+ static const float quad[] = {-1, -1, -1, 1, 1, -1, 1, 1};
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0,
+ D3DPOOL_DEFAULT, &mQuadVertexBuffer, nullptr);
+
+ ANGLE_TRY_HR(context9, result, "Failed to create internal blit vertex shader");
+
+ void *lockPtr = nullptr;
+ result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0);
+
+ ANGLE_TRY_HR(context9, result, "Failed to lock internal blit vertex shader");
+ ASSERT(lockPtr);
+
+ memcpy(lockPtr, quad, sizeof(quad));
+ mQuadVertexBuffer->Unlock();
+
+ static const D3DVERTEXELEMENT9 elements[] = {
+ {0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END()};
+
+ result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration);
+ ANGLE_TRY_HR(context9, result, "Failed to create internal blit vertex shader declaration");
+
+ mGeometryLoaded = true;
+ return angle::Result::Continue;
+}
+
+template <class D3DShaderType>
+angle::Result Blit9::setShader(Context9 *context9,
+ ShaderId source,
+ const char *profile,
+ angle::Result (Renderer9::*createShader)(d3d::Context *,
+ const DWORD *,
+ size_t length,
+ D3DShaderType **outShader),
+ HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType *))
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ D3DShaderType *shader = nullptr;
+
+ if (mCompiledShaders[source] != nullptr)
+ {
+ shader = static_cast<D3DShaderType *>(mCompiledShaders[source]);
+ }
+ else
+ {
+ const BYTE *shaderCode = g_shaderCode[source];
+ size_t shaderSize = g_shaderSize[source];
+ ANGLE_TRY((mRenderer->*createShader)(context9, reinterpret_cast<const DWORD *>(shaderCode),
+ shaderSize, &shader));
+ mCompiledShaders[source] = shader;
+ }
+
+ HRESULT hr = (device->*setShader)(shader);
+ ANGLE_TRY_HR(context9, hr, "Failed to set shader for blit operation");
+ return angle::Result::Continue;
+}
+
+angle::Result Blit9::setVertexShader(Context9 *context9, ShaderId shader)
+{
+ return setShader<IDirect3DVertexShader9>(context9, shader, "vs_2_0",
+ &Renderer9::createVertexShader,
+ &IDirect3DDevice9::SetVertexShader);
+}
+
+angle::Result Blit9::setPixelShader(Context9 *context9, ShaderId shader)
+{
+ return setShader<IDirect3DPixelShader9>(context9, shader, "ps_2_0",
+ &Renderer9::createPixelShader,
+ &IDirect3DDevice9::SetPixelShader);
+}
+
+RECT Blit9::getSurfaceRect(IDirect3DSurface9 *surface) const
+{
+ D3DSURFACE_DESC desc;
+ surface->GetDesc(&desc);
+
+ RECT rect;
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = desc.Width;
+ rect.bottom = desc.Height;
+
+ return rect;
+}
+
+gl::Extents Blit9::getSurfaceSize(IDirect3DSurface9 *surface) const
+{
+ D3DSURFACE_DESC desc;
+ surface->GetDesc(&desc);
+
+ return gl::Extents(desc.Width, desc.Height, 1);
+}
+
+angle::Result Blit9::boxFilter(Context9 *context9,
+ IDirect3DSurface9 *source,
+ IDirect3DSurface9 *dest)
+{
+ ANGLE_TRY(initialize(context9));
+
+ angle::ComPtr<IDirect3DBaseTexture9> texture = nullptr;
+ ANGLE_TRY(copySurfaceToTexture(context9, source, getSurfaceRect(source), &texture));
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ saveState();
+
+ device->SetTexture(0, texture.Get());
+ device->SetRenderTarget(0, dest);
+
+ ANGLE_TRY(setVertexShader(context9, SHADER_VS_STANDARD));
+ ANGLE_TRY(setPixelShader(context9, SHADER_PS_PASSTHROUGH));
+
+ setCommonBlitState();
+ device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
+ device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
+
+ setViewportAndShaderConstants(getSurfaceRect(source), getSurfaceSize(source),
+ getSurfaceRect(dest), false);
+
+ render();
+
+ restoreState();
+
+ return angle::Result::Continue;
+}
+
+angle::Result Blit9::copy2D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level)
+{
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ ANGLE_TRY(initialize(context9));
+
+ const gl::FramebufferAttachment *colorbuffer = framebuffer->getColorAttachment(0);
+ ASSERT(colorbuffer);
+
+ RenderTarget9 *renderTarget9 = nullptr;
+ ANGLE_TRY(colorbuffer->getRenderTarget(context, 0, &renderTarget9));
+ ASSERT(renderTarget9);
+
+ angle::ComPtr<IDirect3DSurface9> source = renderTarget9->getSurface();
+ ASSERT(source);
+
+ angle::ComPtr<IDirect3DSurface9> destSurface = nullptr;
+ TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
+ ANGLE_TRY(
+ storage9->getSurfaceLevel(context, gl::TextureTarget::_2D, level, true, &destSurface));
+ ASSERT(destSurface);
+
+ ANGLE_TRY(copy(context9, source.Get(), nullptr, sourceRect, destFormat, destOffset,
+ destSurface.Get(), false, false, false));
+ return angle::Result::Continue;
+}
+
+angle::Result Blit9::copyCube(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ gl::TextureTarget target,
+ GLint level)
+{
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ ANGLE_TRY(initialize(context9));
+
+ const gl::FramebufferAttachment *colorbuffer = framebuffer->getColorAttachment(0);
+ ASSERT(colorbuffer);
+
+ RenderTarget9 *renderTarget9 = nullptr;
+ ANGLE_TRY(colorbuffer->getRenderTarget(context, 0, &renderTarget9));
+ ASSERT(renderTarget9);
+
+ angle::ComPtr<IDirect3DSurface9> source = renderTarget9->getSurface();
+ ASSERT(source);
+
+ angle::ComPtr<IDirect3DSurface9> destSurface = nullptr;
+ TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
+ ANGLE_TRY(storage9->getSurfaceLevel(context, target, level, true, &destSurface));
+ ASSERT(destSurface);
+
+ return copy(context9, source.Get(), nullptr, sourceRect, destFormat, destOffset,
+ destSurface.Get(), false, false, false);
+}
+
+angle::Result Blit9::copyTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ gl::TextureTarget destTarget,
+ GLint destLevel,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha)
+{
+ Context9 *context9 = GetImplAs<Context9>(context);
+ ANGLE_TRY(initialize(context9));
+
+ TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
+
+ TextureStorage *sourceStorage = nullptr;
+ ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage));
+
+ TextureStorage9_2D *sourceStorage9 = GetAs<TextureStorage9_2D>(sourceStorage);
+ ASSERT(sourceStorage9);
+
+ TextureStorage9 *destStorage9 = GetAs<TextureStorage9>(storage);
+ ASSERT(destStorage9);
+
+ ASSERT(sourceLevel == 0);
+ IDirect3DBaseTexture9 *sourceTexture = nullptr;
+ ANGLE_TRY(sourceStorage9->getBaseTexture(context, &sourceTexture));
+
+ angle::ComPtr<IDirect3DSurface9> sourceSurface = nullptr;
+ ANGLE_TRY(sourceStorage9->getSurfaceLevel(context, gl::TextureTarget::_2D, sourceLevel, true,
+ &sourceSurface));
+
+ angle::ComPtr<IDirect3DSurface9> destSurface = nullptr;
+ ANGLE_TRY(destStorage9->getSurfaceLevel(context, destTarget, destLevel, true, &destSurface));
+
+ return copy(context9, sourceSurface.Get(), sourceTexture, sourceRect, destFormat, destOffset,
+ destSurface.Get(), flipY, premultiplyAlpha, unmultiplyAlpha);
+}
+
+angle::Result Blit9::copy(Context9 *context9,
+ IDirect3DSurface9 *source,
+ IDirect3DBaseTexture9 *sourceTexture,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ IDirect3DSurface9 *dest,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha)
+{
+ ASSERT(source != nullptr && dest != nullptr);
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ D3DSURFACE_DESC sourceDesc;
+ D3DSURFACE_DESC destDesc;
+ source->GetDesc(&sourceDesc);
+ dest->GetDesc(&destDesc);
+
+ // Check if it's possible to use StetchRect
+ if (sourceDesc.Format == destDesc.Format && (destDesc.Usage & D3DUSAGE_RENDERTARGET) &&
+ d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat) && !flipY &&
+ premultiplyAlpha == unmultiplyAlpha)
+ {
+ RECT destRect = {destOffset.x, destOffset.y,
+ destOffset.x + (sourceRect.right - sourceRect.left),
+ destOffset.y + (sourceRect.bottom - sourceRect.top)};
+ HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
+ ANGLE_TRY_HR(context9, result, "StretchRect failed to blit between textures");
+ return angle::Result::Continue;
+ }
+
+ angle::ComPtr<IDirect3DBaseTexture9> texture = sourceTexture;
+ RECT adjustedSourceRect = sourceRect;
+ gl::Extents sourceSize(sourceDesc.Width, sourceDesc.Height, 1);
+
+ if (texture == nullptr)
+ {
+ ANGLE_TRY(copySurfaceToTexture(context9, source, sourceRect, &texture));
+
+ // copySurfaceToTexture only copies in the sourceRect area of the source surface.
+ // Adjust sourceRect so that it is now covering the entire source texture
+ adjustedSourceRect.left = 0;
+ adjustedSourceRect.right = sourceRect.right - sourceRect.left;
+ adjustedSourceRect.top = 0;
+ adjustedSourceRect.bottom = sourceRect.bottom - sourceRect.top;
+
+ sourceSize.width = sourceRect.right - sourceRect.left;
+ sourceSize.height = sourceRect.bottom - sourceRect.top;
+ }
+
+ ANGLE_TRY(formatConvert(context9, texture.Get(), adjustedSourceRect, sourceSize, destFormat,
+ destOffset, dest, flipY, premultiplyAlpha, unmultiplyAlpha));
+ return angle::Result::Continue;
+}
+
+angle::Result Blit9::formatConvert(Context9 *context9,
+ IDirect3DBaseTexture9 *source,
+ const RECT &sourceRect,
+ const gl::Extents &sourceSize,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ IDirect3DSurface9 *dest,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha)
+{
+ ANGLE_TRY(initialize(context9));
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ saveState();
+
+ device->SetTexture(0, source);
+ device->SetRenderTarget(0, dest);
+
+ RECT destRect;
+ destRect.left = destOffset.x;
+ destRect.right = destOffset.x + (sourceRect.right - sourceRect.left);
+ destRect.top = destOffset.y;
+ destRect.bottom = destOffset.y + (sourceRect.bottom - sourceRect.top);
+
+ setViewportAndShaderConstants(sourceRect, sourceSize, destRect, flipY);
+
+ setCommonBlitState();
+
+ angle::Result result =
+ setFormatConvertShaders(context9, destFormat, flipY, premultiplyAlpha, unmultiplyAlpha);
+ if (result == angle::Result::Continue)
+ {
+ render();
+ }
+
+ restoreState();
+
+ return result;
+}
+
+angle::Result Blit9::setFormatConvertShaders(Context9 *context9,
+ GLenum destFormat,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha)
+{
+ ANGLE_TRY(setVertexShader(context9, SHADER_VS_STANDARD));
+
+ switch (destFormat)
+ {
+ case GL_RGBA:
+ case GL_BGRA_EXT:
+ case GL_RGB:
+ case GL_RG_EXT:
+ case GL_RED_EXT:
+ case GL_ALPHA:
+ if (premultiplyAlpha == unmultiplyAlpha)
+ {
+ ANGLE_TRY(setPixelShader(context9, SHADER_PS_COMPONENTMASK));
+ }
+ else if (premultiplyAlpha)
+ {
+ ANGLE_TRY(setPixelShader(context9, SHADER_PS_COMPONENTMASK_PREMULTIPLY_ALPHA));
+ }
+ else
+ {
+ ASSERT(unmultiplyAlpha);
+ ANGLE_TRY(setPixelShader(context9, SHADER_PS_COMPONENTMASK_UNMULTIPLY_ALPHA));
+ }
+ break;
+
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ if (premultiplyAlpha == unmultiplyAlpha)
+ {
+ ANGLE_TRY(setPixelShader(context9, SHADER_PS_LUMINANCE));
+ }
+ else if (premultiplyAlpha)
+ {
+ ANGLE_TRY(setPixelShader(context9, SHADER_PS_LUMINANCE_PREMULTIPLY_ALPHA));
+ }
+ else
+ {
+ ASSERT(unmultiplyAlpha);
+ ANGLE_TRY(setPixelShader(context9, SHADER_PS_LUMINANCE_UNMULTIPLY_ALPHA));
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+
+ enum
+ {
+ X = 0,
+ Y = 1,
+ Z = 2,
+ W = 3
+ };
+
+ // The meaning of this constant depends on the shader that was selected.
+ // See the shader assembly code above for details.
+ // Allocate one array for both registers and split it into two float4's.
+ float psConst[8] = {0};
+ float *multConst = &psConst[0];
+ float *addConst = &psConst[4];
+
+ switch (destFormat)
+ {
+ case GL_RGBA:
+ case GL_BGRA_EXT:
+ multConst[X] = 1;
+ multConst[Y] = 1;
+ multConst[Z] = 1;
+ multConst[W] = 1;
+ addConst[X] = 0;
+ addConst[Y] = 0;
+ addConst[Z] = 0;
+ addConst[W] = 0;
+ break;
+
+ case GL_RGB:
+ multConst[X] = 1;
+ multConst[Y] = 1;
+ multConst[Z] = 1;
+ multConst[W] = 0;
+ addConst[X] = 0;
+ addConst[Y] = 0;
+ addConst[Z] = 0;
+ addConst[W] = 1;
+ break;
+
+ case GL_RG_EXT:
+ multConst[X] = 1;
+ multConst[Y] = 1;
+ multConst[Z] = 0;
+ multConst[W] = 0;
+ addConst[X] = 0;
+ addConst[Y] = 0;
+ addConst[Z] = 0;
+ addConst[W] = 1;
+ break;
+
+ case GL_RED_EXT:
+ multConst[X] = 1;
+ multConst[Y] = 0;
+ multConst[Z] = 0;
+ multConst[W] = 0;
+ addConst[X] = 0;
+ addConst[Y] = 0;
+ addConst[Z] = 0;
+ addConst[W] = 1;
+ break;
+
+ case GL_ALPHA:
+ multConst[X] = 0;
+ multConst[Y] = 0;
+ multConst[Z] = 0;
+ multConst[W] = 1;
+ addConst[X] = 0;
+ addConst[Y] = 0;
+ addConst[Z] = 0;
+ addConst[W] = 0;
+ break;
+
+ case GL_LUMINANCE:
+ multConst[X] = 1;
+ multConst[Y] = 0;
+ multConst[Z] = 0;
+ multConst[W] = 0;
+ addConst[X] = 0;
+ addConst[Y] = 0;
+ addConst[Z] = 0;
+ addConst[W] = 1;
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ multConst[X] = 1;
+ multConst[Y] = 0;
+ multConst[Z] = 0;
+ multConst[W] = 1;
+ addConst[X] = 0;
+ addConst[Y] = 0;
+ addConst[Z] = 0;
+ addConst[W] = 0;
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+
+ mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst, 2);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Blit9::copySurfaceToTexture(Context9 *context9,
+ IDirect3DSurface9 *surface,
+ const RECT &sourceRect,
+ angle::ComPtr<IDirect3DBaseTexture9> *outTexture)
+{
+ ASSERT(surface);
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ D3DSURFACE_DESC sourceDesc;
+ surface->GetDesc(&sourceDesc);
+
+ // Copy the render target into a texture
+ angle::ComPtr<IDirect3DTexture9> texture;
+ HRESULT result = device->CreateTexture(
+ sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1,
+ D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, nullptr);
+ ANGLE_TRY_HR(context9, result, "Failed to allocate internal texture for blit");
+
+ angle::ComPtr<IDirect3DSurface9> textureSurface;
+ result = texture->GetSurfaceLevel(0, &textureSurface);
+ ANGLE_TRY_HR(context9, result, "Failed to query surface of internal blit texture");
+
+ mRenderer->endScene();
+ result = device->StretchRect(surface, &sourceRect, textureSurface.Get(), nullptr, D3DTEXF_NONE);
+ ANGLE_TRY_HR(context9, result, "Failed to copy between internal blit textures");
+ *outTexture = texture;
+
+ return angle::Result::Continue;
+}
+
+void Blit9::setViewportAndShaderConstants(const RECT &sourceRect,
+ const gl::Extents &sourceSize,
+ const RECT &destRect,
+ bool flipY)
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ D3DVIEWPORT9 vp;
+ vp.X = destRect.left;
+ vp.Y = destRect.top;
+ vp.Width = destRect.right - destRect.left;
+ vp.Height = destRect.bottom - destRect.top;
+ vp.MinZ = 0.0f;
+ vp.MaxZ = 1.0f;
+ device->SetViewport(&vp);
+
+ float vertexConstants[8] = {
+ // halfPixelAdjust
+ -1.0f / vp.Width,
+ 1.0f / vp.Height,
+ 0,
+ 0,
+ // texcoordOffset
+ static_cast<float>(sourceRect.left) / sourceSize.width,
+ static_cast<float>(flipY ? sourceRect.bottom : sourceRect.top) / sourceSize.height,
+ static_cast<float>(sourceRect.right - sourceRect.left) / sourceSize.width,
+ static_cast<float>(flipY ? sourceRect.top - sourceRect.bottom
+ : sourceRect.bottom - sourceRect.top) /
+ sourceSize.height,
+ };
+
+ device->SetVertexShaderConstantF(0, vertexConstants, 2);
+}
+
+void Blit9::setCommonBlitState()
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ device->SetDepthStencilSurface(nullptr);
+
+ device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+ device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+ device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+ device->SetRenderState(D3DRS_COLORWRITEENABLE,
+ D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE |
+ D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
+ device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
+ device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+
+ device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+ device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+ device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE);
+ device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+ device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+
+ RECT scissorRect = {}; // Scissoring is disabled for flipping, but we need this to capture and
+ // restore the old rectangle
+ device->SetScissorRect(&scissorRect);
+
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ device->SetStreamSourceFreq(i, 1);
+ }
+}
+
+void Blit9::render()
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float));
+ device->SetVertexDeclaration(mQuadVertexDeclaration);
+
+ mRenderer->startScene();
+ device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+}
+
+void Blit9::saveState()
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ HRESULT hr;
+
+ device->GetDepthStencilSurface(&mSavedDepthStencil);
+ device->GetRenderTarget(0, &mSavedRenderTarget);
+
+ if (mSavedStateBlock == nullptr)
+ {
+ hr = device->BeginStateBlock();
+ ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+
+ setCommonBlitState();
+
+ static const float mockConst[8] = {0};
+
+ device->SetVertexShader(nullptr);
+ device->SetVertexShaderConstantF(0, mockConst, 2);
+ device->SetPixelShader(nullptr);
+ device->SetPixelShaderConstantF(0, mockConst, 2);
+
+ D3DVIEWPORT9 mockVp;
+ mockVp.X = 0;
+ mockVp.Y = 0;
+ mockVp.Width = 1;
+ mockVp.Height = 1;
+ mockVp.MinZ = 0;
+ mockVp.MaxZ = 1;
+
+ device->SetViewport(&mockVp);
+
+ device->SetTexture(0, nullptr);
+
+ device->SetStreamSource(0, mQuadVertexBuffer, 0, 0);
+
+ device->SetVertexDeclaration(mQuadVertexDeclaration);
+
+ hr = device->EndStateBlock(&mSavedStateBlock);
+ ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+ }
+
+ ASSERT(mSavedStateBlock != nullptr);
+
+ if (mSavedStateBlock != nullptr)
+ {
+ hr = mSavedStateBlock->Capture();
+ ASSERT(SUCCEEDED(hr));
+ }
+}
+
+void Blit9::restoreState()
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ device->SetDepthStencilSurface(mSavedDepthStencil);
+ SafeRelease(mSavedDepthStencil);
+
+ device->SetRenderTarget(0, mSavedRenderTarget);
+ SafeRelease(mSavedRenderTarget);
+
+ ASSERT(mSavedStateBlock != nullptr);
+
+ if (mSavedStateBlock != nullptr)
+ {
+ mSavedStateBlock->Apply();
+ }
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Blit9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Blit9.h
new file mode 100644
index 0000000000..1c99413ecd
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Blit9.h
@@ -0,0 +1,166 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Blit9.cpp: Surface copy utility class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_
+
+#include "common/PackedEnums.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+namespace gl
+{
+class Context;
+class Framebuffer;
+class Texture;
+struct Extents;
+struct Offset;
+} // namespace gl
+
+namespace rx
+{
+class Context9;
+class Renderer9;
+class TextureStorage;
+
+namespace d3d
+{
+class Context;
+} // namespace d3d
+
+class Blit9 : angle::NonCopyable
+{
+ public:
+ explicit Blit9(Renderer9 *renderer);
+ ~Blit9();
+
+ angle::Result initialize(Context9 *context9);
+
+ // Copy from source surface to dest surface.
+ // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
+ angle::Result copy2D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level);
+ angle::Result copyCube(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ gl::TextureTarget target,
+ GLint level);
+ angle::Result copyTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ gl::TextureTarget destTarget,
+ GLint destLevel,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha);
+
+ // 2x2 box filter sample from source to dest.
+ // Requires that source is RGB(A) and dest has the same format as source.
+ angle::Result boxFilter(Context9 *context9, IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
+
+ private:
+ Renderer9 *mRenderer;
+
+ bool mGeometryLoaded;
+ IDirect3DVertexBuffer9 *mQuadVertexBuffer;
+ IDirect3DVertexDeclaration9 *mQuadVertexDeclaration;
+
+ // Copy from source texture to dest surface.
+ // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
+ // source is interpreted as RGBA and destFormat specifies the desired result format. For
+ // example, if destFormat = GL_RGB, the alpha channel will be forced to 0.
+ angle::Result formatConvert(Context9 *context9,
+ IDirect3DBaseTexture9 *source,
+ const RECT &sourceRect,
+ const gl::Extents &sourceSize,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ IDirect3DSurface9 *dest,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha);
+ angle::Result setFormatConvertShaders(Context9 *context9,
+ GLenum destFormat,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha);
+
+ angle::Result copy(Context9 *context9,
+ IDirect3DSurface9 *source,
+ IDirect3DBaseTexture9 *sourceTexture,
+ const RECT &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ IDirect3DSurface9 *dest,
+ bool flipY,
+ bool premultiplyAlpha,
+ bool unmultiplyAlpha);
+ angle::Result copySurfaceToTexture(Context9 *context9,
+ IDirect3DSurface9 *surface,
+ const RECT &sourceRect,
+ angle::ComPtr<IDirect3DBaseTexture9> *outTexture);
+ void setViewportAndShaderConstants(const RECT &sourceRect,
+ const gl::Extents &sourceSize,
+ const RECT &destRect,
+ bool flipY);
+ void setCommonBlitState();
+ RECT getSurfaceRect(IDirect3DSurface9 *surface) const;
+ gl::Extents getSurfaceSize(IDirect3DSurface9 *surface) const;
+
+ // This enum is used to index mCompiledShaders and mShaderSource.
+ enum ShaderId
+ {
+ SHADER_VS_STANDARD,
+ SHADER_PS_PASSTHROUGH,
+ SHADER_PS_LUMINANCE,
+ SHADER_PS_LUMINANCE_PREMULTIPLY_ALPHA,
+ SHADER_PS_LUMINANCE_UNMULTIPLY_ALPHA,
+ SHADER_PS_COMPONENTMASK,
+ SHADER_PS_COMPONENTMASK_PREMULTIPLY_ALPHA,
+ SHADER_PS_COMPONENTMASK_UNMULTIPLY_ALPHA,
+ SHADER_COUNT,
+ };
+
+ // This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown.
+ IUnknown *mCompiledShaders[SHADER_COUNT];
+
+ template <class D3DShaderType>
+ angle::Result setShader(Context9 *,
+ ShaderId source,
+ const char *profile,
+ angle::Result (Renderer9::*createShader)(d3d::Context *context,
+ const DWORD *,
+ size_t length,
+ D3DShaderType **outShader),
+ HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType *));
+
+ angle::Result setVertexShader(Context9 *context9, ShaderId shader);
+ angle::Result setPixelShader(Context9 *context9, ShaderId shader);
+ void render();
+
+ void saveState();
+ void restoreState();
+ IDirect3DStateBlock9 *mSavedStateBlock;
+ IDirect3DSurface9 *mSavedRenderTarget;
+ IDirect3DSurface9 *mSavedDepthStencil;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
new file mode 100644
index 0000000000..dbf875134b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
@@ -0,0 +1,141 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Buffer9.cpp Defines the Buffer9 class.
+
+#include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+namespace rx
+{
+
+Buffer9::Buffer9(const gl::BufferState &state, Renderer9 *renderer)
+ : BufferD3D(state, renderer), mSize(0)
+{}
+
+Buffer9::~Buffer9()
+{
+ mSize = 0;
+}
+
+size_t Buffer9::getSize() const
+{
+ return mSize;
+}
+
+bool Buffer9::supportsDirectBinding() const
+{
+ return false;
+}
+
+angle::Result Buffer9::setData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ gl::BufferUsage usage)
+{
+ if (size > mMemory.size())
+ {
+ ANGLE_CHECK_GL_ALLOC(GetImplAs<Context9>(context), mMemory.resize(size));
+ }
+
+ mSize = size;
+ if (data && size > 0)
+ {
+ memcpy(mMemory.data(), data, size);
+ }
+
+ updateD3DBufferUsage(context, usage);
+
+ invalidateStaticData(context);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer9::getData(const gl::Context *context, const uint8_t **outData)
+{
+ if (mMemory.empty())
+ {
+ *outData = nullptr;
+ }
+ else
+ {
+ *outData = mMemory.data();
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer9::setSubData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ size_t offset)
+{
+ if (offset + size > mMemory.size())
+ {
+ ANGLE_CHECK_GL_ALLOC(GetImplAs<Context9>(context), mMemory.resize(size + offset));
+ }
+
+ mSize = std::max(mSize, offset + size);
+ if (data && size > 0)
+ {
+ memcpy(mMemory.data() + offset, data, size);
+ }
+
+ invalidateStaticData(context);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Buffer9::copySubData(const gl::Context *context,
+ BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size)
+{
+ // Note: this method is currently unreachable
+ Buffer9 *sourceBuffer = GetAs<Buffer9>(source);
+ ASSERT(sourceBuffer);
+
+ memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size);
+
+ invalidateStaticData(context);
+
+ return angle::Result::Continue;
+}
+
+// We do not support buffer mapping in D3D9
+angle::Result Buffer9::map(const gl::Context *context, GLenum access, void **mapPtr)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Buffer9::mapRange(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ void **mapPtr)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Buffer9::unmap(const gl::Context *context, GLboolean *result)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Buffer9::markTransformFeedbackUsage(const gl::Context *context)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Buffer9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Buffer9.h
new file mode 100644
index 0000000000..dad120d75b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Buffer9.h
@@ -0,0 +1,63 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Buffer9.h: Defines the rx::Buffer9 class which implements rx::BufferImpl via rx::BufferD3D.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_
+
+#include "common/MemoryBuffer.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+
+namespace rx
+{
+class Renderer9;
+
+class Buffer9 : public BufferD3D
+{
+ public:
+ Buffer9(const gl::BufferState &state, Renderer9 *renderer);
+ ~Buffer9() override;
+
+ // BufferD3D implementation
+ size_t getSize() const override;
+ bool supportsDirectBinding() const override;
+ angle::Result getData(const gl::Context *context, const uint8_t **outData) override;
+
+ // BufferImpl implementation
+ angle::Result setData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ gl::BufferUsage usage) override;
+ angle::Result setSubData(const gl::Context *context,
+ gl::BufferBinding target,
+ const void *data,
+ size_t size,
+ size_t offset) override;
+ angle::Result copySubData(const gl::Context *context,
+ BufferImpl *source,
+ GLintptr sourceOffset,
+ GLintptr destOffset,
+ GLsizeiptr size) override;
+ angle::Result map(const gl::Context *context, GLenum access, void **mapPtr) override;
+ angle::Result mapRange(const gl::Context *context,
+ size_t offset,
+ size_t length,
+ GLbitfield access,
+ void **mapPtr) override;
+ angle::Result unmap(const gl::Context *context, GLboolean *result) override;
+ angle::Result markTransformFeedbackUsage(const gl::Context *context) override;
+
+ private:
+ angle::MemoryBuffer mMemory;
+ size_t mSize;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Context9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
new file mode 100644
index 0000000000..b879d9c93b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
@@ -0,0 +1,529 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context9:
+// D3D9-specific functionality associated with a GL Context.
+//
+
+#include "libANGLE/renderer/d3d/d3d9/Context9.h"
+
+#include "common/entry_points_enum_autogen.h"
+#include "common/string_utils.h"
+#include "libANGLE/renderer/OverlayImpl.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/SamplerD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Fence9.h"
+#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Query9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/StateManager9.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexArray9.h"
+
+namespace rx
+{
+
+Context9::Context9(const gl::State &state, gl::ErrorSet *errorSet, Renderer9 *renderer)
+ : ContextD3D(state, errorSet), mRenderer(renderer)
+{}
+
+Context9::~Context9() {}
+
+angle::Result Context9::initialize()
+{
+ return angle::Result::Continue;
+}
+
+void Context9::onDestroy(const gl::Context *context)
+{
+ mIncompleteTextures.onDestroy(context);
+}
+
+CompilerImpl *Context9::createCompiler()
+{
+ return new CompilerD3D(SH_HLSL_3_0_OUTPUT);
+}
+
+ShaderImpl *Context9::createShader(const gl::ShaderState &data)
+{
+ return new ShaderD3D(data, mRenderer);
+}
+
+ProgramImpl *Context9::createProgram(const gl::ProgramState &data)
+{
+ return new ProgramD3D(data, mRenderer);
+}
+
+FramebufferImpl *Context9::createFramebuffer(const gl::FramebufferState &data)
+{
+ return new Framebuffer9(data, mRenderer);
+}
+
+TextureImpl *Context9::createTexture(const gl::TextureState &state)
+{
+ switch (state.getType())
+ {
+ case gl::TextureType::_2D:
+ // GL_TEXTURE_VIDEO_IMAGE_WEBGL maps to 2D texture on Windows platform.
+ case gl::TextureType::VideoImage:
+ return new TextureD3D_2D(state, mRenderer);
+ case gl::TextureType::CubeMap:
+ return new TextureD3D_Cube(state, mRenderer);
+ case gl::TextureType::External:
+ return new TextureD3D_External(state, mRenderer);
+ default:
+ UNREACHABLE();
+ }
+ return nullptr;
+}
+
+RenderbufferImpl *Context9::createRenderbuffer(const gl::RenderbufferState &state)
+{
+ return new RenderbufferD3D(state, mRenderer);
+}
+
+BufferImpl *Context9::createBuffer(const gl::BufferState &state)
+{
+ return new Buffer9(state, mRenderer);
+}
+
+VertexArrayImpl *Context9::createVertexArray(const gl::VertexArrayState &data)
+{
+ return new VertexArray9(data);
+}
+
+QueryImpl *Context9::createQuery(gl::QueryType type)
+{
+ return new Query9(mRenderer, type);
+}
+
+FenceNVImpl *Context9::createFenceNV()
+{
+ return new FenceNV9(mRenderer);
+}
+
+SyncImpl *Context9::createSync()
+{
+ // D3D9 doesn't support ES 3.0 and its sync objects.
+ UNREACHABLE();
+ return nullptr;
+}
+
+TransformFeedbackImpl *Context9::createTransformFeedback(const gl::TransformFeedbackState &state)
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+SamplerImpl *Context9::createSampler(const gl::SamplerState &state)
+{
+ return new SamplerD3D(state);
+}
+
+ProgramPipelineImpl *Context9::createProgramPipeline(const gl::ProgramPipelineState &data)
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+MemoryObjectImpl *Context9::createMemoryObject()
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+SemaphoreImpl *Context9::createSemaphore()
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+OverlayImpl *Context9::createOverlay(const gl::OverlayState &state)
+{
+ // Not implemented.
+ return new OverlayImpl(state);
+}
+
+angle::Result Context9::flush(const gl::Context *context)
+{
+ return mRenderer->flush(context);
+}
+
+angle::Result Context9::finish(const gl::Context *context)
+{
+ return mRenderer->finish(context);
+}
+
+angle::Result Context9::drawArrays(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count)
+{
+ return mRenderer->genericDrawArrays(context, mode, first, count, 0);
+}
+
+angle::Result Context9::drawArraysInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount)
+{
+ return mRenderer->genericDrawArrays(context, mode, first, count, instanceCount);
+}
+
+angle::Result Context9::drawArraysInstancedBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount,
+ GLuint baseInstance)
+{
+ ANGLE_HR_UNREACHABLE(this);
+ return angle::Result::Continue;
+}
+
+angle::Result Context9::drawElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices)
+{
+ return mRenderer->genericDrawElements(context, mode, count, type, indices, 0);
+}
+
+angle::Result Context9::drawElementsBaseVertex(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLint baseVertex)
+{
+ ANGLE_HR_UNREACHABLE(this);
+ return angle::Result::Continue;
+}
+
+angle::Result Context9::drawElementsInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances)
+{
+ return mRenderer->genericDrawElements(context, mode, count, type, indices, instances);
+}
+
+angle::Result Context9::drawElementsInstancedBaseVertex(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances,
+ GLint baseVertex)
+{
+ ANGLE_HR_UNREACHABLE(this);
+ return angle::Result::Continue;
+}
+
+angle::Result Context9::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances,
+ GLint baseVertex,
+ GLuint baseInstance)
+{
+ ANGLE_HR_UNREACHABLE(this);
+ return angle::Result::Continue;
+}
+
+angle::Result Context9::drawRangeElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices)
+{
+ return mRenderer->genericDrawElements(context, mode, count, type, indices, 0);
+}
+
+angle::Result Context9::drawRangeElementsBaseVertex(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLint baseVertex)
+{
+ ANGLE_HR_UNREACHABLE(this);
+ return angle::Result::Continue;
+}
+
+angle::Result Context9::drawArraysIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const void *indirect)
+{
+ ANGLE_HR_UNREACHABLE(this);
+ return angle::Result::Stop;
+}
+
+angle::Result Context9::drawElementsIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType type,
+ const void *indirect)
+{
+ ANGLE_HR_UNREACHABLE(this);
+ return angle::Result::Stop;
+}
+
+angle::Result Context9::multiDrawArrays(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ GLsizei drawcount)
+{
+ return rx::MultiDrawArraysGeneral(this, context, mode, firsts, counts, drawcount);
+}
+
+angle::Result Context9::multiDrawArraysInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount)
+{
+ return rx::MultiDrawArraysInstancedGeneral(this, context, mode, firsts, counts, instanceCounts,
+ drawcount);
+}
+
+angle::Result Context9::multiDrawArraysIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+angle::Result Context9::multiDrawElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ GLsizei drawcount)
+{
+ return rx::MultiDrawElementsGeneral(this, context, mode, counts, type, indices, drawcount);
+}
+
+angle::Result Context9::multiDrawElementsInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount)
+{
+ return rx::MultiDrawElementsInstancedGeneral(this, context, mode, counts, type, indices,
+ instanceCounts, drawcount);
+}
+
+angle::Result Context9::multiDrawElementsIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType type,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride)
+{
+ UNREACHABLE();
+ return angle::Result::Stop;
+}
+
+angle::Result Context9::multiDrawArraysInstancedBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ const GLuint *baseInstances,
+ GLsizei drawcount)
+{
+ ANGLE_HR_UNREACHABLE(this);
+ return angle::Result::Stop;
+}
+
+angle::Result Context9::multiDrawElementsInstancedBaseVertexBaseInstance(
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount)
+{
+ ANGLE_HR_UNREACHABLE(this);
+ return angle::Result::Stop;
+}
+
+gl::GraphicsResetStatus Context9::getResetStatus()
+{
+ return mRenderer->getResetStatus();
+}
+
+angle::Result Context9::insertEventMarker(GLsizei length, const char *marker)
+{
+ mRenderer->getAnnotator()->setMarker(/*context=*/nullptr, marker);
+ return angle::Result::Continue;
+}
+
+angle::Result Context9::pushGroupMarker(GLsizei length, const char *marker)
+{
+ mRenderer->getAnnotator()->beginEvent(nullptr, angle::EntryPoint::GLPushGroupMarkerEXT, marker,
+ marker);
+ mMarkerStack.push(std::string(marker));
+ return angle::Result::Continue;
+}
+
+angle::Result Context9::popGroupMarker()
+{
+ const char *marker = nullptr;
+ if (!mMarkerStack.empty())
+ {
+ marker = mMarkerStack.top().c_str();
+ mMarkerStack.pop();
+ mRenderer->getAnnotator()->endEvent(nullptr, marker,
+ angle::EntryPoint::GLPopGroupMarkerEXT);
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result Context9::pushDebugGroup(const gl::Context *context,
+ GLenum source,
+ GLuint id,
+ const std::string &message)
+{
+ // Fall through to the EXT_debug_marker functions
+ return pushGroupMarker(static_cast<GLsizei>(message.size()), message.c_str());
+}
+
+angle::Result Context9::popDebugGroup(const gl::Context *context)
+{
+ // Fall through to the EXT_debug_marker functions
+ return popGroupMarker();
+}
+
+angle::Result Context9::syncState(const gl::Context *context,
+ const gl::State::DirtyBits &dirtyBits,
+ const gl::State::DirtyBits &bitMask,
+ gl::Command command)
+{
+ mRenderer->getStateManager()->syncState(mState, dirtyBits);
+ return angle::Result::Continue;
+}
+
+GLint Context9::getGPUDisjoint()
+{
+ return mRenderer->getGPUDisjoint();
+}
+
+GLint64 Context9::getTimestamp()
+{
+ return mRenderer->getTimestamp();
+}
+
+angle::Result Context9::onMakeCurrent(const gl::Context *context)
+{
+ mRenderer->getStateManager()->setAllDirtyBits();
+ return mRenderer->ensureVertexDataManagerInitialized(context);
+}
+
+gl::Caps Context9::getNativeCaps() const
+{
+ return mRenderer->getNativeCaps();
+}
+
+const gl::TextureCapsMap &Context9::getNativeTextureCaps() const
+{
+ return mRenderer->getNativeTextureCaps();
+}
+
+const gl::Extensions &Context9::getNativeExtensions() const
+{
+ return mRenderer->getNativeExtensions();
+}
+
+const gl::Limitations &Context9::getNativeLimitations() const
+{
+ return mRenderer->getNativeLimitations();
+}
+
+ShPixelLocalStorageType Context9::getNativePixelLocalStorageType() const
+{
+ return mRenderer->getNativePixelLocalStorageType();
+}
+
+angle::Result Context9::dispatchCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ)
+{
+ ANGLE_HR_UNREACHABLE(this);
+ return angle::Result::Stop;
+}
+
+angle::Result Context9::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
+{
+ ANGLE_HR_UNREACHABLE(this);
+ return angle::Result::Stop;
+}
+
+angle::Result Context9::memoryBarrier(const gl::Context *context, GLbitfield barriers)
+{
+ ANGLE_HR_UNREACHABLE(this);
+ return angle::Result::Stop;
+}
+
+angle::Result Context9::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
+{
+ ANGLE_HR_UNREACHABLE(this);
+ return angle::Result::Stop;
+}
+
+angle::Result Context9::getIncompleteTexture(const gl::Context *context,
+ gl::TextureType type,
+ gl::Texture **textureOut)
+{
+ return mIncompleteTextures.getIncompleteTexture(context, type, gl::SamplerFormat::Float,
+ nullptr, textureOut);
+}
+
+void Context9::handleResult(HRESULT hr,
+ const char *message,
+ const char *file,
+ const char *function,
+ unsigned int line)
+{
+ ASSERT(FAILED(hr));
+
+ if (d3d9::isDeviceLostError(hr))
+ {
+ mRenderer->notifyDeviceLost();
+ }
+
+ GLenum glErrorCode = DefaultGLErrorCode(hr);
+
+ std::stringstream errorStream;
+ errorStream << "Internal D3D9 error: " << gl::FmtHR(hr) << ": " << message;
+
+ mErrors->handleError(glErrorCode, errorStream.str().c_str(), file, function, line);
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Context9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Context9.h
new file mode 100644
index 0000000000..ce3e930295
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Context9.h
@@ -0,0 +1,265 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Context9:
+// D3D9-specific functionality associated with a GL Context.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_CONTEXT9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_CONTEXT9_H_
+
+#include <stack>
+#include "libANGLE/renderer/d3d/ContextD3D.h"
+
+namespace rx
+{
+class Renderer9;
+
+class Context9 : public ContextD3D
+{
+ public:
+ Context9(const gl::State &state, gl::ErrorSet *errorSet, Renderer9 *renderer);
+ ~Context9() override;
+
+ angle::Result initialize() override;
+ void onDestroy(const gl::Context *context) override;
+
+ // Shader creation
+ CompilerImpl *createCompiler() override;
+ ShaderImpl *createShader(const gl::ShaderState &data) override;
+ ProgramImpl *createProgram(const gl::ProgramState &data) override;
+
+ // Framebuffer creation
+ FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) override;
+
+ // Texture creation
+ TextureImpl *createTexture(const gl::TextureState &state) override;
+
+ // Renderbuffer creation
+ RenderbufferImpl *createRenderbuffer(const gl::RenderbufferState &state) override;
+
+ // Buffer creation
+ BufferImpl *createBuffer(const gl::BufferState &state) override;
+
+ // Vertex Array creation
+ VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override;
+
+ // Query and Fence creation
+ QueryImpl *createQuery(gl::QueryType type) override;
+ FenceNVImpl *createFenceNV() override;
+ SyncImpl *createSync() override;
+
+ // Transform Feedback creation
+ TransformFeedbackImpl *createTransformFeedback(
+ const gl::TransformFeedbackState &state) override;
+
+ // Sampler object creation
+ SamplerImpl *createSampler(const gl::SamplerState &state) override;
+
+ // Program Pipeline object creation
+ ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override;
+
+ // Memory object creation.
+ MemoryObjectImpl *createMemoryObject() override;
+
+ // Semaphore creation.
+ SemaphoreImpl *createSemaphore() override;
+
+ // Overlay creation.
+ OverlayImpl *createOverlay(const gl::OverlayState &state) override;
+
+ // Flush and finish.
+ angle::Result flush(const gl::Context *context) override;
+ angle::Result finish(const gl::Context *context) override;
+
+ // Drawing methods.
+ angle::Result drawArrays(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count) override;
+ angle::Result drawArraysInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount) override;
+ angle::Result drawArraysInstancedBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount,
+ GLuint baseInstance) override;
+
+ angle::Result drawElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices) override;
+ angle::Result drawElementsBaseVertex(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLint baseVertex) override;
+ angle::Result drawElementsInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances) override;
+ angle::Result drawElementsInstancedBaseVertex(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances,
+ GLint baseVertex) override;
+ angle::Result drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances,
+ GLint baseVertex,
+ GLuint baseInstance) override;
+ angle::Result drawRangeElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices) override;
+ angle::Result drawRangeElementsBaseVertex(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLint baseVertex) override;
+ angle::Result drawArraysIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const void *indirect) override;
+ angle::Result drawElementsIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType type,
+ const void *indirect) override;
+
+ angle::Result multiDrawArrays(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ GLsizei drawcount) override;
+ angle::Result multiDrawArraysInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount) override;
+ angle::Result multiDrawArraysIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride) override;
+ angle::Result multiDrawElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ GLsizei drawcount) override;
+ angle::Result multiDrawElementsInstanced(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount) override;
+ angle::Result multiDrawElementsIndirect(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType type,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride) override;
+ angle::Result multiDrawArraysInstancedBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ const GLuint *baseInstances,
+ GLsizei drawcount) override;
+ angle::Result multiDrawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount) override;
+
+ // Device loss
+ gl::GraphicsResetStatus getResetStatus() override;
+
+ // EXT_debug_marker
+ angle::Result insertEventMarker(GLsizei length, const char *marker) override;
+ angle::Result pushGroupMarker(GLsizei length, const char *marker) override;
+ angle::Result popGroupMarker() override;
+
+ // KHR_debug
+ angle::Result pushDebugGroup(const gl::Context *context,
+ GLenum source,
+ GLuint id,
+ const std::string &message) override;
+ angle::Result popDebugGroup(const gl::Context *context) override;
+
+ // State sync with dirty bits.
+ angle::Result syncState(const gl::Context *context,
+ const gl::State::DirtyBits &dirtyBits,
+ const gl::State::DirtyBits &bitMask,
+ gl::Command command) override;
+
+ // Disjoint timer queries
+ GLint getGPUDisjoint() override;
+ GLint64 getTimestamp() override;
+
+ // Context switching
+ angle::Result onMakeCurrent(const gl::Context *context) override;
+
+ // Caps queries
+ gl::Caps getNativeCaps() const override;
+ const gl::TextureCapsMap &getNativeTextureCaps() const override;
+ const gl::Extensions &getNativeExtensions() const override;
+ const gl::Limitations &getNativeLimitations() const override;
+ ShPixelLocalStorageType getNativePixelLocalStorageType() const override;
+
+ angle::Result dispatchCompute(const gl::Context *context,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ) override;
+ angle::Result dispatchComputeIndirect(const gl::Context *context, GLintptr indirect) override;
+
+ angle::Result memoryBarrier(const gl::Context *context, GLbitfield barriers) override;
+ angle::Result memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers) override;
+
+ Renderer9 *getRenderer() const { return mRenderer; }
+
+ angle::Result getIncompleteTexture(const gl::Context *context,
+ gl::TextureType type,
+ gl::Texture **textureOut);
+
+ void handleResult(HRESULT hr,
+ const char *message,
+ const char *file,
+ const char *function,
+ unsigned int line) override;
+
+ private:
+ Renderer9 *mRenderer;
+ IncompleteTextureSet mIncompleteTextures;
+ std::stack<std::string> mMarkerStack;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_CONTEXT9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp
new file mode 100644
index 0000000000..7e597e564b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp
@@ -0,0 +1,48 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DebugAnnotator9.h: D3D9 helpers for adding trace annotations.
+//
+
+#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h"
+
+#include "common/platform.h"
+
+namespace rx
+{
+
+void DebugAnnotator9::beginEvent(gl::Context *context,
+ angle::EntryPoint entryPoint,
+ const char *eventName,
+ const char *eventMessage)
+{
+ angle::LoggingAnnotator::beginEvent(context, entryPoint, eventName, eventMessage);
+ std::mbstate_t state = std::mbstate_t();
+ std::mbsrtowcs(mWCharMessage, &eventMessage, kMaxMessageLength, &state);
+ D3DPERF_BeginEvent(0, mWCharMessage);
+}
+
+void DebugAnnotator9::endEvent(gl::Context *context,
+ const char *eventName,
+ angle::EntryPoint entryPoint)
+{
+ angle::LoggingAnnotator::endEvent(context, eventName, entryPoint);
+ D3DPERF_EndEvent();
+}
+
+void DebugAnnotator9::setMarker(gl::Context *context, const char *markerName)
+{
+ angle::LoggingAnnotator::setMarker(context, markerName);
+ std::mbstate_t state = std::mbstate_t();
+ std::mbsrtowcs(mWCharMessage, &markerName, kMaxMessageLength, &state);
+ D3DPERF_SetMarker(0, mWCharMessage);
+}
+
+bool DebugAnnotator9::getStatus(const gl::Context *context)
+{
+ return !!D3DPERF_GetStatus();
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h
new file mode 100644
index 0000000000..40f8189bea
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h
@@ -0,0 +1,38 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DebugAnnotator9.h: D3D9 helpers for adding trace annotations.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_
+
+#include "libANGLE/LoggingAnnotator.h"
+
+namespace rx
+{
+
+class DebugAnnotator9 : public angle::LoggingAnnotator
+{
+ public:
+ DebugAnnotator9() {}
+ void beginEvent(gl::Context *context,
+ angle::EntryPoint entryPoint,
+ const char *eventName,
+ const char *eventMessage) override;
+ void endEvent(gl::Context *context,
+ const char *eventName,
+ angle::EntryPoint entryPoint) override;
+ void setMarker(gl::Context *context, const char *markerName) override;
+ bool getStatus(const gl::Context *context) override;
+
+ private:
+ static constexpr size_t kMaxMessageLength = 256;
+ wchar_t mWCharMessage[kMaxMessageLength];
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp
new file mode 100644
index 0000000000..e844a9ae70
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp
@@ -0,0 +1,73 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Fence9.cpp: Defines the rx::FenceNV9 class.
+
+#include "libANGLE/renderer/d3d/d3d9/Fence9.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/d3d9/Context9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+
+namespace rx
+{
+
+FenceNV9::FenceNV9(Renderer9 *renderer) : FenceNVImpl(), mRenderer(renderer), mQuery(nullptr) {}
+
+FenceNV9::~FenceNV9()
+{
+ SafeRelease(mQuery);
+}
+
+angle::Result FenceNV9::set(const gl::Context *context, GLenum condition)
+{
+ if (!mQuery)
+ {
+ ANGLE_TRY(mRenderer->allocateEventQuery(context, &mQuery));
+ }
+
+ HRESULT result = mQuery->Issue(D3DISSUE_END);
+ if (FAILED(result))
+ {
+ SafeRelease(mQuery);
+ }
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to end event query");
+ return angle::Result::Continue;
+}
+
+angle::Result FenceNV9::test(const gl::Context *context, GLboolean *outFinished)
+{
+ return testHelper(GetImplAs<Context9>(context), true, outFinished);
+}
+
+angle::Result FenceNV9::finish(const gl::Context *context)
+{
+ GLboolean finished = GL_FALSE;
+ while (finished != GL_TRUE)
+ {
+ ANGLE_TRY(testHelper(GetImplAs<Context9>(context), true, &finished));
+ Sleep(0);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result FenceNV9::testHelper(Context9 *context9,
+ bool flushCommandBuffer,
+ GLboolean *outFinished)
+{
+ ASSERT(mQuery);
+
+ DWORD getDataFlags = (flushCommandBuffer ? D3DGETDATA_FLUSH : 0);
+ HRESULT result = mQuery->GetData(nullptr, 0, getDataFlags);
+ ANGLE_TRY_HR(context9, result, "Failed to get query data");
+ ASSERT(result == S_OK || result == S_FALSE);
+ *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE);
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Fence9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Fence9.h
new file mode 100644
index 0000000000..c46671c102
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Fence9.h
@@ -0,0 +1,39 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Fence9.h: Defines the rx::FenceNV9 class which implements rx::FenceNVImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_
+
+#include "libANGLE/renderer/FenceNVImpl.h"
+#include "libANGLE/renderer/SyncImpl.h"
+
+namespace rx
+{
+class Context9;
+class Renderer9;
+
+class FenceNV9 : public FenceNVImpl
+{
+ public:
+ explicit FenceNV9(Renderer9 *renderer);
+ ~FenceNV9() override;
+
+ void onDestroy(const gl::Context *context) override {}
+ angle::Result set(const gl::Context *context, GLenum condition) override;
+ angle::Result test(const gl::Context *context, GLboolean *outFinished) override;
+ angle::Result finish(const gl::Context *context) override;
+
+ private:
+ angle::Result testHelper(Context9 *context9, bool flushCommandBuffer, GLboolean *outFinished);
+
+ Renderer9 *mRenderer;
+ IDirect3DQuery9 *mQuery;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
new file mode 100644
index 0000000000..f90fefac20
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
@@ -0,0 +1,416 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Framebuffer9.cpp: Implements the Framebuffer9 class.
+
+#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace rx
+{
+Framebuffer9::Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer)
+ : FramebufferD3D(data, renderer), mRenderer(renderer)
+{
+ ASSERT(mRenderer != nullptr);
+}
+
+Framebuffer9::~Framebuffer9() {}
+
+angle::Result Framebuffer9::discard(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Framebuffer9::invalidate(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Framebuffer9::invalidateSub(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Framebuffer9::clearImpl(const gl::Context *context,
+ const ClearParameters &clearParams)
+{
+ ANGLE_TRY(mRenderer->applyRenderTarget(context, mRenderTargetCache.getColors()[0],
+ mRenderTargetCache.getDepthStencil()));
+
+ const gl::State &glState = context->getState();
+ float nearZ = glState.getNearPlane();
+ float farZ = glState.getFarPlane();
+ mRenderer->setViewport(glState.getViewport(), nearZ, farZ, gl::PrimitiveMode::Triangles,
+ glState.getRasterizerState().frontFace, true);
+
+ mRenderer->setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
+
+ mRenderer->clear(clearParams, mRenderTargetCache.getColors()[0],
+ mRenderTargetCache.getDepthStencil());
+ return angle::Result::Continue;
+}
+
+angle::Result Framebuffer9::readPixelsImpl(const gl::Context *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ gl::Buffer *packBuffer,
+ uint8_t *pixels)
+{
+ const gl::FramebufferAttachment *colorbuffer = mState.getColorAttachment(0);
+ ASSERT(colorbuffer);
+
+ RenderTarget9 *renderTarget = nullptr;
+ ANGLE_TRY(colorbuffer->getRenderTarget(context, 0, &renderTarget));
+ ASSERT(renderTarget);
+
+ IDirect3DSurface9 *surface = renderTarget->getSurface();
+ ASSERT(surface);
+
+ D3DSURFACE_DESC desc;
+ surface->GetDesc(&desc);
+
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
+ {
+ UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render
+ // target
+ SafeRelease(surface);
+ ANGLE_TRY_HR(context9, E_OUTOFMEMORY,
+ "ReadPixels is unimplemented for multisampled framebuffer attachments.");
+ }
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+ ASSERT(device);
+
+ HRESULT result;
+ IDirect3DSurface9 *systemSurface = nullptr;
+ bool directToPixels =
+ !pack.reverseRowOrder && pack.alignment <= 4 && mRenderer->getShareHandleSupport() &&
+ area.x == 0 && area.y == 0 && static_cast<UINT>(area.width) == desc.Width &&
+ static_cast<UINT>(area.height) == desc.Height && desc.Format == D3DFMT_A8R8G8B8 &&
+ format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
+ if (directToPixels)
+ {
+ // Use the pixels ptr as a shared handle to write directly into client's memory
+ result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+ D3DPOOL_SYSTEMMEM, &systemSurface,
+ reinterpret_cast<void **>(&pixels));
+ if (FAILED(result))
+ {
+ // Try again without the shared handle
+ directToPixels = false;
+ }
+ }
+
+ if (!directToPixels)
+ {
+ result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+ D3DPOOL_SYSTEMMEM, &systemSurface, nullptr);
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ SafeRelease(surface);
+ ANGLE_TRY_HR(context9, E_OUTOFMEMORY,
+ "Failed to allocate internal texture for ReadPixels.");
+ }
+ }
+
+ result = device->GetRenderTargetData(surface, systemSurface);
+ SafeRelease(surface);
+
+ if (FAILED(result))
+ {
+ SafeRelease(systemSurface);
+
+ // It turns out that D3D will sometimes produce more error
+ // codes than those documented.
+ if (d3d9::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ ANGLE_TRY_HR(context9, E_OUTOFMEMORY, "Failed to read internal render target data.");
+ }
+
+ if (directToPixels)
+ {
+ SafeRelease(systemSurface);
+ return angle::Result::Continue;
+ }
+
+ RECT rect;
+ rect.left = gl::clamp(area.x, 0L, static_cast<LONG>(desc.Width));
+ rect.top = gl::clamp(area.y, 0L, static_cast<LONG>(desc.Height));
+ rect.right = gl::clamp(area.x + area.width, 0L, static_cast<LONG>(desc.Width));
+ rect.bottom = gl::clamp(area.y + area.height, 0L, static_cast<LONG>(desc.Height));
+
+ D3DLOCKED_RECT lock;
+ result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
+
+ if (FAILED(result))
+ {
+ UNREACHABLE();
+ SafeRelease(systemSurface);
+
+ ANGLE_TRY_HR(context9, E_OUTOFMEMORY, "Failed to lock internal render target.");
+ }
+
+ uint8_t *source = static_cast<uint8_t *>(lock.pBits);
+ int inputPitch = lock.Pitch;
+
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
+
+ gl::FormatType formatType(format, type);
+
+ PackPixelsParams packParams;
+ packParams.area.x = rect.left;
+ packParams.area.y = rect.top;
+ packParams.area.width = rect.right - rect.left;
+ packParams.area.height = rect.bottom - rect.top;
+ packParams.destFormat = &GetFormatFromFormatType(format, type);
+ packParams.outputPitch = static_cast<GLuint>(outputPitch);
+ packParams.reverseRowOrder = pack.reverseRowOrder;
+
+ PackPixels(packParams, d3dFormatInfo.info(), inputPitch, source, pixels);
+
+ systemSurface->UnlockRect();
+ SafeRelease(systemSurface);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Framebuffer9::blitImpl(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ const gl::Rectangle *scissor,
+ bool blitRenderTarget,
+ bool blitDepth,
+ bool blitStencil,
+ GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer)
+{
+ ASSERT(filter == GL_NEAREST);
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+ ASSERT(device);
+
+ mRenderer->endScene();
+
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ if (blitRenderTarget)
+ {
+ const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getColorAttachment(0);
+ ASSERT(readBuffer);
+
+ RenderTarget9 *readRenderTarget = nullptr;
+ ANGLE_TRY(readBuffer->getRenderTarget(context, 0, &readRenderTarget));
+ ASSERT(readRenderTarget);
+
+ const gl::FramebufferAttachment *drawBuffer = mState.getColorAttachment(0);
+ ASSERT(drawBuffer);
+
+ RenderTarget9 *drawRenderTarget = nullptr;
+ ANGLE_TRY(
+ drawBuffer->getRenderTarget(context, drawBuffer->getSamples(), &drawRenderTarget));
+ ASSERT(drawRenderTarget);
+
+ // The getSurface calls do an AddRef so save them until after no errors are possible
+ IDirect3DSurface9 *readSurface = readRenderTarget->getSurface();
+ ASSERT(readSurface);
+
+ IDirect3DSurface9 *drawSurface = drawRenderTarget->getSurface();
+ ASSERT(drawSurface);
+
+ gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
+ gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
+
+ RECT srcRect;
+ srcRect.left = sourceArea.x;
+ srcRect.right = sourceArea.x + sourceArea.width;
+ srcRect.top = sourceArea.y;
+ srcRect.bottom = sourceArea.y + sourceArea.height;
+
+ RECT dstRect;
+ dstRect.left = destArea.x;
+ dstRect.right = destArea.x + destArea.width;
+ dstRect.top = destArea.y;
+ dstRect.bottom = destArea.y + destArea.height;
+
+ // Clip the rectangles to the scissor rectangle
+ if (scissor)
+ {
+ if (dstRect.left < scissor->x)
+ {
+ srcRect.left += (scissor->x - dstRect.left);
+ dstRect.left = scissor->x;
+ }
+ if (dstRect.top < scissor->y)
+ {
+ srcRect.top += (scissor->y - dstRect.top);
+ dstRect.top = scissor->y;
+ }
+ if (dstRect.right > scissor->x + scissor->width)
+ {
+ srcRect.right -= (dstRect.right - (scissor->x + scissor->width));
+ dstRect.right = scissor->x + scissor->width;
+ }
+ if (dstRect.bottom > scissor->y + scissor->height)
+ {
+ srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height));
+ dstRect.bottom = scissor->y + scissor->height;
+ }
+ }
+
+ // Clip the rectangles to the destination size
+ if (dstRect.left < 0)
+ {
+ srcRect.left += -dstRect.left;
+ dstRect.left = 0;
+ }
+ if (dstRect.right > dstSize.width)
+ {
+ srcRect.right -= (dstRect.right - dstSize.width);
+ dstRect.right = dstSize.width;
+ }
+ if (dstRect.top < 0)
+ {
+ srcRect.top += -dstRect.top;
+ dstRect.top = 0;
+ }
+ if (dstRect.bottom > dstSize.height)
+ {
+ srcRect.bottom -= (dstRect.bottom - dstSize.height);
+ dstRect.bottom = dstSize.height;
+ }
+
+ // Clip the rectangles to the source size
+ if (srcRect.left < 0)
+ {
+ dstRect.left += -srcRect.left;
+ srcRect.left = 0;
+ }
+ if (srcRect.right > srcSize.width)
+ {
+ dstRect.right -= (srcRect.right - srcSize.width);
+ srcRect.right = srcSize.width;
+ }
+ if (srcRect.top < 0)
+ {
+ dstRect.top += -srcRect.top;
+ srcRect.top = 0;
+ }
+ if (srcRect.bottom > srcSize.height)
+ {
+ dstRect.bottom -= (srcRect.bottom - srcSize.height);
+ srcRect.bottom = srcSize.height;
+ }
+
+ HRESULT result =
+ device->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE);
+
+ SafeRelease(readSurface);
+ SafeRelease(drawSurface);
+
+ ANGLE_TRY_HR(context9, result, "Internal blit failed.");
+ }
+
+ if (blitDepth || blitStencil)
+ {
+ const gl::FramebufferAttachment *readBuffer =
+ sourceFramebuffer->getDepthOrStencilAttachment();
+ ASSERT(readBuffer);
+
+ RenderTarget9 *readDepthStencil = nullptr;
+ ANGLE_TRY(readBuffer->getRenderTarget(context, 0, &readDepthStencil));
+ ASSERT(readDepthStencil);
+
+ const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment();
+ ASSERT(drawBuffer);
+
+ RenderTarget9 *drawDepthStencil = nullptr;
+ ANGLE_TRY(
+ drawBuffer->getRenderTarget(context, drawBuffer->getSamples(), &drawDepthStencil));
+ ASSERT(drawDepthStencil);
+
+ // The getSurface calls do an AddRef so save them until after no errors are possible
+ IDirect3DSurface9 *readSurface = readDepthStencil->getSurface();
+ ASSERT(readDepthStencil);
+
+ IDirect3DSurface9 *drawSurface = drawDepthStencil->getSurface();
+ ASSERT(drawDepthStencil);
+
+ HRESULT result =
+ device->StretchRect(readSurface, nullptr, drawSurface, nullptr, D3DTEXF_NONE);
+
+ SafeRelease(readSurface);
+ SafeRelease(drawSurface);
+
+ ANGLE_TRY_HR(context9, result, "Internal blit failed.");
+ }
+
+ return angle::Result::Continue;
+}
+
+const gl::InternalFormat &Framebuffer9::getImplementationColorReadFormat(
+ const gl::Context *context) const
+{
+ GLenum sizedFormat = mState.getReadAttachment()->getFormat().info->sizedInternalFormat;
+ const d3d9::TextureFormat &textureFormat = d3d9::GetTextureFormatInfo(sizedFormat);
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(textureFormat.renderFormat);
+ const angle::Format &angleFormat = angle::Format::Get(d3dFormatInfo.formatID);
+ return gl::GetSizedInternalFormatInfo(angleFormat.fboImplementationInternalFormat);
+}
+
+angle::Result Framebuffer9::getSamplePosition(const gl::Context *context,
+ size_t index,
+ GLfloat *xy) const
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Framebuffer9::syncState(const gl::Context *context,
+ GLenum binding,
+ const gl::Framebuffer::DirtyBits &dirtyBits,
+ gl::Command command)
+{
+ ANGLE_TRY(FramebufferD3D::syncState(context, binding, dirtyBits, command));
+ ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
+ return angle::Result::Continue;
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
new file mode 100644
index 0000000000..a44118ff34
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
@@ -0,0 +1,89 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Framebuffer9.h: Defines the Framebuffer9 class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_
+
+#include "libANGLE/renderer/RenderTargetCache.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+
+namespace rx
+{
+class Renderer9;
+
+class Framebuffer9 : public FramebufferD3D
+{
+ public:
+ Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer);
+ ~Framebuffer9() override;
+
+ angle::Result discard(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments) override;
+ angle::Result invalidate(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments) override;
+ angle::Result invalidateSub(const gl::Context *context,
+ size_t count,
+ const GLenum *attachments,
+ const gl::Rectangle &area) override;
+
+ angle::Result getSamplePosition(const gl::Context *context,
+ size_t index,
+ GLfloat *xy) const override;
+
+ angle::Result syncState(const gl::Context *context,
+ GLenum binding,
+ const gl::Framebuffer::DirtyBits &dirtyBits,
+ gl::Command command) override;
+
+ const gl::AttachmentArray<RenderTarget9 *> &getCachedColorRenderTargets() const
+ {
+ return mRenderTargetCache.getColors();
+ }
+
+ const RenderTarget9 *getCachedDepthStencilRenderTarget() const
+ {
+ return mRenderTargetCache.getDepthStencil();
+ }
+
+ const gl::InternalFormat &getImplementationColorReadFormat(
+ const gl::Context *context) const override;
+
+ private:
+ angle::Result clearImpl(const gl::Context *context,
+ const ClearParameters &clearParams) override;
+
+ angle::Result readPixelsImpl(const gl::Context *context,
+ const gl::Rectangle &area,
+ GLenum format,
+ GLenum type,
+ size_t outputPitch,
+ const gl::PixelPackState &pack,
+ gl::Buffer *packPixels,
+ uint8_t *pixels) override;
+
+ angle::Result blitImpl(const gl::Context *context,
+ const gl::Rectangle &sourceArea,
+ const gl::Rectangle &destArea,
+ const gl::Rectangle *scissor,
+ bool blitRenderTarget,
+ bool blitDepth,
+ bool blitStencil,
+ GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer) override;
+
+ Renderer9 *const mRenderer;
+
+ RenderTargetCache<RenderTarget9> mRenderTargetCache;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Image9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
new file mode 100644
index 0000000000..229d54ced9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
@@ -0,0 +1,907 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image9.cpp: Implements the rx::Image9 class, which acts as the interface to
+// the actual underlying surfaces of a Texture.
+
+#include "libANGLE/renderer/d3d/d3d9/Image9.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/copyvertex.h"
+#include "libANGLE/renderer/d3d/d3d9/Context9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+
+namespace rx
+{
+
+Image9::Image9(Renderer9 *renderer)
+{
+ mSurface = nullptr;
+ mRenderer = nullptr;
+
+ mD3DPool = D3DPOOL_SYSTEMMEM;
+ mD3DFormat = D3DFMT_UNKNOWN;
+
+ mRenderer = renderer;
+}
+
+Image9::~Image9()
+{
+ SafeRelease(mSurface);
+}
+
+// static
+angle::Result Image9::GenerateMip(Context9 *context9,
+ IDirect3DSurface9 *destSurface,
+ IDirect3DSurface9 *sourceSurface)
+{
+ D3DSURFACE_DESC destDesc;
+ HRESULT result = destSurface->GetDesc(&destDesc);
+ ASSERT(SUCCEEDED(result));
+ ANGLE_TRY_HR(context9, result,
+ "Failed to query the source surface description for mipmap generation");
+
+ D3DSURFACE_DESC sourceDesc;
+ result = sourceSurface->GetDesc(&sourceDesc);
+ ASSERT(SUCCEEDED(result));
+ ANGLE_TRY_HR(context9, result,
+ "Failed to query the destination surface description for mipmap generation");
+
+ ASSERT(sourceDesc.Format == destDesc.Format);
+ ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width);
+ ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height);
+
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(sourceDesc.Format);
+ ASSERT(d3dFormatInfo.info().mipGenerationFunction != nullptr);
+
+ D3DLOCKED_RECT sourceLocked = {};
+ result = sourceSurface->LockRect(&sourceLocked, nullptr, D3DLOCK_READONLY);
+ ASSERT(SUCCEEDED(result));
+ ANGLE_TRY_HR(context9, result, "Failed to lock the source surface for mipmap generation");
+
+ D3DLOCKED_RECT destLocked = {};
+ result = destSurface->LockRect(&destLocked, nullptr, 0);
+ ASSERT(SUCCEEDED(result));
+ ANGLE_TRY_HR(context9, result, "Failed to lock the destination surface for mipmap generation");
+
+ const uint8_t *sourceData = static_cast<const uint8_t *>(sourceLocked.pBits);
+ uint8_t *destData = static_cast<uint8_t *>(destLocked.pBits);
+
+ ASSERT(sourceData && destData);
+
+ d3dFormatInfo.info().mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData,
+ sourceLocked.Pitch, 0, destData, destLocked.Pitch,
+ 0);
+
+ destSurface->UnlockRect();
+ sourceSurface->UnlockRect();
+
+ return angle::Result::Continue;
+}
+
+// static
+angle::Result Image9::GenerateMipmap(Context9 *context9, Image9 *dest, Image9 *source)
+{
+ IDirect3DSurface9 *sourceSurface = nullptr;
+ ANGLE_TRY(source->getSurface(context9, &sourceSurface));
+
+ IDirect3DSurface9 *destSurface = nullptr;
+ ANGLE_TRY(dest->getSurface(context9, &destSurface));
+
+ ANGLE_TRY(GenerateMip(context9, destSurface, sourceSurface));
+
+ dest->markDirty();
+
+ return angle::Result::Continue;
+}
+
+// static
+angle::Result Image9::CopyLockableSurfaces(Context9 *context9,
+ IDirect3DSurface9 *dest,
+ IDirect3DSurface9 *source)
+{
+ D3DLOCKED_RECT sourceLock = {};
+ D3DLOCKED_RECT destLock = {};
+
+ HRESULT result;
+
+ result = source->LockRect(&sourceLock, nullptr, 0);
+ ANGLE_TRY_HR(context9, result, "Failed to lock source surface for copy");
+
+ result = dest->LockRect(&destLock, nullptr, 0);
+ if (FAILED(result))
+ {
+ source->UnlockRect();
+ }
+ ANGLE_TRY_HR(context9, result, "Failed to lock destination surface for copy");
+
+ ASSERT(sourceLock.pBits && destLock.pBits);
+
+ D3DSURFACE_DESC desc;
+ source->GetDesc(&desc);
+
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
+ unsigned int rows = desc.Height / d3dFormatInfo.blockHeight;
+
+ unsigned int bytes = d3d9::ComputeBlockSize(desc.Format, desc.Width, d3dFormatInfo.blockHeight);
+ ASSERT(bytes <= static_cast<unsigned int>(sourceLock.Pitch) &&
+ bytes <= static_cast<unsigned int>(destLock.Pitch));
+
+ for (unsigned int i = 0; i < rows; i++)
+ {
+ memcpy((char *)destLock.pBits + destLock.Pitch * i,
+ (char *)sourceLock.pBits + sourceLock.Pitch * i, bytes);
+ }
+
+ source->UnlockRect();
+ dest->UnlockRect();
+
+ return angle::Result::Continue;
+}
+
+// static
+angle::Result Image9::CopyImage(const gl::Context *context,
+ Image9 *dest,
+ Image9 *source,
+ const gl::Rectangle &sourceRect,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ IDirect3DSurface9 *sourceSurface = nullptr;
+ ANGLE_TRY(source->getSurface(context9, &sourceSurface));
+
+ IDirect3DSurface9 *destSurface = nullptr;
+ ANGLE_TRY(dest->getSurface(context9, &destSurface));
+
+ D3DSURFACE_DESC destDesc;
+ HRESULT result = destSurface->GetDesc(&destDesc);
+ ASSERT(SUCCEEDED(result));
+ ANGLE_TRY_HR(context9, result, "Failed to query the source surface description for CopyImage");
+ const d3d9::D3DFormat &destD3DFormatInfo = d3d9::GetD3DFormatInfo(destDesc.Format);
+
+ D3DSURFACE_DESC sourceDesc;
+ result = sourceSurface->GetDesc(&sourceDesc);
+ ASSERT(SUCCEEDED(result));
+ ANGLE_TRY_HR(context9, result,
+ "Failed to query the destination surface description for CopyImage");
+ const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(sourceDesc.Format);
+
+ D3DLOCKED_RECT sourceLocked = {};
+ result = sourceSurface->LockRect(&sourceLocked, nullptr, D3DLOCK_READONLY);
+ ASSERT(SUCCEEDED(result));
+ ANGLE_TRY_HR(context9, result, "Failed to lock the source surface for CopyImage");
+
+ D3DLOCKED_RECT destLocked = {};
+ result = destSurface->LockRect(&destLocked, nullptr, 0);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
+ {
+ sourceSurface->UnlockRect();
+ }
+ ANGLE_TRY_HR(context9, result, "Failed to lock the destination surface for CopyImage");
+
+ const uint8_t *sourceData = static_cast<const uint8_t *>(sourceLocked.pBits) +
+ sourceRect.x * sourceD3DFormatInfo.pixelBytes +
+ sourceRect.y * sourceLocked.Pitch;
+ uint8_t *destData = static_cast<uint8_t *>(destLocked.pBits) +
+ destOffset.x * destD3DFormatInfo.pixelBytes +
+ destOffset.y * destLocked.Pitch;
+ ASSERT(sourceData && destData);
+
+ CopyImageCHROMIUM(sourceData, sourceLocked.Pitch, sourceD3DFormatInfo.pixelBytes, 0,
+ sourceD3DFormatInfo.info().pixelReadFunction, destData, destLocked.Pitch,
+ destD3DFormatInfo.pixelBytes, 0, destD3DFormatInfo.info().pixelWriteFunction,
+ gl::GetUnsizedFormat(dest->getInternalFormat()),
+ destD3DFormatInfo.info().componentType, sourceRect.width, sourceRect.height,
+ 1, unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+
+ dest->markDirty();
+
+ destSurface->UnlockRect();
+ sourceSurface->UnlockRect();
+
+ return angle::Result::Continue;
+}
+
+bool Image9::redefine(gl::TextureType type,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease)
+{
+ // 3D textures are not supported by the D3D9 backend.
+ ASSERT(size.depth <= 1);
+
+ // Only 2D and cube texture are supported by the D3D9 backend.
+ ASSERT(type == gl::TextureType::_2D || type == gl::TextureType::CubeMap);
+
+ if (mWidth != size.width || mHeight != size.height || mDepth != size.depth ||
+ mInternalFormat != internalformat || forceRelease)
+ {
+ mWidth = size.width;
+ mHeight = size.height;
+ mDepth = size.depth;
+ mType = type;
+ mInternalFormat = internalformat;
+
+ // compute the d3d format that will be used
+ const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalformat);
+ mD3DFormat = d3d9FormatInfo.texFormat;
+ mRenderable = (d3d9FormatInfo.renderFormat != D3DFMT_UNKNOWN);
+
+ SafeRelease(mSurface);
+ mDirty = (d3d9FormatInfo.dataInitializerFunction != nullptr);
+
+ return true;
+ }
+
+ return false;
+}
+
+angle::Result Image9::createSurface(Context9 *context9)
+{
+ if (mSurface)
+ {
+ return angle::Result::Continue;
+ }
+
+ IDirect3DTexture9 *newTexture = nullptr;
+ IDirect3DSurface9 *newSurface = nullptr;
+ const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM;
+ const D3DFORMAT d3dFormat = getD3DFormat();
+
+ if (mWidth != 0 && mHeight != 0)
+ {
+ int levelToFetch = 0;
+ GLsizei requestWidth = mWidth;
+ GLsizei requestHeight = mHeight;
+ d3d9::MakeValidSize(true, d3dFormat, &requestWidth, &requestHeight, &levelToFetch);
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0,
+ d3dFormat, poolToUse, &newTexture, nullptr);
+
+ ANGLE_TRY_HR(context9, result, "Failed to create image surface");
+
+ newTexture->GetSurfaceLevel(levelToFetch, &newSurface);
+ SafeRelease(newTexture);
+
+ const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
+ if (d3dFormatInfo.dataInitializerFunction != nullptr)
+ {
+ RECT entireRect;
+ entireRect.left = 0;
+ entireRect.right = mWidth;
+ entireRect.top = 0;
+ entireRect.bottom = mHeight;
+
+ D3DLOCKED_RECT lockedRect;
+ result = newSurface->LockRect(&lockedRect, &entireRect, 0);
+ ASSERT(SUCCEEDED(result));
+ ANGLE_TRY_HR(context9, result, "Failed to lock image surface");
+
+ d3dFormatInfo.dataInitializerFunction(
+ mWidth, mHeight, 1, static_cast<uint8_t *>(lockedRect.pBits), lockedRect.Pitch, 0);
+
+ result = newSurface->UnlockRect();
+ ASSERT(SUCCEEDED(result));
+ ANGLE_TRY_HR(context9, result, "Failed to unlock image surface");
+ }
+ }
+
+ mSurface = newSurface;
+ mDirty = false;
+ mD3DPool = poolToUse;
+
+ return angle::Result::Continue;
+}
+
+angle::Result Image9::lock(Context9 *context9, D3DLOCKED_RECT *lockedRect, const RECT &rect)
+{
+ ANGLE_TRY(createSurface(context9));
+
+ if (mSurface)
+ {
+ HRESULT result = mSurface->LockRect(lockedRect, &rect, 0);
+ ASSERT(SUCCEEDED(result));
+ ANGLE_TRY_HR(context9, result, "Failed to lock image surface");
+ mDirty = true;
+ }
+
+ return angle::Result::Continue;
+}
+
+void Image9::unlock()
+{
+ if (mSurface)
+ {
+ HRESULT result = mSurface->UnlockRect();
+ ASSERT(SUCCEEDED(result));
+ }
+}
+
+D3DFORMAT Image9::getD3DFormat() const
+{
+ // this should only happen if the image hasn't been redefined first
+ // which would be a bug by the caller
+ ASSERT(mD3DFormat != D3DFMT_UNKNOWN);
+
+ return mD3DFormat;
+}
+
+bool Image9::isDirty() const
+{
+ // Make sure to that this image is marked as dirty even if the staging texture hasn't been
+ // created yet if initialization is required before use.
+ return (mSurface ||
+ d3d9::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != nullptr) &&
+ mDirty;
+}
+
+angle::Result Image9::getSurface(Context9 *context9, IDirect3DSurface9 **outSurface)
+{
+ ANGLE_TRY(createSurface(context9));
+ *outSurface = mSurface;
+ return angle::Result::Continue;
+}
+
+angle::Result Image9::setManagedSurface2D(const gl::Context *context,
+ TextureStorage *storage,
+ int level)
+{
+ IDirect3DSurface9 *surface = nullptr;
+ TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
+ ANGLE_TRY(storage9->getSurfaceLevel(context, gl::TextureTarget::_2D, level, false, &surface));
+ return setManagedSurface(GetImplAs<Context9>(context), surface);
+}
+
+angle::Result Image9::setManagedSurfaceCube(const gl::Context *context,
+ TextureStorage *storage,
+ int face,
+ int level)
+{
+ IDirect3DSurface9 *surface = nullptr;
+ TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
+ ANGLE_TRY(storage9->getSurfaceLevel(context, gl::CubeFaceIndexToTextureTarget(face), level,
+ false, &surface));
+ return setManagedSurface(GetImplAs<Context9>(context), surface);
+}
+
+angle::Result Image9::setManagedSurface(Context9 *context9, IDirect3DSurface9 *surface)
+{
+ D3DSURFACE_DESC desc;
+ surface->GetDesc(&desc);
+ ASSERT(desc.Pool == D3DPOOL_MANAGED);
+
+ if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight)
+ {
+ if (mSurface)
+ {
+ angle::Result result = CopyLockableSurfaces(context9, surface, mSurface);
+ SafeRelease(mSurface);
+ ANGLE_TRY(result);
+ }
+
+ mSurface = surface;
+ mD3DPool = desc.Pool;
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Image9::copyToStorage(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::ImageIndex &index,
+ const gl::Box &region)
+{
+ ANGLE_TRY(createSurface(GetImplAs<Context9>(context)));
+
+ TextureStorage9 *storage9 = GetAs<TextureStorage9>(storage);
+ IDirect3DSurface9 *destSurface = nullptr;
+ ANGLE_TRY(storage9->getSurfaceLevel(context, index.getTarget(), index.getLevelIndex(), true,
+ &destSurface));
+
+ angle::Result result = copyToSurface(GetImplAs<Context9>(context), destSurface, region);
+ SafeRelease(destSurface);
+ return result;
+}
+
+angle::Result Image9::copyToSurface(Context9 *context9,
+ IDirect3DSurface9 *destSurface,
+ const gl::Box &area)
+{
+ ASSERT(area.width > 0 && area.height > 0 && area.depth == 1);
+ ASSERT(destSurface);
+
+ IDirect3DSurface9 *sourceSurface = nullptr;
+ ANGLE_TRY(getSurface(context9, &sourceSurface));
+
+ ASSERT(sourceSurface && sourceSurface != destSurface);
+
+ RECT rect;
+ rect.left = area.x;
+ rect.top = area.y;
+ rect.right = area.x + area.width;
+ rect.bottom = area.y + area.height;
+
+ POINT point = {rect.left, rect.top};
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ if (mD3DPool == D3DPOOL_MANAGED)
+ {
+ D3DSURFACE_DESC desc;
+ sourceSurface->GetDesc(&desc);
+
+ IDirect3DSurface9 *surf = 0;
+ HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+ D3DPOOL_SYSTEMMEM, &surf, nullptr);
+ ANGLE_TRY_HR(context9, result, "Internal CreateOffscreenPlainSurface call failed");
+
+ auto err = CopyLockableSurfaces(context9, surf, sourceSurface);
+ result = device->UpdateSurface(surf, &rect, destSurface, &point);
+ SafeRelease(surf);
+ ANGLE_TRY(err);
+ ASSERT(SUCCEEDED(result));
+ ANGLE_TRY_HR(context9, result, "Internal UpdateSurface call failed");
+ }
+ else
+ {
+ // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools
+ HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point);
+ ASSERT(SUCCEEDED(result));
+ ANGLE_TRY_HR(context9, result, "Internal UpdateSurface call failed");
+ }
+
+ return angle::Result::Continue;
+}
+
+// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as
+// format/type at input into the target pixel rectangle.
+angle::Result Image9::loadData(const gl::Context *context,
+ const gl::Box &area,
+ const gl::PixelUnpackState &unpack,
+ GLenum type,
+ const void *input,
+ bool applySkipImages)
+{
+ // 3D textures are not supported by the D3D9 backend.
+ ASSERT(area.z == 0 && area.depth == 1);
+
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
+ GLuint inputRowPitch = 0;
+ ANGLE_CHECK_GL_MATH(context9, formatInfo.computeRowPitch(type, area.width, unpack.alignment,
+ unpack.rowLength, &inputRowPitch));
+ ASSERT(!applySkipImages);
+ ASSERT(unpack.skipPixels == 0);
+ ASSERT(unpack.skipRows == 0);
+
+ const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
+ ASSERT(d3dFormatInfo.loadFunction != nullptr);
+
+ RECT lockRect = {area.x, area.y, area.x + area.width, area.y + area.height};
+
+ D3DLOCKED_RECT locked;
+ ANGLE_TRY(lock(GetImplAs<Context9>(context), &locked, lockRect));
+
+ d3dFormatInfo.loadFunction(area.width, area.height, area.depth,
+ static_cast<const uint8_t *>(input), inputRowPitch, 0,
+ static_cast<uint8_t *>(locked.pBits), locked.Pitch, 0);
+
+ unlock();
+
+ return angle::Result::Continue;
+}
+
+angle::Result Image9::loadCompressedData(const gl::Context *context,
+ const gl::Box &area,
+ const void *input)
+{
+ // 3D textures are not supported by the D3D9 backend.
+ ASSERT(area.z == 0 && area.depth == 1);
+
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat);
+ GLuint inputRowPitch = 0;
+ ANGLE_CHECK_GL_MATH(
+ context9, formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0, &inputRowPitch));
+
+ GLuint inputDepthPitch = 0;
+ ANGLE_CHECK_GL_MATH(
+ context9, formatInfo.computeDepthPitch(area.height, 0, inputRowPitch, &inputDepthPitch));
+
+ const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
+
+ ASSERT(area.x % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0);
+ ASSERT(area.y % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0);
+
+ ASSERT(d3d9FormatInfo.loadFunction != nullptr);
+
+ RECT lockRect = {area.x, area.y, area.x + area.width, area.y + area.height};
+
+ D3DLOCKED_RECT locked;
+ ANGLE_TRY(lock(GetImplAs<Context9>(context), &locked, lockRect));
+
+ d3d9FormatInfo.loadFunction(area.width, area.height, area.depth,
+ static_cast<const uint8_t *>(input), inputRowPitch, inputDepthPitch,
+ static_cast<uint8_t *>(locked.pBits), locked.Pitch, 0);
+
+ unlock();
+
+ return angle::Result::Continue;
+}
+
+// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete
+// textures
+angle::Result Image9::copyFromRTInternal(Context9 *context9,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ RenderTargetD3D *source)
+{
+ ASSERT(source);
+
+ // ES3.0 only behaviour to copy into a 3d texture
+ ASSERT(destOffset.z == 0);
+
+ RenderTarget9 *renderTarget = GetAs<RenderTarget9>(source);
+
+ angle::ComPtr<IDirect3DSurface9> surface = renderTarget->getSurface();
+ ASSERT(surface);
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ angle::ComPtr<IDirect3DSurface9> renderTargetData = nullptr;
+ D3DSURFACE_DESC description;
+ surface->GetDesc(&description);
+
+ HRESULT hr = device->CreateOffscreenPlainSurface(description.Width, description.Height,
+ description.Format, D3DPOOL_SYSTEMMEM,
+ &renderTargetData, nullptr);
+
+ ANGLE_TRY_HR(context9, hr, "Could not create matching destination surface");
+
+ hr = device->GetRenderTargetData(surface.Get(), renderTargetData.Get());
+
+ ANGLE_TRY_HR(context9, hr, "GetRenderTargetData unexpectedly failed");
+
+ int width = sourceArea.width;
+ int height = sourceArea.height;
+
+ RECT sourceRect = {sourceArea.x, sourceArea.y, sourceArea.x + width, sourceArea.y + height};
+ RECT destRect = {destOffset.x, destOffset.y, destOffset.x + width, destOffset.y + height};
+
+ D3DLOCKED_RECT sourceLock = {};
+ hr = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
+
+ ANGLE_TRY_HR(context9, hr, "Failed to lock the source surface (rectangle might be invalid)");
+
+ D3DLOCKED_RECT destLock = {};
+ angle::Result result = lock(context9, &destLock, destRect);
+ if (result == angle::Result::Stop)
+ {
+ renderTargetData->UnlockRect();
+ }
+ ANGLE_TRY(result);
+
+ ASSERT(destLock.pBits && sourceLock.pBits);
+
+ unsigned char *sourcePixels = (unsigned char *)sourceLock.pBits;
+ unsigned char *destPixels = (unsigned char *)destLock.pBits;
+
+ switch (description.Format)
+ {
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A8R8G8B8:
+ switch (getD3DFormat())
+ {
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A8R8G8B8:
+ for (int y = 0; y < height; y++)
+ {
+ memcpy(destPixels, sourcePixels, 4 * width);
+ sourcePixels += sourceLock.Pitch;
+ destPixels += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_L8:
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ destPixels[x] = sourcePixels[x * 4 + 2];
+ }
+ sourcePixels += sourceLock.Pitch;
+ destPixels += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_A8L8:
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ destPixels[x * 2 + 0] = sourcePixels[x * 4 + 2];
+ destPixels[x * 2 + 1] = sourcePixels[x * 4 + 3];
+ }
+ sourcePixels += sourceLock.Pitch;
+ destPixels += destLock.Pitch;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+ case D3DFMT_R5G6B5:
+ switch (getD3DFormat())
+ {
+ case D3DFMT_X8R8G8B8:
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ unsigned short rgb = ((unsigned short *)sourcePixels)[x];
+ unsigned char red = static_cast<unsigned char>((rgb & 0xF800) >> 8);
+ unsigned char green = static_cast<unsigned char>((rgb & 0x07E0) >> 3);
+ unsigned char blue = static_cast<unsigned char>((rgb & 0x001F) << 3);
+ destPixels[x + 0] = blue | (blue >> 5);
+ destPixels[x + 1] = green | (green >> 6);
+ destPixels[x + 2] = red | (red >> 5);
+ destPixels[x + 3] = 0xFF;
+ }
+ sourcePixels += sourceLock.Pitch;
+ destPixels += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_L8:
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ unsigned char red = sourcePixels[x * 2 + 1] & 0xF8;
+ destPixels[x] = red | (red >> 5);
+ }
+ sourcePixels += sourceLock.Pitch;
+ destPixels += destLock.Pitch;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+ case D3DFMT_A1R5G5B5:
+ switch (getD3DFormat())
+ {
+ case D3DFMT_X8R8G8B8:
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ unsigned short argb = ((unsigned short *)sourcePixels)[x];
+ unsigned char red = static_cast<unsigned char>((argb & 0x7C00) >> 7);
+ unsigned char green = static_cast<unsigned char>((argb & 0x03E0) >> 2);
+ unsigned char blue = static_cast<unsigned char>((argb & 0x001F) << 3);
+ destPixels[x + 0] = blue | (blue >> 5);
+ destPixels[x + 1] = green | (green >> 5);
+ destPixels[x + 2] = red | (red >> 5);
+ destPixels[x + 3] = 0xFF;
+ }
+ sourcePixels += sourceLock.Pitch;
+ destPixels += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_A8R8G8B8:
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ unsigned short argb = ((unsigned short *)sourcePixels)[x];
+ unsigned char red = static_cast<unsigned char>((argb & 0x7C00) >> 7);
+ unsigned char green = static_cast<unsigned char>((argb & 0x03E0) >> 2);
+ unsigned char blue = static_cast<unsigned char>((argb & 0x001F) << 3);
+ unsigned char alpha = (signed short)argb >> 15;
+ destPixels[x + 0] = blue | (blue >> 5);
+ destPixels[x + 1] = green | (green >> 5);
+ destPixels[x + 2] = red | (red >> 5);
+ destPixels[x + 3] = alpha;
+ }
+ sourcePixels += sourceLock.Pitch;
+ destPixels += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_L8:
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ unsigned char red = sourcePixels[x * 2 + 1] & 0x7C;
+ destPixels[x] = (red << 1) | (red >> 4);
+ }
+ sourcePixels += sourceLock.Pitch;
+ destPixels += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_A8L8:
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ unsigned char red = sourcePixels[x * 2 + 1] & 0x7C;
+ destPixels[x * 2 + 0] = (red << 1) | (red >> 4);
+ destPixels[x * 2 + 1] = (signed char)sourcePixels[x * 2 + 1] >> 7;
+ }
+ sourcePixels += sourceLock.Pitch;
+ destPixels += destLock.Pitch;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+ case D3DFMT_A16B16G16R16F:
+ switch (getD3DFormat())
+ {
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A8R8G8B8:
+ for (int y = 0; y < height; y++)
+ {
+ const uint16_t *sourcePixels16F =
+ reinterpret_cast<uint16_t *>(sourcePixels);
+ for (int x = 0; x < width; x++)
+ {
+ float r = gl::float16ToFloat32(sourcePixels16F[x * 4 + 0]);
+ float g = gl::float16ToFloat32(sourcePixels16F[x * 4 + 1]);
+ float b = gl::float16ToFloat32(sourcePixels16F[x * 4 + 2]);
+ float a = gl::float16ToFloat32(sourcePixels16F[x * 4 + 3]);
+ destPixels[x * 4 + 0] = gl::floatToNormalized<uint8_t>(b);
+ destPixels[x * 4 + 1] = gl::floatToNormalized<uint8_t>(g);
+ destPixels[x * 4 + 2] = gl::floatToNormalized<uint8_t>(r);
+ destPixels[x * 4 + 3] = gl::floatToNormalized<uint8_t>(a);
+ }
+ sourcePixels += sourceLock.Pitch;
+ destPixels += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_L8:
+ for (int y = 0; y < height; y++)
+ {
+ const uint16_t *sourcePixels16F =
+ reinterpret_cast<uint16_t *>(sourcePixels);
+ for (int x = 0; x < width; x++)
+ {
+ float r = gl::float16ToFloat32(sourcePixels16F[x * 4]);
+ destPixels[x] = gl::floatToNormalized<uint8_t>(r);
+ }
+ sourcePixels += sourceLock.Pitch;
+ destPixels += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_A8L8:
+ for (int y = 0; y < height; y++)
+ {
+ const uint16_t *sourcePixels16F =
+ reinterpret_cast<uint16_t *>(sourcePixels);
+ for (int x = 0; x < width; x++)
+ {
+ float r = gl::float16ToFloat32(sourcePixels16F[x * 4 + 0]);
+ float a = gl::float16ToFloat32(sourcePixels16F[x * 4 + 3]);
+ destPixels[x * 2 + 0] = gl::floatToNormalized<uint8_t>(r);
+ destPixels[x * 2 + 1] = gl::floatToNormalized<uint8_t>(a);
+ }
+ sourcePixels += sourceLock.Pitch;
+ destPixels += destLock.Pitch;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+ case D3DFMT_A32B32G32R32F:
+ switch (getD3DFormat())
+ {
+ case D3DFMT_X8R8G8B8:
+ case D3DFMT_A8R8G8B8:
+ for (int y = 0; y < height; y++)
+ {
+ const float *sourcePixels32F = reinterpret_cast<float *>(sourcePixels);
+ for (int x = 0; x < width; x++)
+ {
+ float r = sourcePixels32F[x * 4 + 0];
+ float g = sourcePixels32F[x * 4 + 1];
+ float b = sourcePixels32F[x * 4 + 2];
+ float a = sourcePixels32F[x * 4 + 3];
+ destPixels[x * 4 + 0] = gl::floatToNormalized<uint8_t>(b);
+ destPixels[x * 4 + 1] = gl::floatToNormalized<uint8_t>(g);
+ destPixels[x * 4 + 2] = gl::floatToNormalized<uint8_t>(r);
+ destPixels[x * 4 + 3] = gl::floatToNormalized<uint8_t>(a);
+ }
+ sourcePixels += sourceLock.Pitch;
+ destPixels += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_L8:
+ for (int y = 0; y < height; y++)
+ {
+ const float *sourcePixels32F = reinterpret_cast<float *>(sourcePixels);
+ for (int x = 0; x < width; x++)
+ {
+ float r = sourcePixels32F[x * 4];
+ destPixels[x] = gl::floatToNormalized<uint8_t>(r);
+ }
+ sourcePixels += sourceLock.Pitch;
+ destPixels += destLock.Pitch;
+ }
+ break;
+ case D3DFMT_A8L8:
+ for (int y = 0; y < height; y++)
+ {
+ const float *sourcePixels32F = reinterpret_cast<float *>(sourcePixels);
+ for (int x = 0; x < width; x++)
+ {
+ float r = sourcePixels32F[x * 4 + 0];
+ float a = sourcePixels32F[x * 4 + 3];
+ destPixels[x * 2 + 0] = gl::floatToNormalized<uint8_t>(r);
+ destPixels[x * 2 + 1] = gl::floatToNormalized<uint8_t>(a);
+ }
+ sourcePixels += sourceLock.Pitch;
+ destPixels += destLock.Pitch;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ unlock();
+ renderTargetData->UnlockRect();
+
+ mDirty = true;
+ return angle::Result::Continue;
+}
+
+angle::Result Image9::copyFromTexStorage(const gl::Context *context,
+ const gl::ImageIndex &imageIndex,
+ TextureStorage *source)
+{
+ RenderTargetD3D *renderTarget = nullptr;
+ ANGLE_TRY(source->getRenderTarget(context, imageIndex, 0, &renderTarget));
+
+ gl::Rectangle sourceArea(0, 0, mWidth, mHeight);
+ return copyFromRTInternal(GetImplAs<Context9>(context), gl::Offset(), sourceArea, renderTarget);
+}
+
+angle::Result Image9::copyFromFramebuffer(const gl::Context *context,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
+{
+ const gl::FramebufferAttachment *srcAttachment = source->getReadColorAttachment();
+ ASSERT(srcAttachment);
+
+ RenderTargetD3D *renderTarget = nullptr;
+ ANGLE_TRY(srcAttachment->getRenderTarget(context, 0, &renderTarget));
+ ASSERT(renderTarget);
+ return copyFromRTInternal(GetImplAs<Context9>(context), destOffset, sourceArea, renderTarget);
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Image9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Image9.h
new file mode 100644
index 0000000000..80064aa24b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Image9.h
@@ -0,0 +1,112 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image9.h: Defines the rx::Image9 class, which acts as the interface to
+// the actual underlying surfaces of a Texture.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_
+
+#include "common/debug.h"
+#include "libANGLE/renderer/d3d/ImageD3D.h"
+
+namespace gl
+{
+class Framebuffer;
+}
+
+namespace rx
+{
+class Context9;
+class Renderer9;
+
+class Image9 : public ImageD3D
+{
+ public:
+ Image9(Renderer9 *renderer);
+ ~Image9() override;
+
+ static angle::Result GenerateMipmap(Context9 *context9, Image9 *dest, Image9 *source);
+ static angle::Result GenerateMip(Context9 *context9,
+ IDirect3DSurface9 *destSurface,
+ IDirect3DSurface9 *sourceSurface);
+ static angle::Result CopyLockableSurfaces(Context9 *context9,
+ IDirect3DSurface9 *dest,
+ IDirect3DSurface9 *source);
+ static angle::Result CopyImage(const gl::Context *context,
+ Image9 *dest,
+ Image9 *source,
+ const gl::Rectangle &sourceRect,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha);
+
+ bool redefine(gl::TextureType type,
+ GLenum internalformat,
+ const gl::Extents &size,
+ bool forceRelease) override;
+
+ D3DFORMAT getD3DFormat() const;
+
+ bool isDirty() const override;
+
+ angle::Result setManagedSurface2D(const gl::Context *context,
+ TextureStorage *storage,
+ int level) override;
+ angle::Result setManagedSurfaceCube(const gl::Context *context,
+ TextureStorage *storage,
+ int face,
+ int level) override;
+ angle::Result copyToStorage(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::ImageIndex &index,
+ const gl::Box &region) override;
+
+ angle::Result loadData(const gl::Context *context,
+ const gl::Box &area,
+ const gl::PixelUnpackState &unpack,
+ GLenum type,
+ const void *input,
+ bool applySkipImages) override;
+ angle::Result loadCompressedData(const gl::Context *context,
+ const gl::Box &area,
+ const void *input) override;
+
+ angle::Result copyFromTexStorage(const gl::Context *context,
+ const gl::ImageIndex &imageIndex,
+ TextureStorage *source) override;
+ angle::Result copyFromFramebuffer(const gl::Context *context,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ private:
+ angle::Result getSurface(Context9 *context9, IDirect3DSurface9 **outSurface);
+
+ angle::Result createSurface(Context9 *context9);
+ angle::Result setManagedSurface(Context9 *context9, IDirect3DSurface9 *surface);
+ angle::Result copyToSurface(Context9 *context9, IDirect3DSurface9 *dest, const gl::Box &area);
+
+ angle::Result lock(Context9 *context9, D3DLOCKED_RECT *lockedRect, const RECT &rect);
+ void unlock();
+
+ angle::Result copyFromRTInternal(Context9 *context9,
+ const gl::Offset &destOffset,
+ const gl::Rectangle &sourceArea,
+ RenderTargetD3D *source);
+
+ Renderer9 *mRenderer;
+
+ D3DPOOL mD3DPool; // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be
+ // lockable.
+ D3DFORMAT mD3DFormat;
+
+ IDirect3DSurface9 *mSurface;
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp
new file mode 100644
index 0000000000..26bae3bdb8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp
@@ -0,0 +1,161 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation.
+
+#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+namespace rx
+{
+
+IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer)
+{
+ mIndexBuffer = nullptr;
+ mBufferSize = 0;
+ mIndexType = gl::DrawElementsType::InvalidEnum;
+ mDynamic = false;
+}
+
+IndexBuffer9::~IndexBuffer9()
+{
+ SafeRelease(mIndexBuffer);
+}
+
+angle::Result IndexBuffer9::initialize(const gl::Context *context,
+ unsigned int bufferSize,
+ gl::DrawElementsType indexType,
+ bool dynamic)
+{
+ SafeRelease(mIndexBuffer);
+
+ updateSerial();
+
+ if (bufferSize > 0)
+ {
+ D3DFORMAT format = D3DFMT_UNKNOWN;
+ if (indexType == gl::DrawElementsType::UnsignedShort ||
+ indexType == gl::DrawElementsType::UnsignedByte)
+ {
+ format = D3DFMT_INDEX16;
+ }
+ else if (indexType == gl::DrawElementsType::UnsignedInt)
+ {
+ ASSERT(mRenderer->getNativeExtensions().elementIndexUintOES);
+ format = D3DFMT_INDEX32;
+ }
+ else
+ UNREACHABLE();
+
+ DWORD usageFlags = D3DUSAGE_WRITEONLY;
+ if (dynamic)
+ {
+ usageFlags |= D3DUSAGE_DYNAMIC;
+ }
+
+ HRESULT result =
+ mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer);
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), result,
+ "Failed to allocate internal index buffer");
+ }
+
+ mBufferSize = bufferSize;
+ mIndexType = indexType;
+ mDynamic = dynamic;
+
+ return angle::Result::Continue;
+}
+
+angle::Result IndexBuffer9::mapBuffer(const gl::Context *context,
+ unsigned int offset,
+ unsigned int size,
+ void **outMappedMemory)
+{
+ ASSERT(mIndexBuffer);
+
+ DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0;
+
+ void *mapPtr = nullptr;
+ HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags);
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to lock internal index buffer");
+
+ *outMappedMemory = mapPtr;
+ return angle::Result::Continue;
+}
+
+angle::Result IndexBuffer9::unmapBuffer(const gl::Context *context)
+{
+ ASSERT(mIndexBuffer);
+ HRESULT result = mIndexBuffer->Unlock();
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to unlock internal index buffer");
+
+ return angle::Result::Continue;
+}
+
+gl::DrawElementsType IndexBuffer9::getIndexType() const
+{
+ return mIndexType;
+}
+
+unsigned int IndexBuffer9::getBufferSize() const
+{
+ return mBufferSize;
+}
+
+angle::Result IndexBuffer9::setSize(const gl::Context *context,
+ unsigned int bufferSize,
+ gl::DrawElementsType indexType)
+{
+ if (bufferSize > mBufferSize || indexType != mIndexType)
+ {
+ return initialize(context, bufferSize, indexType, mDynamic);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result IndexBuffer9::discard(const gl::Context *context)
+{
+ ASSERT(mIndexBuffer);
+
+ void *mock;
+ HRESULT result;
+
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ result = mIndexBuffer->Lock(0, 1, &mock, D3DLOCK_DISCARD);
+ ANGLE_TRY_HR(context9, result, "Failed to lock internal index buffer");
+
+ result = mIndexBuffer->Unlock();
+ ANGLE_TRY_HR(context9, result, "Failed to unlock internal index buffer");
+
+ return angle::Result::Continue;
+}
+
+D3DFORMAT IndexBuffer9::getIndexFormat() const
+{
+ switch (mIndexType)
+ {
+ case gl::DrawElementsType::UnsignedByte:
+ return D3DFMT_INDEX16;
+ case gl::DrawElementsType::UnsignedShort:
+ return D3DFMT_INDEX16;
+ case gl::DrawElementsType::UnsignedInt:
+ return D3DFMT_INDEX32;
+ default:
+ UNREACHABLE();
+ return D3DFMT_UNKNOWN;
+ }
+}
+
+IDirect3DIndexBuffer9 *IndexBuffer9::getBuffer() const
+{
+ return mIndexBuffer;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h
new file mode 100644
index 0000000000..9493a1ebbe
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h
@@ -0,0 +1,57 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Indexffer9.h: Defines the D3D9 IndexBuffer implementation.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_
+
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+
+namespace rx
+{
+class Renderer9;
+
+class IndexBuffer9 : public IndexBuffer
+{
+ public:
+ explicit IndexBuffer9(Renderer9 *const renderer);
+ ~IndexBuffer9() override;
+
+ angle::Result initialize(const gl::Context *context,
+ unsigned int bufferSize,
+ gl::DrawElementsType indexType,
+ bool dynamic) override;
+
+ angle::Result mapBuffer(const gl::Context *context,
+ unsigned int offset,
+ unsigned int size,
+ void **outMappedMemory) override;
+ angle::Result unmapBuffer(const gl::Context *context) override;
+
+ gl::DrawElementsType getIndexType() const override;
+ unsigned int getBufferSize() const override;
+ angle::Result setSize(const gl::Context *context,
+ unsigned int bufferSize,
+ gl::DrawElementsType indexType) override;
+
+ angle::Result discard(const gl::Context *context) override;
+
+ D3DFORMAT getIndexFormat() const;
+ IDirect3DIndexBuffer9 *getBuffer() const;
+
+ private:
+ Renderer9 *const mRenderer;
+
+ IDirect3DIndexBuffer9 *mIndexBuffer;
+ unsigned int mBufferSize;
+ gl::DrawElementsType mIndexType;
+ bool mDynamic;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp
new file mode 100644
index 0000000000..e4834b44eb
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.cpp
@@ -0,0 +1,37 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow9.cpp: Defines NativeWindow9, a class for managing and
+// performing operations on an EGLNativeWindowType for the D3D9 renderer.
+
+#include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h"
+
+namespace rx
+{
+NativeWindow9::NativeWindow9(EGLNativeWindowType window) : NativeWindowD3D(window) {}
+
+bool NativeWindow9::initialize()
+{
+ return true;
+}
+
+bool NativeWindow9::getClientRect(LPRECT rect) const
+{
+ return GetClientRect(getNativeWindow(), rect) == TRUE;
+}
+
+bool NativeWindow9::isIconic() const
+{
+ return IsIconic(getNativeWindow()) == TRUE;
+}
+
+// static
+bool NativeWindow9::IsValidNativeWindow(EGLNativeWindowType window)
+{
+ return IsWindow(window) == TRUE;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h
new file mode 100644
index 0000000000..aae9e13cc0
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/NativeWindow9.h
@@ -0,0 +1,35 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeWindow9.h: Defines NativeWindow9, a class for managing and
+// performing operations on an EGLNativeWindowType for the D3D9 renderer.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_NATIVEWINDOW9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_NATIVEWINDOW9_H_
+
+#include "common/debug.h"
+#include "common/platform.h"
+
+#include "libANGLE/renderer/d3d/NativeWindowD3D.h"
+
+namespace rx
+{
+
+class NativeWindow9 : public NativeWindowD3D
+{
+ public:
+ explicit NativeWindow9(EGLNativeWindowType window);
+
+ bool initialize() override;
+ bool getClientRect(LPRECT rect) const override;
+ bool isIconic() const override;
+
+ static bool IsValidNativeWindow(EGLNativeWindowType window);
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_NATIVEWINDOW9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Query9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Query9.cpp
new file mode 100644
index 0000000000..aeefd6a29f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Query9.cpp
@@ -0,0 +1,176 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl.
+
+#include "libANGLE/renderer/d3d/d3d9/Query9.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/d3d/d3d9/Context9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+
+#include <GLES2/gl2ext.h>
+
+namespace rx
+{
+Query9::Query9(Renderer9 *renderer, gl::QueryType type)
+ : QueryImpl(type),
+ mGetDataAttemptCount(0),
+ mResult(GL_FALSE),
+ mQueryFinished(false),
+ mRenderer(renderer),
+ mQuery(nullptr)
+{}
+
+Query9::~Query9()
+{
+ SafeRelease(mQuery);
+}
+
+angle::Result Query9::begin(const gl::Context *context)
+{
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ D3DQUERYTYPE d3dQueryType = gl_d3d9::ConvertQueryType(getType());
+ if (mQuery == nullptr)
+ {
+ HRESULT result = mRenderer->getDevice()->CreateQuery(d3dQueryType, &mQuery);
+ ANGLE_TRY_HR(context9, result, "Internal query creation failed");
+ }
+
+ if (d3dQueryType != D3DQUERYTYPE_EVENT)
+ {
+ HRESULT result = mQuery->Issue(D3DISSUE_BEGIN);
+ ASSERT(SUCCEEDED(result));
+ ANGLE_TRY_HR(context9, result, "Failed to begin internal query");
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Query9::end(const gl::Context *context)
+{
+ Context9 *context9 = GetImplAs<Context9>(context);
+ ASSERT(mQuery);
+
+ HRESULT result = mQuery->Issue(D3DISSUE_END);
+ ASSERT(SUCCEEDED(result));
+ ANGLE_TRY_HR(context9, result, "Failed to end internal query");
+ mQueryFinished = false;
+ mResult = GL_FALSE;
+
+ return angle::Result::Continue;
+}
+
+angle::Result Query9::queryCounter(const gl::Context *context)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+}
+
+template <typename T>
+angle::Result Query9::getResultBase(Context9 *context9, T *params)
+{
+ while (!mQueryFinished)
+ {
+ ANGLE_TRY(testQuery(context9));
+
+ if (!mQueryFinished)
+ {
+ Sleep(0);
+ }
+ }
+
+ ASSERT(mQueryFinished);
+ *params = static_cast<T>(mResult);
+ return angle::Result::Continue;
+}
+
+angle::Result Query9::getResult(const gl::Context *context, GLint *params)
+{
+ return getResultBase(GetImplAs<Context9>(context), params);
+}
+
+angle::Result Query9::getResult(const gl::Context *context, GLuint *params)
+{
+ return getResultBase(GetImplAs<Context9>(context), params);
+}
+
+angle::Result Query9::getResult(const gl::Context *context, GLint64 *params)
+{
+ return getResultBase(GetImplAs<Context9>(context), params);
+}
+
+angle::Result Query9::getResult(const gl::Context *context, GLuint64 *params)
+{
+ return getResultBase(GetImplAs<Context9>(context), params);
+}
+
+angle::Result Query9::isResultAvailable(const gl::Context *context, bool *available)
+{
+ ANGLE_TRY(testQuery(GetImplAs<Context9>(context)));
+ *available = mQueryFinished;
+ return angle::Result::Continue;
+}
+
+angle::Result Query9::testQuery(Context9 *context9)
+{
+ if (!mQueryFinished)
+ {
+ ASSERT(mQuery);
+
+ HRESULT result = S_OK;
+ switch (getType())
+ {
+ case gl::QueryType::AnySamples:
+ case gl::QueryType::AnySamplesConservative:
+ {
+ DWORD numPixels = 0;
+ result = mQuery->GetData(&numPixels, sizeof(numPixels), D3DGETDATA_FLUSH);
+ if (result == S_OK)
+ {
+ mQueryFinished = true;
+ mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE;
+ }
+ break;
+ }
+
+ case gl::QueryType::CommandsCompleted:
+ {
+ BOOL completed = FALSE;
+ result = mQuery->GetData(&completed, sizeof(completed), D3DGETDATA_FLUSH);
+ if (result == S_OK)
+ {
+ mQueryFinished = true;
+ mResult = (completed == TRUE) ? GL_TRUE : GL_FALSE;
+ }
+ break;
+ }
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ if (!mQueryFinished)
+ {
+ ANGLE_TRY_HR(context9, result, "Failed to test get query result");
+
+ mGetDataAttemptCount++;
+ bool checkDeviceLost =
+ (mGetDataAttemptCount % kPollingD3DDeviceLostCheckFrequency) == 0;
+ if (checkDeviceLost && mRenderer->testDeviceLost())
+ {
+ ANGLE_TRY_HR(context9, D3DERR_DEVICELOST,
+ "Failed to test get query result, device is lost");
+ }
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Query9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Query9.h
new file mode 100644
index 0000000000..df10ded225
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Query9.h
@@ -0,0 +1,50 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Query9.h: Defines the rx::Query9 class which implements rx::QueryImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_
+
+#include "libANGLE/renderer/QueryImpl.h"
+
+namespace rx
+{
+class Context9;
+class Renderer9;
+
+class Query9 : public QueryImpl
+{
+ public:
+ Query9(Renderer9 *renderer, gl::QueryType type);
+ ~Query9() override;
+
+ angle::Result begin(const gl::Context *context) override;
+ angle::Result end(const gl::Context *context) override;
+ angle::Result queryCounter(const gl::Context *context) override;
+ angle::Result getResult(const gl::Context *context, GLint *params) override;
+ angle::Result getResult(const gl::Context *context, GLuint *params) override;
+ angle::Result getResult(const gl::Context *context, GLint64 *params) override;
+ angle::Result getResult(const gl::Context *context, GLuint64 *params) override;
+ angle::Result isResultAvailable(const gl::Context *context, bool *available) override;
+
+ private:
+ angle::Result testQuery(Context9 *context9);
+
+ template <typename T>
+ angle::Result getResultBase(Context9 *context9, T *params);
+
+ unsigned int mGetDataAttemptCount;
+ GLuint64 mResult;
+ bool mQueryFinished;
+
+ Renderer9 *mRenderer;
+ IDirect3DQuery9 *mQuery;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp
new file mode 100644
index 0000000000..54c3291799
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp
@@ -0,0 +1,160 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9
+// pointers retained by renderbuffers.
+
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+
+namespace rx
+{
+
+// TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being
+// given.
+TextureRenderTarget9::TextureRenderTarget9(IDirect3DBaseTexture9 *texture,
+ size_t textureLevel,
+ IDirect3DSurface9 *surface,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei samples)
+ : mWidth(width),
+ mHeight(height),
+ mDepth(depth),
+ mInternalFormat(internalFormat),
+ mD3DFormat(D3DFMT_UNKNOWN),
+ mSamples(samples),
+ mTexture(texture),
+ mTextureLevel(textureLevel),
+ mRenderTarget(surface)
+{
+ ASSERT(mDepth == 1);
+
+ if (mRenderTarget)
+ {
+ D3DSURFACE_DESC description;
+ mRenderTarget->GetDesc(&description);
+ mD3DFormat = description.Format;
+ }
+}
+
+TextureRenderTarget9::~TextureRenderTarget9()
+{
+ SafeRelease(mTexture);
+ SafeRelease(mRenderTarget);
+}
+
+GLsizei TextureRenderTarget9::getWidth() const
+{
+ return mWidth;
+}
+
+GLsizei TextureRenderTarget9::getHeight() const
+{
+ return mHeight;
+}
+
+GLsizei TextureRenderTarget9::getDepth() const
+{
+ return mDepth;
+}
+
+GLenum TextureRenderTarget9::getInternalFormat() const
+{
+ return mInternalFormat;
+}
+
+GLsizei TextureRenderTarget9::getSamples() const
+{
+ return mSamples;
+}
+
+IDirect3DBaseTexture9 *TextureRenderTarget9::getTexture() const
+{
+ return mTexture;
+}
+
+size_t TextureRenderTarget9::getTextureLevel() const
+{
+ return mTextureLevel;
+}
+
+IDirect3DSurface9 *TextureRenderTarget9::getSurface() const
+{
+ // Caller is responsible for releasing the returned surface reference.
+ // TODO: remove the AddRef to match RenderTarget11
+ if (mRenderTarget)
+ {
+ mRenderTarget->AddRef();
+ }
+
+ return mRenderTarget;
+}
+
+D3DFORMAT TextureRenderTarget9::getD3DFormat() const
+{
+ return mD3DFormat;
+}
+
+SurfaceRenderTarget9::SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth)
+ : mSwapChain(swapChain), mDepth(depth)
+{}
+
+SurfaceRenderTarget9::~SurfaceRenderTarget9() {}
+
+GLsizei SurfaceRenderTarget9::getWidth() const
+{
+ return mSwapChain->getWidth();
+}
+
+GLsizei SurfaceRenderTarget9::getHeight() const
+{
+ return mSwapChain->getHeight();
+}
+
+GLsizei SurfaceRenderTarget9::getDepth() const
+{
+ return 1;
+}
+
+GLenum SurfaceRenderTarget9::getInternalFormat() const
+{
+ return (mDepth ? mSwapChain->getDepthBufferInternalFormat()
+ : mSwapChain->getRenderTargetInternalFormat());
+}
+
+GLsizei SurfaceRenderTarget9::getSamples() const
+{
+ // Our EGL surfaces do not support multisampling.
+ return 0;
+}
+
+IDirect3DSurface9 *SurfaceRenderTarget9::getSurface() const
+{
+ return (mDepth ? mSwapChain->getDepthStencil() : mSwapChain->getRenderTarget());
+}
+
+IDirect3DBaseTexture9 *SurfaceRenderTarget9::getTexture() const
+{
+ return (mDepth ? nullptr : mSwapChain->getOffscreenTexture());
+}
+
+size_t SurfaceRenderTarget9::getTextureLevel() const
+{
+ return 0;
+}
+
+D3DFORMAT SurfaceRenderTarget9::getD3DFormat() const
+{
+ return d3d9::GetTextureFormatInfo(getInternalFormat()).texFormat;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h
new file mode 100644
index 0000000000..010955eb41
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h
@@ -0,0 +1,98 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTarget9.h: Defines a D3D9-specific wrapper for IDirect3DSurface9 pointers
+// retained by Renderbuffers.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_
+
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+
+namespace rx
+{
+class Renderer9;
+class SwapChain9;
+
+class RenderTarget9 : public RenderTargetD3D
+{
+ public:
+ RenderTarget9() {}
+ ~RenderTarget9() override {}
+ // Retrieve the texture that backs this render target, may be null for swap chain render
+ // targets.
+ virtual IDirect3DBaseTexture9 *getTexture() const = 0;
+ virtual size_t getTextureLevel() const = 0;
+
+ virtual IDirect3DSurface9 *getSurface() const = 0;
+
+ virtual D3DFORMAT getD3DFormat() const = 0;
+};
+
+class TextureRenderTarget9 : public RenderTarget9
+{
+ public:
+ TextureRenderTarget9(IDirect3DBaseTexture9 *texture,
+ size_t textureLevel,
+ IDirect3DSurface9 *surface,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei samples);
+ ~TextureRenderTarget9() override;
+
+ GLsizei getWidth() const override;
+ GLsizei getHeight() const override;
+ GLsizei getDepth() const override;
+ GLenum getInternalFormat() const override;
+ GLsizei getSamples() const override;
+
+ IDirect3DBaseTexture9 *getTexture() const override;
+ size_t getTextureLevel() const override;
+ IDirect3DSurface9 *getSurface() const override;
+
+ D3DFORMAT getD3DFormat() const override;
+
+ private:
+ GLsizei mWidth;
+ GLsizei mHeight;
+ GLsizei mDepth;
+ GLenum mInternalFormat;
+ D3DFORMAT mD3DFormat;
+ GLsizei mSamples;
+
+ IDirect3DBaseTexture9 *mTexture;
+ size_t mTextureLevel;
+ IDirect3DSurface9 *mRenderTarget;
+};
+
+class SurfaceRenderTarget9 : public RenderTarget9
+{
+ public:
+ SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth);
+ ~SurfaceRenderTarget9() override;
+
+ GLsizei getWidth() const override;
+ GLsizei getHeight() const override;
+ GLsizei getDepth() const override;
+ GLenum getInternalFormat() const override;
+ GLsizei getSamples() const override;
+
+ IDirect3DBaseTexture9 *getTexture() const override;
+ size_t getTextureLevel() const override;
+ IDirect3DSurface9 *getSurface() const override;
+
+ D3DFORMAT getD3DFormat() const override;
+
+ private:
+ SwapChain9 *mSwapChain;
+ bool mDepth;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
new file mode 100644
index 0000000000..d80997392d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
@@ -0,0 +1,3338 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer.
+
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+#include <EGL/eglext.h>
+#include <sstream>
+
+#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/features.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/DeviceD3D.h"
+#include "libANGLE/renderer/d3d/DisplayD3D.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/Blit9.h"
+#include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Context9.h"
+#include "libANGLE/renderer/d3d/d3d9/Fence9.h"
+#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Image9.h"
+#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h"
+#include "libANGLE/renderer/d3d/d3d9/Query9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h"
+#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexArray9.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/driver_utils_d3d.h"
+#include "libANGLE/renderer/driver_utils.h"
+#include "libANGLE/trace.h"
+
+#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
+# define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
+#endif
+
+// Enable ANGLE_SUPPORT_SHADER_MODEL_2 if you wish devices with only shader model 2.
+// Such a device would not be conformant.
+#ifndef ANGLE_SUPPORT_SHADER_MODEL_2
+# define ANGLE_SUPPORT_SHADER_MODEL_2 0
+#endif
+
+namespace rx
+{
+
+namespace
+{
+enum
+{
+ MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256,
+ MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32,
+ MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224,
+ MAX_VARYING_VECTORS_SM2 = 8,
+ MAX_VARYING_VECTORS_SM3 = 10,
+
+ MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4
+};
+
+template <typename T>
+static void DrawPoints(IDirect3DDevice9 *device, GLsizei count, const void *indices, int minIndex)
+{
+ for (int i = 0; i < count; i++)
+ {
+ unsigned int indexValue =
+ static_cast<unsigned int>(static_cast<const T *>(indices)[i]) - minIndex;
+ device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1);
+ }
+}
+
+// A hard limit on buffer size. This works around a problem in the NVIDIA drivers where buffer sizes
+// close to MAX_UINT would give undefined results. The limit of MAX_UINT/2 should be generous enough
+// for almost any demanding application.
+constexpr UINT kMaximumBufferSizeHardLimit = std::numeric_limits<UINT>::max() >> 1;
+} // anonymous namespace
+
+Renderer9::Renderer9(egl::Display *display) : RendererD3D(display), mStateManager(this)
+{
+ mD3d9Module = nullptr;
+
+ mD3d9 = nullptr;
+ mD3d9Ex = nullptr;
+ mDevice = nullptr;
+ mDeviceEx = nullptr;
+ mDeviceWindow = nullptr;
+ mBlit = nullptr;
+
+ mAdapter = D3DADAPTER_DEFAULT;
+
+ const egl::AttributeMap &attributes = display->getAttributeMap();
+ EGLint requestedDeviceType = static_cast<EGLint>(attributes.get(
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE));
+ switch (requestedDeviceType)
+ {
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
+ mDeviceType = D3DDEVTYPE_HAL;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
+ mDeviceType = D3DDEVTYPE_REF;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+ mDeviceType = D3DDEVTYPE_NULLREF;
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+
+ mMaskedClearSavedState = nullptr;
+
+ mVertexDataManager = nullptr;
+ mIndexDataManager = nullptr;
+ mLineLoopIB = nullptr;
+ mCountingIB = nullptr;
+
+ mMaxNullColorbufferLRU = 0;
+ for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+ {
+ mNullRenderTargetCache[i].lruCount = 0;
+ mNullRenderTargetCache[i].width = 0;
+ mNullRenderTargetCache[i].height = 0;
+ mNullRenderTargetCache[i].renderTarget = nullptr;
+ }
+
+ mAppliedVertexShader = nullptr;
+ mAppliedPixelShader = nullptr;
+ mAppliedProgramSerial = 0;
+
+ gl::InitializeDebugAnnotations(&mAnnotator);
+}
+
+void Renderer9::setGlobalDebugAnnotator()
+{
+ gl::InitializeDebugAnnotations(&mAnnotator);
+}
+
+Renderer9::~Renderer9()
+{
+ if (mDevice)
+ {
+ // If the device is lost, reset it first to prevent leaving the driver in an unstable state
+ if (testDeviceLost())
+ {
+ resetDevice();
+ }
+ }
+
+ release();
+}
+
+void Renderer9::release()
+{
+ gl::UninitializeDebugAnnotations();
+
+ mTranslatedAttribCache.clear();
+
+ releaseDeviceResources();
+
+ SafeRelease(mDevice);
+ SafeRelease(mDeviceEx);
+ SafeRelease(mD3d9);
+ SafeRelease(mD3d9Ex);
+
+ mCompiler.release();
+
+ if (mDeviceWindow)
+ {
+ DestroyWindow(mDeviceWindow);
+ mDeviceWindow = nullptr;
+ }
+
+ mD3d9Module = nullptr;
+}
+
+egl::Error Renderer9::initialize()
+{
+ ANGLE_TRACE_EVENT0("gpu.angle", "GetModuleHandle_d3d9");
+ mD3d9Module = ::LoadLibrary(TEXT("d3d9.dll"));
+
+ if (mD3d9Module == nullptr)
+ {
+ return egl::EglNotInitialized(D3D9_INIT_MISSING_DEP) << "No D3D9 module found.";
+ }
+
+ typedef HRESULT(WINAPI * Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex **);
+ Direct3DCreate9ExFunc Direct3DCreate9ExPtr =
+ reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
+
+ // Use Direct3D9Ex if available. Among other things, this version is less
+ // inclined to report a lost context, for example when the user switches
+ // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are
+ // available.
+ if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr &&
+ SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "D3d9Ex_QueryInterface");
+ ASSERT(mD3d9Ex);
+ mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast<void **>(&mD3d9));
+ ASSERT(mD3d9);
+ }
+ else
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "Direct3DCreate9");
+ mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
+ }
+
+ if (!mD3d9)
+ {
+ return egl::EglNotInitialized(D3D9_INIT_MISSING_DEP) << "Could not create D3D9 device.";
+ }
+
+ if (mDisplay->getNativeDisplayId() != nullptr)
+ {
+ // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context
+ // corresponds to
+ }
+
+ HRESULT result;
+
+ // Give up on getting device caps after about one second.
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "GetDeviceCaps");
+ for (int i = 0; i < 10; ++i)
+ {
+ result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
+ if (SUCCEEDED(result))
+ {
+ break;
+ }
+ else if (result == D3DERR_NOTAVAILABLE)
+ {
+ Sleep(100); // Give the driver some time to initialize/recover
+ }
+ else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY,
+ // D3DERR_INVALIDDEVICE, or another error we can't recover
+ // from
+ {
+ return egl::EglNotInitialized(D3D9_INIT_OTHER_ERROR)
+ << "Failed to get device caps, " << gl::FmtHR(result);
+ }
+ }
+ }
+
+#if ANGLE_SUPPORT_SHADER_MODEL_2
+ size_t minShaderModel = 2;
+#else
+ size_t minShaderModel = 3;
+#endif
+
+ if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(minShaderModel, 0))
+ {
+ return egl::EglNotInitialized(D3D9_INIT_UNSUPPORTED_VERSION)
+ << "Renderer does not support PS " << minShaderModel << ".0, aborting!";
+ }
+
+ // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture
+ // to a render target texture is not supported. This is required by
+ // Texture2D::ensureRenderTarget.
+ if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
+ {
+ return egl::EglNotInitialized(D3D9_INIT_UNSUPPORTED_STRETCHRECT)
+ << "Renderer does not support StretctRect from textures.";
+ }
+
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "GetAdapterIdentifier");
+ mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
+ }
+
+ static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
+ static const TCHAR className[] = TEXT("STATIC");
+
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "CreateWindowEx");
+ mDeviceWindow =
+ CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1,
+ 1, HWND_MESSAGE, nullptr, GetModuleHandle(nullptr), nullptr);
+ }
+
+ D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
+ DWORD behaviorFlags =
+ D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED;
+
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "D3d9_CreateDevice");
+ result = mD3d9->CreateDevice(
+ mAdapter, mDeviceType, mDeviceWindow,
+ behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
+ &presentParameters, &mDevice);
+
+ if (FAILED(result))
+ {
+ ERR() << "CreateDevice1 failed: (" << gl::FmtHR(result) << ")";
+ }
+ }
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
+ {
+ return egl::EglBadAlloc(D3D9_INIT_OUT_OF_MEMORY)
+ << "CreateDevice failed: device lost or out of memory (" << gl::FmtHR(result) << ")";
+ }
+
+ if (FAILED(result))
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "D3d9_CreateDevice2");
+ result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow,
+ behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING,
+ &presentParameters, &mDevice);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY ||
+ result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
+ return egl::EglBadAlloc(D3D9_INIT_OUT_OF_MEMORY)
+ << "CreateDevice2 failed: device lost, not available, or of out of memory ("
+ << gl::FmtHR(result) << ")";
+ }
+ }
+
+ if (mD3d9Ex)
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "mDevice_QueryInterface");
+ result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void **)&mDeviceEx);
+ ASSERT(SUCCEEDED(result));
+ }
+
+ {
+ ANGLE_TRACE_EVENT0("gpu.angle", "ShaderCache initialize");
+ mVertexShaderCache.initialize(mDevice);
+ mPixelShaderCache.initialize(mDevice);
+ }
+
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ // Check vertex texture support
+ // Only Direct3D 10 ready devices support all the necessary vertex texture formats.
+ // We test this using D3D9 by checking support for the R16F format.
+ mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) &&
+ SUCCEEDED(mD3d9->CheckDeviceFormat(
+ mAdapter, mDeviceType, currentDisplayMode.Format,
+ D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F));
+
+ ANGLE_TRY(initializeDevice());
+
+ return egl::NoError();
+}
+
+// do any one-time device initialization
+// NOTE: this is also needed after a device lost/reset
+// to reset the scene status and ensure the default states are reset.
+egl::Error Renderer9::initializeDevice()
+{
+ // Permanent non-default states
+ mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
+ mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE);
+
+ if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
+ {
+ mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD &)mDeviceCaps.MaxPointSize);
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f
+ }
+
+ const gl::Caps &rendererCaps = getNativeCaps();
+
+ mCurVertexSamplerStates.resize(rendererCaps.maxShaderTextureImageUnits[gl::ShaderType::Vertex]);
+ mCurPixelSamplerStates.resize(
+ rendererCaps.maxShaderTextureImageUnits[gl::ShaderType::Fragment]);
+
+ mCurVertexTextures.resize(rendererCaps.maxShaderTextureImageUnits[gl::ShaderType::Vertex]);
+ mCurPixelTextures.resize(rendererCaps.maxShaderTextureImageUnits[gl::ShaderType::Fragment]);
+
+ markAllStateDirty();
+
+ mSceneStarted = false;
+
+ ASSERT(!mBlit);
+ mBlit = new Blit9(this);
+
+ ASSERT(!mVertexDataManager && !mIndexDataManager);
+ mIndexDataManager = new IndexDataManager(this);
+
+ mTranslatedAttribCache.resize(getNativeCaps().maxVertexAttributes);
+
+ mStateManager.initialize();
+
+ return egl::NoError();
+}
+
+D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
+{
+ D3DPRESENT_PARAMETERS presentParameters = {};
+
+ // The default swap chain is never actually used. Surface will create a new swap chain with the
+ // proper parameters.
+ presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
+ presentParameters.BackBufferCount = 1;
+ presentParameters.BackBufferFormat = D3DFMT_UNKNOWN;
+ presentParameters.BackBufferWidth = 1;
+ presentParameters.BackBufferHeight = 1;
+ presentParameters.EnableAutoDepthStencil = FALSE;
+ presentParameters.Flags = 0;
+ presentParameters.hDeviceWindow = mDeviceWindow;
+ presentParameters.MultiSampleQuality = 0;
+ presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE;
+ presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
+ presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ presentParameters.Windowed = TRUE;
+
+ return presentParameters;
+}
+
+egl::ConfigSet Renderer9::generateConfigs()
+{
+ static const GLenum colorBufferFormats[] = {
+ GL_BGR5_A1_ANGLEX,
+ GL_BGRA8_EXT,
+ GL_RGB565,
+
+ };
+
+ static const GLenum depthStencilBufferFormats[] = {
+ GL_NONE,
+ GL_DEPTH_COMPONENT32_OES,
+ GL_DEPTH24_STENCIL8_OES,
+ GL_DEPTH_COMPONENT24_OES,
+ GL_DEPTH_COMPONENT16,
+ };
+
+ const gl::Caps &rendererCaps = getNativeCaps();
+ const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps();
+
+ D3DDISPLAYMODE currentDisplayMode;
+ mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
+
+ // Determine the min and max swap intervals
+ int minSwapInterval = 4;
+ int maxSwapInterval = 0;
+
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
+ {
+ minSwapInterval = std::min(minSwapInterval, 0);
+ maxSwapInterval = std::max(maxSwapInterval, 0);
+ }
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
+ {
+ minSwapInterval = std::min(minSwapInterval, 1);
+ maxSwapInterval = std::max(maxSwapInterval, 1);
+ }
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)
+ {
+ minSwapInterval = std::min(minSwapInterval, 2);
+ maxSwapInterval = std::max(maxSwapInterval, 2);
+ }
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)
+ {
+ minSwapInterval = std::min(minSwapInterval, 3);
+ maxSwapInterval = std::max(maxSwapInterval, 3);
+ }
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)
+ {
+ minSwapInterval = std::min(minSwapInterval, 4);
+ maxSwapInterval = std::max(maxSwapInterval, 4);
+ }
+
+ egl::ConfigSet configs;
+ for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++)
+ {
+ GLenum colorBufferInternalFormat = colorBufferFormats[formatIndex];
+ const gl::TextureCaps &colorBufferFormatCaps =
+ rendererTextureCaps.get(colorBufferInternalFormat);
+ if (colorBufferFormatCaps.renderbuffer)
+ {
+ ASSERT(colorBufferFormatCaps.textureAttachment);
+ for (size_t depthStencilIndex = 0;
+ depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++)
+ {
+ GLenum depthStencilBufferInternalFormat =
+ depthStencilBufferFormats[depthStencilIndex];
+ const gl::TextureCaps &depthStencilBufferFormatCaps =
+ rendererTextureCaps.get(depthStencilBufferInternalFormat);
+ if (depthStencilBufferFormatCaps.renderbuffer ||
+ depthStencilBufferInternalFormat == GL_NONE)
+ {
+ ASSERT(depthStencilBufferFormatCaps.textureAttachment ||
+ depthStencilBufferInternalFormat == GL_NONE);
+ const gl::InternalFormat &colorBufferFormatInfo =
+ gl::GetSizedInternalFormatInfo(colorBufferInternalFormat);
+ const gl::InternalFormat &depthStencilBufferFormatInfo =
+ gl::GetSizedInternalFormatInfo(depthStencilBufferInternalFormat);
+ const d3d9::TextureFormat &d3d9ColorBufferFormatInfo =
+ d3d9::GetTextureFormatInfo(colorBufferInternalFormat);
+
+ egl::Config config;
+ config.renderTargetFormat = colorBufferInternalFormat;
+ config.depthStencilFormat = depthStencilBufferInternalFormat;
+ config.bufferSize = colorBufferFormatInfo.pixelBytes * 8;
+ config.redSize = colorBufferFormatInfo.redBits;
+ config.greenSize = colorBufferFormatInfo.greenBits;
+ config.blueSize = colorBufferFormatInfo.blueBits;
+ config.luminanceSize = colorBufferFormatInfo.luminanceBits;
+ config.alphaSize = colorBufferFormatInfo.alphaBits;
+ config.alphaMaskSize = 0;
+ config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB);
+ config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA ||
+ colorBufferFormatInfo.format == GL_BGRA_EXT);
+ config.colorBufferType = EGL_RGB_BUFFER;
+ // Mark as slow if blits to the back-buffer won't be straight forward
+ config.configCaveat =
+ (currentDisplayMode.Format == d3d9ColorBufferFormatInfo.renderFormat)
+ ? EGL_NONE
+ : EGL_SLOW_CONFIG;
+ config.configID = static_cast<EGLint>(configs.size() + 1);
+ config.conformant = EGL_OPENGL_ES2_BIT;
+ config.depthSize = depthStencilBufferFormatInfo.depthBits;
+ config.level = 0;
+ config.matchNativePixmap = EGL_NONE;
+ config.maxPBufferWidth = rendererCaps.max2DTextureSize;
+ config.maxPBufferHeight = rendererCaps.max2DTextureSize;
+ config.maxPBufferPixels =
+ rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
+ config.maxSwapInterval = maxSwapInterval;
+ config.minSwapInterval = minSwapInterval;
+ config.nativeRenderable = EGL_FALSE;
+ config.nativeVisualID = 0;
+ config.nativeVisualType = EGL_NONE;
+ config.renderableType = EGL_OPENGL_ES2_BIT;
+ config.sampleBuffers = 0; // FIXME: enumerate multi-sampling
+ config.samples = 0;
+ config.stencilSize = depthStencilBufferFormatInfo.stencilBits;
+ config.surfaceType =
+ EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+ config.transparentType = EGL_NONE;
+ config.transparentRedValue = 0;
+ config.transparentGreenValue = 0;
+ config.transparentBlueValue = 0;
+ config.colorComponentType = gl_egl::GLComponentTypeToEGLColorComponentType(
+ colorBufferFormatInfo.componentType);
+
+ configs.add(config);
+ }
+ }
+ }
+ }
+
+ ASSERT(configs.size() > 0);
+ return configs;
+}
+
+void Renderer9::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const
+{
+ outExtensions->createContextRobustness = true;
+
+ if (getShareHandleSupport())
+ {
+ outExtensions->d3dShareHandleClientBuffer = true;
+ outExtensions->surfaceD3DTexture2DShareHandle = true;
+ }
+ outExtensions->d3dTextureClientBuffer = true;
+
+ outExtensions->querySurfacePointer = true;
+ outExtensions->windowFixedSize = true;
+ outExtensions->postSubBuffer = true;
+
+ outExtensions->image = true;
+ outExtensions->imageBase = true;
+ outExtensions->glTexture2DImage = true;
+ outExtensions->glRenderbufferImage = true;
+
+ outExtensions->noConfigContext = true;
+
+ // Contexts are virtualized so textures and semaphores can be shared globally
+ outExtensions->displayTextureShareGroup = true;
+ outExtensions->displaySemaphoreShareGroup = true;
+
+ // D3D9 can be used without an output surface
+ outExtensions->surfacelessContext = true;
+
+ outExtensions->robustResourceInitializationANGLE = true;
+}
+
+void Renderer9::startScene()
+{
+ if (!mSceneStarted)
+ {
+ long result = mDevice->BeginScene();
+ if (SUCCEEDED(result))
+ {
+ // This is defensive checking against the device being
+ // lost at unexpected times.
+ mSceneStarted = true;
+ }
+ }
+}
+
+void Renderer9::endScene()
+{
+ if (mSceneStarted)
+ {
+ // EndScene can fail if the device was lost, for example due
+ // to a TDR during a draw call.
+ mDevice->EndScene();
+ mSceneStarted = false;
+ }
+}
+
+angle::Result Renderer9::flush(const gl::Context *context)
+{
+ IDirect3DQuery9 *query = nullptr;
+ ANGLE_TRY(allocateEventQuery(context, &query));
+
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ HRESULT result = query->Issue(D3DISSUE_END);
+ ANGLE_TRY_HR(context9, result, "Failed to issue event query");
+
+ // Grab the query data once
+ result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
+ freeEventQuery(query);
+ ANGLE_TRY_HR(context9, result, "Failed to get event query data");
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::finish(const gl::Context *context)
+{
+ IDirect3DQuery9 *query = nullptr;
+ ANGLE_TRY(allocateEventQuery(context, &query));
+
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ HRESULT result = query->Issue(D3DISSUE_END);
+ ANGLE_TRY_HR(context9, result, "Failed to issue event query");
+
+ // Grab the query data once
+ result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
+ if (FAILED(result))
+ {
+ freeEventQuery(query);
+ }
+ ANGLE_TRY_HR(context9, result, "Failed to get event query data");
+
+ // Loop until the query completes
+ unsigned int attempt = 0;
+ while (result == S_FALSE)
+ {
+ // Keep polling, but allow other threads to do something useful first
+ ScheduleYield();
+
+ result = query->GetData(nullptr, 0, D3DGETDATA_FLUSH);
+ attempt++;
+
+ if (result == S_FALSE)
+ {
+ // explicitly check for device loss
+ // some drivers seem to return S_FALSE even if the device is lost
+ // instead of D3DERR_DEVICELOST like they should
+ bool checkDeviceLost = (attempt % kPollingD3DDeviceLostCheckFrequency) == 0;
+ if (checkDeviceLost && testDeviceLost())
+ {
+ result = D3DERR_DEVICELOST;
+ }
+ }
+
+ if (FAILED(result))
+ {
+ freeEventQuery(query);
+ }
+ ANGLE_TRY_HR(context9, result, "Failed to get event query data");
+ }
+
+ freeEventQuery(query);
+
+ return angle::Result::Continue;
+}
+
+bool Renderer9::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ return NativeWindow9::IsValidNativeWindow(window);
+}
+
+NativeWindowD3D *Renderer9::createNativeWindow(EGLNativeWindowType window,
+ const egl::Config *,
+ const egl::AttributeMap &) const
+{
+ return new NativeWindow9(window);
+}
+
+SwapChainD3D *Renderer9::createSwapChain(NativeWindowD3D *nativeWindow,
+ HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation,
+ EGLint samples)
+{
+ return new SwapChain9(this, GetAs<NativeWindow9>(nativeWindow), shareHandle, d3dTexture,
+ backBufferFormat, depthBufferFormat, orientation);
+}
+
+egl::Error Renderer9::getD3DTextureInfo(const egl::Config *configuration,
+ IUnknown *d3dTexture,
+ const egl::AttributeMap &attribs,
+ EGLint *width,
+ EGLint *height,
+ GLsizei *samples,
+ gl::Format *glFormat,
+ const angle::Format **angleFormat,
+ UINT *arraySlice) const
+{
+ IDirect3DTexture9 *texture = nullptr;
+ if (FAILED(d3dTexture->QueryInterface(&texture)))
+ {
+ return egl::EglBadParameter() << "Client buffer is not a IDirect3DTexture9";
+ }
+
+ IDirect3DDevice9 *textureDevice = nullptr;
+ texture->GetDevice(&textureDevice);
+ if (textureDevice != mDevice)
+ {
+ SafeRelease(texture);
+ return egl::EglBadParameter() << "Texture's device does not match.";
+ }
+ SafeRelease(textureDevice);
+
+ D3DSURFACE_DESC desc;
+ texture->GetLevelDesc(0, &desc);
+ SafeRelease(texture);
+
+ if (width)
+ {
+ *width = static_cast<EGLint>(desc.Width);
+ }
+ if (height)
+ {
+ *height = static_cast<EGLint>(desc.Height);
+ }
+
+ // GetSamplesCount() returns 0 when multisampling isn't used.
+ GLsizei sampleCount = d3d9_gl::GetSamplesCount(desc.MultiSampleType);
+ if ((configuration && configuration->samples > 1) || sampleCount != 0)
+ {
+ return egl::EglBadParameter() << "Multisampling not supported for client buffer texture";
+ }
+ if (samples)
+ {
+ *samples = static_cast<EGLint>(sampleCount);
+ }
+
+ // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
+ switch (desc.Format)
+ {
+ case D3DFMT_R8G8B8:
+ case D3DFMT_A8R8G8B8:
+ case D3DFMT_A16B16G16R16F:
+ case D3DFMT_A32B32G32R32F:
+ break;
+
+ default:
+ return egl::EglBadParameter()
+ << "Unknown client buffer texture format: " << desc.Format;
+ }
+
+ const auto &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
+ ASSERT(d3dFormatInfo.info().id != angle::FormatID::NONE);
+
+ if (glFormat)
+ {
+ *glFormat = gl::Format(d3dFormatInfo.info().glInternalFormat);
+ }
+
+ if (angleFormat)
+ {
+
+ *angleFormat = &d3dFormatInfo.info();
+ }
+
+ if (arraySlice)
+ {
+ *arraySlice = 0;
+ }
+
+ return egl::NoError();
+}
+
+egl::Error Renderer9::validateShareHandle(const egl::Config *config,
+ HANDLE shareHandle,
+ const egl::AttributeMap &attribs) const
+{
+ if (shareHandle == nullptr)
+ {
+ return egl::EglBadParameter() << "NULL share handle.";
+ }
+
+ EGLint width = attribs.getAsInt(EGL_WIDTH, 0);
+ EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
+ ASSERT(width != 0 && height != 0);
+
+ const d3d9::TextureFormat &backBufferd3dFormatInfo =
+ d3d9::GetTextureFormatInfo(config->renderTargetFormat);
+
+ IDirect3DTexture9 *texture = nullptr;
+ HRESULT result = mDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET,
+ backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT,
+ &texture, &shareHandle);
+ if (FAILED(result))
+ {
+ return egl::EglBadParameter() << "Failed to open share handle, " << gl::FmtHR(result);
+ }
+
+ DWORD levelCount = texture->GetLevelCount();
+
+ D3DSURFACE_DESC desc;
+ texture->GetLevelDesc(0, &desc);
+ SafeRelease(texture);
+
+ if (levelCount != 1 || desc.Width != static_cast<UINT>(width) ||
+ desc.Height != static_cast<UINT>(height) ||
+ desc.Format != backBufferd3dFormatInfo.texFormat)
+ {
+ return egl::EglBadParameter() << "Invalid texture parameters in share handle texture.";
+ }
+
+ return egl::NoError();
+}
+
+ContextImpl *Renderer9::createContext(const gl::State &state, gl::ErrorSet *errorSet)
+{
+ return new Context9(state, errorSet, this);
+}
+
+void *Renderer9::getD3DDevice()
+{
+ return mDevice;
+}
+
+angle::Result Renderer9::allocateEventQuery(const gl::Context *context, IDirect3DQuery9 **outQuery)
+{
+ if (mEventQueryPool.empty())
+ {
+ HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, outQuery);
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to allocate event query");
+ }
+ else
+ {
+ *outQuery = mEventQueryPool.back();
+ mEventQueryPool.pop_back();
+ }
+
+ return angle::Result::Continue;
+}
+
+void Renderer9::freeEventQuery(IDirect3DQuery9 *query)
+{
+ if (mEventQueryPool.size() > 1000)
+ {
+ SafeRelease(query);
+ }
+ else
+ {
+ mEventQueryPool.push_back(query);
+ }
+}
+
+angle::Result Renderer9::createVertexShader(d3d::Context *context,
+ const DWORD *function,
+ size_t length,
+ IDirect3DVertexShader9 **outShader)
+{
+ return mVertexShaderCache.create(context, function, length, outShader);
+}
+
+angle::Result Renderer9::createPixelShader(d3d::Context *context,
+ const DWORD *function,
+ size_t length,
+ IDirect3DPixelShader9 **outShader)
+{
+ return mPixelShaderCache.create(context, function, length, outShader);
+}
+
+HRESULT Renderer9::createVertexBuffer(UINT Length,
+ DWORD Usage,
+ IDirect3DVertexBuffer9 **ppVertexBuffer)
+{
+ // Force buffers to be limited to a fixed max size.
+ if (Length > kMaximumBufferSizeHardLimit)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ D3DPOOL Pool = getBufferPool(Usage);
+ return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, nullptr);
+}
+
+VertexBuffer *Renderer9::createVertexBuffer()
+{
+ return new VertexBuffer9(this);
+}
+
+HRESULT Renderer9::createIndexBuffer(UINT Length,
+ DWORD Usage,
+ D3DFORMAT Format,
+ IDirect3DIndexBuffer9 **ppIndexBuffer)
+{
+ // Force buffers to be limited to a fixed max size.
+ if (Length > kMaximumBufferSizeHardLimit)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ D3DPOOL Pool = getBufferPool(Usage);
+ return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, nullptr);
+}
+
+IndexBuffer *Renderer9::createIndexBuffer()
+{
+ return new IndexBuffer9(this);
+}
+
+StreamProducerImpl *Renderer9::createStreamProducerD3DTexture(
+ egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs)
+{
+ // Streams are not supported under D3D9
+ UNREACHABLE();
+ return nullptr;
+}
+
+bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const
+{
+ // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3.
+ return false;
+}
+
+angle::Result Renderer9::fastCopyBufferToTexture(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea)
+{
+ // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3.
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Renderer9::setSamplerState(const gl::Context *context,
+ gl::ShaderType type,
+ int index,
+ gl::Texture *texture,
+ const gl::SamplerState &samplerState)
+{
+ CurSamplerState &appliedSampler = (type == gl::ShaderType::Fragment)
+ ? mCurPixelSamplerStates[index]
+ : mCurVertexSamplerStates[index];
+
+ // Make sure to add the level offset for our tiny compressed texture workaround
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+
+ TextureStorage *storage = nullptr;
+ ANGLE_TRY(textureD3D->getNativeTexture(context, &storage));
+
+ // Storage should exist, texture should be complete
+ ASSERT(storage);
+
+ DWORD baseLevel = texture->getBaseLevel() + storage->getTopLevel();
+
+ if (appliedSampler.forceSet || appliedSampler.baseLevel != baseLevel ||
+ memcmp(&samplerState, &appliedSampler, sizeof(gl::SamplerState)) != 0)
+ {
+ int d3dSamplerOffset = (type == gl::ShaderType::Fragment) ? 0 : D3DVERTEXTEXTURESAMPLER0;
+ int d3dSampler = index + d3dSamplerOffset;
+
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU,
+ gl_d3d9::ConvertTextureWrap(samplerState.getWrapS()));
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV,
+ gl_d3d9::ConvertTextureWrap(samplerState.getWrapT()));
+
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER,
+ gl_d3d9::ConvertMagFilter(samplerState.getMagFilter(),
+ samplerState.getMaxAnisotropy()));
+
+ D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
+ float lodBias;
+ gl_d3d9::ConvertMinFilter(samplerState.getMinFilter(), &d3dMinFilter, &d3dMipFilter,
+ &lodBias, samplerState.getMaxAnisotropy(), baseLevel);
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, baseLevel);
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPMAPLODBIAS, static_cast<DWORD>(lodBias));
+ if (getNativeExtensions().textureFilterAnisotropicEXT)
+ {
+ DWORD maxAnisotropy = std::min(mDeviceCaps.MaxAnisotropy,
+ static_cast<DWORD>(samplerState.getMaxAnisotropy()));
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, maxAnisotropy);
+ }
+
+ const bool isSrgb = gl::GetSizedInternalFormatInfo(textureD3D->getBaseLevelInternalFormat())
+ .colorEncoding == GL_SRGB;
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_SRGBTEXTURE, isSrgb);
+
+ ASSERT(texture->getBorderColor().type == angle::ColorGeneric::Type::Float);
+ mDevice->SetSamplerState(d3dSampler, D3DSAMP_BORDERCOLOR,
+ gl_d3d9::ConvertColor(texture->getBorderColor().colorF));
+ }
+
+ appliedSampler.forceSet = false;
+ appliedSampler.samplerState = samplerState;
+ appliedSampler.baseLevel = baseLevel;
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::setTexture(const gl::Context *context,
+ gl::ShaderType type,
+ int index,
+ gl::Texture *texture)
+{
+ int d3dSamplerOffset = (type == gl::ShaderType::Fragment) ? 0 : D3DVERTEXTEXTURESAMPLER0;
+ int d3dSampler = index + d3dSamplerOffset;
+ IDirect3DBaseTexture9 *d3dTexture = nullptr;
+ bool forceSetTexture = false;
+
+ std::vector<uintptr_t> &appliedTextures =
+ (type == gl::ShaderType::Fragment) ? mCurPixelTextures : mCurVertexTextures;
+
+ if (texture)
+ {
+ TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
+
+ TextureStorage *texStorage = nullptr;
+ ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage));
+
+ // Texture should be complete and have a storage
+ ASSERT(texStorage);
+
+ TextureStorage9 *storage9 = GetAs<TextureStorage9>(texStorage);
+ ANGLE_TRY(storage9->getBaseTexture(context, &d3dTexture));
+
+ // If we get NULL back from getBaseTexture here, something went wrong
+ // in the texture class and we're unexpectedly missing the d3d texture
+ ASSERT(d3dTexture != nullptr);
+
+ forceSetTexture = textureImpl->hasDirtyImages();
+ textureImpl->resetDirty();
+ }
+
+ if (forceSetTexture || appliedTextures[index] != reinterpret_cast<uintptr_t>(d3dTexture))
+ {
+ mDevice->SetTexture(d3dSampler, d3dTexture);
+ }
+
+ appliedTextures[index] = reinterpret_cast<uintptr_t>(d3dTexture);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::updateState(const gl::Context *context, gl::PrimitiveMode drawMode)
+{
+ const auto &glState = context->getState();
+
+ // Applies the render target surface, depth stencil surface, viewport rectangle and
+ // scissor rectangle to the renderer
+ gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
+ ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit());
+
+ Framebuffer9 *framebuffer9 = GetImplAs<Framebuffer9>(framebuffer);
+
+ ANGLE_TRY(applyRenderTarget(context, framebuffer9->getCachedColorRenderTargets()[0],
+ framebuffer9->getCachedDepthStencilRenderTarget()));
+
+ // Setting viewport state
+ setViewport(glState.getViewport(), glState.getNearPlane(), glState.getFarPlane(), drawMode,
+ glState.getRasterizerState().frontFace, false);
+
+ // Setting scissors state
+ setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
+
+ // Setting blend, depth stencil, and rasterizer states
+ // Since framebuffer->getSamples will return the original samples which may be different with
+ // the sample counts that we set in render target view, here we use renderTarget->getSamples to
+ // get the actual samples.
+ GLsizei samples = 0;
+ const gl::FramebufferAttachment *firstColorAttachment = framebuffer->getFirstColorAttachment();
+ if (firstColorAttachment)
+ {
+ ASSERT(firstColorAttachment->isAttached());
+ RenderTarget9 *renderTarget = nullptr;
+ ANGLE_TRY(firstColorAttachment->getRenderTarget(context, firstColorAttachment->getSamples(),
+ &renderTarget));
+ samples = renderTarget->getSamples();
+
+ mDevice->SetRenderState(D3DRS_SRGBWRITEENABLE,
+ renderTarget->getInternalFormat() == GL_SRGB8_ALPHA8);
+ }
+ gl::RasterizerState rasterizer = glState.getRasterizerState();
+ rasterizer.pointDrawMode = (drawMode == gl::PrimitiveMode::Points);
+ rasterizer.multiSample = (samples != 0);
+
+ ANGLE_TRY(setBlendDepthRasterStates(context, drawMode));
+
+ mStateManager.resetDirtyBits();
+
+ return angle::Result::Continue;
+}
+
+void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled)
+{
+ mStateManager.setScissorState(scissor, enabled);
+}
+
+angle::Result Renderer9::setBlendDepthRasterStates(const gl::Context *context,
+ gl::PrimitiveMode drawMode)
+{
+ const auto &glState = context->getState();
+ gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
+ ASSERT(!drawFramebuffer->hasAnyDirtyBit());
+ // Since framebuffer->getSamples will return the original samples which may be different with
+ // the sample counts that we set in render target view, here we use renderTarget->getSamples to
+ // get the actual samples.
+ GLsizei samples = 0;
+ const gl::FramebufferAttachment *firstColorAttachment =
+ drawFramebuffer->getFirstColorAttachment();
+ if (firstColorAttachment)
+ {
+ ASSERT(firstColorAttachment->isAttached());
+ RenderTarget9 *renderTarget = nullptr;
+ ANGLE_TRY(firstColorAttachment->getRenderTarget(context, firstColorAttachment->getSamples(),
+ &renderTarget));
+ samples = renderTarget->getSamples();
+ }
+ gl::RasterizerState rasterizer = glState.getRasterizerState();
+ rasterizer.pointDrawMode = (drawMode == gl::PrimitiveMode::Points);
+ rasterizer.multiSample = (samples != 0);
+
+ unsigned int mask = GetBlendSampleMask(glState, samples);
+ mStateManager.setBlendDepthRasterStates(glState, mask);
+ return angle::Result::Continue;
+}
+
+void Renderer9::setViewport(const gl::Rectangle &viewport,
+ float zNear,
+ float zFar,
+ gl::PrimitiveMode drawMode,
+ GLenum frontFace,
+ bool ignoreViewport)
+{
+ mStateManager.setViewportState(viewport, zNear, zFar, drawMode, frontFace, ignoreViewport);
+}
+
+bool Renderer9::applyPrimitiveType(gl::PrimitiveMode mode, GLsizei count, bool usesPointSize)
+{
+ switch (mode)
+ {
+ case gl::PrimitiveMode::Points:
+ mPrimitiveType = D3DPT_POINTLIST;
+ mPrimitiveCount = count;
+ break;
+ case gl::PrimitiveMode::Lines:
+ mPrimitiveType = D3DPT_LINELIST;
+ mPrimitiveCount = count / 2;
+ break;
+ case gl::PrimitiveMode::LineLoop:
+ mPrimitiveType = D3DPT_LINESTRIP;
+ mPrimitiveCount =
+ count - 1; // D3D doesn't support line loops, so we draw the last line separately
+ break;
+ case gl::PrimitiveMode::LineStrip:
+ mPrimitiveType = D3DPT_LINESTRIP;
+ mPrimitiveCount = count - 1;
+ break;
+ case gl::PrimitiveMode::Triangles:
+ mPrimitiveType = D3DPT_TRIANGLELIST;
+ mPrimitiveCount = count / 3;
+ break;
+ case gl::PrimitiveMode::TriangleStrip:
+ mPrimitiveType = D3DPT_TRIANGLESTRIP;
+ mPrimitiveCount = count - 2;
+ break;
+ case gl::PrimitiveMode::TriangleFan:
+ mPrimitiveType = D3DPT_TRIANGLEFAN;
+ mPrimitiveCount = count - 2;
+ break;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+
+ return mPrimitiveCount > 0;
+}
+
+angle::Result Renderer9::getNullColorRenderTarget(const gl::Context *context,
+ const RenderTarget9 *depthRenderTarget,
+ const RenderTarget9 **outColorRenderTarget)
+{
+ ASSERT(depthRenderTarget);
+
+ const gl::Extents &size = depthRenderTarget->getExtents();
+
+ // search cached nullcolorbuffers
+ for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+ {
+ if (mNullRenderTargetCache[i].renderTarget != nullptr &&
+ mNullRenderTargetCache[i].width == size.width &&
+ mNullRenderTargetCache[i].height == size.height)
+ {
+ mNullRenderTargetCache[i].lruCount = ++mMaxNullColorbufferLRU;
+ *outColorRenderTarget = mNullRenderTargetCache[i].renderTarget;
+ return angle::Result::Continue;
+ }
+ }
+
+ RenderTargetD3D *nullRenderTarget = nullptr;
+ ANGLE_TRY(createRenderTarget(context, size.width, size.height, GL_NONE, 0, &nullRenderTarget));
+
+ // add nullbuffer to the cache
+ NullRenderTargetCacheEntry *oldest = &mNullRenderTargetCache[0];
+ for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+ {
+ if (mNullRenderTargetCache[i].lruCount < oldest->lruCount)
+ {
+ oldest = &mNullRenderTargetCache[i];
+ }
+ }
+
+ SafeDelete(oldest->renderTarget);
+ oldest->renderTarget = GetAs<RenderTarget9>(nullRenderTarget);
+ oldest->lruCount = ++mMaxNullColorbufferLRU;
+ oldest->width = size.width;
+ oldest->height = size.height;
+
+ *outColorRenderTarget = oldest->renderTarget;
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::applyRenderTarget(const gl::Context *context,
+ const RenderTarget9 *colorRenderTargetIn,
+ const RenderTarget9 *depthStencilRenderTarget)
+{
+ // if there is no color attachment we must synthesize a NULL colorattachment
+ // to keep the D3D runtime happy. This should only be possible if depth texturing.
+ const RenderTarget9 *colorRenderTarget = colorRenderTargetIn;
+ if (colorRenderTarget == nullptr)
+ {
+ ANGLE_TRY(getNullColorRenderTarget(context, depthStencilRenderTarget, &colorRenderTarget));
+ }
+ ASSERT(colorRenderTarget != nullptr);
+
+ size_t renderTargetWidth = 0;
+ size_t renderTargetHeight = 0;
+
+ bool renderTargetChanged = false;
+ unsigned int renderTargetSerial = colorRenderTarget->getSerial();
+ if (renderTargetSerial != mAppliedRenderTargetSerial)
+ {
+ // Apply the render target on the device
+ IDirect3DSurface9 *renderTargetSurface = colorRenderTarget->getSurface();
+ ASSERT(renderTargetSurface);
+
+ mDevice->SetRenderTarget(0, renderTargetSurface);
+ SafeRelease(renderTargetSurface);
+
+ renderTargetWidth = colorRenderTarget->getWidth();
+ renderTargetHeight = colorRenderTarget->getHeight();
+
+ mAppliedRenderTargetSerial = renderTargetSerial;
+ renderTargetChanged = true;
+ }
+
+ unsigned int depthStencilSerial = 0;
+ if (depthStencilRenderTarget != nullptr)
+ {
+ depthStencilSerial = depthStencilRenderTarget->getSerial();
+ }
+
+ if (depthStencilSerial != mAppliedDepthStencilSerial || !mDepthStencilInitialized)
+ {
+ unsigned int depthSize = 0;
+ unsigned int stencilSize = 0;
+
+ // Apply the depth stencil on the device
+ if (depthStencilRenderTarget)
+ {
+ IDirect3DSurface9 *depthStencilSurface = depthStencilRenderTarget->getSurface();
+ ASSERT(depthStencilSurface);
+
+ mDevice->SetDepthStencilSurface(depthStencilSurface);
+ SafeRelease(depthStencilSurface);
+
+ const gl::InternalFormat &format =
+ gl::GetSizedInternalFormatInfo(depthStencilRenderTarget->getInternalFormat());
+
+ depthSize = format.depthBits;
+ stencilSize = format.stencilBits;
+ }
+ else
+ {
+ mDevice->SetDepthStencilSurface(nullptr);
+ }
+
+ mStateManager.updateDepthSizeIfChanged(mDepthStencilInitialized, depthSize);
+ mStateManager.updateStencilSizeIfChanged(mDepthStencilInitialized, stencilSize);
+
+ mAppliedDepthStencilSerial = depthStencilSerial;
+ mDepthStencilInitialized = true;
+ }
+
+ if (renderTargetChanged || !mRenderTargetDescInitialized)
+ {
+ mStateManager.forceSetBlendState();
+ mStateManager.forceSetScissorState();
+ mStateManager.setRenderTargetBounds(renderTargetWidth, renderTargetHeight);
+ mRenderTargetDescInitialized = true;
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::applyVertexBuffer(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instances,
+ TranslatedIndexData * /*indexInfo*/)
+{
+ const gl::State &state = context->getState();
+ ANGLE_TRY(mVertexDataManager->prepareVertexData(context, first, count, &mTranslatedAttribCache,
+ instances));
+
+ return mVertexDeclarationCache.applyDeclaration(context, mDevice, mTranslatedAttribCache,
+ state.getProgram(), first, instances,
+ &mRepeatDraw);
+}
+
+// Applies the indices and element array bindings to the Direct3D 9 device
+angle::Result Renderer9::applyIndexBuffer(const gl::Context *context,
+ const void *indices,
+ GLsizei count,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType type,
+ TranslatedIndexData *indexInfo)
+{
+ gl::VertexArray *vao = context->getState().getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
+
+ gl::DrawElementsType dstType = gl::DrawElementsType::InvalidEnum;
+ ANGLE_TRY(GetIndexTranslationDestType(context, count, type, indices, false, &dstType));
+
+ ANGLE_TRY(mIndexDataManager->prepareIndexData(context, type, dstType, count, elementArrayBuffer,
+ indices, indexInfo));
+
+ // Directly binding the storage buffer is not supported for d3d9
+ ASSERT(indexInfo->storage == nullptr);
+
+ if (indexInfo->serial != mAppliedIBSerial)
+ {
+ IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(indexInfo->indexBuffer);
+
+ mDevice->SetIndices(indexBuffer->getBuffer());
+ mAppliedIBSerial = indexInfo->serial;
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::drawArraysImpl(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint startVertex,
+ GLsizei count,
+ GLsizei instances)
+{
+ ASSERT(!context->getState().isTransformFeedbackActiveUnpaused());
+
+ startScene();
+
+ if (mode == gl::PrimitiveMode::LineLoop)
+ {
+ return drawLineLoop(context, count, gl::DrawElementsType::InvalidEnum, nullptr, 0, nullptr);
+ }
+
+ if (instances > 0)
+ {
+ StaticIndexBufferInterface *countingIB = nullptr;
+ ANGLE_TRY(getCountingIB(context, count, &countingIB));
+
+ if (mAppliedIBSerial != countingIB->getSerial())
+ {
+ IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(countingIB->getIndexBuffer());
+
+ mDevice->SetIndices(indexBuffer->getBuffer());
+ mAppliedIBSerial = countingIB->getSerial();
+ }
+
+ for (int i = 0; i < mRepeatDraw; i++)
+ {
+ mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount);
+ }
+
+ return angle::Result::Continue;
+ }
+
+ // Regular case
+ mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount);
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::drawElementsImpl(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances)
+{
+ TranslatedIndexData indexInfo;
+
+ ANGLE_TRY(applyIndexBuffer(context, indices, count, mode, type, &indexInfo));
+
+ gl::IndexRange indexRange;
+ ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(context, type, count, indices,
+ &indexRange));
+
+ size_t vertexCount = indexRange.vertexCount();
+ ANGLE_TRY(applyVertexBuffer(context, mode, static_cast<GLsizei>(indexRange.start),
+ static_cast<GLsizei>(vertexCount), instances, &indexInfo));
+
+ startScene();
+
+ int minIndex = static_cast<int>(indexRange.start);
+
+ gl::VertexArray *vao = context->getState().getVertexArray();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
+
+ if (mode == gl::PrimitiveMode::Points)
+ {
+ return drawIndexedPoints(context, count, type, indices, minIndex, elementArrayBuffer);
+ }
+
+ if (mode == gl::PrimitiveMode::LineLoop)
+ {
+ return drawLineLoop(context, count, type, indices, minIndex, elementArrayBuffer);
+ }
+
+ for (int i = 0; i < mRepeatDraw; i++)
+ {
+ mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex,
+ static_cast<UINT>(vertexCount), indexInfo.startIndex,
+ mPrimitiveCount);
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::drawLineLoop(const gl::Context *context,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ int minIndex,
+ gl::Buffer *elementArrayBuffer)
+{
+ // Get the raw indices for an indexed draw
+ if (type != gl::DrawElementsType::InvalidEnum && elementArrayBuffer)
+ {
+ BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+ const uint8_t *bufferData = nullptr;
+ ANGLE_TRY(storage->getData(context, &bufferData));
+ indices = bufferData + offset;
+ }
+
+ unsigned int startIndex = 0;
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ if (getNativeExtensions().elementIndexUintOES)
+ {
+ if (!mLineLoopIB)
+ {
+ mLineLoopIB = new StreamingIndexBufferInterface(this);
+ ANGLE_TRY(mLineLoopIB->reserveBufferSpace(context, INITIAL_INDEX_BUFFER_SIZE,
+ gl::DrawElementsType::UnsignedInt));
+ }
+
+ // Checked by Renderer9::applyPrimitiveType
+ ASSERT(count >= 0);
+
+ ANGLE_CHECK(context9,
+ static_cast<unsigned int>(count) + 1 <=
+ (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)),
+ "Failed to create a 32-bit looping index buffer for "
+ "GL_LINE_LOOP, too many indices required.",
+ GL_OUT_OF_MEMORY);
+
+ const unsigned int spaceNeeded =
+ (static_cast<unsigned int>(count) + 1) * sizeof(unsigned int);
+ ANGLE_TRY(mLineLoopIB->reserveBufferSpace(context, spaceNeeded,
+ gl::DrawElementsType::UnsignedInt));
+
+ void *mappedMemory = nullptr;
+ unsigned int offset = 0;
+ ANGLE_TRY(mLineLoopIB->mapBuffer(context, spaceNeeded, &mappedMemory, &offset));
+
+ startIndex = static_cast<unsigned int>(offset) / 4;
+ unsigned int *data = static_cast<unsigned int *>(mappedMemory);
+
+ switch (type)
+ {
+ case gl::DrawElementsType::InvalidEnum: // Non-indexed draw
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+ data[count] = 0;
+ break;
+ case gl::DrawElementsType::UnsignedByte:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLubyte *>(indices)[i];
+ }
+ data[count] = static_cast<const GLubyte *>(indices)[0];
+ break;
+ case gl::DrawElementsType::UnsignedShort:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLushort *>(indices)[i];
+ }
+ data[count] = static_cast<const GLushort *>(indices)[0];
+ break;
+ case gl::DrawElementsType::UnsignedInt:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLuint *>(indices)[i];
+ }
+ data[count] = static_cast<const GLuint *>(indices)[0];
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ ANGLE_TRY(mLineLoopIB->unmapBuffer(context));
+ }
+ else
+ {
+ if (!mLineLoopIB)
+ {
+ mLineLoopIB = new StreamingIndexBufferInterface(this);
+ ANGLE_TRY(mLineLoopIB->reserveBufferSpace(context, INITIAL_INDEX_BUFFER_SIZE,
+ gl::DrawElementsType::UnsignedShort));
+ }
+
+ // Checked by Renderer9::applyPrimitiveType
+ ASSERT(count >= 0);
+
+ ANGLE_CHECK(context9,
+ static_cast<unsigned int>(count) + 1 <=
+ (std::numeric_limits<unsigned short>::max() / sizeof(unsigned short)),
+ "Failed to create a 16-bit looping index buffer for "
+ "GL_LINE_LOOP, too many indices required.",
+ GL_OUT_OF_MEMORY);
+
+ const unsigned int spaceNeeded =
+ (static_cast<unsigned int>(count) + 1) * sizeof(unsigned short);
+ ANGLE_TRY(mLineLoopIB->reserveBufferSpace(context, spaceNeeded,
+ gl::DrawElementsType::UnsignedShort));
+
+ void *mappedMemory = nullptr;
+ unsigned int offset;
+ ANGLE_TRY(mLineLoopIB->mapBuffer(context, spaceNeeded, &mappedMemory, &offset));
+
+ startIndex = static_cast<unsigned int>(offset) / 2;
+ unsigned short *data = static_cast<unsigned short *>(mappedMemory);
+
+ switch (type)
+ {
+ case gl::DrawElementsType::InvalidEnum: // Non-indexed draw
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<unsigned short>(i);
+ }
+ data[count] = 0;
+ break;
+ case gl::DrawElementsType::UnsignedByte:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLubyte *>(indices)[i];
+ }
+ data[count] = static_cast<const GLubyte *>(indices)[0];
+ break;
+ case gl::DrawElementsType::UnsignedShort:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLushort *>(indices)[i];
+ }
+ data[count] = static_cast<const GLushort *>(indices)[0];
+ break;
+ case gl::DrawElementsType::UnsignedInt:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<unsigned short>(static_cast<const GLuint *>(indices)[i]);
+ }
+ data[count] = static_cast<unsigned short>(static_cast<const GLuint *>(indices)[0]);
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ ANGLE_TRY(mLineLoopIB->unmapBuffer(context));
+ }
+
+ if (mAppliedIBSerial != mLineLoopIB->getSerial())
+ {
+ IndexBuffer9 *indexBuffer = GetAs<IndexBuffer9>(mLineLoopIB->getIndexBuffer());
+
+ mDevice->SetIndices(indexBuffer->getBuffer());
+ mAppliedIBSerial = mLineLoopIB->getSerial();
+ }
+
+ mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count);
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::drawIndexedPoints(const gl::Context *context,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ int minIndex,
+ gl::Buffer *elementArrayBuffer)
+{
+ // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call
+ // for each individual point. This call is not expected to happen often.
+
+ if (elementArrayBuffer)
+ {
+ BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
+ intptr_t offset = reinterpret_cast<intptr_t>(indices);
+
+ const uint8_t *bufferData = nullptr;
+ ANGLE_TRY(storage->getData(context, &bufferData));
+ indices = bufferData + offset;
+ }
+
+ switch (type)
+ {
+ case gl::DrawElementsType::UnsignedByte:
+ DrawPoints<GLubyte>(mDevice, count, indices, minIndex);
+ return angle::Result::Continue;
+ case gl::DrawElementsType::UnsignedShort:
+ DrawPoints<GLushort>(mDevice, count, indices, minIndex);
+ return angle::Result::Continue;
+ case gl::DrawElementsType::UnsignedInt:
+ DrawPoints<GLuint>(mDevice, count, indices, minIndex);
+ return angle::Result::Continue;
+ default:
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ }
+}
+
+angle::Result Renderer9::getCountingIB(const gl::Context *context,
+ size_t count,
+ StaticIndexBufferInterface **outIB)
+{
+ // Update the counting index buffer if it is not large enough or has not been created yet.
+ if (count <= 65536) // 16-bit indices
+ {
+ const unsigned int spaceNeeded = static_cast<unsigned int>(count) * sizeof(unsigned short);
+
+ if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded)
+ {
+ SafeDelete(mCountingIB);
+ mCountingIB = new StaticIndexBufferInterface(this);
+ ANGLE_TRY(mCountingIB->reserveBufferSpace(context, spaceNeeded,
+ gl::DrawElementsType::UnsignedShort));
+
+ void *mappedMemory = nullptr;
+ ANGLE_TRY(mCountingIB->mapBuffer(context, spaceNeeded, &mappedMemory, nullptr));
+
+ unsigned short *data = static_cast<unsigned short *>(mappedMemory);
+ for (size_t i = 0; i < count; i++)
+ {
+ data[i] = static_cast<unsigned short>(i);
+ }
+
+ ANGLE_TRY(mCountingIB->unmapBuffer(context));
+ }
+ }
+ else if (getNativeExtensions().elementIndexUintOES)
+ {
+ const unsigned int spaceNeeded = static_cast<unsigned int>(count) * sizeof(unsigned int);
+
+ if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded)
+ {
+ SafeDelete(mCountingIB);
+ mCountingIB = new StaticIndexBufferInterface(this);
+ ANGLE_TRY(mCountingIB->reserveBufferSpace(context, spaceNeeded,
+ gl::DrawElementsType::UnsignedInt));
+
+ void *mappedMemory = nullptr;
+ ANGLE_TRY(mCountingIB->mapBuffer(context, spaceNeeded, &mappedMemory, nullptr));
+
+ unsigned int *data = static_cast<unsigned int *>(mappedMemory);
+ for (unsigned int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+
+ ANGLE_TRY(mCountingIB->unmapBuffer(context));
+ }
+ }
+ else
+ {
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), E_OUTOFMEMORY,
+ "Could not create a counting index buffer for glDrawArraysInstanced.");
+ }
+
+ *outIB = mCountingIB;
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::applyShaders(const gl::Context *context, gl::PrimitiveMode drawMode)
+{
+ const gl::State &state = context->getState();
+ d3d::Context *contextD3D = GetImplAs<ContextD3D>(context);
+
+ // This method is called single-threaded.
+ ANGLE_TRY(ensureHLSLCompilerInitialized(contextD3D));
+
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(state.getProgram());
+ VertexArray9 *vao = GetImplAs<VertexArray9>(state.getVertexArray());
+ programD3D->updateCachedInputLayout(vao->getCurrentStateSerial(), state);
+
+ ShaderExecutableD3D *vertexExe = nullptr;
+ ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(contextD3D, &vertexExe, nullptr));
+
+ const gl::Framebuffer *drawFramebuffer = state.getDrawFramebuffer();
+ programD3D->updateCachedOutputLayout(context, drawFramebuffer);
+
+ ShaderExecutableD3D *pixelExe = nullptr;
+ ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(contextD3D, &pixelExe, nullptr));
+
+ IDirect3DVertexShader9 *vertexShader =
+ (vertexExe ? GetAs<ShaderExecutable9>(vertexExe)->getVertexShader() : nullptr);
+ IDirect3DPixelShader9 *pixelShader =
+ (pixelExe ? GetAs<ShaderExecutable9>(pixelExe)->getPixelShader() : nullptr);
+
+ if (vertexShader != mAppliedVertexShader)
+ {
+ mDevice->SetVertexShader(vertexShader);
+ mAppliedVertexShader = vertexShader;
+ }
+
+ if (pixelShader != mAppliedPixelShader)
+ {
+ mDevice->SetPixelShader(pixelShader);
+ mAppliedPixelShader = pixelShader;
+ }
+
+ // D3D9 has a quirk where creating multiple shaders with the same content
+ // can return the same shader pointer. Because GL programs store different data
+ // per-program, checking the program serial guarantees we upload fresh
+ // uniform data even if our shader pointers are the same.
+ // https://code.google.com/p/angleproject/issues/detail?id=661
+ unsigned int programSerial = programD3D->getSerial();
+ if (programSerial != mAppliedProgramSerial)
+ {
+ programD3D->dirtyAllUniforms();
+ mStateManager.forceSetDXUniformsState();
+ mAppliedProgramSerial = programSerial;
+ }
+
+ applyUniforms(programD3D);
+
+ // Driver uniforms
+ mStateManager.setShaderConstants();
+
+ return angle::Result::Continue;
+}
+
+void Renderer9::applyUniforms(ProgramD3D *programD3D)
+{
+ // Skip updates if we're not dirty. Note that D3D9 cannot have compute or geometry.
+ if (!programD3D->anyShaderUniformsDirty())
+ {
+ return;
+ }
+
+ const auto &uniformArray = programD3D->getD3DUniforms();
+
+ for (const D3DUniform *targetUniform : uniformArray)
+ {
+ // Built-in uniforms must be skipped.
+ if (!targetUniform->isReferencedByShader(gl::ShaderType::Vertex) &&
+ !targetUniform->isReferencedByShader(gl::ShaderType::Fragment))
+ continue;
+
+ const GLfloat *f = reinterpret_cast<const GLfloat *>(targetUniform->firstNonNullData());
+ const GLint *i = reinterpret_cast<const GLint *>(targetUniform->firstNonNullData());
+
+ switch (targetUniform->typeInfo.type)
+ {
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_EXTERNAL_OES:
+ case GL_SAMPLER_VIDEO_IMAGE_WEBGL:
+ break;
+ case GL_BOOL:
+ case GL_BOOL_VEC2:
+ case GL_BOOL_VEC3:
+ case GL_BOOL_VEC4:
+ applyUniformnbv(targetUniform, i);
+ break;
+ case GL_FLOAT:
+ case GL_FLOAT_VEC2:
+ case GL_FLOAT_VEC3:
+ case GL_FLOAT_VEC4:
+ case GL_FLOAT_MAT2:
+ case GL_FLOAT_MAT3:
+ case GL_FLOAT_MAT4:
+ applyUniformnfv(targetUniform, f);
+ break;
+ case GL_INT:
+ case GL_INT_VEC2:
+ case GL_INT_VEC3:
+ case GL_INT_VEC4:
+ applyUniformniv(targetUniform, i);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+
+ programD3D->markUniformsClean();
+}
+
+void Renderer9::applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v)
+{
+ if (targetUniform->isReferencedByShader(gl::ShaderType::Fragment))
+ {
+ mDevice->SetPixelShaderConstantF(
+ targetUniform->mShaderRegisterIndexes[gl::ShaderType::Fragment], v,
+ targetUniform->registerCount);
+ }
+
+ if (targetUniform->isReferencedByShader(gl::ShaderType::Vertex))
+ {
+ mDevice->SetVertexShaderConstantF(
+ targetUniform->mShaderRegisterIndexes[gl::ShaderType::Vertex], v,
+ targetUniform->registerCount);
+ }
+}
+
+void Renderer9::applyUniformniv(const D3DUniform *targetUniform, const GLint *v)
+{
+ ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
+ GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
+
+ for (unsigned int i = 0; i < targetUniform->registerCount; i++)
+ {
+ vector[i][0] = (GLfloat)v[4 * i + 0];
+ vector[i][1] = (GLfloat)v[4 * i + 1];
+ vector[i][2] = (GLfloat)v[4 * i + 2];
+ vector[i][3] = (GLfloat)v[4 * i + 3];
+ }
+
+ applyUniformnfv(targetUniform, (GLfloat *)vector);
+}
+
+void Renderer9::applyUniformnbv(const D3DUniform *targetUniform, const GLint *v)
+{
+ ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9);
+ GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4];
+
+ for (unsigned int i = 0; i < targetUniform->registerCount; i++)
+ {
+ vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f;
+ vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f;
+ vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f;
+ vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f;
+ }
+
+ applyUniformnfv(targetUniform, (GLfloat *)vector);
+}
+
+void Renderer9::clear(const ClearParameters &clearParams,
+ const RenderTarget9 *colorRenderTarget,
+ const RenderTarget9 *depthStencilRenderTarget)
+{
+ // Clearing buffers with non-float values is not supported by Renderer9 and ES 2.0
+ ASSERT(clearParams.colorType == GL_FLOAT);
+
+ // Clearing individual buffers other than buffer zero is not supported by Renderer9 and ES 2.0
+ bool clearColor = clearParams.clearColor[0];
+ for (unsigned int i = 0; i < clearParams.clearColor.size(); i++)
+ {
+ ASSERT(clearParams.clearColor[i] == clearColor);
+ }
+
+ float depth = gl::clamp01(clearParams.depthValue);
+ DWORD stencil = clearParams.stencilValue & 0x000000FF;
+
+ unsigned int stencilUnmasked = 0x0;
+ if (clearParams.clearStencil && depthStencilRenderTarget)
+ {
+ const gl::InternalFormat &depthStencilFormat =
+ gl::GetSizedInternalFormatInfo(depthStencilRenderTarget->getInternalFormat());
+ if (depthStencilFormat.stencilBits > 0)
+ {
+ const d3d9::D3DFormat &d3dFormatInfo =
+ d3d9::GetD3DFormatInfo(depthStencilRenderTarget->getD3DFormat());
+ stencilUnmasked = (0x1 << d3dFormatInfo.stencilBits) - 1;
+ }
+ }
+
+ const bool needMaskedStencilClear =
+ clearParams.clearStencil &&
+ (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
+
+ bool needMaskedColorClear = false;
+ D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0);
+ if (clearColor)
+ {
+ ASSERT(colorRenderTarget != nullptr);
+
+ const gl::InternalFormat &formatInfo =
+ gl::GetSizedInternalFormatInfo(colorRenderTarget->getInternalFormat());
+ const d3d9::D3DFormat &d3dFormatInfo =
+ d3d9::GetD3DFormatInfo(colorRenderTarget->getD3DFormat());
+
+ color =
+ D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && d3dFormatInfo.alphaBits > 0)
+ ? 1.0f
+ : clearParams.colorF.alpha),
+ gl::unorm<8>((formatInfo.redBits == 0 && d3dFormatInfo.redBits > 0)
+ ? 0.0f
+ : clearParams.colorF.red),
+ gl::unorm<8>((formatInfo.greenBits == 0 && d3dFormatInfo.greenBits > 0)
+ ? 0.0f
+ : clearParams.colorF.green),
+ gl::unorm<8>((formatInfo.blueBits == 0 && d3dFormatInfo.blueBits > 0)
+ ? 0.0f
+ : clearParams.colorF.blue));
+
+ const uint8_t colorMask =
+ gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(0, clearParams.colorMask);
+ bool r, g, b, a;
+ gl::BlendStateExt::UnpackColorMask(colorMask, &r, &g, &b, &a);
+ if ((formatInfo.redBits > 0 && !r) || (formatInfo.greenBits > 0 && !g) ||
+ (formatInfo.blueBits > 0 && !b) || (formatInfo.alphaBits > 0 && !a))
+ {
+ needMaskedColorClear = true;
+ }
+ }
+
+ if (needMaskedColorClear || needMaskedStencilClear)
+ {
+ // State which is altered in all paths from this point to the clear call is saved.
+ // State which is altered in only some paths will be flagged dirty in the case that
+ // that path is taken.
+ HRESULT hr;
+ if (mMaskedClearSavedState == nullptr)
+ {
+ hr = mDevice->BeginStateBlock();
+ ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+
+ mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
+ mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+ mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+ mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
+ mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ mDevice->SetPixelShader(nullptr);
+ mDevice->SetVertexShader(nullptr);
+ mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
+ mDevice->SetStreamSource(0, nullptr, 0, 0);
+ mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+ mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
+ mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
+ mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
+ mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
+
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mDevice->SetStreamSourceFreq(i, 1);
+ }
+
+ hr = mDevice->EndStateBlock(&mMaskedClearSavedState);
+ ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
+ }
+
+ ASSERT(mMaskedClearSavedState != nullptr);
+
+ if (mMaskedClearSavedState != nullptr)
+ {
+ hr = mMaskedClearSavedState->Capture();
+ ASSERT(SUCCEEDED(hr));
+ }
+
+ mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
+ mDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+ mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+
+ if (clearColor)
+ {
+ // clearParams.colorMask follows the same packing scheme as
+ // D3DCOLORWRITEENABLE_RED/GREEN/BLUE/ALPHA
+ mDevice->SetRenderState(
+ D3DRS_COLORWRITEENABLE,
+ gl::BlendStateExt::ColorMaskStorage::GetValueIndexed(0, clearParams.colorMask));
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
+ }
+
+ if (stencilUnmasked != 0x0 && clearParams.clearStencil)
+ {
+ mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+ mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
+ mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
+ mDevice->SetRenderState(D3DRS_STENCILREF, stencil);
+ mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask);
+ mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
+ mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
+ mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
+ }
+ else
+ {
+ mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ }
+
+ mDevice->SetPixelShader(nullptr);
+ mDevice->SetVertexShader(nullptr);
+ mDevice->SetFVF(D3DFVF_XYZRHW);
+ mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+ mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
+ mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
+ mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
+ mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color);
+ mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
+
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mDevice->SetStreamSourceFreq(i, 1);
+ }
+
+ int renderTargetWidth = mStateManager.getRenderTargetWidth();
+ int renderTargetHeight = mStateManager.getRenderTargetHeight();
+
+ float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges
+ quad[0][0] = -0.5f;
+ quad[0][1] = renderTargetHeight - 0.5f;
+ quad[0][2] = 0.0f;
+ quad[0][3] = 1.0f;
+
+ quad[1][0] = renderTargetWidth - 0.5f;
+ quad[1][1] = renderTargetHeight - 0.5f;
+ quad[1][2] = 0.0f;
+ quad[1][3] = 1.0f;
+
+ quad[2][0] = -0.5f;
+ quad[2][1] = -0.5f;
+ quad[2][2] = 0.0f;
+ quad[2][3] = 1.0f;
+
+ quad[3][0] = renderTargetWidth - 0.5f;
+ quad[3][1] = -0.5f;
+ quad[3][2] = 0.0f;
+ quad[3][3] = 1.0f;
+
+ startScene();
+ mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
+
+ if (clearParams.clearDepth)
+ {
+ mDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
+ mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
+ mDevice->Clear(0, nullptr, D3DCLEAR_ZBUFFER, color, depth, stencil);
+ }
+
+ if (mMaskedClearSavedState != nullptr)
+ {
+ mMaskedClearSavedState->Apply();
+ }
+ }
+ else if (clearColor || clearParams.clearDepth || clearParams.clearStencil)
+ {
+ DWORD dxClearFlags = 0;
+ if (clearColor)
+ {
+ dxClearFlags |= D3DCLEAR_TARGET;
+ }
+ if (clearParams.clearDepth)
+ {
+ dxClearFlags |= D3DCLEAR_ZBUFFER;
+ }
+ if (clearParams.clearStencil)
+ {
+ dxClearFlags |= D3DCLEAR_STENCIL;
+ }
+
+ mDevice->Clear(0, nullptr, dxClearFlags, color, depth, stencil);
+ }
+}
+
+void Renderer9::markAllStateDirty()
+{
+ mAppliedRenderTargetSerial = 0;
+ mAppliedDepthStencilSerial = 0;
+ mDepthStencilInitialized = false;
+ mRenderTargetDescInitialized = false;
+
+ mStateManager.forceSetRasterState();
+ mStateManager.forceSetDepthStencilState();
+ mStateManager.forceSetBlendState();
+ mStateManager.forceSetScissorState();
+ mStateManager.forceSetViewportState();
+
+ ASSERT(mCurVertexSamplerStates.size() == mCurVertexTextures.size());
+ for (unsigned int i = 0; i < mCurVertexTextures.size(); i++)
+ {
+ mCurVertexSamplerStates[i].forceSet = true;
+ mCurVertexTextures[i] = angle::DirtyPointer;
+ }
+
+ ASSERT(mCurPixelSamplerStates.size() == mCurPixelTextures.size());
+ for (unsigned int i = 0; i < mCurPixelSamplerStates.size(); i++)
+ {
+ mCurPixelSamplerStates[i].forceSet = true;
+ mCurPixelTextures[i] = angle::DirtyPointer;
+ }
+
+ mAppliedIBSerial = 0;
+ mAppliedVertexShader = nullptr;
+ mAppliedPixelShader = nullptr;
+ mAppliedProgramSerial = 0;
+ mStateManager.forceSetDXUniformsState();
+
+ mVertexDeclarationCache.markStateDirty();
+}
+
+void Renderer9::releaseDeviceResources()
+{
+ for (size_t i = 0; i < mEventQueryPool.size(); i++)
+ {
+ SafeRelease(mEventQueryPool[i]);
+ }
+ mEventQueryPool.clear();
+
+ SafeRelease(mMaskedClearSavedState);
+
+ mVertexShaderCache.clear();
+ mPixelShaderCache.clear();
+
+ SafeDelete(mBlit);
+ SafeDelete(mVertexDataManager);
+ SafeDelete(mIndexDataManager);
+ SafeDelete(mLineLoopIB);
+ SafeDelete(mCountingIB);
+
+ for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++)
+ {
+ SafeDelete(mNullRenderTargetCache[i].renderTarget);
+ }
+}
+
+// set notify to true to broadcast a message to all contexts of the device loss
+bool Renderer9::testDeviceLost()
+{
+ HRESULT status = getDeviceStatusCode();
+ return FAILED(status);
+}
+
+HRESULT Renderer9::getDeviceStatusCode()
+{
+ HRESULT status = D3D_OK;
+
+ if (mDeviceEx)
+ {
+ status = mDeviceEx->CheckDeviceState(nullptr);
+ }
+ else if (mDevice)
+ {
+ status = mDevice->TestCooperativeLevel();
+ }
+
+ return status;
+}
+
+bool Renderer9::testDeviceResettable()
+{
+ // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted
+ // DEVICEREMOVED indicates the device has been stopped and must be recreated
+ switch (getDeviceStatusCode())
+ {
+ case D3DERR_DEVICENOTRESET:
+ case D3DERR_DEVICEHUNG:
+ return true;
+ case D3DERR_DEVICELOST:
+ return (mDeviceEx != nullptr);
+ case D3DERR_DEVICEREMOVED:
+ ASSERT(mDeviceEx != nullptr);
+ return isRemovedDeviceResettable();
+ default:
+ return false;
+ }
+}
+
+bool Renderer9::resetDevice()
+{
+ releaseDeviceResources();
+
+ D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
+
+ HRESULT result = D3D_OK;
+ bool lost = testDeviceLost();
+ bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED);
+
+ // Device Removed is a feature which is only present with D3D9Ex
+ ASSERT(mDeviceEx != nullptr || !removedDevice);
+
+ for (int attempts = 3; lost && attempts > 0; attempts--)
+ {
+ if (removedDevice)
+ {
+ // Device removed, which may trigger on driver reinstallation,
+ // may cause a longer wait other reset attempts before the
+ // system is ready to handle creating a new device.
+ Sleep(800);
+ lost = !resetRemovedDevice();
+ }
+ else if (mDeviceEx)
+ {
+ Sleep(500); // Give the graphics driver some CPU time
+ result = mDeviceEx->ResetEx(&presentParameters, nullptr);
+ lost = testDeviceLost();
+ }
+ else
+ {
+ result = mDevice->TestCooperativeLevel();
+ while (result == D3DERR_DEVICELOST)
+ {
+ Sleep(100); // Give the graphics driver some CPU time
+ result = mDevice->TestCooperativeLevel();
+ }
+
+ if (result == D3DERR_DEVICENOTRESET)
+ {
+ result = mDevice->Reset(&presentParameters);
+ }
+ lost = testDeviceLost();
+ }
+ }
+
+ if (FAILED(result))
+ {
+ ERR() << "Reset/ResetEx failed multiple times, " << gl::FmtHR(result);
+ return false;
+ }
+
+ if (removedDevice && lost)
+ {
+ ERR() << "Device lost reset failed multiple times";
+ return false;
+ }
+
+ // If the device was removed, we already finished re-initialization in resetRemovedDevice
+ if (!removedDevice)
+ {
+ // reset device defaults
+ if (initializeDevice().isError())
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool Renderer9::isRemovedDeviceResettable() const
+{
+ bool success = false;
+
+#if ANGLE_D3D9EX == ANGLE_ENABLED
+ IDirect3D9Ex *d3d9Ex = nullptr;
+ typedef HRESULT(WINAPI * Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex **);
+ Direct3DCreate9ExFunc Direct3DCreate9ExPtr =
+ reinterpret_cast<Direct3DCreate9ExFunc>(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex"));
+
+ if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex)))
+ {
+ D3DCAPS9 deviceCaps;
+ HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps);
+ success = SUCCEEDED(result);
+ }
+
+ SafeRelease(d3d9Ex);
+#else
+ UNREACHABLE();
+#endif
+
+ return success;
+}
+
+bool Renderer9::resetRemovedDevice()
+{
+ // From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx:
+ // The hardware adapter has been removed. Application must destroy the device, do enumeration of
+ // adapters and create another Direct3D device. If application continues rendering without
+ // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only.
+ release();
+ return !initialize().isError();
+}
+
+VendorID Renderer9::getVendorId() const
+{
+ return static_cast<VendorID>(mAdapterIdentifier.VendorId);
+}
+
+std::string Renderer9::getRendererDescription() const
+{
+ std::ostringstream rendererString;
+
+ rendererString << mAdapterIdentifier.Description;
+ if (getShareHandleSupport())
+ {
+ rendererString << " Direct3D9Ex";
+ }
+ else
+ {
+ rendererString << " Direct3D9";
+ }
+
+ rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_"
+ << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion);
+ rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_"
+ << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
+
+ return rendererString.str();
+}
+
+DeviceIdentifier Renderer9::getAdapterIdentifier() const
+{
+ DeviceIdentifier deviceIdentifier = {};
+ deviceIdentifier.VendorId = static_cast<UINT>(mAdapterIdentifier.VendorId);
+ deviceIdentifier.DeviceId = static_cast<UINT>(mAdapterIdentifier.DeviceId);
+ deviceIdentifier.SubSysId = static_cast<UINT>(mAdapterIdentifier.SubSysId);
+ deviceIdentifier.Revision = static_cast<UINT>(mAdapterIdentifier.Revision);
+ deviceIdentifier.FeatureLevel = 0;
+
+ return deviceIdentifier;
+}
+
+unsigned int Renderer9::getReservedVertexUniformVectors() const
+{
+ return d3d9_gl::GetReservedVertexUniformVectors();
+}
+
+unsigned int Renderer9::getReservedFragmentUniformVectors() const
+{
+ return d3d9_gl::GetReservedFragmentUniformVectors();
+}
+
+bool Renderer9::getShareHandleSupport() const
+{
+ // PIX doesn't seem to support using share handles, so disable them.
+ return (mD3d9Ex != nullptr) && !gl::DebugAnnotationsActive(/*context=*/nullptr);
+}
+
+int Renderer9::getMajorShaderModel() const
+{
+ return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion);
+}
+
+int Renderer9::getMinorShaderModel() const
+{
+ return D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
+}
+
+std::string Renderer9::getShaderModelSuffix() const
+{
+ return "";
+}
+
+DWORD Renderer9::getCapsDeclTypes() const
+{
+ return mDeviceCaps.DeclTypes;
+}
+
+D3DPOOL Renderer9::getBufferPool(DWORD usage) const
+{
+ if (mD3d9Ex != nullptr)
+ {
+ return D3DPOOL_DEFAULT;
+ }
+ else
+ {
+ if (!(usage & D3DUSAGE_DYNAMIC))
+ {
+ return D3DPOOL_MANAGED;
+ }
+ }
+
+ return D3DPOOL_DEFAULT;
+}
+
+angle::Result Renderer9::copyImage2D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level)
+{
+ RECT rect;
+ rect.left = sourceRect.x;
+ rect.top = sourceRect.y;
+ rect.right = sourceRect.x + sourceRect.width;
+ rect.bottom = sourceRect.y + sourceRect.height;
+
+ return mBlit->copy2D(context, framebuffer, rect, destFormat, destOffset, storage, level);
+}
+
+angle::Result Renderer9::copyImageCube(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ gl::TextureTarget target,
+ GLint level)
+{
+ RECT rect;
+ rect.left = sourceRect.x;
+ rect.top = sourceRect.y;
+ rect.right = sourceRect.x + sourceRect.width;
+ rect.bottom = sourceRect.y + sourceRect.height;
+
+ return mBlit->copyCube(context, framebuffer, rect, destFormat, destOffset, storage, target,
+ level);
+}
+
+angle::Result Renderer9::copyImage3D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level)
+{
+ // 3D textures are not available in the D3D9 backend.
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Renderer9::copyImage2DArray(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level)
+{
+ // 2D array textures are not available in the D3D9 backend.
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Renderer9::copyTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ gl::TextureTarget srcTarget,
+ const gl::Box &sourceBox,
+ GLenum destFormat,
+ GLenum destType,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ gl::TextureTarget destTarget,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+ RECT rect;
+ rect.left = sourceBox.x;
+ rect.top = sourceBox.y;
+ rect.right = sourceBox.x + sourceBox.width;
+ rect.bottom = sourceBox.y + sourceBox.height;
+
+ return mBlit->copyTexture(context, source, sourceLevel, rect, destFormat, destOffset, storage,
+ destTarget, destLevel, unpackFlipY, unpackPremultiplyAlpha,
+ unpackUnmultiplyAlpha);
+}
+
+angle::Result Renderer9::copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ TextureStorage *storage,
+ GLint destLevel)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Renderer9::createRenderTarget(const gl::Context *context,
+ int width,
+ int height,
+ GLenum format,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format);
+
+ const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format);
+ GLuint supportedSamples = textureCaps.getNearestSamples(samples);
+
+ IDirect3DTexture9 *texture = nullptr;
+ IDirect3DSurface9 *renderTarget = nullptr;
+ if (width > 0 && height > 0)
+ {
+ bool requiresInitialization = false;
+ HRESULT result = D3DERR_INVALIDCALL;
+
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(format);
+ if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
+ {
+ result = mDevice->CreateDepthStencilSurface(
+ width, height, d3d9FormatInfo.renderFormat,
+ gl_d3d9::GetMultisampleType(supportedSamples), 0, FALSE, &renderTarget, nullptr);
+ }
+ else
+ {
+ requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != nullptr);
+ if (supportedSamples > 0)
+ {
+ result = mDevice->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat,
+ gl_d3d9::GetMultisampleType(supportedSamples),
+ 0, FALSE, &renderTarget, nullptr);
+ }
+ else
+ {
+ result = mDevice->CreateTexture(
+ width, height, 1, D3DUSAGE_RENDERTARGET, d3d9FormatInfo.texFormat,
+ getTexturePool(D3DUSAGE_RENDERTARGET), &texture, nullptr);
+ if (!FAILED(result))
+ {
+ result = texture->GetSurfaceLevel(0, &renderTarget);
+ }
+ }
+ }
+
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to create render target");
+
+ if (requiresInitialization)
+ {
+ // This format requires that the data be initialized before the render target can be
+ // used Unfortunately this requires a Get call on the d3d device but it is far better
+ // than having to mark the render target as lockable and copy data to the gpu.
+ IDirect3DSurface9 *prevRenderTarget = nullptr;
+ mDevice->GetRenderTarget(0, &prevRenderTarget);
+ mDevice->SetRenderTarget(0, renderTarget);
+ mDevice->Clear(0, nullptr, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0);
+ mDevice->SetRenderTarget(0, prevRenderTarget);
+ }
+ }
+
+ *outRT = new TextureRenderTarget9(texture, 0, renderTarget, format, width, height, 1,
+ supportedSamples);
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::createRenderTargetCopy(const gl::Context *context,
+ RenderTargetD3D *source,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(source != nullptr);
+
+ RenderTargetD3D *newRT = nullptr;
+ ANGLE_TRY(createRenderTarget(context, source->getWidth(), source->getHeight(),
+ source->getInternalFormat(), source->getSamples(), &newRT));
+
+ RenderTarget9 *source9 = GetAs<RenderTarget9>(source);
+ RenderTarget9 *dest9 = GetAs<RenderTarget9>(newRT);
+
+ HRESULT result = mDevice->StretchRect(source9->getSurface(), nullptr, dest9->getSurface(),
+ nullptr, D3DTEXF_NONE);
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to copy render target");
+
+ *outRT = newRT;
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::loadExecutable(d3d::Context *context,
+ const uint8_t *function,
+ size_t length,
+ gl::ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ ShaderExecutableD3D **outExecutable)
+{
+ // Transform feedback is not supported in ES2 or D3D9
+ ASSERT(streamOutVaryings.empty());
+
+ switch (type)
+ {
+ case gl::ShaderType::Vertex:
+ {
+ IDirect3DVertexShader9 *vshader = nullptr;
+ ANGLE_TRY(createVertexShader(context, (DWORD *)function, length, &vshader));
+ *outExecutable = new ShaderExecutable9(function, length, vshader);
+ }
+ break;
+ case gl::ShaderType::Fragment:
+ {
+ IDirect3DPixelShader9 *pshader = nullptr;
+ ANGLE_TRY(createPixelShader(context, (DWORD *)function, length, &pshader));
+ *outExecutable = new ShaderExecutable9(function, length, pshader);
+ }
+ break;
+ default:
+ ANGLE_HR_UNREACHABLE(context);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::compileToExecutable(d3d::Context *context,
+ gl::InfoLog &infoLog,
+ const std::string &shaderHLSL,
+ gl::ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ const CompilerWorkaroundsD3D &workarounds,
+ ShaderExecutableD3D **outExectuable)
+{
+ // Transform feedback is not supported in ES2 or D3D9
+ ASSERT(streamOutVaryings.empty());
+
+ std::stringstream profileStream;
+
+ switch (type)
+ {
+ case gl::ShaderType::Vertex:
+ profileStream << "vs";
+ break;
+ case gl::ShaderType::Fragment:
+ profileStream << "ps";
+ break;
+ default:
+ ANGLE_HR_UNREACHABLE(context);
+ }
+
+ profileStream << "_" << ((getMajorShaderModel() >= 3) ? 3 : 2);
+ profileStream << "_"
+ << "0";
+
+ std::string profile = profileStream.str();
+
+ UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL;
+
+ if (workarounds.skipOptimization)
+ {
+ flags = D3DCOMPILE_SKIP_OPTIMIZATION;
+ }
+ else if (workarounds.useMaxOptimization)
+ {
+ flags = D3DCOMPILE_OPTIMIZATION_LEVEL3;
+ }
+
+ if (gl::DebugAnnotationsActive(/*context=*/nullptr))
+ {
+#ifndef NDEBUG
+ flags = D3DCOMPILE_SKIP_OPTIMIZATION;
+#endif
+
+ flags |= D3DCOMPILE_DEBUG;
+ }
+
+ // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders
+ // when it would otherwise pass with alternative options. Try the default flags first and if
+ // compilation fails, try some alternatives.
+ std::vector<CompileConfig> configs;
+ configs.push_back(CompileConfig(flags, "default"));
+ configs.push_back(CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control"));
+ configs.push_back(CompileConfig(flags | D3DCOMPILE_PREFER_FLOW_CONTROL, "prefer flow control"));
+
+ ID3DBlob *binary = nullptr;
+ std::string debugInfo;
+ angle::Result error = mCompiler.compileToBinary(context, infoLog, shaderHLSL, profile, configs,
+ nullptr, &binary, &debugInfo);
+ ANGLE_TRY(error);
+
+ // It's possible that binary is NULL if the compiler failed in all configurations. Set the
+ // executable to NULL and return GL_NO_ERROR to signify that there was a link error but the
+ // internal state is still OK.
+ if (!binary)
+ {
+ *outExectuable = nullptr;
+ return angle::Result::Continue;
+ }
+
+ error = loadExecutable(context, reinterpret_cast<const uint8_t *>(binary->GetBufferPointer()),
+ binary->GetBufferSize(), type, streamOutVaryings, separatedOutputBuffers,
+ outExectuable);
+
+ SafeRelease(binary);
+ ANGLE_TRY(error);
+
+ if (!debugInfo.empty())
+ {
+ (*outExectuable)->appendDebugInfo(debugInfo);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::ensureHLSLCompilerInitialized(d3d::Context *context)
+{
+ return mCompiler.ensureInitialized(context);
+}
+
+UniformStorageD3D *Renderer9::createUniformStorage(size_t storageSize)
+{
+ return new UniformStorageD3D(storageSize);
+}
+
+angle::Result Renderer9::boxFilter(Context9 *context9,
+ IDirect3DSurface9 *source,
+ IDirect3DSurface9 *dest)
+{
+ return mBlit->boxFilter(context9, source, dest);
+}
+
+D3DPOOL Renderer9::getTexturePool(DWORD usage) const
+{
+ if (mD3d9Ex != nullptr)
+ {
+ return D3DPOOL_DEFAULT;
+ }
+ else
+ {
+ if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET)))
+ {
+ return D3DPOOL_MANAGED;
+ }
+ }
+
+ return D3DPOOL_DEFAULT;
+}
+
+angle::Result Renderer9::copyToRenderTarget(const gl::Context *context,
+ IDirect3DSurface9 *dest,
+ IDirect3DSurface9 *source,
+ bool fromManaged)
+{
+ ASSERT(source && dest);
+
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ HRESULT result = D3DERR_OUTOFVIDEOMEMORY;
+
+ if (fromManaged)
+ {
+ D3DSURFACE_DESC desc;
+ source->GetDesc(&desc);
+
+ IDirect3DSurface9 *surf = 0;
+ result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+ D3DPOOL_SYSTEMMEM, &surf, nullptr);
+
+ if (SUCCEEDED(result))
+ {
+ ANGLE_TRY(Image9::CopyLockableSurfaces(context9, surf, source));
+ result = mDevice->UpdateSurface(surf, nullptr, dest, nullptr);
+ SafeRelease(surf);
+ }
+ }
+ else
+ {
+ endScene();
+ result = mDevice->StretchRect(source, nullptr, dest, nullptr, D3DTEXF_NONE);
+ }
+
+ ANGLE_TRY_HR(context9, result, "Failed to blit internal texture");
+ return angle::Result::Continue;
+}
+
+RendererClass Renderer9::getRendererClass() const
+{
+ return RENDERER_D3D9;
+}
+
+ImageD3D *Renderer9::createImage()
+{
+ return new Image9(this);
+}
+
+ExternalImageSiblingImpl *Renderer9::createExternalImageSibling(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs)
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+angle::Result Renderer9::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src)
+{
+ Image9 *src9 = GetAs<Image9>(src);
+ Image9 *dst9 = GetAs<Image9>(dest);
+ return Image9::GenerateMipmap(GetImplAs<Context9>(context), dst9, src9);
+}
+
+angle::Result Renderer9::generateMipmapUsingD3D(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::TextureState &textureState)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result Renderer9::copyImage(const gl::Context *context,
+ ImageD3D *dest,
+ ImageD3D *source,
+ const gl::Box &sourceBox,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+ Image9 *dest9 = GetAs<Image9>(dest);
+ Image9 *src9 = GetAs<Image9>(source);
+ return Image9::CopyImage(context, dest9, src9, sourceBox.toRect(), destOffset, unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha);
+}
+
+TextureStorage *Renderer9::createTextureStorage2D(SwapChainD3D *swapChain, const std::string &label)
+{
+ SwapChain9 *swapChain9 = GetAs<SwapChain9>(swapChain);
+ return new TextureStorage9_2D(this, swapChain9, label);
+}
+
+TextureStorage *Renderer9::createTextureStorageEGLImage(EGLImageD3D *eglImage,
+ RenderTargetD3D *renderTargetD3D,
+ const std::string &label)
+{
+ return new TextureStorage9_EGLImage(this, eglImage, GetAs<RenderTarget9>(renderTargetD3D),
+ label);
+}
+
+TextureStorage *Renderer9::createTextureStorageBuffer(
+ const gl::OffsetBindingPointer<gl::Buffer> &buffer,
+ GLenum internalFormat,
+ const std::string &label)
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+TextureStorage *Renderer9::createTextureStorageExternal(
+ egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc,
+ const std::string &label)
+{
+ UNIMPLEMENTED();
+ return nullptr;
+}
+
+TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ const std::string &label,
+ bool hintLevelZeroOnly)
+{
+ return new TextureStorage9_2D(this, internalformat, bindFlags.renderTarget, width, height,
+ levels, label);
+}
+
+TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat,
+ BindFlags bindFlags,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly,
+ const std::string &label)
+{
+ return new TextureStorage9_Cube(this, internalformat, bindFlags.renderTarget, size, levels,
+ hintLevelZeroOnly, label);
+}
+
+TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ const std::string &label)
+{
+ // 3D textures are not supported by the D3D9 backend.
+ UNREACHABLE();
+
+ return nullptr;
+}
+
+TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ const std::string &label)
+{
+ // 2D array textures are not supported by the D3D9 backend.
+ UNREACHABLE();
+
+ return nullptr;
+}
+
+TextureStorage *Renderer9::createTextureStorage2DMultisample(GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ int samples,
+ bool fixedSampleLocations,
+ const std::string &label)
+{
+ // 2D multisampled textures are not supported by the D3D9 backend.
+ UNREACHABLE();
+
+ return nullptr;
+}
+
+TextureStorage *Renderer9::createTextureStorage2DMultisampleArray(GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ int samples,
+ bool fixedSampleLocations,
+ const std::string &label)
+{
+ // 2D multisampled textures are not supported by the D3D9 backend.
+ UNREACHABLE();
+
+ return nullptr;
+}
+
+bool Renderer9::getLUID(LUID *adapterLuid) const
+{
+ adapterLuid->HighPart = 0;
+ adapterLuid->LowPart = 0;
+
+ if (mD3d9Ex)
+ {
+ mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid);
+ return true;
+ }
+
+ return false;
+}
+
+VertexConversionType Renderer9::getVertexConversionType(angle::FormatID vertexFormatID) const
+{
+ return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatID).conversionType;
+}
+
+GLenum Renderer9::getVertexComponentType(angle::FormatID vertexFormatID) const
+{
+ return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatID).componentType;
+}
+
+angle::Result Renderer9::getVertexSpaceRequired(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance,
+ unsigned int *bytesRequiredOut) const
+{
+ if (!attrib.enabled)
+ {
+ *bytesRequiredOut = 16u;
+ return angle::Result::Continue;
+ }
+
+ angle::FormatID vertexFormatID = gl::GetVertexFormatID(attrib, gl::VertexAttribType::Float);
+ const d3d9::VertexFormat &d3d9VertexInfo =
+ d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatID);
+
+ unsigned int elementCount = 0;
+ const unsigned int divisor = binding.getDivisor();
+ if (instances == 0 || divisor == 0)
+ {
+ elementCount = static_cast<unsigned int>(count);
+ }
+ else
+ {
+ // Round up to divisor, if possible
+ elementCount = UnsignedCeilDivide(static_cast<unsigned int>(instances), divisor);
+ }
+
+ bool check = (d3d9VertexInfo.outputElementSize >
+ std::numeric_limits<unsigned int>::max() / elementCount);
+ ANGLE_CHECK(GetImplAs<Context9>(context), !check,
+ "New vertex buffer size would result in an overflow.", GL_OUT_OF_MEMORY);
+
+ *bytesRequiredOut = static_cast<unsigned int>(d3d9VertexInfo.outputElementSize) * elementCount;
+ return angle::Result::Continue;
+}
+
+void Renderer9::generateCaps(gl::Caps *outCaps,
+ gl::TextureCapsMap *outTextureCaps,
+ gl::Extensions *outExtensions,
+ gl::Limitations *outLimitations) const
+{
+ d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps,
+ outExtensions, outLimitations);
+}
+
+void Renderer9::initializeFeatures(angle::FeaturesD3D *features) const
+{
+ if (!mDisplay->getState().featuresAllDisabled)
+ {
+ d3d9::InitializeFeatures(features);
+ }
+ ApplyFeatureOverrides(features, mDisplay->getState());
+}
+
+void Renderer9::initializeFrontendFeatures(angle::FrontendFeatures *features) const {}
+
+DeviceImpl *Renderer9::createEGLDevice()
+{
+ return new DeviceD3D(EGL_D3D9_DEVICE_ANGLE, mDevice);
+}
+
+Renderer9::CurSamplerState::CurSamplerState()
+ : forceSet(true), baseLevel(std::numeric_limits<size_t>::max()), samplerState()
+{}
+
+angle::Result Renderer9::genericDrawElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances)
+{
+ const gl::State &state = context->getState();
+ gl::Program *program = context->getState().getProgram();
+ ASSERT(program != nullptr);
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+ bool usesPointSize = programD3D->usesPointSize();
+
+ programD3D->updateSamplerMapping();
+
+ if (!applyPrimitiveType(mode, count, usesPointSize))
+ {
+ return angle::Result::Continue;
+ }
+
+ ANGLE_TRY(updateState(context, mode));
+ ANGLE_TRY(applyTextures(context));
+ ANGLE_TRY(applyShaders(context, mode));
+
+ if (!skipDraw(state, mode))
+ {
+ ANGLE_TRY(drawElementsImpl(context, mode, count, type, indices, instances));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::genericDrawArrays(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instances)
+{
+ gl::Program *program = context->getState().getProgram();
+ ASSERT(program != nullptr);
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+ bool usesPointSize = programD3D->usesPointSize();
+
+ programD3D->updateSamplerMapping();
+
+ if (!applyPrimitiveType(mode, count, usesPointSize))
+ {
+ return angle::Result::Continue;
+ }
+
+ ANGLE_TRY(updateState(context, mode));
+ ANGLE_TRY(applyVertexBuffer(context, mode, first, count, instances, nullptr));
+ ANGLE_TRY(applyTextures(context));
+ ANGLE_TRY(applyShaders(context, mode));
+
+ if (!skipDraw(context->getState(), mode))
+ {
+ ANGLE_TRY(drawArraysImpl(context, mode, first, count, instances));
+ }
+
+ return angle::Result::Continue;
+}
+
+FramebufferImpl *Renderer9::createDefaultFramebuffer(const gl::FramebufferState &state)
+{
+ return new Framebuffer9(state, this);
+}
+
+gl::Version Renderer9::getMaxSupportedESVersion() const
+{
+ return gl::Version(2, 0);
+}
+
+gl::Version Renderer9::getMaxConformantESVersion() const
+{
+ return gl::Version(2, 0);
+}
+
+angle::Result Renderer9::clearRenderTarget(const gl::Context *context,
+ RenderTargetD3D *renderTarget,
+ const gl::ColorF &clearColorValue,
+ const float clearDepthValue,
+ const unsigned int clearStencilValue)
+{
+ D3DCOLOR color =
+ D3DCOLOR_ARGB(gl::unorm<8>(clearColorValue.alpha), gl::unorm<8>(clearColorValue.red),
+ gl::unorm<8>(clearColorValue.green), gl::unorm<8>(clearColorValue.blue));
+ float depth = clearDepthValue;
+ DWORD stencil = clearStencilValue & 0x000000FF;
+
+ unsigned int renderTargetSerial = renderTarget->getSerial();
+ RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTarget);
+ IDirect3DSurface9 *renderTargetSurface = renderTarget9->getSurface();
+ ASSERT(renderTargetSurface);
+
+ DWORD dxClearFlags = 0;
+
+ const gl::InternalFormat &internalFormatInfo =
+ gl::GetSizedInternalFormatInfo(renderTarget->getInternalFormat());
+ if (internalFormatInfo.depthBits > 0 || internalFormatInfo.stencilBits > 0)
+ {
+ dxClearFlags = D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL;
+ if (mAppliedDepthStencilSerial != renderTargetSerial)
+ {
+ mDevice->SetDepthStencilSurface(renderTargetSurface);
+ }
+ }
+ else
+ {
+ dxClearFlags = D3DCLEAR_TARGET;
+ if (mAppliedRenderTargetSerial != renderTargetSerial)
+ {
+ mDevice->SetRenderTarget(0, renderTargetSurface);
+ }
+ }
+ SafeRelease(renderTargetSurface);
+
+ D3DVIEWPORT9 viewport;
+ viewport.X = 0;
+ viewport.Y = 0;
+ viewport.Width = renderTarget->getWidth();
+ viewport.Height = renderTarget->getHeight();
+ mDevice->SetViewport(&viewport);
+
+ mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+
+ mDevice->Clear(0, nullptr, dxClearFlags, color, depth, stencil);
+
+ markAllStateDirty();
+
+ return angle::Result::Continue;
+}
+
+bool Renderer9::canSelectViewInVertexShader() const
+{
+ return false;
+}
+
+// For each Direct3D sampler of either the pixel or vertex stage,
+// looks up the corresponding OpenGL texture image unit and texture type,
+// and sets the texture and its addressing/filtering state (or NULL when inactive).
+// Sampler mapping needs to be up-to-date on the program object before this is called.
+angle::Result Renderer9::applyTextures(const gl::Context *context, gl::ShaderType shaderType)
+{
+ const auto &glState = context->getState();
+ const auto &caps = context->getCaps();
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(glState.getProgram());
+
+ ASSERT(!programD3D->isSamplerMappingDirty());
+
+ // TODO(jmadill): Use the Program's sampler bindings.
+ const gl::ActiveTexturesCache &activeTextures = glState.getActiveTexturesCache();
+
+ const gl::RangeUI samplerRange = programD3D->getUsedSamplerRange(shaderType);
+ for (unsigned int samplerIndex = samplerRange.low(); samplerIndex < samplerRange.high();
+ samplerIndex++)
+ {
+ GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps);
+ ASSERT(textureUnit != -1);
+ gl::Texture *texture = activeTextures[textureUnit];
+
+ // A nullptr texture indicates incomplete.
+ if (texture)
+ {
+ gl::Sampler *samplerObject = glState.getSampler(textureUnit);
+
+ const gl::SamplerState &samplerState =
+ samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState();
+
+ ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState));
+ ANGLE_TRY(setTexture(context, shaderType, samplerIndex, texture));
+ }
+ else
+ {
+ gl::TextureType textureType =
+ programD3D->getSamplerTextureType(shaderType, samplerIndex);
+
+ // Texture is not sampler complete or it is in use by the framebuffer. Bind the
+ // incomplete texture.
+ gl::Texture *incompleteTexture = nullptr;
+ ANGLE_TRY(getIncompleteTexture(context, textureType, &incompleteTexture));
+ ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture,
+ incompleteTexture->getSamplerState()));
+ ANGLE_TRY(setTexture(context, shaderType, samplerIndex, incompleteTexture));
+ }
+ }
+
+ // Set all the remaining textures to NULL
+ int samplerCount = (shaderType == gl::ShaderType::Fragment)
+ ? caps.maxShaderTextureImageUnits[gl::ShaderType::Fragment]
+ : caps.maxShaderTextureImageUnits[gl::ShaderType::Vertex];
+
+ // TODO(jmadill): faster way?
+ for (int samplerIndex = samplerRange.high(); samplerIndex < samplerCount; samplerIndex++)
+ {
+ ANGLE_TRY(setTexture(context, shaderType, samplerIndex, nullptr));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::applyTextures(const gl::Context *context)
+{
+ ANGLE_TRY(applyTextures(context, gl::ShaderType::Vertex));
+ ANGLE_TRY(applyTextures(context, gl::ShaderType::Fragment));
+ return angle::Result::Continue;
+}
+
+angle::Result Renderer9::getIncompleteTexture(const gl::Context *context,
+ gl::TextureType type,
+ gl::Texture **textureOut)
+{
+ return GetImplAs<Context9>(context)->getIncompleteTexture(context, type, textureOut);
+}
+
+angle::Result Renderer9::ensureVertexDataManagerInitialized(const gl::Context *context)
+{
+ if (!mVertexDataManager)
+ {
+ mVertexDataManager = new VertexDataManager(this);
+ ANGLE_TRY(mVertexDataManager->initialize(context));
+ }
+
+ return angle::Result::Continue;
+}
+
+std::string Renderer9::getVendorString() const
+{
+ return GetVendorString(getVendorId());
+}
+
+std::string Renderer9::getVersionString(bool includeFullVersion) const
+{
+ std::ostringstream versionString;
+ std::string driverName(mAdapterIdentifier.Driver);
+ if (!driverName.empty())
+ {
+ versionString << mAdapterIdentifier.Driver;
+ }
+ else
+ {
+ versionString << "D3D9";
+ }
+
+ if (includeFullVersion)
+ {
+ versionString << " -";
+ versionString << GetDriverVersionString(mAdapterIdentifier.DriverVersion);
+ }
+
+ return versionString.str();
+}
+
+RendererD3D *CreateRenderer9(egl::Display *display)
+{
+ return new Renderer9(display);
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Renderer9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
new file mode 100644
index 0000000000..67a20f56ba
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
@@ -0,0 +1,586 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Renderer9.h: Defines a back-end specific class for the D3D9 renderer.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_
+
+#include "common/angleutils.h"
+#include "common/mathutil.h"
+#include "libANGLE/renderer/d3d/HLSLCompiler.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h"
+#include "libANGLE/renderer/d3d/d3d9/ShaderCache.h"
+#include "libANGLE/renderer/d3d/d3d9/StateManager9.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h"
+#include "libANGLE/renderer/driver_utils.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+}
+
+namespace egl
+{
+class AttributeMap;
+}
+
+namespace rx
+{
+class Blit9;
+class Context9;
+class IndexDataManager;
+class ProgramD3D;
+class RenderTarget9;
+class StreamingIndexBufferInterface;
+class StaticIndexBufferInterface;
+class VertexDataManager;
+struct ClearParameters;
+struct D3DUniform;
+struct TranslatedAttribute;
+
+class Renderer9 : public RendererD3D
+{
+ public:
+ explicit Renderer9(egl::Display *display);
+ ~Renderer9() override;
+
+ egl::Error initialize() override;
+ bool resetDevice() override;
+
+ egl::ConfigSet generateConfigs() override;
+ void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const override;
+
+ void startScene();
+ void endScene();
+
+ angle::Result flush(const gl::Context *context);
+ angle::Result finish(const gl::Context *context);
+
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+ NativeWindowD3D *createNativeWindow(EGLNativeWindowType window,
+ const egl::Config *config,
+ const egl::AttributeMap &attribs) const override;
+
+ SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow,
+ HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation,
+ EGLint samples) override;
+ egl::Error getD3DTextureInfo(const egl::Config *configuration,
+ IUnknown *d3dTexture,
+ const egl::AttributeMap &attribs,
+ EGLint *width,
+ EGLint *height,
+ GLsizei *samples,
+ gl::Format *glFormat,
+ const angle::Format **angleFormat,
+ UINT *arraySlice) const override;
+ egl::Error validateShareHandle(const egl::Config *config,
+ HANDLE shareHandle,
+ const egl::AttributeMap &attribs) const override;
+
+ ContextImpl *createContext(const gl::State &state, gl::ErrorSet *errorSet) override;
+
+ angle::Result allocateEventQuery(const gl::Context *context, IDirect3DQuery9 **outQuery);
+ void freeEventQuery(IDirect3DQuery9 *query);
+
+ // resource creation
+ angle::Result createVertexShader(d3d::Context *context,
+ const DWORD *function,
+ size_t length,
+ IDirect3DVertexShader9 **outShader);
+ angle::Result createPixelShader(d3d::Context *context,
+ const DWORD *function,
+ size_t length,
+ IDirect3DPixelShader9 **outShader);
+ HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer);
+ HRESULT createIndexBuffer(UINT Length,
+ DWORD Usage,
+ D3DFORMAT Format,
+ IDirect3DIndexBuffer9 **ppIndexBuffer);
+ angle::Result setSamplerState(const gl::Context *context,
+ gl::ShaderType type,
+ int index,
+ gl::Texture *texture,
+ const gl::SamplerState &sampler);
+ angle::Result setTexture(const gl::Context *context,
+ gl::ShaderType type,
+ int index,
+ gl::Texture *texture);
+
+ angle::Result updateState(const gl::Context *context, gl::PrimitiveMode drawMode);
+
+ void setScissorRectangle(const gl::Rectangle &scissor, bool enabled);
+ void setViewport(const gl::Rectangle &viewport,
+ float zNear,
+ float zFar,
+ gl::PrimitiveMode drawMode,
+ GLenum frontFace,
+ bool ignoreViewport);
+
+ angle::Result applyRenderTarget(const gl::Context *context,
+ const RenderTarget9 *colorRenderTarget,
+ const RenderTarget9 *depthStencilRenderTarget);
+ void applyUniforms(ProgramD3D *programD3D);
+ bool applyPrimitiveType(gl::PrimitiveMode primitiveType,
+ GLsizei elementCount,
+ bool usesPointSize);
+ angle::Result applyVertexBuffer(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instances,
+ TranslatedIndexData *indexInfo);
+ angle::Result applyIndexBuffer(const gl::Context *context,
+ const void *indices,
+ GLsizei count,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType type,
+ TranslatedIndexData *indexInfo);
+
+ void clear(const ClearParameters &clearParams,
+ const RenderTarget9 *colorRenderTarget,
+ const RenderTarget9 *depthStencilRenderTarget);
+
+ void markAllStateDirty();
+
+ // lost device
+ bool testDeviceLost() override;
+ bool testDeviceResettable() override;
+
+ VendorID getVendorId() const;
+ DeviceIdentifier getAdapterIdentifier() const override;
+
+ IDirect3DDevice9 *getDevice() { return mDevice; }
+ void *getD3DDevice() override;
+
+ unsigned int getReservedVertexUniformVectors() const;
+ unsigned int getReservedFragmentUniformVectors() const;
+
+ bool getShareHandleSupport() const;
+
+ int getMajorShaderModel() const override;
+ int getMinorShaderModel() const override;
+ std::string getShaderModelSuffix() const override;
+
+ DWORD getCapsDeclTypes() const;
+
+ // Pixel operations
+ angle::Result copyImage2D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+ angle::Result copyImageCube(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ gl::TextureTarget target,
+ GLint level) override;
+ angle::Result copyImage3D(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+ angle::Result copyImage2DArray(const gl::Context *context,
+ const gl::Framebuffer *framebuffer,
+ const gl::Rectangle &sourceRect,
+ GLenum destFormat,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ GLint level) override;
+
+ angle::Result copyTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ gl::TextureTarget srcTarget,
+ const gl::Box &sourceBox,
+ GLenum destFormat,
+ GLenum destType,
+ const gl::Offset &destOffset,
+ TextureStorage *storage,
+ gl::TextureTarget destTarget,
+ GLint destLevel,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha) override;
+ angle::Result copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source,
+ GLint sourceLevel,
+ TextureStorage *storage,
+ GLint destLevel) override;
+
+ // RenderTarget creation
+ angle::Result createRenderTarget(const gl::Context *context,
+ int width,
+ int height,
+ GLenum format,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+ angle::Result createRenderTargetCopy(const gl::Context *context,
+ RenderTargetD3D *source,
+ RenderTargetD3D **outRT) override;
+
+ // Shader operations
+ angle::Result loadExecutable(d3d::Context *context,
+ const uint8_t *function,
+ size_t length,
+ gl::ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ ShaderExecutableD3D **outExecutable) override;
+ angle::Result compileToExecutable(d3d::Context *context,
+ gl::InfoLog &infoLog,
+ const std::string &shaderHLSL,
+ gl::ShaderType type,
+ const std::vector<D3DVarying> &streamOutVaryings,
+ bool separatedOutputBuffers,
+ const CompilerWorkaroundsD3D &workarounds,
+ ShaderExecutableD3D **outExectuable) override;
+ angle::Result ensureHLSLCompilerInitialized(d3d::Context *context) override;
+
+ UniformStorageD3D *createUniformStorage(size_t storageSize) override;
+
+ // Image operations
+ ImageD3D *createImage() override;
+ ExternalImageSiblingImpl *createExternalImageSibling(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs) override;
+ angle::Result generateMipmap(const gl::Context *context,
+ ImageD3D *dest,
+ ImageD3D *source) override;
+ angle::Result generateMipmapUsingD3D(const gl::Context *context,
+ TextureStorage *storage,
+ const gl::TextureState &textureState) override;
+ angle::Result copyImage(const gl::Context *context,
+ ImageD3D *dest,
+ ImageD3D *source,
+ const gl::Box &sourceBox,
+ const gl::Offset &destOffset,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha) override;
+ TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain,
+ const std::string &label) override;
+ TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage,
+ RenderTargetD3D *renderTargetD3D,
+ const std::string &label) override;
+
+ TextureStorage *createTextureStorageBuffer(const gl::OffsetBindingPointer<gl::Buffer> &buffer,
+ GLenum internalFormat,
+ const std::string &label) override;
+
+ TextureStorage *createTextureStorageExternal(egl::Stream *stream,
+ const egl::Stream::GLTextureDescription &desc,
+ const std::string &label) override;
+
+ TextureStorage *createTextureStorage2D(GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ const std::string &label,
+ bool hintLevelZeroOnly) override;
+ TextureStorage *createTextureStorageCube(GLenum internalformat,
+ BindFlags bindFlags,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly,
+ const std::string &label) override;
+ TextureStorage *createTextureStorage3D(GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ const std::string &label) override;
+ TextureStorage *createTextureStorage2DArray(GLenum internalformat,
+ BindFlags bindFlags,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ const std::string &label) override;
+
+ TextureStorage *createTextureStorage2DMultisample(GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ int samples,
+ bool fixedSampleLocations,
+ const std::string &label) override;
+ TextureStorage *createTextureStorage2DMultisampleArray(GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ int levels,
+ int samples,
+ bool fixedSampleLocations,
+ const std::string &label) override;
+
+ // Buffer creation
+ VertexBuffer *createVertexBuffer() override;
+ IndexBuffer *createIndexBuffer() override;
+
+ // Stream Creation
+ StreamProducerImpl *createStreamProducerD3DTexture(egl::Stream::ConsumerType consumerType,
+ const egl::AttributeMap &attribs) override;
+
+ // Buffer-to-texture and Texture-to-buffer copies
+ bool supportsFastCopyBufferToTexture(GLenum internalFormat) const override;
+ angle::Result fastCopyBufferToTexture(const gl::Context *context,
+ const gl::PixelUnpackState &unpack,
+ gl::Buffer *unpackBuffer,
+ unsigned int offset,
+ RenderTargetD3D *destRenderTarget,
+ GLenum destinationFormat,
+ GLenum sourcePixelsType,
+ const gl::Box &destArea) override;
+
+ // D3D9-renderer specific methods
+ angle::Result boxFilter(Context9 *context9, IDirect3DSurface9 *source, IDirect3DSurface9 *dest);
+
+ D3DPOOL getTexturePool(DWORD usage) const;
+
+ bool getLUID(LUID *adapterLuid) const override;
+ VertexConversionType getVertexConversionType(angle::FormatID vertexFormatID) const override;
+ GLenum getVertexComponentType(angle::FormatID vertexFormatID) const override;
+
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+ // function.
+ angle::Result getVertexSpaceRequired(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ size_t count,
+ GLsizei instances,
+ GLuint baseInstance,
+ unsigned int *bytesRequiredOut) const override;
+
+ angle::Result copyToRenderTarget(const gl::Context *context,
+ IDirect3DSurface9 *dest,
+ IDirect3DSurface9 *source,
+ bool fromManaged);
+
+ RendererClass getRendererClass() const override;
+
+ D3DDEVTYPE getD3D9DeviceType() const { return mDeviceType; }
+
+ DeviceImpl *createEGLDevice() override;
+
+ StateManager9 *getStateManager() { return &mStateManager; }
+
+ angle::Result genericDrawArrays(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instances);
+
+ angle::Result genericDrawElements(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances);
+
+ // Necessary hack for default framebuffers in D3D.
+ FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override;
+
+ DebugAnnotator9 *getAnnotator() { return &mAnnotator; }
+
+ gl::Version getMaxSupportedESVersion() const override;
+ gl::Version getMaxConformantESVersion() const override;
+
+ angle::Result clearRenderTarget(const gl::Context *context,
+ RenderTargetD3D *renderTarget,
+ const gl::ColorF &clearColorValue,
+ const float clearDepthValue,
+ const unsigned int clearStencilValue) override;
+
+ bool canSelectViewInVertexShader() const override;
+
+ angle::Result getIncompleteTexture(const gl::Context *context,
+ gl::TextureType type,
+ gl::Texture **textureOut) override;
+
+ angle::Result ensureVertexDataManagerInitialized(const gl::Context *context);
+
+ void setGlobalDebugAnnotator() override;
+
+ std::string getRendererDescription() const override;
+ std::string getVendorString() const override;
+ std::string getVersionString(bool includeFullVersion) const override;
+
+ private:
+ angle::Result drawArraysImpl(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLint startVertex,
+ GLsizei count,
+ GLsizei instances);
+ angle::Result drawElementsImpl(const gl::Context *context,
+ gl::PrimitiveMode mode,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ GLsizei instances);
+
+ angle::Result applyShaders(const gl::Context *context, gl::PrimitiveMode drawMode);
+
+ angle::Result applyTextures(const gl::Context *context);
+ angle::Result applyTextures(const gl::Context *context, gl::ShaderType shaderType);
+
+ void generateCaps(gl::Caps *outCaps,
+ gl::TextureCapsMap *outTextureCaps,
+ gl::Extensions *outExtensions,
+ gl::Limitations *outLimitations) const override;
+
+ void initializeFeatures(angle::FeaturesD3D *features) const override;
+
+ void initializeFrontendFeatures(angle::FrontendFeatures *features) const override;
+
+ angle::Result setBlendDepthRasterStates(const gl::Context *context, gl::PrimitiveMode drawMode);
+
+ void release();
+
+ void applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v);
+ void applyUniformniv(const D3DUniform *targetUniform, const GLint *v);
+ void applyUniformnbv(const D3DUniform *targetUniform, const GLint *v);
+
+ angle::Result drawLineLoop(const gl::Context *context,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ int minIndex,
+ gl::Buffer *elementArrayBuffer);
+ angle::Result drawIndexedPoints(const gl::Context *context,
+ GLsizei count,
+ gl::DrawElementsType type,
+ const void *indices,
+ int minIndex,
+ gl::Buffer *elementArrayBuffer);
+
+ angle::Result getCountingIB(const gl::Context *context,
+ size_t count,
+ StaticIndexBufferInterface **outIB);
+
+ angle::Result getNullColorRenderTarget(const gl::Context *context,
+ const RenderTarget9 *depthRenderTarget,
+ const RenderTarget9 **outColorRenderTarget);
+
+ D3DPOOL getBufferPool(DWORD usage) const;
+
+ HMODULE mD3d9Module;
+
+ egl::Error initializeDevice();
+ D3DPRESENT_PARAMETERS getDefaultPresentParameters();
+ void releaseDeviceResources();
+
+ HRESULT getDeviceStatusCode();
+ bool isRemovedDeviceResettable() const;
+ bool resetRemovedDevice();
+
+ UINT mAdapter;
+ D3DDEVTYPE mDeviceType;
+ IDirect3D9 *mD3d9; // Always valid after successful initialization.
+ IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported.
+ IDirect3DDevice9 *mDevice;
+ IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported.
+
+ HLSLCompiler mCompiler;
+
+ Blit9 *mBlit;
+
+ HWND mDeviceWindow;
+
+ D3DCAPS9 mDeviceCaps;
+ D3DADAPTER_IDENTIFIER9 mAdapterIdentifier;
+
+ D3DPRIMITIVETYPE mPrimitiveType;
+ int mPrimitiveCount;
+ GLsizei mRepeatDraw;
+
+ bool mSceneStarted;
+
+ bool mVertexTextureSupport;
+
+ // current render target states
+ unsigned int mAppliedRenderTargetSerial;
+ unsigned int mAppliedDepthStencilSerial;
+ bool mDepthStencilInitialized;
+ bool mRenderTargetDescInitialized;
+
+ IDirect3DStateBlock9 *mMaskedClearSavedState;
+
+ StateManager9 mStateManager;
+
+ // Currently applied sampler states
+ struct CurSamplerState
+ {
+ CurSamplerState();
+
+ bool forceSet;
+ size_t baseLevel;
+ gl::SamplerState samplerState;
+ };
+ std::vector<CurSamplerState> mCurVertexSamplerStates;
+ std::vector<CurSamplerState> mCurPixelSamplerStates;
+
+ // Currently applied textures
+ std::vector<uintptr_t> mCurVertexTextures;
+ std::vector<uintptr_t> mCurPixelTextures;
+
+ unsigned int mAppliedIBSerial;
+ IDirect3DVertexShader9 *mAppliedVertexShader;
+ IDirect3DPixelShader9 *mAppliedPixelShader;
+ unsigned int mAppliedProgramSerial;
+
+ // A pool of event queries that are currently unused.
+ std::vector<IDirect3DQuery9 *> mEventQueryPool;
+ VertexShaderCache mVertexShaderCache;
+ PixelShaderCache mPixelShaderCache;
+
+ VertexDataManager *mVertexDataManager;
+ VertexDeclarationCache mVertexDeclarationCache;
+
+ IndexDataManager *mIndexDataManager;
+ StreamingIndexBufferInterface *mLineLoopIB;
+ StaticIndexBufferInterface *mCountingIB;
+
+ enum
+ {
+ NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12
+ };
+ struct NullRenderTargetCacheEntry
+ {
+ UINT lruCount;
+ int width;
+ int height;
+ RenderTarget9 *renderTarget;
+ };
+
+ std::array<NullRenderTargetCacheEntry, NUM_NULL_COLORBUFFER_CACHE_ENTRIES>
+ mNullRenderTargetCache;
+ UINT mMaxNullColorbufferLRU;
+
+ std::vector<TranslatedAttribute> mTranslatedAttribCache;
+
+ DebugAnnotator9 mAnnotator;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h
new file mode 100644
index 0000000000..bd1a4cf269
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h
@@ -0,0 +1,110 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderCache: Defines rx::ShaderCache, a cache of Direct3D shader objects
+// keyed by their byte code.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/d3d/d3d9/Context9.h"
+
+#include <cstddef>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+
+namespace rx
+{
+template <typename ShaderObject>
+class ShaderCache : angle::NonCopyable
+{
+ public:
+ ShaderCache() : mDevice(nullptr) {}
+
+ ~ShaderCache()
+ {
+ // Call clear while the device is still valid.
+ ASSERT(mMap.empty());
+ }
+
+ void initialize(IDirect3DDevice9 *device) { mDevice = device; }
+
+ angle::Result create(d3d::Context *context,
+ const DWORD *function,
+ size_t length,
+ ShaderObject **outShaderObject)
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ std::string key(reinterpret_cast<const char *>(function), length);
+ typename Map::iterator it = mMap.find(key);
+ if (it != mMap.end())
+ {
+ it->second->AddRef();
+ *outShaderObject = it->second;
+ return angle::Result::Continue;
+ }
+
+ ShaderObject *shader;
+ HRESULT result = createShader(function, &shader);
+ ANGLE_TRY_HR(context, result, "Failed to create shader");
+
+ // Random eviction policy.
+ if (mMap.size() >= kMaxMapSize)
+ {
+ SafeRelease(mMap.begin()->second);
+ mMap.erase(mMap.begin());
+ }
+
+ shader->AddRef();
+ mMap[key] = shader;
+
+ *outShaderObject = shader;
+ return angle::Result::Continue;
+ }
+
+ void clear()
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it)
+ {
+ SafeRelease(it->second);
+ }
+
+ mMap.clear();
+ }
+
+ private:
+ const static size_t kMaxMapSize = 100;
+
+ HRESULT createShader(const DWORD *function, IDirect3DVertexShader9 **shader)
+ {
+ return mDevice->CreateVertexShader(function, shader);
+ }
+
+ HRESULT createShader(const DWORD *function, IDirect3DPixelShader9 **shader)
+ {
+ return mDevice->CreatePixelShader(function, shader);
+ }
+
+ typedef angle::HashMap<std::string, ShaderObject *> Map;
+ Map mMap;
+ std::mutex mMutex;
+
+ IDirect3DDevice9 *mDevice;
+};
+
+typedef ShaderCache<IDirect3DVertexShader9> VertexShaderCache;
+typedef ShaderCache<IDirect3DPixelShader9> PixelShaderCache;
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp
new file mode 100644
index 0000000000..b5c237f9a7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp
@@ -0,0 +1,51 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader
+// executable implementation details.
+
+#include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+ShaderExecutable9::ShaderExecutable9(const void *function,
+ size_t length,
+ IDirect3DPixelShader9 *executable)
+ : ShaderExecutableD3D(function, length)
+{
+ mPixelExecutable = executable;
+ mVertexExecutable = nullptr;
+}
+
+ShaderExecutable9::ShaderExecutable9(const void *function,
+ size_t length,
+ IDirect3DVertexShader9 *executable)
+ : ShaderExecutableD3D(function, length)
+{
+ mVertexExecutable = executable;
+ mPixelExecutable = nullptr;
+}
+
+ShaderExecutable9::~ShaderExecutable9()
+{
+ SafeRelease(mVertexExecutable);
+ SafeRelease(mPixelExecutable);
+}
+
+IDirect3DVertexShader9 *ShaderExecutable9::getVertexShader() const
+{
+ return mVertexExecutable;
+}
+
+IDirect3DPixelShader9 *ShaderExecutable9::getPixelShader() const
+{
+ return mPixelExecutable;
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h
new file mode 100644
index 0000000000..0c8c595ef0
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h
@@ -0,0 +1,35 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderExecutable9.h: Defines a D3D9-specific class to contain shader
+// executable implementation details.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_
+
+#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
+
+namespace rx
+{
+
+class ShaderExecutable9 : public ShaderExecutableD3D
+{
+ public:
+ ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable);
+ ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable);
+ ~ShaderExecutable9() override;
+
+ IDirect3DPixelShader9 *getPixelShader() const;
+ IDirect3DVertexShader9 *getVertexShader() const;
+
+ private:
+ IDirect3DPixelShader9 *mPixelExecutable;
+ IDirect3DVertexShader9 *mVertexExecutable;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp
new file mode 100644
index 0000000000..cad011b25a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp
@@ -0,0 +1,888 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StateManager9.cpp: Defines a class for caching D3D9 state
+#include "libANGLE/renderer/d3d/d3d9/StateManager9.h"
+
+#include "common/bitset_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+
+namespace rx
+{
+
+StateManager9::StateManager9(Renderer9 *renderer9)
+ : mUsingZeroColorMaskWorkaround(false),
+ mCurSampleAlphaToCoverage(false),
+ mCurBlendState(),
+ mCurBlendColor(0, 0, 0, 0),
+ mCurSampleMask(0),
+ mCurRasterState(),
+ mCurDepthSize(0),
+ mCurDepthStencilState(),
+ mCurStencilRef(0),
+ mCurStencilBackRef(0),
+ mCurFrontFaceCCW(0),
+ mCurStencilSize(0),
+ mCurScissorRect(),
+ mCurScissorEnabled(false),
+ mCurViewport(),
+ mCurNear(0.0f),
+ mCurFar(0.0f),
+ mCurDepthFront(0.0f),
+ mCurIgnoreViewport(false),
+ mRenderer9(renderer9),
+ mDirtyBits()
+{
+ mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
+ mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
+ mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+ mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE);
+ mBlendStateDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+ mBlendStateDirtyBits.set(DIRTY_BIT_DITHER);
+ mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_MASK);
+
+ mRasterizerStateDirtyBits.set(DIRTY_BIT_CULL_MODE);
+ mRasterizerStateDirtyBits.set(DIRTY_BIT_DEPTH_BIAS);
+
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT);
+ mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK);
+
+ mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED);
+ mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_RECT);
+}
+
+StateManager9::~StateManager9() {}
+
+void StateManager9::initialize()
+{
+ mUsingZeroColorMaskWorkaround = IsAMD(mRenderer9->getVendorId());
+}
+
+void StateManager9::forceSetBlendState()
+{
+ mDirtyBits |= mBlendStateDirtyBits;
+}
+
+void StateManager9::forceSetRasterState()
+{
+ mDirtyBits |= mRasterizerStateDirtyBits;
+}
+
+void StateManager9::forceSetDepthStencilState()
+{
+ mDirtyBits |= mDepthStencilStateDirtyBits;
+}
+
+void StateManager9::forceSetScissorState()
+{
+ mDirtyBits |= mScissorStateDirtyBits;
+}
+
+void StateManager9::forceSetViewportState()
+{
+ mForceSetViewport = true;
+}
+
+void StateManager9::forceSetDXUniformsState()
+{
+ mDxUniformsDirty = true;
+}
+
+void StateManager9::updateStencilSizeIfChanged(bool depthStencilInitialized,
+ unsigned int stencilSize)
+{
+ if (!depthStencilInitialized || stencilSize != mCurStencilSize)
+ {
+ mCurStencilSize = stencilSize;
+ forceSetDepthStencilState();
+ }
+}
+
+void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits)
+{
+ if (!dirtyBits.any())
+ {
+ return;
+ }
+
+ for (auto dirtyBit : dirtyBits)
+ {
+ switch (dirtyBit)
+ {
+ case gl::State::DIRTY_BIT_BLEND_ENABLED:
+ if (state.getBlendState().blend != mCurBlendState.blend)
+ {
+ mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
+ // BlendColor and funcs and equations has to be set if blend is enabled
+ mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
+ mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+
+ // The color mask may have to be updated if the blend state changes
+ if (mUsingZeroColorMaskWorkaround)
+ {
+ mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+ }
+ }
+ break;
+ case gl::State::DIRTY_BIT_BLEND_FUNCS:
+ {
+ const gl::BlendState &blendState = state.getBlendState();
+ if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB ||
+ blendState.destBlendRGB != mCurBlendState.destBlendRGB ||
+ blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha ||
+ blendState.destBlendAlpha != mCurBlendState.destBlendAlpha)
+ {
+ mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+ // BlendColor depends on the values of blend funcs
+ mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
+
+ // The color mask may have to be updated if the blend funcs change
+ if (mUsingZeroColorMaskWorkaround)
+ {
+ mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+ }
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
+ {
+ const gl::BlendState &blendState = state.getBlendState();
+ if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB ||
+ blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha)
+ {
+ mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+
+ // The color mask may have to be updated if the blend funcs change
+ if (mUsingZeroColorMaskWorkaround)
+ {
+ mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+ }
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
+ if (state.isSampleAlphaToCoverageEnabled() != mCurSampleAlphaToCoverage)
+ {
+ mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE);
+ }
+ break;
+ case gl::State::DIRTY_BIT_COLOR_MASK:
+ {
+ const gl::BlendState &blendState = state.getBlendState();
+ if (blendState.colorMaskRed != mCurBlendState.colorMaskRed ||
+ blendState.colorMaskGreen != mCurBlendState.colorMaskGreen ||
+ blendState.colorMaskBlue != mCurBlendState.colorMaskBlue ||
+ blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha)
+ {
+ mDirtyBits.set(DIRTY_BIT_COLOR_MASK);
+
+ // The color mask can cause the blend state to get out of sync when using the
+ // zero color mask workaround
+ if (mUsingZeroColorMaskWorkaround)
+ {
+ mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED);
+ mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS);
+ }
+ }
+ break;
+ }
+ case gl::State::DIRTY_BIT_DITHER_ENABLED:
+ if (state.getRasterizerState().dither != mCurRasterState.dither)
+ {
+ mDirtyBits.set(DIRTY_BIT_DITHER);
+ }
+ break;
+ case gl::State::DIRTY_BIT_BLEND_COLOR:
+ if (state.getBlendColor() != mCurBlendColor)
+ {
+ mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
+ }
+ break;
+ case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
+ if (state.getRasterizerState().cullFace != mCurRasterState.cullFace)
+ {
+ mDirtyBits.set(DIRTY_BIT_CULL_MODE);
+ }
+ break;
+ case gl::State::DIRTY_BIT_CULL_FACE:
+ if (state.getRasterizerState().cullMode != mCurRasterState.cullMode)
+ {
+ mDirtyBits.set(DIRTY_BIT_CULL_MODE);
+ }
+ break;
+ case gl::State::DIRTY_BIT_FRONT_FACE:
+ if (state.getRasterizerState().frontFace != mCurRasterState.frontFace)
+ {
+ mDirtyBits.set(DIRTY_BIT_CULL_MODE);
+
+ // Viewport state depends on rasterizer.frontface
+ mDirtyBits.set(DIRTY_BIT_VIEWPORT);
+ }
+ break;
+ case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
+ if (state.getRasterizerState().polygonOffsetFill !=
+ mCurRasterState.polygonOffsetFill)
+ {
+ mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS);
+ }
+ break;
+ case gl::State::DIRTY_BIT_POLYGON_OFFSET:
+ {
+ const gl::RasterizerState &rasterizerState = state.getRasterizerState();
+ if (rasterizerState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor ||
+ rasterizerState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits)
+ {
+ mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS);
+ }
+ break;
+ }
+ // Depth and stencil redundant state changes are guarded in the
+ // frontend so for related cases here just set the dirty bit.
+ case gl::State::DIRTY_BIT_DEPTH_MASK:
+ if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask)
+ {
+ mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK);
+ }
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED:
+ mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC);
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_FUNC:
+ mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED:
+ mDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED);
+ // If we enable the stencil test, all of these must be set
+ mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+ mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+ mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
+ mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
+ mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT);
+ mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT:
+ mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK:
+ mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
+ mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK:
+ mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT:
+ mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT);
+ break;
+ case gl::State::DIRTY_BIT_STENCIL_OPS_BACK:
+ mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK);
+ break;
+ case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED:
+ if (state.isScissorTestEnabled() != mCurScissorEnabled)
+ {
+ mDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED);
+ // If scissor is enabled, we have to set the scissor rect
+ mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT);
+ }
+ break;
+ case gl::State::DIRTY_BIT_SCISSOR:
+ if (state.getScissor() != mCurScissorRect)
+ {
+ mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT);
+ }
+ break;
+ case gl::State::DIRTY_BIT_DEPTH_RANGE:
+ mDirtyBits.set(DIRTY_BIT_VIEWPORT);
+ break;
+ case gl::State::DIRTY_BIT_VIEWPORT:
+ if (state.getViewport() != mCurViewport)
+ {
+ mDirtyBits.set(DIRTY_BIT_VIEWPORT);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void StateManager9::setBlendDepthRasterStates(const gl::State &glState, unsigned int sampleMask)
+{
+ const gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
+
+ const gl::BlendState &blendState = glState.getBlendState();
+ const gl::ColorF &blendColor = glState.getBlendColor();
+ const gl::RasterizerState &rasterState = glState.getRasterizerState();
+
+ const auto &depthStencilState = glState.getDepthStencilState();
+ bool frontFaceCCW = (glState.getRasterizerState().frontFace == GL_CCW);
+ unsigned int maxStencil = (1 << mCurStencilSize) - 1;
+
+ // All the depth stencil states depends on the front face ccw variable
+ if (frontFaceCCW != mCurFrontFaceCCW)
+ {
+ forceSetDepthStencilState();
+ mCurFrontFaceCCW = frontFaceCCW;
+ }
+
+ for (auto dirtyBit : mDirtyBits)
+ {
+ switch (dirtyBit)
+ {
+ case DIRTY_BIT_BLEND_ENABLED:
+ setBlendEnabled(blendState.blend);
+ break;
+ case DIRTY_BIT_BLEND_COLOR:
+ setBlendColor(blendState, blendColor);
+ break;
+ case DIRTY_BIT_BLEND_FUNCS_EQUATIONS:
+ setBlendFuncsEquations(blendState);
+ break;
+ case DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE:
+ setSampleAlphaToCoverage(glState.isSampleAlphaToCoverageEnabled());
+ break;
+ case DIRTY_BIT_COLOR_MASK:
+ setColorMask(framebuffer, blendState.colorMaskRed, blendState.colorMaskBlue,
+ blendState.colorMaskGreen, blendState.colorMaskAlpha);
+ break;
+ case DIRTY_BIT_DITHER:
+ setDither(rasterState.dither);
+ break;
+ case DIRTY_BIT_CULL_MODE:
+ setCullMode(rasterState.cullFace, rasterState.cullMode, rasterState.frontFace);
+ break;
+ case DIRTY_BIT_DEPTH_BIAS:
+ setDepthBias(rasterState.polygonOffsetFill, rasterState.polygonOffsetFactor,
+ rasterState.polygonOffsetUnits);
+ break;
+ case DIRTY_BIT_STENCIL_DEPTH_MASK:
+ setDepthMask(depthStencilState.depthMask);
+ break;
+ case DIRTY_BIT_STENCIL_DEPTH_FUNC:
+ setDepthFunc(depthStencilState.depthTest, depthStencilState.depthFunc);
+ break;
+ case DIRTY_BIT_STENCIL_TEST_ENABLED:
+ setStencilTestEnabled(depthStencilState.stencilTest);
+ break;
+ case DIRTY_BIT_STENCIL_FUNCS_FRONT:
+ setStencilFuncsFront(depthStencilState.stencilFunc, depthStencilState.stencilMask,
+ glState.getStencilRef(), frontFaceCCW, maxStencil);
+ break;
+ case DIRTY_BIT_STENCIL_FUNCS_BACK:
+ setStencilFuncsBack(depthStencilState.stencilBackFunc,
+ depthStencilState.stencilBackMask, glState.getStencilBackRef(),
+ frontFaceCCW, maxStencil);
+ break;
+ case DIRTY_BIT_STENCIL_WRITEMASK_FRONT:
+ setStencilWriteMask(depthStencilState.stencilWritemask, frontFaceCCW);
+ break;
+ case DIRTY_BIT_STENCIL_WRITEMASK_BACK:
+ setStencilBackWriteMask(depthStencilState.stencilBackWritemask, frontFaceCCW);
+ break;
+ case DIRTY_BIT_STENCIL_OPS_FRONT:
+ setStencilOpsFront(depthStencilState.stencilFail,
+ depthStencilState.stencilPassDepthFail,
+ depthStencilState.stencilPassDepthPass, frontFaceCCW);
+ break;
+ case DIRTY_BIT_STENCIL_OPS_BACK:
+ setStencilOpsBack(depthStencilState.stencilBackFail,
+ depthStencilState.stencilBackPassDepthFail,
+ depthStencilState.stencilBackPassDepthPass, frontFaceCCW);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (sampleMask != mCurSampleMask)
+ {
+ setSampleMask(sampleMask);
+ }
+}
+
+void StateManager9::setViewportState(const gl::Rectangle &viewport,
+ float zNear,
+ float zFar,
+ gl::PrimitiveMode drawMode,
+ GLenum frontFace,
+ bool ignoreViewport)
+{
+ if (!mDirtyBits.test(DIRTY_BIT_VIEWPORT) && mCurIgnoreViewport == ignoreViewport)
+ return;
+
+ gl::Rectangle actualViewport = viewport;
+ float actualZNear = gl::clamp01(zNear);
+ float actualZFar = gl::clamp01(zFar);
+
+ if (ignoreViewport)
+ {
+ actualViewport.x = 0;
+ actualViewport.y = 0;
+ actualViewport.width = static_cast<int>(mRenderTargetBounds.width);
+ actualViewport.height = static_cast<int>(mRenderTargetBounds.height);
+ actualZNear = 0.0f;
+ actualZFar = 1.0f;
+ }
+
+ D3DVIEWPORT9 dxViewport;
+ dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast<int>(mRenderTargetBounds.width));
+ dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast<int>(mRenderTargetBounds.height));
+ dxViewport.Width =
+ gl::clamp(actualViewport.width, 0,
+ static_cast<int>(mRenderTargetBounds.width) - static_cast<int>(dxViewport.X));
+ dxViewport.Height =
+ gl::clamp(actualViewport.height, 0,
+ static_cast<int>(mRenderTargetBounds.height) - static_cast<int>(dxViewport.Y));
+ dxViewport.MinZ = actualZNear;
+ dxViewport.MaxZ = actualZFar;
+
+ float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f);
+
+ mRenderer9->getDevice()->SetViewport(&dxViewport);
+
+ mCurViewport = actualViewport;
+ mCurNear = actualZNear;
+ mCurFar = actualZFar;
+ mCurDepthFront = depthFront;
+ mCurIgnoreViewport = ignoreViewport;
+
+ // Setting shader constants
+ dx_VertexConstants9 vc = {};
+ dx_PixelConstants9 pc = {};
+
+ vc.viewAdjust[0] =
+ static_cast<float>((actualViewport.width - static_cast<int>(dxViewport.Width)) +
+ 2 * (actualViewport.x - static_cast<int>(dxViewport.X)) - 1) /
+ dxViewport.Width;
+ vc.viewAdjust[1] =
+ static_cast<float>((actualViewport.height - static_cast<int>(dxViewport.Height)) +
+ 2 * (actualViewport.y - static_cast<int>(dxViewport.Y)) - 1) /
+ dxViewport.Height;
+ vc.viewAdjust[2] = static_cast<float>(actualViewport.width) / dxViewport.Width;
+ vc.viewAdjust[3] = static_cast<float>(actualViewport.height) / dxViewport.Height;
+
+ pc.viewCoords[0] = actualViewport.width * 0.5f;
+ pc.viewCoords[1] = actualViewport.height * 0.5f;
+ pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f);
+ pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
+
+ pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
+ pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
+ pc.depthFront[2] = depthFront;
+
+ vc.depthRange[0] = actualZNear;
+ vc.depthRange[1] = actualZFar;
+ vc.depthRange[2] = actualZFar - actualZNear;
+
+ pc.depthRange[0] = actualZNear;
+ pc.depthRange[1] = actualZFar;
+ pc.depthRange[2] = actualZFar - actualZNear;
+
+ if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants9)) != 0)
+ {
+ mVertexConstants = vc;
+ mDxUniformsDirty = true;
+ }
+
+ if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants9)) != 0)
+ {
+ mPixelConstants = pc;
+ mDxUniformsDirty = true;
+ }
+
+ mForceSetViewport = false;
+}
+
+void StateManager9::setShaderConstants()
+{
+ if (!mDxUniformsDirty)
+ return;
+
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetVertexShaderConstantF(0, reinterpret_cast<float *>(&mVertexConstants),
+ sizeof(dx_VertexConstants9) / sizeof(float[4]));
+ device->SetPixelShaderConstantF(0, reinterpret_cast<float *>(&mPixelConstants),
+ sizeof(dx_PixelConstants9) / sizeof(float[4]));
+ mDxUniformsDirty = false;
+}
+
+// This is separate from the main state loop because other functions
+// outside call only setScissorState to update scissor state
+void StateManager9::setScissorState(const gl::Rectangle &scissor, bool enabled)
+{
+ if (mDirtyBits.test(DIRTY_BIT_SCISSOR_ENABLED))
+ setScissorEnabled(enabled);
+
+ if (mDirtyBits.test(DIRTY_BIT_SCISSOR_RECT))
+ setScissorRect(scissor, enabled);
+}
+
+void StateManager9::setRenderTargetBounds(size_t width, size_t height)
+{
+ mRenderTargetBounds.width = (int)width;
+ mRenderTargetBounds.height = (int)height;
+ forceSetViewportState();
+}
+
+void StateManager9::setScissorEnabled(bool scissorEnabled)
+{
+ mRenderer9->getDevice()->SetRenderState(D3DRS_SCISSORTESTENABLE, scissorEnabled ? TRUE : FALSE);
+ mCurScissorEnabled = scissorEnabled;
+}
+
+void StateManager9::setScissorRect(const gl::Rectangle &scissor, bool enabled)
+{
+ if (!enabled)
+ return;
+
+ RECT rect;
+ rect.left = gl::clamp(scissor.x, 0, static_cast<int>(mRenderTargetBounds.width));
+ rect.top = gl::clamp(scissor.y, 0, static_cast<int>(mRenderTargetBounds.height));
+ rect.right =
+ gl::clamp(scissor.x + scissor.width, 0, static_cast<int>(mRenderTargetBounds.width));
+ rect.bottom =
+ gl::clamp(scissor.y + scissor.height, 0, static_cast<int>(mRenderTargetBounds.height));
+ mRenderer9->getDevice()->SetScissorRect(&rect);
+}
+
+void StateManager9::setDepthFunc(bool depthTest, GLenum depthFunc)
+{
+ if (depthTest)
+ {
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
+ device->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthFunc));
+ }
+ else
+ {
+ mRenderer9->getDevice()->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+ }
+
+ mCurDepthStencilState.depthTest = depthTest;
+ mCurDepthStencilState.depthFunc = depthFunc;
+}
+
+void StateManager9::setStencilOpsFront(GLenum stencilFail,
+ GLenum stencilPassDepthFail,
+ GLenum stencilPassDepthPass,
+ bool frontFaceCCW)
+{
+ // TODO(dianx) It may be slightly more efficient todo these and other similar areas
+ // with separate dirty bits.
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
+ gl_d3d9::ConvertStencilOp(stencilFail));
+ device->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
+ gl_d3d9::ConvertStencilOp(stencilPassDepthFail));
+ device->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
+ gl_d3d9::ConvertStencilOp(stencilPassDepthPass));
+
+ mCurDepthStencilState.stencilFail = stencilFail;
+ mCurDepthStencilState.stencilPassDepthFail = stencilPassDepthFail;
+ mCurDepthStencilState.stencilPassDepthPass = stencilPassDepthPass;
+}
+
+void StateManager9::setStencilOpsBack(GLenum stencilBackFail,
+ GLenum stencilBackPassDepthFail,
+ GLenum stencilBackPassDepthPass,
+ bool frontFaceCCW)
+{
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
+ gl_d3d9::ConvertStencilOp(stencilBackFail));
+ device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
+ gl_d3d9::ConvertStencilOp(stencilBackPassDepthFail));
+ device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
+ gl_d3d9::ConvertStencilOp(stencilBackPassDepthPass));
+
+ mCurDepthStencilState.stencilBackFail = stencilBackFail;
+ mCurDepthStencilState.stencilBackPassDepthFail = stencilBackPassDepthFail;
+ mCurDepthStencilState.stencilBackPassDepthPass = stencilBackPassDepthPass;
+}
+
+void StateManager9::setStencilBackWriteMask(GLuint stencilBackWriteMask, bool frontFaceCCW)
+{
+ mRenderer9->getDevice()->SetRenderState(
+ !frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWriteMask);
+
+ mCurDepthStencilState.stencilBackWritemask = stencilBackWriteMask;
+}
+
+void StateManager9::setStencilFuncsBack(GLenum stencilBackFunc,
+ GLuint stencilBackMask,
+ GLint stencilBackRef,
+ bool frontFaceCCW,
+ unsigned int maxStencil)
+{
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
+ gl_d3d9::ConvertComparison(stencilBackFunc));
+ device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
+ (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil);
+ device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK,
+ stencilBackMask);
+
+ mCurDepthStencilState.stencilBackFunc = stencilBackFunc;
+ mCurStencilBackRef = stencilBackRef;
+ mCurDepthStencilState.stencilBackMask = stencilBackMask;
+}
+
+void StateManager9::setStencilWriteMask(GLuint stencilWriteMask, bool frontFaceCCW)
+{
+ mRenderer9->getDevice()->SetRenderState(
+ frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWriteMask);
+ mCurDepthStencilState.stencilWritemask = stencilWriteMask;
+}
+
+void StateManager9::setStencilFuncsFront(GLenum stencilFunc,
+ GLuint stencilMask,
+ GLint stencilRef,
+ bool frontFaceCCW,
+ unsigned int maxStencil)
+{
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
+ gl_d3d9::ConvertComparison(stencilFunc));
+ device->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF,
+ (stencilRef < static_cast<int>(maxStencil)) ? stencilRef : maxStencil);
+ device->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask);
+
+ mCurDepthStencilState.stencilFunc = stencilFunc;
+ mCurStencilRef = stencilRef;
+ mCurDepthStencilState.stencilMask = stencilMask;
+}
+void StateManager9::setStencilTestEnabled(bool stencilTestEnabled)
+{
+ if (stencilTestEnabled && mCurStencilSize > 0)
+ {
+ mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, TRUE);
+ mRenderer9->getDevice()->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
+ }
+ else
+ {
+ mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ }
+
+ mCurDepthStencilState.stencilTest = stencilTestEnabled;
+}
+
+void StateManager9::setDepthMask(bool depthMask)
+{
+ mRenderer9->getDevice()->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE);
+ mCurDepthStencilState.depthMask = depthMask;
+}
+
+// TODO(dianx) one bit for sampleAlphaToCoverage
+void StateManager9::setSampleAlphaToCoverage(bool enabled)
+{
+ if (enabled)
+ {
+ // D3D9 support for alpha-to-coverage is vendor-specific.
+ UNIMPLEMENTED();
+ }
+}
+
+void StateManager9::setBlendColor(const gl::BlendState &blendState, const gl::ColorF &blendColor)
+{
+ if (!blendState.blend)
+ return;
+
+ if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA &&
+ blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
+ blendState.destBlendRGB != GL_CONSTANT_ALPHA &&
+ blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
+ {
+ mRenderer9->getDevice()->SetRenderState(D3DRS_BLENDFACTOR,
+ gl_d3d9::ConvertColor(blendColor));
+ }
+ else
+ {
+ mRenderer9->getDevice()->SetRenderState(
+ D3DRS_BLENDFACTOR,
+ D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha),
+ gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha)));
+ }
+ mCurBlendColor = blendColor;
+}
+
+void StateManager9::setBlendFuncsEquations(const gl::BlendState &blendState)
+{
+ if (!blendState.blend)
+ return;
+
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+
+ device->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB));
+ device->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB));
+ device->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB));
+
+ if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha ||
+ blendState.destBlendRGB != blendState.destBlendAlpha ||
+ blendState.blendEquationRGB != blendState.blendEquationAlpha)
+ {
+ device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
+
+ device->SetRenderState(D3DRS_SRCBLENDALPHA,
+ gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha));
+ device->SetRenderState(D3DRS_DESTBLENDALPHA,
+ gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha));
+ device->SetRenderState(D3DRS_BLENDOPALPHA,
+ gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha));
+ }
+ else
+ {
+ device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
+ }
+
+ mCurBlendState.sourceBlendRGB = blendState.sourceBlendRGB;
+ mCurBlendState.destBlendRGB = blendState.destBlendRGB;
+ mCurBlendState.blendEquationRGB = blendState.blendEquationRGB;
+ mCurBlendState.blendEquationAlpha = blendState.blendEquationAlpha;
+}
+
+void StateManager9::setBlendEnabled(bool enabled)
+{
+ mRenderer9->getDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, enabled ? TRUE : FALSE);
+ mCurBlendState.blend = enabled;
+}
+
+void StateManager9::setDither(bool dither)
+{
+ mRenderer9->getDevice()->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE);
+ mCurRasterState.dither = dither;
+}
+
+// TODO(dianx) one bit for color mask
+void StateManager9::setColorMask(const gl::Framebuffer *framebuffer,
+ bool red,
+ bool blue,
+ bool green,
+ bool alpha)
+{
+ // Set the color mask
+
+ const auto *attachment = framebuffer->getFirstColorAttachment();
+ const auto &format = attachment ? attachment->getFormat() : gl::Format::Invalid();
+
+ DWORD colorMask = gl_d3d9::ConvertColorMask(
+ format.info->redBits > 0 && red, format.info->greenBits > 0 && green,
+ format.info->blueBits > 0 && blue, format.info->alphaBits > 0 && alpha);
+
+ // Apparently some ATI cards have a bug where a draw with a zero color write mask can cause
+ // later draws to have incorrect results. Instead, set a nonzero color write mask but modify the
+ // blend state so that no drawing is done.
+ // http://anglebug.com/169
+ if (colorMask == 0 && mUsingZeroColorMaskWorkaround)
+ {
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ // Enable green channel, but set blending so nothing will be drawn.
+ device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
+
+ device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+
+ device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
+ device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
+ device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
+
+ mCurBlendState.colorMaskRed = false;
+ mCurBlendState.colorMaskGreen = true;
+ mCurBlendState.colorMaskBlue = false;
+ mCurBlendState.colorMaskAlpha = false;
+
+ mCurBlendState.blend = true;
+ mCurBlendState.sourceBlendRGB = GL_ZERO;
+ mCurBlendState.sourceBlendAlpha = GL_ZERO;
+ mCurBlendState.destBlendRGB = GL_ONE;
+ mCurBlendState.destBlendAlpha = GL_ONE;
+ mCurBlendState.blendEquationRGB = GL_FUNC_ADD;
+ mCurBlendState.blendEquationAlpha = GL_FUNC_ADD;
+ }
+ else
+ {
+ mRenderer9->getDevice()->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
+
+ mCurBlendState.colorMaskRed = red;
+ mCurBlendState.colorMaskGreen = green;
+ mCurBlendState.colorMaskBlue = blue;
+ mCurBlendState.colorMaskAlpha = alpha;
+ }
+}
+
+void StateManager9::setSampleMask(unsigned int sampleMask)
+{
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ // Set the multisample mask
+ device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
+ device->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast<DWORD>(sampleMask));
+
+ mCurSampleMask = sampleMask;
+}
+
+void StateManager9::setCullMode(bool cullFace, gl::CullFaceMode cullMode, GLenum frontFace)
+{
+ if (cullFace)
+ {
+ mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE,
+ gl_d3d9::ConvertCullMode(cullMode, frontFace));
+ }
+ else
+ {
+ mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ }
+
+ mCurRasterState.cullFace = cullFace;
+ mCurRasterState.cullMode = cullMode;
+ mCurRasterState.frontFace = frontFace;
+}
+
+void StateManager9::setDepthBias(bool polygonOffsetFill,
+ GLfloat polygonOffsetFactor,
+ GLfloat polygonOffsetUnits)
+{
+ if (polygonOffsetFill)
+ {
+ if (mCurDepthSize > 0)
+ {
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD *)&polygonOffsetFactor);
+
+ float depthBias = ldexp(polygonOffsetUnits, -static_cast<int>(mCurDepthSize));
+ device->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD *)&depthBias);
+ }
+ }
+ else
+ {
+ IDirect3DDevice9 *device = mRenderer9->getDevice();
+ device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
+ device->SetRenderState(D3DRS_DEPTHBIAS, 0);
+ }
+
+ mCurRasterState.polygonOffsetFill = polygonOffsetFill;
+ mCurRasterState.polygonOffsetFactor = polygonOffsetFactor;
+ mCurRasterState.polygonOffsetUnits = polygonOffsetUnits;
+}
+
+void StateManager9::updateDepthSizeIfChanged(bool depthStencilInitialized, unsigned int depthSize)
+{
+ if (!depthStencilInitialized || depthSize != mCurDepthSize)
+ {
+ mCurDepthSize = depthSize;
+ forceSetRasterState();
+ }
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/StateManager9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/StateManager9.h
new file mode 100644
index 0000000000..b047b69cdd
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/StateManager9.h
@@ -0,0 +1,211 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// StateManager9.h: Defines a class for caching D3D9 state
+
+#ifndef LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_
+#define LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_
+
+#include "libANGLE/State.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+namespace rx
+{
+
+class Renderer9;
+
+struct dx_VertexConstants9
+{
+ float depthRange[4];
+ float viewAdjust[4];
+ float viewCoords[4];
+};
+
+struct dx_PixelConstants9
+{
+ float depthRange[4];
+ float viewCoords[4];
+ float depthFront[4];
+};
+
+class StateManager9 final : angle::NonCopyable
+{
+ public:
+ StateManager9(Renderer9 *renderer9);
+ ~StateManager9();
+
+ void initialize();
+
+ void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits);
+
+ void setBlendDepthRasterStates(const gl::State &glState, unsigned int sampleMask);
+ void setScissorState(const gl::Rectangle &scissor, bool enabled);
+ void setViewportState(const gl::Rectangle &viewport,
+ float zNear,
+ float zFar,
+ gl::PrimitiveMode drawMode,
+ GLenum frontFace,
+ bool ignoreViewport);
+
+ void setShaderConstants();
+
+ void forceSetBlendState();
+ void forceSetRasterState();
+ void forceSetDepthStencilState();
+ void forceSetScissorState();
+ void forceSetViewportState();
+ void forceSetDXUniformsState();
+
+ void updateDepthSizeIfChanged(bool depthStencilInitialized, unsigned int depthSize);
+ void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize);
+
+ void setRenderTargetBounds(size_t width, size_t height);
+
+ int getRenderTargetWidth() const { return mRenderTargetBounds.width; }
+ int getRenderTargetHeight() const { return mRenderTargetBounds.height; }
+
+ void setAllDirtyBits() { mDirtyBits.set(); }
+ void resetDirtyBits() { mDirtyBits.reset(); }
+
+ private:
+ // Blend state functions
+ void setBlendEnabled(bool enabled);
+ void setBlendColor(const gl::BlendState &blendState, const gl::ColorF &blendColor);
+ void setBlendFuncsEquations(const gl::BlendState &blendState);
+ void setColorMask(const gl::Framebuffer *framebuffer,
+ bool red,
+ bool blue,
+ bool green,
+ bool alpha);
+ void setSampleAlphaToCoverage(bool enabled);
+ void setDither(bool dither);
+ void setSampleMask(unsigned int sampleMask);
+
+ // Current raster state functions
+ void setCullMode(bool cullFace, gl::CullFaceMode cullMode, GLenum frontFace);
+ void setDepthBias(bool polygonOffsetFill,
+ GLfloat polygonOffsetFactor,
+ GLfloat polygonOffsetUnits);
+
+ // Depth stencil state functions
+ void setStencilOpsFront(GLenum stencilFail,
+ GLenum stencilPassDepthFail,
+ GLenum stencilPassDepthPass,
+ bool frontFaceCCW);
+ void setStencilOpsBack(GLenum stencilBackFail,
+ GLenum stencilBackPassDepthFail,
+ GLenum stencilBackPassDepthPass,
+ bool frontFaceCCW);
+ void setStencilBackWriteMask(GLuint stencilBackWriteMask, bool frontFaceCCW);
+ void setDepthFunc(bool depthTest, GLenum depthFunc);
+ void setStencilTestEnabled(bool enabled);
+ void setDepthMask(bool depthMask);
+ void setStencilFuncsFront(GLenum stencilFunc,
+ GLuint stencilMask,
+ GLint stencilRef,
+ bool frontFaceCCW,
+ unsigned int maxStencil);
+ void setStencilFuncsBack(GLenum stencilBackFunc,
+ GLuint stencilBackMask,
+ GLint stencilBackRef,
+ bool frontFaceCCW,
+ unsigned int maxStencil);
+ void setStencilWriteMask(GLuint stencilWriteMask, bool frontFaceCCW);
+
+ void setScissorEnabled(bool scissorEnabled);
+ void setScissorRect(const gl::Rectangle &scissor, bool enabled);
+
+ enum DirtyBitType
+ {
+ // Blend dirty bits
+ DIRTY_BIT_BLEND_ENABLED,
+ DIRTY_BIT_BLEND_COLOR,
+ DIRTY_BIT_BLEND_FUNCS_EQUATIONS,
+ DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE,
+ DIRTY_BIT_COLOR_MASK,
+ DIRTY_BIT_DITHER,
+ DIRTY_BIT_SAMPLE_MASK,
+
+ // Rasterizer dirty bits
+ DIRTY_BIT_CULL_MODE,
+ DIRTY_BIT_DEPTH_BIAS,
+
+ // Depth stencil dirty bits
+ DIRTY_BIT_STENCIL_DEPTH_MASK,
+ DIRTY_BIT_STENCIL_DEPTH_FUNC,
+ DIRTY_BIT_STENCIL_TEST_ENABLED,
+ DIRTY_BIT_STENCIL_FUNCS_FRONT,
+ DIRTY_BIT_STENCIL_FUNCS_BACK,
+ DIRTY_BIT_STENCIL_WRITEMASK_FRONT,
+ DIRTY_BIT_STENCIL_WRITEMASK_BACK,
+ DIRTY_BIT_STENCIL_OPS_FRONT,
+ DIRTY_BIT_STENCIL_OPS_BACK,
+
+ // Scissor dirty bits
+ DIRTY_BIT_SCISSOR_ENABLED,
+ DIRTY_BIT_SCISSOR_RECT,
+
+ // Viewport dirty bits
+ DIRTY_BIT_VIEWPORT,
+
+ DIRTY_BIT_MAX
+ };
+
+ using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
+
+ bool mUsingZeroColorMaskWorkaround;
+
+ bool mCurSampleAlphaToCoverage;
+
+ // Currently applied blend state
+ gl::BlendState mCurBlendState;
+ gl::ColorF mCurBlendColor;
+ unsigned int mCurSampleMask;
+ DirtyBits mBlendStateDirtyBits;
+
+ // Currently applied raster state
+ gl::RasterizerState mCurRasterState;
+ unsigned int mCurDepthSize;
+ DirtyBits mRasterizerStateDirtyBits;
+
+ // Currently applied depth stencil state
+ gl::DepthStencilState mCurDepthStencilState;
+ int mCurStencilRef;
+ int mCurStencilBackRef;
+ bool mCurFrontFaceCCW;
+ unsigned int mCurStencilSize;
+ DirtyBits mDepthStencilStateDirtyBits;
+
+ // Currently applied scissor states
+ gl::Rectangle mCurScissorRect;
+ bool mCurScissorEnabled;
+ gl::Extents mRenderTargetBounds;
+ DirtyBits mScissorStateDirtyBits;
+
+ // Currently applied viewport states
+ bool mForceSetViewport;
+ gl::Rectangle mCurViewport;
+ float mCurNear;
+ float mCurFar;
+ float mCurDepthFront;
+ bool mCurIgnoreViewport;
+
+ dx_VertexConstants9 mVertexConstants;
+ dx_PixelConstants9 mPixelConstants;
+ bool mDxUniformsDirty;
+
+ // FIXME: Unsupported by D3D9
+ static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
+ static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
+ static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
+
+ Renderer9 *mRenderer9;
+ DirtyBits mDirtyBits;
+};
+
+} // namespace rx
+#endif // LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
new file mode 100644
index 0000000000..c8abac7a57
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
@@ -0,0 +1,472 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain.
+
+#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
+
+#include "libANGLE/features.h"
+#include "libANGLE/renderer/d3d/d3d9/NativeWindow9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+
+namespace rx
+{
+
+SwapChain9::SwapChain9(Renderer9 *renderer,
+ NativeWindow9 *nativeWindow,
+ HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation)
+ : SwapChainD3D(shareHandle, d3dTexture, backBufferFormat, depthBufferFormat),
+ mRenderer(renderer),
+ mWidth(-1),
+ mHeight(-1),
+ mSwapInterval(-1),
+ mNativeWindow(nativeWindow),
+ mSwapChain(nullptr),
+ mBackBuffer(nullptr),
+ mRenderTarget(nullptr),
+ mDepthStencil(nullptr),
+ mOffscreenTexture(nullptr),
+ mColorRenderTarget(this, false),
+ mDepthStencilRenderTarget(this, true)
+{
+ ASSERT(orientation == 0);
+}
+
+SwapChain9::~SwapChain9()
+{
+ release();
+}
+
+void SwapChain9::release()
+{
+ SafeRelease(mSwapChain);
+ SafeRelease(mBackBuffer);
+ SafeRelease(mDepthStencil);
+ SafeRelease(mRenderTarget);
+ SafeRelease(mOffscreenTexture);
+
+ if (mNativeWindow->getNativeWindow())
+ {
+ mShareHandle = nullptr;
+ }
+}
+
+static DWORD convertInterval(EGLint interval)
+{
+#if ANGLE_VSYNC == ANGLE_DISABLED
+ return D3DPRESENT_INTERVAL_IMMEDIATE;
+#else
+ switch (interval)
+ {
+ case 0:
+ return D3DPRESENT_INTERVAL_IMMEDIATE;
+ case 1:
+ return D3DPRESENT_INTERVAL_ONE;
+ case 2:
+ return D3DPRESENT_INTERVAL_TWO;
+ case 3:
+ return D3DPRESENT_INTERVAL_THREE;
+ case 4:
+ return D3DPRESENT_INTERVAL_FOUR;
+ default:
+ UNREACHABLE();
+ }
+
+ return D3DPRESENT_INTERVAL_DEFAULT;
+#endif
+}
+
+EGLint SwapChain9::resize(DisplayD3D *displayD3D, int backbufferWidth, int backbufferHeight)
+{
+ // D3D9 does not support resizing swap chains without recreating them
+ return reset(displayD3D, backbufferWidth, backbufferHeight, mSwapInterval);
+}
+
+EGLint SwapChain9::reset(DisplayD3D *displayD3D,
+ int backbufferWidth,
+ int backbufferHeight,
+ EGLint swapInterval)
+{
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ if (device == nullptr)
+ {
+ return EGL_BAD_ACCESS;
+ }
+
+ // Evict all non-render target textures to system memory and release all resources
+ // before reallocating them to free up as much video memory as possible.
+ device->EvictManagedResources();
+
+ HRESULT result;
+
+ // Release specific resources to free up memory for the new render target, while the
+ // old render target still exists for the purpose of preserving its contents.
+ SafeRelease(mSwapChain);
+ SafeRelease(mBackBuffer);
+ SafeRelease(mOffscreenTexture);
+ SafeRelease(mDepthStencil);
+
+ const d3d9::TextureFormat &backBufferd3dFormatInfo =
+ d3d9::GetTextureFormatInfo(mOffscreenRenderTargetFormat);
+ if (mD3DTexture != nullptr)
+ {
+ result = mD3DTexture->QueryInterface(&mOffscreenTexture);
+ ASSERT(SUCCEEDED(result));
+ }
+ else
+ {
+ HANDLE *pShareHandle = nullptr;
+ if (!mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport())
+ {
+ pShareHandle = &mShareHandle;
+ }
+
+ result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
+ backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT,
+ &mOffscreenTexture, pShareHandle);
+ if (FAILED(result))
+ {
+ ERR() << "Could not create offscreen texture, " << gl::FmtHR(result);
+ release();
+
+ if (d3d9::isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+ }
+
+ IDirect3DSurface9 *oldRenderTarget = mRenderTarget;
+
+ result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget);
+ ASSERT(SUCCEEDED(result));
+
+ if (oldRenderTarget)
+ {
+ RECT rect = {0, 0, mWidth, mHeight};
+
+ if (rect.right > static_cast<LONG>(backbufferWidth))
+ {
+ rect.right = backbufferWidth;
+ }
+
+ if (rect.bottom > static_cast<LONG>(backbufferHeight))
+ {
+ rect.bottom = backbufferHeight;
+ }
+
+ mRenderer->endScene();
+
+ result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE);
+ ASSERT(SUCCEEDED(result));
+
+ SafeRelease(oldRenderTarget);
+ }
+
+ const d3d9::TextureFormat &depthBufferd3dFormatInfo =
+ d3d9::GetTextureFormatInfo(mDepthBufferFormat);
+
+ // Don't create a swapchain for NULLREF devices
+ D3DDEVTYPE deviceType = mRenderer->getD3D9DeviceType();
+ EGLNativeWindowType window = mNativeWindow->getNativeWindow();
+ if (window && deviceType != D3DDEVTYPE_NULLREF)
+ {
+ D3DPRESENT_PARAMETERS presentParameters = {};
+ presentParameters.AutoDepthStencilFormat = depthBufferd3dFormatInfo.renderFormat;
+ presentParameters.BackBufferCount = 1;
+ presentParameters.BackBufferFormat = backBufferd3dFormatInfo.renderFormat;
+ presentParameters.EnableAutoDepthStencil = FALSE;
+ presentParameters.Flags = 0;
+ presentParameters.hDeviceWindow = window;
+ presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented
+ presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented
+ presentParameters.PresentationInterval = convertInterval(swapInterval);
+ presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
+ presentParameters.Windowed = TRUE;
+ presentParameters.BackBufferWidth = backbufferWidth;
+ presentParameters.BackBufferHeight = backbufferHeight;
+
+ // http://crbug.com/140239
+ // http://crbug.com/143434
+ //
+ // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a
+ // multiple of 64 pixels in width when using the integrated Intel. This rounds the width up
+ // rather than down.
+ //
+ // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present.
+ // Therefore, when the vendor ID is not Intel, the back buffer width must be exactly the
+ // same width as the window or horizontal scaling will occur.
+ if (IsIntel(mRenderer->getVendorId()))
+ {
+ presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64;
+ }
+
+ result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY ||
+ result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST);
+
+ ERR() << "Could not create additional swap chains or offscreen surfaces, "
+ << gl::FmtHR(result);
+ release();
+
+ if (d3d9::isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+
+ result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
+ ASSERT(SUCCEEDED(result));
+ InvalidateRect(window, nullptr, FALSE);
+ }
+
+ if (mDepthBufferFormat != GL_NONE)
+ {
+ result = device->CreateDepthStencilSurface(
+ backbufferWidth, backbufferHeight, depthBufferd3dFormatInfo.renderFormat,
+ D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, nullptr);
+
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY ||
+ result == D3DERR_INVALIDCALL);
+
+ ERR() << "Could not create depthstencil surface for new swap chain, "
+ << gl::FmtHR(result);
+ release();
+
+ if (d3d9::isDeviceLostError(result))
+ {
+ return EGL_CONTEXT_LOST;
+ }
+ else
+ {
+ return EGL_BAD_ALLOC;
+ }
+ }
+ }
+
+ mWidth = backbufferWidth;
+ mHeight = backbufferHeight;
+ mSwapInterval = swapInterval;
+
+ return EGL_SUCCESS;
+}
+
+// parameters should be validated/clamped by caller
+EGLint SwapChain9::swapRect(DisplayD3D *displayD3D, EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ if (!mSwapChain)
+ {
+ return EGL_SUCCESS;
+ }
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+
+ // Disable all pipeline operations
+ device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
+ device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
+ device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
+ device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
+ device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
+ device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
+ device->SetRenderState(D3DRS_COLORWRITEENABLE,
+ D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE |
+ D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
+ device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE);
+ device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
+ device->SetPixelShader(nullptr);
+ device->SetVertexShader(nullptr);
+
+ device->SetRenderTarget(0, mBackBuffer);
+ device->SetDepthStencilSurface(nullptr);
+
+ device->SetTexture(0, mOffscreenTexture);
+ device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
+ device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
+ device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
+ device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
+ device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
+ device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
+ device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
+ device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
+
+ for (UINT streamIndex = 0; streamIndex < gl::MAX_VERTEX_ATTRIBS; streamIndex++)
+ {
+ device->SetStreamSourceFreq(streamIndex, 1);
+ }
+
+ D3DVIEWPORT9 viewport = {0, 0, static_cast<DWORD>(mWidth), static_cast<DWORD>(mHeight),
+ 0.0f, 1.0f};
+ device->SetViewport(&viewport);
+
+ float x1 = x - 0.5f;
+ float y1 = (mHeight - y - height) - 0.5f;
+ float x2 = (x + width) - 0.5f;
+ float y2 = (mHeight - y) - 0.5f;
+
+ float u1 = x / float(mWidth);
+ float v1 = y / float(mHeight);
+ float u2 = (x + width) / float(mWidth);
+ float v2 = (y + height) / float(mHeight);
+
+ float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2},
+ {x2, y1, 0.0f, 1.0f, u2, v2},
+ {x2, y2, 0.0f, 1.0f, u2, v1},
+ {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v
+
+ mRenderer->startScene();
+ device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float));
+ mRenderer->endScene();
+
+ device->SetTexture(0, nullptr);
+
+ RECT rect = {static_cast<LONG>(x), static_cast<LONG>(mHeight - y - height),
+ static_cast<LONG>(x + width), static_cast<LONG>(mHeight - y)};
+
+ HRESULT result = mSwapChain->Present(&rect, &rect, nullptr, nullptr, 0);
+
+ mRenderer->markAllStateDirty();
+
+ if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY ||
+ result == D3DERR_DRIVERINTERNALERROR)
+ {
+ return EGL_BAD_ALLOC;
+ }
+
+ // On Windows 8 systems, IDirect3DSwapChain9::Present sometimes returns 0x88760873 when the
+ // windows is in the process of entering/exiting fullscreen. This code doesn't seem to have any
+ // documentation. The device appears to be ok after emitting this error so simply return a
+ // failure to swap.
+ if (result == static_cast<HRESULT>(0x88760873) || result == static_cast<HRESULT>(0x88760872))
+ {
+ return EGL_BAD_MATCH;
+ }
+
+ // http://crbug.com/313210
+ // If our swap failed, trigger a device lost event. Resetting will work around an AMD-specific
+ // device removed bug with lost contexts when reinstalling drivers.
+ if (FAILED(result))
+ {
+ mRenderer->notifyDeviceLost();
+ return EGL_CONTEXT_LOST;
+ }
+
+ return EGL_SUCCESS;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+// TODO: remove the AddRef to match SwapChain11
+IDirect3DSurface9 *SwapChain9::getRenderTarget()
+{
+ if (mRenderTarget)
+ {
+ mRenderTarget->AddRef();
+ }
+
+ return mRenderTarget;
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+// TODO: remove the AddRef to match SwapChain11
+IDirect3DSurface9 *SwapChain9::getDepthStencil()
+{
+ if (mDepthStencil)
+ {
+ mDepthStencil->AddRef();
+ }
+
+ return mDepthStencil;
+}
+
+// Increments refcount on texture.
+// caller must Release() the returned texture
+// TODO: remove the AddRef to match SwapChain11
+IDirect3DTexture9 *SwapChain9::getOffscreenTexture()
+{
+ if (mOffscreenTexture)
+ {
+ mOffscreenTexture->AddRef();
+ }
+
+ return mOffscreenTexture;
+}
+
+void *SwapChain9::getKeyedMutex()
+{
+ UNREACHABLE();
+ return nullptr;
+}
+
+egl::Error SwapChain9::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
+{
+ UNREACHABLE();
+ return egl::EglBadSurface();
+}
+
+void SwapChain9::recreate()
+{
+ if (!mSwapChain)
+ {
+ return;
+ }
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+ if (device == nullptr)
+ {
+ return;
+ }
+
+ D3DPRESENT_PARAMETERS presentParameters;
+ HRESULT result = mSwapChain->GetPresentParameters(&presentParameters);
+ ASSERT(SUCCEEDED(result));
+
+ IDirect3DSwapChain9 *newSwapChain = nullptr;
+ result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain);
+ if (FAILED(result))
+ {
+ return;
+ }
+
+ SafeRelease(mSwapChain);
+ mSwapChain = newSwapChain;
+
+ SafeRelease(mBackBuffer);
+ result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer);
+ ASSERT(SUCCEEDED(result));
+}
+
+RenderTargetD3D *SwapChain9::getColorRenderTarget()
+{
+ return &mColorRenderTarget;
+}
+
+RenderTargetD3D *SwapChain9::getDepthStencilRenderTarget()
+{
+ return &mDepthStencilRenderTarget;
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
new file mode 100644
index 0000000000..2b3176967d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
@@ -0,0 +1,80 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SwapChain9.h: Defines a back-end specific class for the D3D9 swap chain.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+
+namespace rx
+{
+class NativeWindow9;
+class Renderer9;
+
+class SwapChain9 : public SwapChainD3D
+{
+ public:
+ SwapChain9(Renderer9 *renderer,
+ NativeWindow9 *nativeWindow,
+ HANDLE shareHandle,
+ IUnknown *d3dTexture,
+ GLenum backBufferFormat,
+ GLenum depthBufferFormat,
+ EGLint orientation);
+ ~SwapChain9() override;
+
+ EGLint resize(DisplayD3D *displayD3D, EGLint backbufferWidth, EGLint backbufferHeight) override;
+ EGLint reset(DisplayD3D *displayD3D,
+ EGLint backbufferWidth,
+ EGLint backbufferHeight,
+ EGLint swapInterval) override;
+ EGLint swapRect(DisplayD3D *displayD3D,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height) override;
+ void recreate() override;
+
+ RenderTargetD3D *getColorRenderTarget() override;
+ RenderTargetD3D *getDepthStencilRenderTarget() override;
+
+ virtual IDirect3DSurface9 *getRenderTarget();
+ virtual IDirect3DSurface9 *getDepthStencil();
+ virtual IDirect3DTexture9 *getOffscreenTexture();
+
+ EGLint getWidth() const { return mWidth; }
+ EGLint getHeight() const { return mHeight; }
+
+ void *getKeyedMutex() override;
+
+ egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
+
+ private:
+ void release();
+
+ Renderer9 *mRenderer;
+ EGLint mWidth;
+ EGLint mHeight;
+ EGLint mSwapInterval;
+
+ NativeWindow9 *mNativeWindow;
+
+ IDirect3DSwapChain9 *mSwapChain;
+ IDirect3DSurface9 *mBackBuffer;
+ IDirect3DSurface9 *mRenderTarget;
+ IDirect3DSurface9 *mDepthStencil;
+ IDirect3DTexture9 *mOffscreenTexture;
+
+ SurfaceRenderTarget9 mColorRenderTarget;
+ SurfaceRenderTarget9 mDepthStencilRenderTarget;
+};
+
+} // namespace rx
+#endif // LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
new file mode 100644
index 0000000000..b2fea07fd5
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
@@ -0,0 +1,575 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureStorage9.cpp: Implements the abstract rx::TextureStorage9 class and its concrete derived
+// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the
+// D3D9 texture.
+
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/EGLImageD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+
+namespace rx
+{
+TextureStorage9::TextureStorage9(Renderer9 *renderer, DWORD usage, const std::string &label)
+ : TextureStorage(label),
+ mTopLevel(0),
+ mMipLevels(0),
+ mTextureWidth(0),
+ mTextureHeight(0),
+ mInternalFormat(GL_NONE),
+ mTextureFormat(D3DFMT_UNKNOWN),
+ mRenderer(renderer),
+ mD3DUsage(usage),
+ mD3DPool(mRenderer->getTexturePool(usage))
+{}
+
+TextureStorage9::~TextureStorage9() {}
+
+DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, bool renderTarget)
+{
+ DWORD d3dusage = 0;
+
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
+ const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
+ if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
+ {
+ d3dusage |= D3DUSAGE_DEPTHSTENCIL;
+ }
+ else if (renderTarget && (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN))
+ {
+ d3dusage |= D3DUSAGE_RENDERTARGET;
+ }
+
+ return d3dusage;
+}
+
+bool TextureStorage9::isRenderTarget() const
+{
+ return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0;
+}
+
+bool TextureStorage9::isManaged() const
+{
+ return (mD3DPool == D3DPOOL_MANAGED);
+}
+
+bool TextureStorage9::supportsNativeMipmapFunction() const
+{
+ return false;
+}
+
+D3DPOOL TextureStorage9::getPool() const
+{
+ return mD3DPool;
+}
+
+DWORD TextureStorage9::getUsage() const
+{
+ return mD3DUsage;
+}
+
+int TextureStorage9::getTopLevel() const
+{
+ return mTopLevel;
+}
+
+int TextureStorage9::getLevelCount() const
+{
+ return static_cast<int>(mMipLevels) - mTopLevel;
+}
+
+angle::Result TextureStorage9::setData(const gl::Context *context,
+ const gl::ImageIndex &index,
+ ImageD3D *image,
+ const gl::Box *destBox,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixelData)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer,
+ SwapChain9 *swapchain,
+ const std::string &label)
+ : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET, label)
+{
+ IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture();
+ mTexture = surfaceTexture;
+ mMipLevels = surfaceTexture->GetLevelCount();
+
+ mInternalFormat = swapchain->getRenderTargetInternalFormat();
+
+ D3DSURFACE_DESC surfaceDesc;
+ surfaceTexture->GetLevelDesc(0, &surfaceDesc);
+ mTextureWidth = surfaceDesc.Width;
+ mTextureHeight = surfaceDesc.Height;
+ mTextureFormat = surfaceDesc.Format;
+
+ mRenderTargets.resize(mMipLevels, nullptr);
+}
+
+TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer,
+ GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ const std::string &label)
+ : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget), label)
+{
+ mTexture = nullptr;
+
+ mInternalFormat = internalformat;
+
+ const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
+ mTextureFormat = d3dFormatInfo.texFormat;
+
+ d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel);
+ mTextureWidth = width;
+ mTextureHeight = height;
+ mMipLevels = mTopLevel + levels;
+
+ mRenderTargets.resize(levels, nullptr);
+}
+
+TextureStorage9_2D::~TextureStorage9_2D()
+{
+ SafeRelease(mTexture);
+ for (RenderTargetD3D *renderTarget : mRenderTargets)
+ {
+ SafeDelete(renderTarget);
+ }
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+angle::Result TextureStorage9_2D::getSurfaceLevel(const gl::Context *context,
+ gl::TextureTarget target,
+ int level,
+ bool dirty,
+ IDirect3DSurface9 **outSurface)
+{
+ ASSERT(target == gl::TextureTarget::_2D);
+
+ IDirect3DBaseTexture9 *baseTexture = nullptr;
+ ANGLE_TRY(getBaseTexture(context, &baseTexture));
+
+ IDirect3DTexture9 *texture = static_cast<IDirect3DTexture9 *>(baseTexture);
+
+ HRESULT result = texture->GetSurfaceLevel(level + mTopLevel, outSurface);
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to get the surface from a texture");
+
+ // With managed textures the driver needs to be informed of updates to the lower mipmap levels
+ if (level + mTopLevel != 0 && isManaged() && dirty)
+ {
+ texture->AddDirtyRect(nullptr);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage9_2D::findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const
+{
+ ASSERT(index.getLevelIndex() < getLevelCount());
+
+ ASSERT(outRT);
+ *outRT = mRenderTargets[index.getLevelIndex()];
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage9_2D::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(index.getLevelIndex() < getLevelCount());
+
+ if (!mRenderTargets[index.getLevelIndex()] && isRenderTarget())
+ {
+ IDirect3DBaseTexture9 *baseTexture = nullptr;
+ ANGLE_TRY(getBaseTexture(context, &baseTexture));
+
+ IDirect3DSurface9 *surface = nullptr;
+ ANGLE_TRY(getSurfaceLevel(context, gl::TextureTarget::_2D, index.getLevelIndex(), false,
+ &surface));
+
+ size_t textureMipLevel = mTopLevel + index.getLevelIndex();
+ size_t mipWidth = std::max<size_t>(mTextureWidth >> textureMipLevel, 1u);
+ size_t mipHeight = std::max<size_t>(mTextureHeight >> textureMipLevel, 1u);
+
+ baseTexture->AddRef();
+ mRenderTargets[index.getLevelIndex()] = new TextureRenderTarget9(
+ baseTexture, textureMipLevel, surface, mInternalFormat, static_cast<GLsizei>(mipWidth),
+ static_cast<GLsizei>(mipHeight), 1, 0);
+ }
+
+ ASSERT(outRT);
+ *outRT = mRenderTargets[index.getLevelIndex()];
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage9_2D::generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex)
+{
+ angle::ComPtr<IDirect3DSurface9> upper = nullptr;
+ ANGLE_TRY(getSurfaceLevel(context, gl::TextureTarget::_2D, sourceIndex.getLevelIndex(), false,
+ &upper));
+
+ angle::ComPtr<IDirect3DSurface9> lower = nullptr;
+ ANGLE_TRY(
+ getSurfaceLevel(context, gl::TextureTarget::_2D, destIndex.getLevelIndex(), true, &lower));
+
+ ASSERT(upper && lower);
+ return mRenderer->boxFilter(GetImplAs<Context9>(context), upper.Get(), lower.Get());
+}
+
+angle::Result TextureStorage9_2D::getBaseTexture(const gl::Context *context,
+ IDirect3DBaseTexture9 **outTexture)
+{
+ // if the width or height is not positive this should be treated as an incomplete texture
+ // we handle that here by skipping the d3d texture creation
+ if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
+ {
+ ASSERT(mMipLevels > 0);
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+ HRESULT result = device->CreateTexture(static_cast<unsigned int>(mTextureWidth),
+ static_cast<unsigned int>(mTextureHeight),
+ static_cast<unsigned int>(mMipLevels), getUsage(),
+ mTextureFormat, getPool(), &mTexture, nullptr);
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to create 2D storage texture");
+ }
+
+ *outTexture = mTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage9_2D::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
+{
+ ASSERT(destStorage);
+
+ TextureStorage9_2D *dest9 = GetAs<TextureStorage9_2D>(destStorage);
+
+ int levels = getLevelCount();
+ for (int i = 0; i < levels; ++i)
+ {
+ angle::ComPtr<IDirect3DSurface9> srcSurf = nullptr;
+ ANGLE_TRY(getSurfaceLevel(context, gl::TextureTarget::_2D, i, false, &srcSurf));
+
+ angle::ComPtr<IDirect3DSurface9> dstSurf = nullptr;
+ ANGLE_TRY(dest9->getSurfaceLevel(context, gl::TextureTarget::_2D, i, true, &dstSurf));
+
+ ANGLE_TRY(
+ mRenderer->copyToRenderTarget(context, dstSurf.Get(), srcSurf.Get(), isManaged()));
+ }
+
+ return angle::Result::Continue;
+}
+
+TextureStorage9_EGLImage::TextureStorage9_EGLImage(Renderer9 *renderer,
+ EGLImageD3D *image,
+ RenderTarget9 *renderTarget9,
+ const std::string &label)
+ : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET, label), mImage(image)
+{
+
+ mInternalFormat = renderTarget9->getInternalFormat();
+ mTextureFormat = renderTarget9->getD3DFormat();
+ mTextureWidth = renderTarget9->getWidth();
+ mTextureHeight = renderTarget9->getHeight();
+ mTopLevel = static_cast<int>(renderTarget9->getTextureLevel());
+ mMipLevels = mTopLevel + 1;
+}
+
+TextureStorage9_EGLImage::~TextureStorage9_EGLImage() {}
+
+angle::Result TextureStorage9_EGLImage::getSurfaceLevel(const gl::Context *context,
+ gl::TextureTarget target,
+ int level,
+ bool,
+ IDirect3DSurface9 **outSurface)
+{
+ ASSERT(target == gl::TextureTarget::_2D);
+ ASSERT(level == 0);
+
+ RenderTargetD3D *renderTargetD3D = nullptr;
+ ANGLE_TRY(mImage->getRenderTarget(context, &renderTargetD3D));
+
+ RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D);
+
+ *outSurface = renderTarget9->getSurface();
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage9_EGLImage::findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const
+{
+ // Since the render target of a EGL image will be updated when orphaning, trying to find a cache
+ // of it can be rarely useful.
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage9_EGLImage::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(!index.hasLayer());
+ ASSERT(index.getLevelIndex() == 0);
+ ASSERT(samples == 0);
+
+ return mImage->getRenderTarget(context, outRT);
+}
+
+angle::Result TextureStorage9_EGLImage::getBaseTexture(const gl::Context *context,
+ IDirect3DBaseTexture9 **outTexture)
+{
+ RenderTargetD3D *renderTargetD3D = nullptr;
+ ANGLE_TRY(mImage->getRenderTarget(context, &renderTargetD3D));
+
+ RenderTarget9 *renderTarget9 = GetAs<RenderTarget9>(renderTargetD3D);
+ *outTexture = renderTarget9->getTexture();
+ ASSERT(*outTexture != nullptr);
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage9_EGLImage::generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &,
+ const gl::ImageIndex &)
+{
+ ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
+ return angle::Result::Stop;
+}
+
+angle::Result TextureStorage9_EGLImage::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
+{
+ ASSERT(destStorage);
+ ASSERT(getLevelCount() == 1);
+
+ TextureStorage9 *dest9 = GetAs<TextureStorage9>(destStorage);
+
+ IDirect3DBaseTexture9 *destBaseTexture9 = nullptr;
+ ANGLE_TRY(dest9->getBaseTexture(context, &destBaseTexture9));
+
+ IDirect3DTexture9 *destTexture9 = static_cast<IDirect3DTexture9 *>(destBaseTexture9);
+
+ angle::ComPtr<IDirect3DSurface9> destSurface = nullptr;
+ HRESULT result = destTexture9->GetSurfaceLevel(destStorage->getTopLevel(), &destSurface);
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to get the surface from a texture");
+
+ RenderTargetD3D *sourceRenderTarget = nullptr;
+ ANGLE_TRY(mImage->getRenderTarget(context, &sourceRenderTarget));
+
+ RenderTarget9 *sourceRenderTarget9 = GetAs<RenderTarget9>(sourceRenderTarget);
+ ANGLE_TRY(mRenderer->copyToRenderTarget(context, destSurface.Get(),
+ sourceRenderTarget9->getSurface(), isManaged()));
+
+ if (destStorage->getTopLevel() != 0)
+ {
+ destTexture9->AddDirtyRect(nullptr);
+ }
+
+ return angle::Result::Continue;
+}
+
+TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer,
+ GLenum internalformat,
+ bool renderTarget,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly,
+ const std::string &label)
+ : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget), label)
+{
+ mTexture = nullptr;
+ for (size_t i = 0; i < gl::kCubeFaceCount; ++i)
+ {
+ mRenderTarget[i] = nullptr;
+ }
+
+ mInternalFormat = internalformat;
+
+ const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat);
+ mTextureFormat = d3dFormatInfo.texFormat;
+
+ int height = size;
+ d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel);
+ mTextureWidth = size;
+ mTextureHeight = size;
+ mMipLevels = mTopLevel + levels;
+}
+
+TextureStorage9_Cube::~TextureStorage9_Cube()
+{
+ SafeRelease(mTexture);
+
+ for (size_t i = 0; i < gl::kCubeFaceCount; ++i)
+ {
+ SafeDelete(mRenderTarget[i]);
+ }
+}
+
+// Increments refcount on surface.
+// caller must Release() the returned surface
+angle::Result TextureStorage9_Cube::getSurfaceLevel(const gl::Context *context,
+ gl::TextureTarget target,
+ int level,
+ bool dirty,
+ IDirect3DSurface9 **outSurface)
+{
+ IDirect3DBaseTexture9 *baseTexture = nullptr;
+ ANGLE_TRY(getBaseTexture(context, &baseTexture));
+
+ IDirect3DCubeTexture9 *texture = static_cast<IDirect3DCubeTexture9 *>(baseTexture);
+
+ D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(target);
+ HRESULT result = texture->GetCubeMapSurface(face, level, outSurface);
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to get the surface from a texture");
+
+ // With managed textures the driver needs to be informed of updates to the lower mipmap levels
+ if (level != 0 && isManaged() && dirty)
+ {
+ texture->AddDirtyRect(face, nullptr);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage9_Cube::findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const
+{
+ ASSERT(outRT);
+ ASSERT(index.getLevelIndex() == 0);
+ ASSERT(samples == 0);
+
+ ASSERT(index.getType() == gl::TextureType::CubeMap &&
+ gl::IsCubeMapFaceTarget(index.getTarget()));
+ const size_t renderTargetIndex = index.cubeMapFaceIndex();
+
+ *outRT = mRenderTarget[renderTargetIndex];
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage9_Cube::getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT)
+{
+ ASSERT(outRT);
+ ASSERT(index.getLevelIndex() == 0);
+ ASSERT(samples == 0);
+
+ ASSERT(index.getType() == gl::TextureType::CubeMap &&
+ gl::IsCubeMapFaceTarget(index.getTarget()));
+ const size_t renderTargetIndex = index.cubeMapFaceIndex();
+
+ if (mRenderTarget[renderTargetIndex] == nullptr && isRenderTarget())
+ {
+ IDirect3DBaseTexture9 *baseTexture = nullptr;
+ ANGLE_TRY(getBaseTexture(context, &baseTexture));
+
+ IDirect3DSurface9 *surface = nullptr;
+ ANGLE_TRY(getSurfaceLevel(context, index.getTarget(), mTopLevel + index.getLevelIndex(),
+ false, &surface));
+
+ baseTexture->AddRef();
+ mRenderTarget[renderTargetIndex] = new TextureRenderTarget9(
+ baseTexture, mTopLevel + index.getLevelIndex(), surface, mInternalFormat,
+ static_cast<GLsizei>(mTextureWidth), static_cast<GLsizei>(mTextureHeight), 1, 0);
+ }
+
+ *outRT = mRenderTarget[renderTargetIndex];
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage9_Cube::generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex)
+{
+ angle::ComPtr<IDirect3DSurface9> upper = nullptr;
+ ANGLE_TRY(getSurfaceLevel(context, sourceIndex.getTarget(), sourceIndex.getLevelIndex(), false,
+ &upper));
+
+ angle::ComPtr<IDirect3DSurface9> lower = nullptr;
+ ANGLE_TRY(
+ getSurfaceLevel(context, destIndex.getTarget(), destIndex.getLevelIndex(), true, &lower));
+
+ ASSERT(upper && lower);
+ return mRenderer->boxFilter(GetImplAs<Context9>(context), upper.Get(), lower.Get());
+}
+
+angle::Result TextureStorage9_Cube::getBaseTexture(const gl::Context *context,
+ IDirect3DBaseTexture9 **outTexture)
+{
+ // if the size is not positive this should be treated as an incomplete texture
+ // we handle that here by skipping the d3d texture creation
+ if (mTexture == nullptr && mTextureWidth > 0 && mTextureHeight > 0)
+ {
+ ASSERT(mMipLevels > 0);
+ ASSERT(mTextureWidth == mTextureHeight);
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+ HRESULT result = device->CreateCubeTexture(
+ static_cast<unsigned int>(mTextureWidth), static_cast<unsigned int>(mMipLevels),
+ getUsage(), mTextureFormat, getPool(), &mTexture, nullptr);
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to create cube storage texture");
+ }
+
+ *outTexture = mTexture;
+ return angle::Result::Continue;
+}
+
+angle::Result TextureStorage9_Cube::copyToStorage(const gl::Context *context,
+ TextureStorage *destStorage)
+{
+ ASSERT(destStorage);
+
+ TextureStorage9_Cube *dest9 = GetAs<TextureStorage9_Cube>(destStorage);
+
+ int levels = getLevelCount();
+ for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
+ {
+ for (int i = 0; i < levels; i++)
+ {
+ angle::ComPtr<IDirect3DSurface9> srcSurf = nullptr;
+ ANGLE_TRY(getSurfaceLevel(context, face, i, false, &srcSurf));
+
+ angle::ComPtr<IDirect3DSurface9> dstSurf = nullptr;
+ ANGLE_TRY(dest9->getSurfaceLevel(context, face, i, true, &dstSurf));
+
+ ANGLE_TRY(
+ mRenderer->copyToRenderTarget(context, dstSurf.Get(), srcSurf.Get(), isManaged()));
+ }
+ }
+
+ return angle::Result::Continue;
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h
new file mode 100644
index 0000000000..9882c341f9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h
@@ -0,0 +1,186 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureStorage9.h: Defines the abstract rx::TextureStorage9 class and its concrete derived
+// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the
+// D3D9 texture.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_
+
+#include "common/debug.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
+
+namespace rx
+{
+class EGLImageD3D;
+class Renderer9;
+class SwapChain9;
+class RenderTargetD3D;
+class RenderTarget9;
+
+class TextureStorage9 : public TextureStorage
+{
+ public:
+ ~TextureStorage9() override;
+
+ static DWORD GetTextureUsage(GLenum internalformat, bool renderTarget);
+
+ D3DPOOL getPool() const;
+ DWORD getUsage() const;
+
+ virtual angle::Result getSurfaceLevel(const gl::Context *context,
+ gl::TextureTarget target,
+ int level,
+ bool dirty,
+ IDirect3DSurface9 **outSurface) = 0;
+ virtual angle::Result getBaseTexture(const gl::Context *context,
+ IDirect3DBaseTexture9 **outTexture) = 0;
+
+ int getTopLevel() const override;
+ bool isRenderTarget() const override;
+ bool isUnorderedAccess() const override { return false; }
+ bool isManaged() const override;
+ bool supportsNativeMipmapFunction() const override;
+ int getLevelCount() const override;
+
+ angle::Result setData(const gl::Context *context,
+ const gl::ImageIndex &index,
+ ImageD3D *image,
+ const gl::Box *destBox,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixelData) override;
+
+ protected:
+ int mTopLevel;
+ size_t mMipLevels;
+ size_t mTextureWidth;
+ size_t mTextureHeight;
+ GLenum mInternalFormat;
+ D3DFORMAT mTextureFormat;
+
+ Renderer9 *mRenderer;
+
+ TextureStorage9(Renderer9 *renderer, DWORD usage, const std::string &label);
+
+ private:
+ const DWORD mD3DUsage;
+ const D3DPOOL mD3DPool;
+};
+
+class TextureStorage9_2D : public TextureStorage9
+{
+ public:
+ TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchain, const std::string &label);
+ TextureStorage9_2D(Renderer9 *renderer,
+ GLenum internalformat,
+ bool renderTarget,
+ GLsizei width,
+ GLsizei height,
+ int levels,
+ const std::string &label);
+ ~TextureStorage9_2D() override;
+
+ angle::Result getSurfaceLevel(const gl::Context *context,
+ gl::TextureTarget target,
+ int level,
+ bool dirty,
+ IDirect3DSurface9 **outSurface) override;
+ angle::Result findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const override;
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+ angle::Result getBaseTexture(const gl::Context *context,
+ IDirect3DBaseTexture9 **outTexture) override;
+ angle::Result generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex) override;
+ angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
+
+ private:
+ IDirect3DTexture9 *mTexture;
+ std::vector<RenderTarget9 *> mRenderTargets;
+};
+
+class TextureStorage9_EGLImage final : public TextureStorage9
+{
+ public:
+ TextureStorage9_EGLImage(Renderer9 *renderer,
+ EGLImageD3D *image,
+ RenderTarget9 *renderTarget9,
+ const std::string &label);
+ ~TextureStorage9_EGLImage() override;
+
+ angle::Result getSurfaceLevel(const gl::Context *context,
+ gl::TextureTarget target,
+ int level,
+ bool dirty,
+ IDirect3DSurface9 **outSurface) override;
+ angle::Result findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const override;
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+ angle::Result getBaseTexture(const gl::Context *context,
+ IDirect3DBaseTexture9 **outTexture) override;
+ angle::Result generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex) override;
+ angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
+
+ private:
+ EGLImageD3D *mImage;
+};
+
+class TextureStorage9_Cube : public TextureStorage9
+{
+ public:
+ TextureStorage9_Cube(Renderer9 *renderer,
+ GLenum internalformat,
+ bool renderTarget,
+ int size,
+ int levels,
+ bool hintLevelZeroOnly,
+ const std::string &label);
+
+ ~TextureStorage9_Cube() override;
+
+ angle::Result getSurfaceLevel(const gl::Context *context,
+ gl::TextureTarget target,
+ int level,
+ bool dirty,
+ IDirect3DSurface9 **outSurface) override;
+ angle::Result findRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) const override;
+ angle::Result getRenderTarget(const gl::Context *context,
+ const gl::ImageIndex &index,
+ GLsizei samples,
+ RenderTargetD3D **outRT) override;
+ angle::Result getBaseTexture(const gl::Context *context,
+ IDirect3DBaseTexture9 **outTexture) override;
+ angle::Result generateMipmap(const gl::Context *context,
+ const gl::ImageIndex &sourceIndex,
+ const gl::ImageIndex &destIndex) override;
+ angle::Result copyToStorage(const gl::Context *context, TextureStorage *destStorage) override;
+
+ private:
+ IDirect3DCubeTexture9 *mTexture;
+ RenderTarget9 *mRenderTarget[gl::kCubeFaceCount];
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h
new file mode 100644
index 0000000000..a9c1ee7d4b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h
@@ -0,0 +1,57 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexArray9.h: Defines the rx::VertexArray9 class which implements rx::VertexArrayImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_
+
+#include "libANGLE/Context.h"
+#include "libANGLE/renderer/VertexArrayImpl.h"
+#include "libANGLE/renderer/d3d/d3d9/Context9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
+namespace rx
+{
+class Renderer9;
+
+class VertexArray9 : public VertexArrayImpl
+{
+ public:
+ VertexArray9(const gl::VertexArrayState &data) : VertexArrayImpl(data) {}
+
+ angle::Result syncState(const gl::Context *context,
+ const gl::VertexArray::DirtyBits &dirtyBits,
+ gl::VertexArray::DirtyAttribBitsArray *attribBits,
+ gl::VertexArray::DirtyBindingBitsArray *bindingBits) override;
+
+ ~VertexArray9() override {}
+
+ Serial getCurrentStateSerial() const { return mCurrentStateSerial; }
+
+ private:
+ Serial mCurrentStateSerial;
+};
+
+inline angle::Result VertexArray9::syncState(const gl::Context *context,
+ const gl::VertexArray::DirtyBits &dirtyBits,
+ gl::VertexArray::DirtyAttribBitsArray *attribBits,
+ gl::VertexArray::DirtyBindingBitsArray *bindingBits)
+{
+
+ ASSERT(dirtyBits.any());
+ Renderer9 *renderer = GetImplAs<Context9>(context)->getRenderer();
+ mCurrentStateSerial = renderer->generateSerial();
+
+ // Clear the dirty bits in the back-end here.
+ memset(attribBits, 0, sizeof(gl::VertexArray::DirtyAttribBitsArray));
+ memset(bindingBits, 0, sizeof(gl::VertexArray::DirtyBindingBitsArray));
+
+ return angle::Result::Continue;
+}
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp
new file mode 100644
index 0000000000..915928686a
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp
@@ -0,0 +1,153 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation.
+
+#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/vertexconversion.h"
+
+namespace rx
+{
+
+VertexBuffer9::VertexBuffer9(Renderer9 *renderer) : mRenderer(renderer)
+{
+ mVertexBuffer = nullptr;
+ mBufferSize = 0;
+ mDynamicUsage = false;
+}
+
+VertexBuffer9::~VertexBuffer9()
+{
+ SafeRelease(mVertexBuffer);
+}
+
+angle::Result VertexBuffer9::initialize(const gl::Context *context,
+ unsigned int size,
+ bool dynamicUsage)
+{
+ SafeRelease(mVertexBuffer);
+
+ updateSerial();
+
+ if (size > 0)
+ {
+ DWORD flags = D3DUSAGE_WRITEONLY;
+ if (dynamicUsage)
+ {
+ flags |= D3DUSAGE_DYNAMIC;
+ }
+
+ HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer);
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), result,
+ "Failed to allocate internal vertex buffer");
+ }
+
+ mBufferSize = size;
+ mDynamicUsage = dynamicUsage;
+ return angle::Result::Continue;
+}
+
+angle::Result VertexBuffer9::storeVertexAttributes(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ gl::VertexAttribType currentValueType,
+ GLint start,
+ size_t count,
+ GLsizei instances,
+ unsigned int offset,
+ const uint8_t *sourceData)
+{
+ ASSERT(mVertexBuffer);
+
+ size_t inputStride = gl::ComputeVertexAttributeStride(attrib, binding);
+ size_t elementSize = gl::ComputeVertexAttributeTypeSize(attrib);
+
+ DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0;
+
+ uint8_t *mapPtr = nullptr;
+
+ unsigned int mapSize = 0;
+ ANGLE_TRY(
+ mRenderer->getVertexSpaceRequired(context, attrib, binding, count, instances, 0, &mapSize));
+
+ HRESULT result =
+ mVertexBuffer->Lock(offset, mapSize, reinterpret_cast<void **>(&mapPtr), lockFlags);
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), result, "Failed to lock internal vertex buffer");
+
+ const uint8_t *input = sourceData;
+
+ if (instances == 0 || binding.getDivisor() == 0)
+ {
+ input += inputStride * start;
+ }
+
+ angle::FormatID vertexFormatID = gl::GetVertexFormatID(attrib, currentValueType);
+ const d3d9::VertexFormat &d3dVertexInfo =
+ d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormatID);
+ bool needsConversion = (d3dVertexInfo.conversionType & VERTEX_CONVERT_CPU) > 0;
+
+ if (!needsConversion && inputStride == elementSize)
+ {
+ size_t copySize = count * inputStride;
+ memcpy(mapPtr, input, copySize);
+ }
+ else
+ {
+ d3dVertexInfo.copyFunction(input, inputStride, count, mapPtr);
+ }
+
+ mVertexBuffer->Unlock();
+
+ return angle::Result::Continue;
+}
+
+unsigned int VertexBuffer9::getBufferSize() const
+{
+ return mBufferSize;
+}
+
+angle::Result VertexBuffer9::setBufferSize(const gl::Context *context, unsigned int size)
+{
+ if (size > mBufferSize)
+ {
+ return initialize(context, size, mDynamicUsage);
+ }
+ else
+ {
+ return angle::Result::Continue;
+ }
+}
+
+angle::Result VertexBuffer9::discard(const gl::Context *context)
+{
+ ASSERT(mVertexBuffer);
+
+ void *mock;
+ HRESULT result;
+
+ Context9 *context9 = GetImplAs<Context9>(context);
+
+ result = mVertexBuffer->Lock(0, 1, &mock, D3DLOCK_DISCARD);
+ ANGLE_TRY_HR(context9, result, "Failed to lock internal vertex buffer for discarding");
+
+ result = mVertexBuffer->Unlock();
+ ANGLE_TRY_HR(context9, result, "Failed to unlock internal vertex buffer for discarding");
+
+ return angle::Result::Continue;
+}
+
+IDirect3DVertexBuffer9 *VertexBuffer9::getBuffer() const
+{
+ return mVertexBuffer;
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h
new file mode 100644
index 0000000000..d5c156e5f5
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h
@@ -0,0 +1,56 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexBuffer9.h: Defines the D3D9 VertexBuffer implementation.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_
+
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
+
+namespace rx
+{
+class Renderer9;
+
+class VertexBuffer9 : public VertexBuffer
+{
+ public:
+ explicit VertexBuffer9(Renderer9 *renderer);
+
+ angle::Result initialize(const gl::Context *context,
+ unsigned int size,
+ bool dynamicUsage) override;
+
+ // Warning: you should ensure binding really matches attrib.bindingIndex before using this
+ // function.
+ angle::Result storeVertexAttributes(const gl::Context *context,
+ const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ gl::VertexAttribType currentValueType,
+ GLint start,
+ size_t count,
+ GLsizei instances,
+ unsigned int offset,
+ const uint8_t *sourceData) override;
+
+ unsigned int getBufferSize() const override;
+ angle::Result setBufferSize(const gl::Context *context, unsigned int size) override;
+ angle::Result discard(const gl::Context *context) override;
+
+ IDirect3DVertexBuffer9 *getBuffer() const;
+
+ private:
+ ~VertexBuffer9() override;
+ Renderer9 *mRenderer;
+
+ IDirect3DVertexBuffer9 *mVertexBuffer;
+ unsigned int mBufferSize;
+ bool mDynamicUsage;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp
new file mode 100644
index 0000000000..e129ae9786
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp
@@ -0,0 +1,262 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations.
+
+#include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/Context9.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+
+namespace rx
+{
+
+VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0)
+{
+ for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+ {
+ mVertexDeclCache[i].vertexDeclaration = nullptr;
+ mVertexDeclCache[i].lruCount = 0;
+ }
+
+ for (VBData &vb : mAppliedVBs)
+ {
+ vb.serial = 0;
+ }
+
+ mLastSetVDecl = nullptr;
+ mInstancingEnabled = true;
+}
+
+VertexDeclarationCache::~VertexDeclarationCache()
+{
+ for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+ {
+ SafeRelease(mVertexDeclCache[i].vertexDeclaration);
+ }
+}
+
+angle::Result VertexDeclarationCache::applyDeclaration(
+ const gl::Context *context,
+ IDirect3DDevice9 *device,
+ const std::vector<TranslatedAttribute> &attributes,
+ gl::Program *program,
+ GLint start,
+ GLsizei instances,
+ GLsizei *repeatDraw)
+{
+ ASSERT(gl::MAX_VERTEX_ATTRIBS >= attributes.size());
+
+ *repeatDraw = 1;
+
+ const size_t invalidAttribIndex = attributes.size();
+ size_t indexedAttribute = invalidAttribIndex;
+ size_t instancedAttribute = invalidAttribIndex;
+
+ if (instances == 0)
+ {
+ for (size_t i = 0; i < attributes.size(); ++i)
+ {
+ if (attributes[i].divisor != 0)
+ {
+ // If a divisor is set, it still applies even if an instanced draw was not used, so
+ // treat as a single-instance draw.
+ instances = 1;
+ break;
+ }
+ }
+ }
+
+ if (instances > 0)
+ {
+ // Find an indexed attribute to be mapped to D3D stream 0
+ for (size_t i = 0; i < attributes.size(); i++)
+ {
+ if (attributes[i].active)
+ {
+ if (indexedAttribute == invalidAttribIndex && attributes[i].divisor == 0)
+ {
+ indexedAttribute = i;
+ }
+ else if (instancedAttribute == invalidAttribIndex && attributes[i].divisor != 0)
+ {
+ instancedAttribute = i;
+ }
+ if (indexedAttribute != invalidAttribIndex &&
+ instancedAttribute != invalidAttribIndex)
+ break; // Found both an indexed and instanced attribute
+ }
+ }
+
+ // The validation layer checks that there is at least one active attribute with a zero
+ // divisor as per the GL_ANGLE_instanced_arrays spec.
+ ASSERT(indexedAttribute != invalidAttribIndex);
+ }
+
+ D3DCAPS9 caps;
+ device->GetDeviceCaps(&caps);
+
+ D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1];
+ D3DVERTEXELEMENT9 *element = &elements[0];
+
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+ const auto &semanticIndexes = programD3D->getAttribLocationToD3DSemantics();
+
+ for (size_t i = 0; i < attributes.size(); i++)
+ {
+ if (attributes[i].active)
+ {
+ // Directly binding the storage buffer is not supported for d3d9
+ ASSERT(attributes[i].storage == nullptr);
+
+ int stream = static_cast<int>(i);
+
+ if (instances > 0)
+ {
+ // Due to a bug on ATI cards we can't enable instancing when none of the attributes
+ // are instanced.
+ if (instancedAttribute == invalidAttribIndex)
+ {
+ *repeatDraw = instances;
+ }
+ else
+ {
+ if (i == indexedAttribute)
+ {
+ stream = 0;
+ }
+ else if (i == 0)
+ {
+ stream = static_cast<int>(indexedAttribute);
+ }
+
+ UINT frequency = 1;
+
+ if (attributes[i].divisor == 0)
+ {
+ frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances;
+ }
+ else
+ {
+ frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor;
+ }
+
+ device->SetStreamSourceFreq(stream, frequency);
+ mInstancingEnabled = true;
+ }
+ }
+
+ VertexBuffer9 *vertexBuffer = GetAs<VertexBuffer9>(attributes[i].vertexBuffer.get());
+
+ unsigned int offset = 0;
+ ANGLE_TRY(attributes[i].computeOffset(context, start, &offset));
+
+ if (mAppliedVBs[stream].serial != attributes[i].serial ||
+ mAppliedVBs[stream].stride != attributes[i].stride ||
+ mAppliedVBs[stream].offset != offset)
+ {
+ device->SetStreamSource(stream, vertexBuffer->getBuffer(), offset,
+ attributes[i].stride);
+ mAppliedVBs[stream].serial = attributes[i].serial;
+ mAppliedVBs[stream].stride = attributes[i].stride;
+ mAppliedVBs[stream].offset = offset;
+ }
+
+ angle::FormatID vertexformatID =
+ gl::GetVertexFormatID(*attributes[i].attribute, gl::VertexAttribType::Float);
+ const d3d9::VertexFormat &d3d9VertexInfo =
+ d3d9::GetVertexFormatInfo(caps.DeclTypes, vertexformatID);
+
+ element->Stream = static_cast<WORD>(stream);
+ element->Offset = 0;
+ element->Type = static_cast<BYTE>(d3d9VertexInfo.nativeFormat);
+ element->Method = D3DDECLMETHOD_DEFAULT;
+ element->Usage = D3DDECLUSAGE_TEXCOORD;
+ element->UsageIndex = static_cast<BYTE>(semanticIndexes[i]);
+ element++;
+ }
+ }
+
+ if (instances == 0 || instancedAttribute == invalidAttribIndex)
+ {
+ if (mInstancingEnabled)
+ {
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ device->SetStreamSourceFreq(i, 1);
+ }
+
+ mInstancingEnabled = false;
+ }
+ }
+
+ static const D3DVERTEXELEMENT9 end = D3DDECL_END();
+ *(element++) = end;
+
+ for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+ {
+ VertexDeclCacheEntry *entry = &mVertexDeclCache[i];
+ if (memcmp(entry->cachedElements, elements,
+ (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 &&
+ entry->vertexDeclaration)
+ {
+ entry->lruCount = ++mMaxLru;
+ if (entry->vertexDeclaration != mLastSetVDecl)
+ {
+ device->SetVertexDeclaration(entry->vertexDeclaration);
+ mLastSetVDecl = entry->vertexDeclaration;
+ }
+
+ return angle::Result::Continue;
+ }
+ }
+
+ VertexDeclCacheEntry *lastCache = mVertexDeclCache;
+
+ for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
+ {
+ if (mVertexDeclCache[i].lruCount < lastCache->lruCount)
+ {
+ lastCache = &mVertexDeclCache[i];
+ }
+ }
+
+ if (lastCache->vertexDeclaration != nullptr)
+ {
+ SafeRelease(lastCache->vertexDeclaration);
+ // mLastSetVDecl is set to the replacement, so we don't have to worry
+ // about it.
+ }
+
+ memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9));
+ HRESULT result = device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration);
+ ANGLE_TRY_HR(GetImplAs<Context9>(context), result,
+ "Failed to create internal vertex declaration");
+
+ device->SetVertexDeclaration(lastCache->vertexDeclaration);
+ mLastSetVDecl = lastCache->vertexDeclaration;
+ lastCache->lruCount = ++mMaxLru;
+
+ return angle::Result::Continue;
+}
+
+void VertexDeclarationCache::markStateDirty()
+{
+ for (VBData &vb : mAppliedVBs)
+ {
+ vb.serial = 0;
+ }
+
+ mLastSetVDecl = nullptr;
+ mInstancingEnabled = true; // Forces it to be disabled when not used
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h
new file mode 100644
index 0000000000..22e677d800
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h
@@ -0,0 +1,68 @@
+//
+// Copyright 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// VertexDeclarationCache.h: Defines a helper class to construct and cache vertex declarations.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_
+
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+
+namespace gl
+{
+class VertexDataManager;
+class Program;
+} // namespace gl
+
+namespace rx
+{
+class VertexDeclarationCache
+{
+ public:
+ VertexDeclarationCache();
+ ~VertexDeclarationCache();
+
+ angle::Result applyDeclaration(const gl::Context *context,
+ IDirect3DDevice9 *device,
+ const std::vector<TranslatedAttribute> &attributes,
+ gl::Program *program,
+ GLint start,
+ GLsizei instances,
+ GLsizei *repeatDraw);
+
+ void markStateDirty();
+
+ private:
+ UINT mMaxLru;
+
+ enum
+ {
+ NUM_VERTEX_DECL_CACHE_ENTRIES = 32
+ };
+
+ struct VBData
+ {
+ unsigned int serial;
+ unsigned int stride;
+ unsigned int offset;
+ };
+
+ VBData mAppliedVBs[gl::MAX_VERTEX_ATTRIBS];
+ IDirect3DVertexDeclaration9 *mLastSetVDecl;
+ bool mInstancingEnabled;
+
+ struct VertexDeclCacheEntry
+ {
+ D3DVERTEXELEMENT9 cachedElements[gl::MAX_VERTEX_ATTRIBS + 1];
+ UINT lruCount;
+ IDirect3DVertexDeclaration9 *vertexDeclaration;
+ } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES];
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp
new file mode 100644
index 0000000000..19a10b9cfb
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp
@@ -0,0 +1,695 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// formatutils9.cpp: Queries for GL image formats and their translations to D3D9
+// formats.
+
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+#include "anglebase/no_destructor.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/vertexconversion.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace d3d9
+{
+
+constexpr D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z')));
+constexpr D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L')));
+
+// A map to determine the pixel size and mip generation function of a given D3D format
+typedef std::map<D3DFORMAT, D3DFormat> D3D9FormatInfoMap;
+
+typedef std::pair<GLint, InitializeTextureDataFunction> InternalFormatInitialzerPair;
+typedef std::map<GLint, InitializeTextureDataFunction> InternalFormatInitialzerMap;
+
+static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap()
+{
+ using namespace angle; // For image initialization functions
+
+ InternalFormatInitialzerMap map;
+
+ map.insert(InternalFormatInitialzerPair(
+ GL_RGB16F, Initialize4ComponentData<GLhalf, 0x0000, 0x0000, 0x0000, gl::Float16One>));
+ map.insert(InternalFormatInitialzerPair(
+ GL_RGB32F,
+ Initialize4ComponentData<GLfloat, 0x00000000, 0x00000000, 0x00000000, gl::Float32One>));
+
+ return map;
+}
+
+static void UnreachableLoad(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ UNREACHABLE();
+}
+
+typedef std::pair<GLenum, TextureFormat> D3D9FormatPair;
+typedef std::map<GLenum, TextureFormat> D3D9FormatMap;
+
+TextureFormat::TextureFormat()
+ : texFormat(D3DFMT_UNKNOWN),
+ renderFormat(D3DFMT_UNKNOWN),
+ dataInitializerFunction(nullptr),
+ loadFunction(UnreachableLoad)
+{}
+
+static inline void InsertD3D9FormatInfo(D3D9FormatMap *map,
+ GLenum internalFormat,
+ D3DFORMAT texFormat,
+ D3DFORMAT renderFormat,
+ LoadImageFunction loadFunction)
+{
+ TextureFormat info;
+ info.texFormat = texFormat;
+ info.renderFormat = renderFormat;
+
+ static const angle::base::NoDestructor<InternalFormatInitialzerMap> dataInitializationMap(
+ BuildInternalFormatInitialzerMap());
+ InternalFormatInitialzerMap::const_iterator dataInitIter =
+ dataInitializationMap->find(internalFormat);
+ info.dataInitializerFunction =
+ (dataInitIter != dataInitializationMap->end()) ? dataInitIter->second : nullptr;
+
+ info.loadFunction = loadFunction;
+
+ map->insert(std::make_pair(internalFormat, info));
+}
+
+static D3D9FormatMap BuildD3D9FormatMap()
+{
+ using namespace angle; // For image loading functions
+
+ D3D9FormatMap map;
+
+ // clang-format off
+ // | Internal format | Texture format | Render format | Load function |
+ InsertD3D9FormatInfo(&map, GL_NONE, D3DFMT_NULL, D3DFMT_NULL, UnreachableLoad );
+
+ // We choose to downsample the GL_DEPTH_COMPONENT32_OES format to a 24-bit format because D3DFMT_D32 is not widely
+ // supported. We're allowed to do this because:
+ // - The ES spec 2.0.25 sec 3.7.1 states that we're allowed to store texture formats with internal format
+ // resolutions of our own choosing.
+ // - OES_depth_texture states that downsampling of the depth formats is allowed.
+ // - ANGLE_depth_texture does not state minimum required resolutions of the depth texture formats it
+ // introduces.
+ // In ES3 however, there are minimum resolutions for the texture formats and this would not be allowed.
+
+ InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT16, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad );
+ InsertD3D9FormatInfo(&map, GL_DEPTH_COMPONENT32_OES, D3DFMT_INTZ, D3DFMT_D24X8, UnreachableLoad );
+ InsertD3D9FormatInfo(&map, GL_DEPTH24_STENCIL8_OES, D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad );
+ InsertD3D9FormatInfo(&map, GL_STENCIL_INDEX8, D3DFMT_UNKNOWN, D3DFMT_D24S8, UnreachableLoad ); // TODO: What's the texture format?
+
+ InsertD3D9FormatInfo(&map, GL_RGBA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative<GLfloat, 4> );
+ InsertD3D9FormatInfo(&map, GL_RGB32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative3To4<GLfloat, gl::Float32One>);
+ InsertD3D9FormatInfo(&map, GL_RG32F_EXT, D3DFMT_G32R32F, D3DFMT_G32R32F, LoadToNative<GLfloat, 2> );
+ InsertD3D9FormatInfo(&map, GL_R32F_EXT, D3DFMT_R32F, D3DFMT_R32F, LoadToNative<GLfloat, 1> );
+ InsertD3D9FormatInfo(&map, GL_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadA32FToRGBA32F );
+ InsertD3D9FormatInfo(&map, GL_LUMINANCE32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadL32FToRGBA32F );
+ InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT, D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadLA32FToRGBA32F );
+
+ InsertD3D9FormatInfo(&map, GL_RGBA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative<GLhalf, 4> );
+ InsertD3D9FormatInfo(&map, GL_RGB16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative3To4<GLhalf, gl::Float16One> );
+ InsertD3D9FormatInfo(&map, GL_RG16F_EXT, D3DFMT_G16R16F, D3DFMT_G16R16F, LoadToNative<GLhalf, 2> );
+ InsertD3D9FormatInfo(&map, GL_R16F_EXT, D3DFMT_R16F, D3DFMT_R16F, LoadToNative<GLhalf, 1> );
+ InsertD3D9FormatInfo(&map, GL_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadA16FToRGBA16F );
+ InsertD3D9FormatInfo(&map, GL_LUMINANCE16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadL16FToRGBA16F );
+ InsertD3D9FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT, D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadLA16FToRGBA16F );
+
+ InsertD3D9FormatInfo(&map, GL_ALPHA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadA8ToBGRA8 );
+
+ InsertD3D9FormatInfo(&map, GL_RGB8_OES, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRGB8ToBGRX8 );
+ InsertD3D9FormatInfo(&map, GL_RGB565, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR5G6B5ToBGRA8 );
+ InsertD3D9FormatInfo(&map, GL_RGBA8_OES, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA8ToBGRA8 );
+ InsertD3D9FormatInfo(&map, GL_RGBA4, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA4ToBGRA8 );
+ InsertD3D9FormatInfo(&map, GL_RGB5_A1, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGB5A1ToBGRA8 );
+ InsertD3D9FormatInfo(&map, GL_R8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR8ToBGRX8 );
+ InsertD3D9FormatInfo(&map, GL_RG8_EXT, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRG8ToBGRX8 );
+
+ InsertD3D9FormatInfo(&map, GL_SRGB8, D3DFMT_X8R8G8B8, D3DFMT_UNKNOWN, LoadRGB8ToBGRX8 );
+ InsertD3D9FormatInfo(&map, GL_SRGB8_ALPHA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA8ToBGRA8 );
+
+ InsertD3D9FormatInfo(&map, GL_BGRA8_EXT, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadToNative<GLubyte, 4> );
+ InsertD3D9FormatInfo(&map, GL_BGRA4_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGRA4ToBGRA8 );
+ InsertD3D9FormatInfo(&map, GL_BGR5_A1_ANGLEX, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGR5A1ToBGRA8 );
+
+ InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 8> );
+ InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 8> );
+ InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3DFMT_DXT3, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 16> );
+ InsertD3D9FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3DFMT_DXT5, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 16> );
+
+ InsertD3D9FormatInfo(&map, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 8> );
+ InsertD3D9FormatInfo(&map, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 8> );
+ InsertD3D9FormatInfo(&map, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, D3DFMT_DXT3, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 16> );
+ InsertD3D9FormatInfo(&map, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, D3DFMT_DXT5, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 1, 16> );
+
+ // These formats require checking if the renderer supports D3DFMT_L8 or D3DFMT_A8L8 and
+ // then changing the format and loading function appropriately.
+ InsertD3D9FormatInfo(&map, GL_LUMINANCE8_EXT, D3DFMT_L8, D3DFMT_UNKNOWN, LoadToNative<GLubyte, 1> );
+ InsertD3D9FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, D3DFMT_A8L8, D3DFMT_UNKNOWN, LoadToNative<GLubyte, 2> );
+ // clang-format on
+
+ return map;
+}
+
+const TextureFormat &GetTextureFormatInfo(GLenum internalFormat)
+{
+ static const angle::base::NoDestructor<D3D9FormatMap> formatMap(BuildD3D9FormatMap());
+ D3D9FormatMap::const_iterator iter = formatMap->find(internalFormat);
+ if (iter != formatMap->end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ static const TextureFormat defaultInfo;
+ return defaultInfo;
+ }
+}
+
+static GLenum GetDeclTypeComponentType(D3DDECLTYPE declType)
+{
+ switch (declType)
+ {
+ case D3DDECLTYPE_FLOAT1:
+ return GL_FLOAT;
+ case D3DDECLTYPE_FLOAT2:
+ return GL_FLOAT;
+ case D3DDECLTYPE_FLOAT3:
+ return GL_FLOAT;
+ case D3DDECLTYPE_FLOAT4:
+ return GL_FLOAT;
+ case D3DDECLTYPE_UBYTE4:
+ return GL_UNSIGNED_INT;
+ case D3DDECLTYPE_SHORT2:
+ return GL_INT;
+ case D3DDECLTYPE_SHORT4:
+ return GL_INT;
+ case D3DDECLTYPE_UBYTE4N:
+ return GL_UNSIGNED_NORMALIZED;
+ case D3DDECLTYPE_SHORT4N:
+ return GL_SIGNED_NORMALIZED;
+ case D3DDECLTYPE_USHORT4N:
+ return GL_UNSIGNED_NORMALIZED;
+ case D3DDECLTYPE_SHORT2N:
+ return GL_SIGNED_NORMALIZED;
+ case D3DDECLTYPE_USHORT2N:
+ return GL_UNSIGNED_NORMALIZED;
+ default:
+ UNREACHABLE();
+ return GL_NONE;
+ }
+}
+
+// Attribute format conversion
+enum
+{
+ NUM_GL_VERTEX_ATTRIB_TYPES = 6
+};
+
+struct TranslationDescription
+{
+ DWORD capsFlag;
+ VertexFormat preferredConversion;
+ VertexFormat fallbackConversion;
+};
+
+// Mapping from OpenGL-ES vertex attrib type to D3D decl type:
+//
+// BYTE SHORT (Cast)
+// BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm)
+// UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast)
+// UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize)
+// SHORT SHORT (Identity)
+// SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize)
+// UNSIGNED_SHORT FLOAT (Cast)
+// UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize)
+// FIXED (not in WebGL) FLOAT (FixedToFloat)
+// FLOAT FLOAT (Identity)
+
+// GLToCType maps from GL type (as GLenum) to the C typedef.
+template <GLenum GLType>
+struct GLToCType
+{};
+
+template <>
+struct GLToCType<GL_BYTE>
+{
+ typedef GLbyte type;
+};
+template <>
+struct GLToCType<GL_UNSIGNED_BYTE>
+{
+ typedef GLubyte type;
+};
+template <>
+struct GLToCType<GL_SHORT>
+{
+ typedef GLshort type;
+};
+template <>
+struct GLToCType<GL_UNSIGNED_SHORT>
+{
+ typedef GLushort type;
+};
+template <>
+struct GLToCType<GL_FIXED>
+{
+ typedef GLuint type;
+};
+template <>
+struct GLToCType<GL_FLOAT>
+{
+ typedef GLfloat type;
+};
+
+// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.)
+enum D3DVertexType
+{
+ D3DVT_FLOAT,
+ D3DVT_SHORT,
+ D3DVT_SHORT_NORM,
+ D3DVT_UBYTE,
+ D3DVT_UBYTE_NORM,
+ D3DVT_USHORT_NORM
+};
+
+// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type.
+template <unsigned int D3DType>
+struct D3DToCType
+{};
+
+template <>
+struct D3DToCType<D3DVT_FLOAT>
+{
+ typedef float type;
+};
+template <>
+struct D3DToCType<D3DVT_SHORT>
+{
+ typedef short type;
+};
+template <>
+struct D3DToCType<D3DVT_SHORT_NORM>
+{
+ typedef short type;
+};
+template <>
+struct D3DToCType<D3DVT_UBYTE>
+{
+ typedef unsigned char type;
+};
+template <>
+struct D3DToCType<D3DVT_UBYTE_NORM>
+{
+ typedef unsigned char type;
+};
+template <>
+struct D3DToCType<D3DVT_USHORT_NORM>
+{
+ typedef unsigned short type;
+};
+
+// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener
+// that will provide the appropriate final size.
+template <unsigned int type, int size>
+struct WidenRule
+{};
+
+template <int size>
+struct WidenRule<D3DVT_FLOAT, size> : NoWiden<size>
+{};
+template <int size>
+struct WidenRule<D3DVT_SHORT, size> : WidenToEven<size>
+{};
+template <int size>
+struct WidenRule<D3DVT_SHORT_NORM, size> : WidenToEven<size>
+{};
+template <int size>
+struct WidenRule<D3DVT_UBYTE, size> : WidenToFour<size>
+{};
+template <int size>
+struct WidenRule<D3DVT_UBYTE_NORM, size> : WidenToFour<size>
+{};
+template <int size>
+struct WidenRule<D3DVT_USHORT_NORM, size> : WidenToEven<size>
+{};
+
+// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D
+// vertex type & size combination.
+template <unsigned int d3dtype, int size>
+struct VertexTypeFlags
+{};
+
+template <unsigned int _capflag, unsigned int _declflag>
+struct VertexTypeFlagsHelper
+{
+ enum
+ {
+ capflag = _capflag
+ };
+ enum
+ {
+ declflag = _declflag
+ };
+};
+
+template <>
+struct VertexTypeFlags<D3DVT_FLOAT, 1> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1>
+{};
+template <>
+struct VertexTypeFlags<D3DVT_FLOAT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2>
+{};
+template <>
+struct VertexTypeFlags<D3DVT_FLOAT, 3> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3>
+{};
+template <>
+struct VertexTypeFlags<D3DVT_FLOAT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4>
+{};
+template <>
+struct VertexTypeFlags<D3DVT_SHORT, 2> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2>
+{};
+template <>
+struct VertexTypeFlags<D3DVT_SHORT, 4> : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4>
+{};
+template <>
+struct VertexTypeFlags<D3DVT_SHORT_NORM, 2>
+ : VertexTypeFlagsHelper<D3DDTCAPS_SHORT2N, D3DDECLTYPE_SHORT2N>
+{};
+template <>
+struct VertexTypeFlags<D3DVT_SHORT_NORM, 4>
+ : VertexTypeFlagsHelper<D3DDTCAPS_SHORT4N, D3DDECLTYPE_SHORT4N>
+{};
+template <>
+struct VertexTypeFlags<D3DVT_UBYTE, 4> : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4, D3DDECLTYPE_UBYTE4>
+{};
+template <>
+struct VertexTypeFlags<D3DVT_UBYTE_NORM, 4>
+ : VertexTypeFlagsHelper<D3DDTCAPS_UBYTE4N, D3DDECLTYPE_UBYTE4N>
+{};
+template <>
+struct VertexTypeFlags<D3DVT_USHORT_NORM, 2>
+ : VertexTypeFlagsHelper<D3DDTCAPS_USHORT2N, D3DDECLTYPE_USHORT2N>
+{};
+template <>
+struct VertexTypeFlags<D3DVT_USHORT_NORM, 4>
+ : VertexTypeFlagsHelper<D3DDTCAPS_USHORT4N, D3DDECLTYPE_USHORT4N>
+{};
+
+// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as
+// D3DVertexType enums).
+template <GLenum GLtype, bool normalized>
+struct VertexTypeMapping
+{};
+
+template <D3DVertexType Preferred, D3DVertexType Fallback = Preferred>
+struct VertexTypeMappingBase
+{
+ enum
+ {
+ preferred = Preferred
+ };
+ enum
+ {
+ fallback = Fallback
+ };
+};
+
+template <>
+struct VertexTypeMapping<GL_BYTE, false> : VertexTypeMappingBase<D3DVT_SHORT>
+{}; // Cast
+template <>
+struct VertexTypeMapping<GL_BYTE, true> : VertexTypeMappingBase<D3DVT_FLOAT>
+{}; // Normalize
+template <>
+struct VertexTypeMapping<GL_UNSIGNED_BYTE, false> : VertexTypeMappingBase<D3DVT_UBYTE, D3DVT_FLOAT>
+{}; // Identity, Cast
+template <>
+struct VertexTypeMapping<GL_UNSIGNED_BYTE, true>
+ : VertexTypeMappingBase<D3DVT_UBYTE_NORM, D3DVT_FLOAT>
+{}; // Identity, Normalize
+template <>
+struct VertexTypeMapping<GL_SHORT, false> : VertexTypeMappingBase<D3DVT_SHORT>
+{}; // Identity
+template <>
+struct VertexTypeMapping<GL_SHORT, true> : VertexTypeMappingBase<D3DVT_SHORT_NORM, D3DVT_FLOAT>
+{}; // Cast, Normalize
+template <>
+struct VertexTypeMapping<GL_UNSIGNED_SHORT, false> : VertexTypeMappingBase<D3DVT_FLOAT>
+{}; // Cast
+template <>
+struct VertexTypeMapping<GL_UNSIGNED_SHORT, true>
+ : VertexTypeMappingBase<D3DVT_USHORT_NORM, D3DVT_FLOAT>
+{}; // Cast, Normalize
+template <bool normalized>
+struct VertexTypeMapping<GL_FIXED, normalized> : VertexTypeMappingBase<D3DVT_FLOAT>
+{}; // FixedToFloat
+template <bool normalized>
+struct VertexTypeMapping<GL_FLOAT, normalized> : VertexTypeMappingBase<D3DVT_FLOAT>
+{}; // Identity
+
+// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule
+// (Cast, Normalize, Identity, FixedToFloat). The conversion rules themselves are defined in
+// vertexconversion.h.
+
+// Almost all cases are covered by Cast (including those that are actually Identity since Cast<T,T>
+// knows it's an identity mapping).
+template <GLenum fromType, bool normalized, unsigned int toType>
+struct ConversionRule : Cast<typename GLToCType<fromType>::type, typename D3DToCType<toType>::type>
+{};
+
+// All conversions from normalized types to float use the Normalize operator.
+template <GLenum fromType>
+struct ConversionRule<fromType, true, D3DVT_FLOAT> : Normalize<typename GLToCType<fromType>::type>
+{};
+
+// Use a full specialization for this so that it preferentially matches ahead of the generic
+// normalize-to-float rules.
+template <>
+struct ConversionRule<GL_FIXED, true, D3DVT_FLOAT> : FixedToFloat<GLint, 16>
+{};
+template <>
+struct ConversionRule<GL_FIXED, false, D3DVT_FLOAT> : FixedToFloat<GLint, 16>
+{};
+
+// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues
+// (i.e. 0/1) whether it is normalized or not.
+template <class T, bool normalized>
+struct DefaultVertexValuesStage2
+{};
+
+template <class T>
+struct DefaultVertexValuesStage2<T, true> : NormalizedDefaultValues<T>
+{};
+template <class T>
+struct DefaultVertexValuesStage2<T, false> : SimpleDefaultValues<T>
+{};
+
+// Work out the default value rule for a D3D type (expressed as the C type) and
+template <class T, bool normalized>
+struct DefaultVertexValues : DefaultVertexValuesStage2<T, normalized>
+{};
+template <bool normalized>
+struct DefaultVertexValues<float, normalized> : SimpleDefaultValues<float>
+{};
+
+// Policy rules for use with Converter, to choose whether to use the preferred or fallback
+// conversion. The fallback conversion produces an output that all D3D9 devices must support.
+template <class T>
+struct UsePreferred
+{
+ enum
+ {
+ type = T::preferred
+ };
+};
+template <class T>
+struct UseFallback
+{
+ enum
+ {
+ type = T::fallback
+ };
+};
+
+// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback
+// conversion, it provides all the members of the appropriate VertexDataConverter, the
+// D3DCAPS9::DeclTypes flag in cap flag and the D3DDECLTYPE member needed for the vertex declaration
+// in declflag.
+template <GLenum fromType, bool normalized, int size, template <class T> class PreferenceRule>
+struct Converter
+ : VertexDataConverter<
+ typename GLToCType<fromType>::type,
+ WidenRule<PreferenceRule<VertexTypeMapping<fromType, normalized>>::type, size>,
+ ConversionRule<fromType,
+ normalized,
+ PreferenceRule<VertexTypeMapping<fromType, normalized>>::type>,
+ DefaultVertexValues<typename D3DToCType<PreferenceRule<
+ VertexTypeMapping<fromType, normalized>>::type>::type,
+ normalized>>
+{
+ private:
+ enum
+ {
+ d3dtype = PreferenceRule<VertexTypeMapping<fromType, normalized>>::type
+ };
+ enum
+ {
+ d3dsize = WidenRule<d3dtype, size>::finalWidth
+ };
+
+ public:
+ enum
+ {
+ capflag = VertexTypeFlags<d3dtype, d3dsize>::capflag
+ };
+ enum
+ {
+ declflag = VertexTypeFlags<d3dtype, d3dsize>::declflag
+ };
+};
+
+VertexFormat::VertexFormat()
+ : conversionType(VERTEX_CONVERT_NONE),
+ outputElementSize(0),
+ copyFunction(nullptr),
+ nativeFormat(D3DDECLTYPE_UNUSED),
+ componentType(GL_NONE)
+{}
+
+// Initialize a TranslationInfo
+VertexFormat CreateVertexFormatInfo(bool identity,
+ size_t elementSize,
+ VertexCopyFunction copyFunc,
+ D3DDECLTYPE nativeFormat)
+{
+ VertexFormat formatInfo;
+ formatInfo.conversionType = identity ? VERTEX_CONVERT_NONE : VERTEX_CONVERT_CPU;
+ formatInfo.outputElementSize = elementSize;
+ formatInfo.copyFunction = copyFunc;
+ formatInfo.nativeFormat = nativeFormat;
+ formatInfo.componentType = GetDeclTypeComponentType(nativeFormat);
+ return formatInfo;
+}
+
+#define TRANSLATION(type, norm, size, preferred) \
+ CreateVertexFormatInfo( \
+ Converter<type, norm, size, preferred>::identity, \
+ Converter<type, norm, size, preferred>::finalSize, \
+ Converter<type, norm, size, preferred>::convertArray, \
+ static_cast<D3DDECLTYPE>(Converter<type, norm, size, preferred>::declflag))
+
+#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \
+ { \
+ Converter<type, norm, size, UsePreferred>::capflag, \
+ TRANSLATION(type, norm, size, UsePreferred), \
+ TRANSLATION(type, norm, size, UseFallback) \
+ }
+
+#define TRANSLATIONS_FOR_TYPE(type) \
+ { \
+ {TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), \
+ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), \
+ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), \
+ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4)}, \
+ {TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), \
+ TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), \
+ TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), \
+ TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4)}, \
+ }
+
+#define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \
+ { \
+ {TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), \
+ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), \
+ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), \
+ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4)}, \
+ {TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), \
+ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), \
+ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), \
+ TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4)}, \
+ }
+
+static inline unsigned int ComputeTypeIndex(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return 0;
+ case GL_UNSIGNED_BYTE:
+ return 1;
+ case GL_SHORT:
+ return 2;
+ case GL_UNSIGNED_SHORT:
+ return 3;
+ case GL_FIXED:
+ return 4;
+ case GL_FLOAT:
+ return 5;
+
+ default:
+ UNREACHABLE();
+ return 5;
+ }
+}
+
+const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, angle::FormatID vertexFormatID)
+{
+ static DWORD initializedDeclTypes = 0;
+ static VertexFormat formatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
+ if (initializedDeclTypes != supportedDeclTypes)
+ {
+ const TranslationDescription
+ translations[NUM_GL_VERTEX_ATTRIB_TYPES][2]
+ [4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
+ {TRANSLATIONS_FOR_TYPE(GL_BYTE), TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE),
+ TRANSLATIONS_FOR_TYPE(GL_SHORT), TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT),
+ TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED), TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT)};
+ for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++)
+ {
+ for (unsigned int j = 0; j < 2; j++)
+ {
+ for (unsigned int k = 0; k < 4; k++)
+ {
+ if (translations[i][j][k].capsFlag == 0 ||
+ (supportedDeclTypes & translations[i][j][k].capsFlag) != 0)
+ {
+ formatConverters[i][j][k] = translations[i][j][k].preferredConversion;
+ }
+ else
+ {
+ formatConverters[i][j][k] = translations[i][j][k].fallbackConversion;
+ }
+ }
+ }
+ }
+ initializedDeclTypes = supportedDeclTypes;
+ }
+
+ const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromID(vertexFormatID);
+
+ // Pure integer attributes only supported in ES3.0
+ ASSERT(!vertexFormat.pureInteger);
+ return formatConverters[ComputeTypeIndex(vertexFormat.type)][vertexFormat.normalized]
+ [vertexFormat.components - 1];
+}
+} // namespace d3d9
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/formatutils9.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/formatutils9.h
new file mode 100644
index 0000000000..c3997ec0e9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/formatutils9.h
@@ -0,0 +1,59 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// formatutils9.h: Queries for GL image formats and their translations to D3D9
+// formats.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_
+
+#include <map>
+
+#include "common/platform.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/Format.h"
+#include "libANGLE/renderer/copyvertex.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.h"
+#include "libANGLE/renderer/d3d_format.h"
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace rx
+{
+
+class Renderer9;
+
+namespace d3d9
+{
+
+struct VertexFormat
+{
+ VertexFormat();
+
+ VertexConversionType conversionType;
+ size_t outputElementSize;
+ VertexCopyFunction copyFunction;
+ D3DDECLTYPE nativeFormat;
+ GLenum componentType;
+};
+const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, angle::FormatID vertexFormatID);
+
+struct TextureFormat
+{
+ TextureFormat();
+
+ D3DFORMAT texFormat;
+ D3DFORMAT renderFormat;
+
+ InitializeTextureDataFunction dataInitializerFunction;
+
+ LoadImageFunction loadFunction;
+};
+const TextureFormat &GetTextureFormatInfo(GLenum internalFormat);
+} // namespace d3d9
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
new file mode 100644
index 0000000000..79e5c9cb06
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -0,0 +1,845 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// renderer9_utils.cpp: Conversion functions and other utility routines
+// specific to the D3D9 renderer.
+
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+
+#include "common/debug.h"
+#include "common/mathutil.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/driver_utils.h"
+#include "platform/FeaturesD3D_autogen.h"
+#include "platform/PlatformMethods.h"
+
+#include "third_party/systeminfo/SystemInfo.h"
+
+namespace rx
+{
+
+namespace gl_d3d9
+{
+
+D3DCMPFUNC ConvertComparison(GLenum comparison)
+{
+ D3DCMPFUNC d3dComp = D3DCMP_ALWAYS;
+ switch (comparison)
+ {
+ case GL_NEVER:
+ d3dComp = D3DCMP_NEVER;
+ break;
+ case GL_ALWAYS:
+ d3dComp = D3DCMP_ALWAYS;
+ break;
+ case GL_LESS:
+ d3dComp = D3DCMP_LESS;
+ break;
+ case GL_LEQUAL:
+ d3dComp = D3DCMP_LESSEQUAL;
+ break;
+ case GL_EQUAL:
+ d3dComp = D3DCMP_EQUAL;
+ break;
+ case GL_GREATER:
+ d3dComp = D3DCMP_GREATER;
+ break;
+ case GL_GEQUAL:
+ d3dComp = D3DCMP_GREATEREQUAL;
+ break;
+ case GL_NOTEQUAL:
+ d3dComp = D3DCMP_NOTEQUAL;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return d3dComp;
+}
+
+D3DCOLOR ConvertColor(gl::ColorF color)
+{
+ return D3DCOLOR_RGBA(gl::unorm<8>(color.red), gl::unorm<8>(color.green),
+ gl::unorm<8>(color.blue), gl::unorm<8>(color.alpha));
+}
+
+D3DBLEND ConvertBlendFunc(GLenum blend)
+{
+ D3DBLEND d3dBlend = D3DBLEND_ZERO;
+
+ switch (blend)
+ {
+ case GL_ZERO:
+ d3dBlend = D3DBLEND_ZERO;
+ break;
+ case GL_ONE:
+ d3dBlend = D3DBLEND_ONE;
+ break;
+ case GL_SRC_COLOR:
+ d3dBlend = D3DBLEND_SRCCOLOR;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ d3dBlend = D3DBLEND_INVSRCCOLOR;
+ break;
+ case GL_DST_COLOR:
+ d3dBlend = D3DBLEND_DESTCOLOR;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ d3dBlend = D3DBLEND_INVDESTCOLOR;
+ break;
+ case GL_SRC_ALPHA:
+ d3dBlend = D3DBLEND_SRCALPHA;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ d3dBlend = D3DBLEND_INVSRCALPHA;
+ break;
+ case GL_DST_ALPHA:
+ d3dBlend = D3DBLEND_DESTALPHA;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ d3dBlend = D3DBLEND_INVDESTALPHA;
+ break;
+ case GL_CONSTANT_COLOR:
+ d3dBlend = D3DBLEND_BLENDFACTOR;
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ d3dBlend = D3DBLEND_INVBLENDFACTOR;
+ break;
+ case GL_CONSTANT_ALPHA:
+ d3dBlend = D3DBLEND_BLENDFACTOR;
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ d3dBlend = D3DBLEND_INVBLENDFACTOR;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ d3dBlend = D3DBLEND_SRCALPHASAT;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return d3dBlend;
+}
+
+D3DBLENDOP ConvertBlendOp(GLenum blendOp)
+{
+ D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD;
+
+ switch (blendOp)
+ {
+ case GL_FUNC_ADD:
+ d3dBlendOp = D3DBLENDOP_ADD;
+ break;
+ case GL_FUNC_SUBTRACT:
+ d3dBlendOp = D3DBLENDOP_SUBTRACT;
+ break;
+ case GL_FUNC_REVERSE_SUBTRACT:
+ d3dBlendOp = D3DBLENDOP_REVSUBTRACT;
+ break;
+ case GL_MIN_EXT:
+ d3dBlendOp = D3DBLENDOP_MIN;
+ break;
+ case GL_MAX_EXT:
+ d3dBlendOp = D3DBLENDOP_MAX;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return d3dBlendOp;
+}
+
+D3DSTENCILOP ConvertStencilOp(GLenum stencilOp)
+{
+ D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP;
+
+ switch (stencilOp)
+ {
+ case GL_ZERO:
+ d3dStencilOp = D3DSTENCILOP_ZERO;
+ break;
+ case GL_KEEP:
+ d3dStencilOp = D3DSTENCILOP_KEEP;
+ break;
+ case GL_REPLACE:
+ d3dStencilOp = D3DSTENCILOP_REPLACE;
+ break;
+ case GL_INCR:
+ d3dStencilOp = D3DSTENCILOP_INCRSAT;
+ break;
+ case GL_DECR:
+ d3dStencilOp = D3DSTENCILOP_DECRSAT;
+ break;
+ case GL_INVERT:
+ d3dStencilOp = D3DSTENCILOP_INVERT;
+ break;
+ case GL_INCR_WRAP:
+ d3dStencilOp = D3DSTENCILOP_INCR;
+ break;
+ case GL_DECR_WRAP:
+ d3dStencilOp = D3DSTENCILOP_DECR;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return d3dStencilOp;
+}
+
+D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap)
+{
+ D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP;
+
+ switch (wrap)
+ {
+ case GL_REPEAT:
+ d3dWrap = D3DTADDRESS_WRAP;
+ break;
+ case GL_CLAMP_TO_EDGE:
+ d3dWrap = D3DTADDRESS_CLAMP;
+ break;
+ case GL_CLAMP_TO_BORDER:
+ d3dWrap = D3DTADDRESS_BORDER;
+ break;
+ case GL_MIRRORED_REPEAT:
+ d3dWrap = D3DTADDRESS_MIRROR;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return d3dWrap;
+}
+
+D3DCULL ConvertCullMode(gl::CullFaceMode cullFace, GLenum frontFace)
+{
+ D3DCULL cull = D3DCULL_CCW;
+ switch (cullFace)
+ {
+ case gl::CullFaceMode::Front:
+ cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW);
+ break;
+ case gl::CullFaceMode::Back:
+ cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW);
+ break;
+ case gl::CullFaceMode::FrontAndBack:
+ cull = D3DCULL_NONE; // culling will be handled during draw
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return cull;
+}
+
+D3DCUBEMAP_FACES ConvertCubeFace(gl::TextureTarget cubeFace)
+{
+ D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X;
+
+ switch (cubeFace)
+ {
+ case gl::TextureTarget::CubeMapPositiveX:
+ face = D3DCUBEMAP_FACE_POSITIVE_X;
+ break;
+ case gl::TextureTarget::CubeMapNegativeX:
+ face = D3DCUBEMAP_FACE_NEGATIVE_X;
+ break;
+ case gl::TextureTarget::CubeMapPositiveY:
+ face = D3DCUBEMAP_FACE_POSITIVE_Y;
+ break;
+ case gl::TextureTarget::CubeMapNegativeY:
+ face = D3DCUBEMAP_FACE_NEGATIVE_Y;
+ break;
+ case gl::TextureTarget::CubeMapPositiveZ:
+ face = D3DCUBEMAP_FACE_POSITIVE_Z;
+ break;
+ case gl::TextureTarget::CubeMapNegativeZ:
+ face = D3DCUBEMAP_FACE_NEGATIVE_Z;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return face;
+}
+
+DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha)
+{
+ return (red ? D3DCOLORWRITEENABLE_RED : 0) | (green ? D3DCOLORWRITEENABLE_GREEN : 0) |
+ (blue ? D3DCOLORWRITEENABLE_BLUE : 0) | (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0);
+}
+
+D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy)
+{
+ if (maxAnisotropy > 1.0f)
+ {
+ return D3DTEXF_ANISOTROPIC;
+ }
+
+ D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT;
+ switch (magFilter)
+ {
+ case GL_NEAREST:
+ d3dMagFilter = D3DTEXF_POINT;
+ break;
+ case GL_LINEAR:
+ d3dMagFilter = D3DTEXF_LINEAR;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return d3dMagFilter;
+}
+
+void ConvertMinFilter(GLenum minFilter,
+ D3DTEXTUREFILTERTYPE *d3dMinFilter,
+ D3DTEXTUREFILTERTYPE *d3dMipFilter,
+ float *d3dLodBias,
+ float maxAnisotropy,
+ size_t baseLevel)
+{
+ switch (minFilter)
+ {
+ case GL_NEAREST:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_NONE;
+ break;
+ case GL_LINEAR:
+ *d3dMinFilter = D3DTEXF_LINEAR;
+ *d3dMipFilter = D3DTEXF_NONE;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_POINT;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ *d3dMinFilter = D3DTEXF_LINEAR;
+ *d3dMipFilter = D3DTEXF_POINT;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ *d3dMinFilter = D3DTEXF_LINEAR;
+ *d3dMipFilter = D3DTEXF_LINEAR;
+ break;
+ default:
+ *d3dMinFilter = D3DTEXF_POINT;
+ *d3dMipFilter = D3DTEXF_NONE;
+ UNREACHABLE();
+ }
+
+ // Disabling mipmapping will always sample from level 0 of the texture. It is possible to work
+ // around this by modifying D3DSAMP_MAXMIPLEVEL to force a specific mip level to become the
+ // lowest sampled mip level and using a large negative value for D3DSAMP_MIPMAPLODBIAS to
+ // ensure that only the base mip level is sampled.
+ if (baseLevel > 0 && *d3dMipFilter == D3DTEXF_NONE)
+ {
+ *d3dMipFilter = D3DTEXF_POINT;
+ *d3dLodBias = -static_cast<float>(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+ }
+ else
+ {
+ *d3dLodBias = 0.0f;
+ }
+
+ if (maxAnisotropy > 1.0f)
+ {
+ *d3dMinFilter = D3DTEXF_ANISOTROPIC;
+ }
+}
+
+D3DQUERYTYPE ConvertQueryType(gl::QueryType type)
+{
+ switch (type)
+ {
+ case gl::QueryType::AnySamples:
+ case gl::QueryType::AnySamplesConservative:
+ return D3DQUERYTYPE_OCCLUSION;
+ case gl::QueryType::CommandsCompleted:
+ return D3DQUERYTYPE_EVENT;
+ default:
+ UNREACHABLE();
+ return static_cast<D3DQUERYTYPE>(0);
+ }
+}
+
+D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples)
+{
+ return (samples > 1) ? static_cast<D3DMULTISAMPLE_TYPE>(samples) : D3DMULTISAMPLE_NONE;
+}
+
+} // namespace gl_d3d9
+
+namespace d3d9_gl
+{
+
+unsigned int GetReservedVaryingVectors()
+{
+ // We reserve two registers for "dx_Position" and "gl_Position". The spec says they
+ // don't count towards the varying limit, so we must make space for them. We also
+ // reserve the last register since it can only pass a PSIZE, and not any arbitrary
+ // varying.
+ return 3;
+}
+
+unsigned int GetReservedVertexUniformVectors()
+{
+ return 3; // dx_ViewCoords, dx_ViewAdjust and dx_DepthRange.
+}
+
+unsigned int GetReservedFragmentUniformVectors()
+{
+ return 4; // dx_ViewCoords, dx_DepthFront, dx_DepthRange, dx_FragCoordoffset.
+}
+
+GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type)
+{
+ return (type != D3DMULTISAMPLE_NONMASKABLE) ? type : 0;
+}
+
+bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format)
+{
+ GLenum internalFormat = d3d9::GetD3DFormatInfo(d3dformat).info().glInternalFormat;
+ GLenum convertedFormat = gl::GetSizedInternalFormatInfo(internalFormat).format;
+ return convertedFormat == format;
+}
+
+static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat,
+ IDirect3D9 *d3d9,
+ D3DDEVTYPE deviceType,
+ UINT adapter,
+ D3DFORMAT adapterFormat)
+{
+ gl::TextureCaps textureCaps;
+
+ const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalFormat);
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
+
+ if (d3dFormatInfo.texFormat != D3DFMT_UNKNOWN)
+ {
+ if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
+ {
+ textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(
+ adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat));
+ }
+ else
+ {
+ textureCaps.texturable =
+ SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0,
+ D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)) &&
+ SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0,
+ D3DRTYPE_CUBETEXTURE, d3dFormatInfo.texFormat));
+ if (textureCaps.texturable && (formatInfo.colorEncoding == GL_SRGB))
+ {
+ textureCaps.texturable =
+ SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat,
+ D3DUSAGE_QUERY_SRGBREAD, D3DRTYPE_TEXTURE,
+ d3dFormatInfo.texFormat)) &&
+ SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat,
+ D3DUSAGE_QUERY_SRGBREAD, D3DRTYPE_CUBETEXTURE,
+ d3dFormatInfo.texFormat));
+ }
+ }
+
+ textureCaps.filterable = SUCCEEDED(
+ d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER,
+ D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat));
+ }
+
+ if (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN)
+ {
+ textureCaps.textureAttachment = SUCCEEDED(
+ d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET,
+ D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat));
+ if (textureCaps.textureAttachment && (formatInfo.colorEncoding == GL_SRGB))
+ {
+ textureCaps.textureAttachment = SUCCEEDED(d3d9->CheckDeviceFormat(
+ adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_SRGBWRITE, D3DRTYPE_TEXTURE,
+ d3dFormatInfo.renderFormat));
+ }
+
+ if ((formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) &&
+ !textureCaps.textureAttachment)
+ {
+ textureCaps.textureAttachment = SUCCEEDED(
+ d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL,
+ D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat));
+ }
+ textureCaps.renderbuffer = textureCaps.textureAttachment;
+ textureCaps.blendable = textureCaps.renderbuffer;
+
+ textureCaps.sampleCounts.insert(1);
+ for (unsigned int i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++)
+ {
+ D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i);
+
+ HRESULT result = d3d9->CheckDeviceMultiSampleType(
+ adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, nullptr);
+ if (SUCCEEDED(result))
+ {
+ textureCaps.sampleCounts.insert(i);
+ }
+ }
+ }
+
+ return textureCaps;
+}
+
+void GenerateCaps(IDirect3D9 *d3d9,
+ IDirect3DDevice9 *device,
+ D3DDEVTYPE deviceType,
+ UINT adapter,
+ gl::Caps *caps,
+ gl::TextureCapsMap *textureCapsMap,
+ gl::Extensions *extensions,
+ gl::Limitations *limitations)
+{
+ D3DCAPS9 deviceCaps;
+ if (FAILED(d3d9->GetDeviceCaps(adapter, deviceType, &deviceCaps)))
+ {
+ // Can't continue with out device caps
+ return;
+ }
+
+ D3DDISPLAYMODE currentDisplayMode;
+ d3d9->GetAdapterDisplayMode(adapter, &currentDisplayMode);
+
+ GLuint maxSamples = 0;
+ for (GLenum internalFormat : gl::GetAllSizedInternalFormats())
+ {
+ gl::TextureCaps textureCaps = GenerateTextureFormatCaps(internalFormat, d3d9, deviceType,
+ adapter, currentDisplayMode.Format);
+ textureCapsMap->insert(internalFormat, textureCaps);
+
+ maxSamples = std::max(maxSamples, textureCaps.getMaxSamples());
+ }
+
+ // GL core feature limits
+ caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
+
+ // 3D textures are unimplemented in D3D9
+ caps->max3DTextureSize = 1;
+
+ // Only one limit in GL, use the minimum dimension
+ caps->max2DTextureSize = std::min(deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight);
+
+ // D3D treats cube maps as a special case of 2D textures
+ caps->maxCubeMapTextureSize = caps->max2DTextureSize;
+
+ // Array textures are not available in D3D9
+ caps->maxArrayTextureLayers = 1;
+
+ // ES3-only feature
+ caps->maxLODBias = 0.0f;
+
+ // No specific limits on render target size, maximum 2D texture size is equivalent
+ caps->maxRenderbufferSize = caps->max2DTextureSize;
+
+ // Draw buffers are not supported in D3D9
+ caps->maxDrawBuffers = 1;
+ caps->maxColorAttachments = 1;
+
+ // No specific limits on viewport size, maximum 2D texture size is equivalent
+ caps->maxViewportWidth = caps->max2DTextureSize;
+ caps->maxViewportHeight = caps->maxViewportWidth;
+
+ // Point size is clamped to 1.0f when the shader model is less than 3
+ caps->minAliasedPointSize = 1.0f;
+ caps->maxAliasedPointSize =
+ ((D3DSHADER_VERSION_MAJOR(deviceCaps.PixelShaderVersion) >= 3) ? deviceCaps.MaxPointSize
+ : 1.0f);
+
+ // Wide lines not supported
+ caps->minAliasedLineWidth = 1.0f;
+ caps->maxAliasedLineWidth = 1.0f;
+
+ // Primitive count limits (unused in ES2)
+ caps->maxElementsIndices = 0;
+ caps->maxElementsVertices = 0;
+
+ // Program and shader binary formats (no supported shader binary formats)
+ caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
+
+ caps->vertexHighpFloat.setIEEEFloat();
+ caps->vertexMediumpFloat.setIEEEFloat();
+ caps->vertexLowpFloat.setIEEEFloat();
+ caps->fragmentHighpFloat.setIEEEFloat();
+ caps->fragmentMediumpFloat.setIEEEFloat();
+ caps->fragmentLowpFloat.setIEEEFloat();
+
+ // Some (most) hardware only supports single-precision floating-point numbers,
+ // which can accurately represent integers up to +/-16777216
+ caps->vertexHighpInt.setSimulatedInt(24);
+ caps->vertexMediumpInt.setSimulatedInt(24);
+ caps->vertexLowpInt.setSimulatedInt(24);
+ caps->fragmentHighpInt.setSimulatedInt(24);
+ caps->fragmentMediumpInt.setSimulatedInt(24);
+ caps->fragmentLowpInt.setSimulatedInt(24);
+
+ // WaitSync is ES3-only, set to zero
+ caps->maxServerWaitTimeout = 0;
+
+ // Vertex shader limits
+ caps->maxVertexAttributes = 16;
+ // Vertex Attrib Binding not supported.
+ caps->maxVertexAttribBindings = caps->maxVertexAttributes;
+
+ const size_t MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256;
+ caps->maxVertexUniformVectors =
+ MAX_VERTEX_CONSTANT_VECTORS_D3D9 - GetReservedVertexUniformVectors();
+ caps->maxShaderUniformComponents[gl::ShaderType::Vertex] = caps->maxVertexUniformVectors * 4;
+
+ caps->maxShaderUniformBlocks[gl::ShaderType::Vertex] = 0;
+
+ // SM3 only supports 12 output variables, but the special 12th register is only for PSIZE.
+ const unsigned int MAX_VERTEX_OUTPUT_VECTORS_SM3 = 12 - GetReservedVaryingVectors();
+ const unsigned int MAX_VERTEX_OUTPUT_VECTORS_SM2 = 10 - GetReservedVaryingVectors();
+ caps->maxVertexOutputComponents =
+ ((deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) ? MAX_VERTEX_OUTPUT_VECTORS_SM3
+ : MAX_VERTEX_OUTPUT_VECTORS_SM2) *
+ 4;
+
+ // Only Direct3D 10 ready devices support all the necessary vertex texture formats.
+ // We test this using D3D9 by checking support for the R16F format.
+ if (deviceCaps.VertexShaderVersion >= D3DVS_VERSION(3, 0) &&
+ SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, currentDisplayMode.Format,
+ D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE,
+ D3DFMT_R16F)))
+ {
+ const size_t MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4;
+ caps->maxShaderTextureImageUnits[gl::ShaderType::Vertex] = MAX_TEXTURE_IMAGE_UNITS_VTF_SM3;
+ }
+ else
+ {
+ caps->maxShaderTextureImageUnits[gl::ShaderType::Vertex] = 0;
+ }
+
+ // Fragment shader limits
+ const size_t MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224;
+ const size_t MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32;
+ caps->maxFragmentUniformVectors =
+ ((deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) ? MAX_PIXEL_CONSTANT_VECTORS_SM3
+ : MAX_PIXEL_CONSTANT_VECTORS_SM2) -
+ GetReservedFragmentUniformVectors();
+ caps->maxShaderUniformComponents[gl::ShaderType::Fragment] =
+ caps->maxFragmentUniformVectors * 4;
+ caps->maxShaderUniformBlocks[gl::ShaderType::Fragment] = 0;
+ caps->maxFragmentInputComponents = caps->maxVertexOutputComponents;
+ caps->maxShaderTextureImageUnits[gl::ShaderType::Fragment] = 16;
+ caps->minProgramTexelOffset = 0;
+ caps->maxProgramTexelOffset = 0;
+
+ // Aggregate shader limits (unused in ES2)
+ caps->maxUniformBufferBindings = 0;
+ caps->maxUniformBlockSize = 0;
+ caps->uniformBufferOffsetAlignment = 0;
+ caps->maxCombinedUniformBlocks = 0;
+ caps->maxCombinedShaderUniformComponents[gl::ShaderType::Vertex] = 0;
+ caps->maxCombinedShaderUniformComponents[gl::ShaderType::Fragment] = 0;
+ caps->maxVaryingComponents = 0;
+
+ // Aggregate shader limits
+ caps->maxVaryingVectors = caps->maxVertexOutputComponents / 4;
+ caps->maxCombinedTextureImageUnits = caps->maxShaderTextureImageUnits[gl::ShaderType::Vertex] +
+ caps->maxShaderTextureImageUnits[gl::ShaderType::Fragment];
+
+ // Transform feedback limits
+ caps->maxTransformFeedbackInterleavedComponents = 0;
+ caps->maxTransformFeedbackSeparateAttributes = 0;
+ caps->maxTransformFeedbackSeparateComponents = 0;
+
+ // Multisample limits
+ caps->maxSamples = maxSamples;
+
+ // GL extension support
+ extensions->setTextureExtensionSupport(*textureCapsMap);
+ extensions->elementIndexUintOES = deviceCaps.MaxVertexIndex >= (1 << 16);
+ extensions->getProgramBinaryOES = true;
+ extensions->rgb8Rgba8OES = true;
+ extensions->readFormatBgraEXT = true;
+ extensions->pixelBufferObjectNV = false;
+ extensions->mapbufferOES = false;
+ extensions->mapBufferRangeEXT = false;
+
+ // D3D does not allow depth textures to have more than one mipmap level OES_depth_texture
+ // allows for that so we can't implement full support with the D3D9 back end.
+ extensions->depthTextureOES = false;
+
+ // textureRgEXT is emulated and not performant.
+ extensions->textureRgEXT = false;
+
+ // GL_KHR_parallel_shader_compile
+ extensions->parallelShaderCompileKHR = true;
+
+ D3DADAPTER_IDENTIFIER9 adapterId = {};
+ if (SUCCEEDED(d3d9->GetAdapterIdentifier(adapter, 0, &adapterId)))
+ {
+ // ATI cards on XP have problems with non-power-of-two textures.
+ extensions->textureNpotOES =
+ !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
+ !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
+ !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
+ !(!isWindowsVistaOrGreater() && IsAMD(adapterId.VendorId));
+
+ // Disable depth texture support on AMD cards (See ANGLE issue 839)
+ if (IsAMD(adapterId.VendorId))
+ {
+ extensions->depthTextureANGLE = false;
+ extensions->depthTextureOES = false;
+ }
+ }
+ else
+ {
+ extensions->textureNpotOES = false;
+ }
+
+ extensions->drawBuffersEXT = false;
+ extensions->textureStorageEXT = true;
+
+ // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per
+ // the spec
+ extensions->textureFilterAnisotropicEXT =
+ (deviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && deviceCaps.MaxAnisotropy >= 2;
+ caps->maxTextureAnisotropy = static_cast<GLfloat>(deviceCaps.MaxAnisotropy);
+
+ // Check occlusion query support by trying to create one
+ IDirect3DQuery9 *occlusionQuery = nullptr;
+ extensions->occlusionQueryBooleanEXT =
+ SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery;
+ SafeRelease(occlusionQuery);
+
+ // Check event query support by trying to create one
+ IDirect3DQuery9 *eventQuery = nullptr;
+ extensions->fenceNV =
+ SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery;
+ SafeRelease(eventQuery);
+
+ extensions->disjointTimerQueryEXT = false;
+ extensions->robustnessEXT = true;
+ // It seems that only DirectX 10 and higher enforce the well-defined behavior of always
+ // returning zero values when out-of-bounds reads. See
+ // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_robustness.txt
+ extensions->robustBufferAccessBehaviorKHR = false;
+ extensions->blendMinmaxEXT = true;
+ // Although according to
+ // https://docs.microsoft.com/en-us/windows/desktop/direct3ddxgi/format-support-for-direct3d-feature-level-9-1-hardware
+ // D3D9 doesn't have full blending capability for RGBA32F. But turns out it could provide
+ // correct blending result in reality. As a result of some regression reports by client app, we
+ // decided to turn floatBlendEXT on for D3D9
+ extensions->floatBlendEXT = true;
+ extensions->framebufferBlitANGLE = true;
+ extensions->framebufferMultisampleANGLE = true;
+ extensions->instancedArraysANGLE = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
+ // D3D9 requires at least one attribute that has a divisor of 0, which isn't required by the EXT
+ // extension
+ extensions->instancedArraysEXT = false;
+ extensions->packReverseRowOrderANGLE = true;
+ extensions->standardDerivativesOES =
+ (deviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0;
+ extensions->shaderTextureLodEXT = true;
+ extensions->fragDepthEXT = true;
+ extensions->textureUsageANGLE = true;
+ extensions->translatedShaderSourceANGLE = true;
+ extensions->fboRenderMipmapOES = true;
+ extensions->discardFramebufferEXT = false; // It would be valid to set this to true, since
+ // glDiscardFramebufferEXT is just a hint
+ extensions->colorBufferFloatEXT = false;
+ extensions->debugMarkerEXT = true;
+ extensions->EGLImageOES = true;
+ extensions->EGLImageExternalOES = true;
+ extensions->unpackSubimageEXT = true;
+ extensions->packSubimageNV = true;
+ extensions->syncQueryCHROMIUM = extensions->fenceNV;
+ extensions->copyTextureCHROMIUM = true;
+ extensions->textureBorderClampOES = true;
+ extensions->videoTextureWEBGL = true;
+
+ // D3D9 has no concept of separate masks and refs for front and back faces in the depth stencil
+ // state.
+ limitations->noSeparateStencilRefsAndMasks = true;
+
+ // D3D9 shader models have limited support for looping, so the Appendix A
+ // index/loop limitations are necessary. Workarounds that are needed to
+ // support dynamic indexing of vectors on HLSL also don't work on D3D9.
+ limitations->shadersRequireIndexedLoopValidation = true;
+
+ // D3D9 cannot support constant color and alpha blend funcs together
+ limitations->noSimultaneousConstantColorAndAlphaBlendFunc = true;
+
+ // D3D9 cannot support unclamped constant blend color
+ limitations->noUnclampedBlendColor = true;
+
+ // D3D9 cannot support packing more than one variable to a single varying.
+ // TODO(jmadill): Implement more sophisticated component packing in D3D9.
+ limitations->noFlexibleVaryingPacking = true;
+
+ // D3D9 does not support vertex attribute aliasing
+ limitations->noVertexAttributeAliasing = true;
+
+ // D3D9 does not support compressed textures where the base mip level is not a multiple of 4
+ limitations->compressedBaseMipLevelMultipleOfFour = true;
+}
+
+} // namespace d3d9_gl
+
+namespace d3d9
+{
+
+GLuint ComputeBlockSize(D3DFORMAT format, GLuint width, GLuint height)
+{
+ const D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(format);
+ GLuint numBlocksWide = (width + d3dFormatInfo.blockWidth - 1) / d3dFormatInfo.blockWidth;
+ GLuint numBlocksHight = (height + d3dFormatInfo.blockHeight - 1) / d3dFormatInfo.blockHeight;
+ return (d3dFormatInfo.pixelBytes * numBlocksWide * numBlocksHight);
+}
+
+void MakeValidSize(bool isImage,
+ D3DFORMAT format,
+ GLsizei *requestWidth,
+ GLsizei *requestHeight,
+ int *levelOffset)
+{
+ const D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(format);
+
+ int upsampleCount = 0;
+ // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already.
+ if (isImage || *requestWidth < static_cast<GLsizei>(d3dFormatInfo.blockWidth) ||
+ *requestHeight < static_cast<GLsizei>(d3dFormatInfo.blockHeight))
+ {
+ while (*requestWidth % d3dFormatInfo.blockWidth != 0 ||
+ *requestHeight % d3dFormatInfo.blockHeight != 0)
+ {
+ *requestWidth <<= 1;
+ *requestHeight <<= 1;
+ upsampleCount++;
+ }
+ }
+ *levelOffset = upsampleCount;
+}
+
+void InitializeFeatures(angle::FeaturesD3D *features)
+{
+ ANGLE_FEATURE_CONDITION(features, mrtPerfWorkaround, true);
+ ANGLE_FEATURE_CONDITION(features, setDataFasterThanImageUpload, false);
+ ANGLE_FEATURE_CONDITION(features, setDataFasterThanImageUploadOn128bitFormats, false);
+ ANGLE_FEATURE_CONDITION(features, useInstancedPointSpriteEmulation, false);
+
+ // TODO(jmadill): Disable workaround when we have a fixed compiler DLL.
+ ANGLE_FEATURE_CONDITION(features, expandIntegerPowExpressions, true);
+
+ // crbug.com/1011627 Turn this on for D3D9.
+ ANGLE_FEATURE_CONDITION(features, allowClearForRobustResourceInit, true);
+}
+
+} // namespace d3d9
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h
new file mode 100644
index 0000000000..b900e9c44c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h
@@ -0,0 +1,105 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// renderer9_utils.h: Conversion functions and other utility routines
+// specific to the D3D9 renderer
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_
+
+#include "common/Color.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Error.h"
+#include "platform/FeaturesD3D_autogen.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+}
+
+namespace rx
+{
+class RenderTarget9;
+
+namespace gl_d3d9
+{
+
+D3DCMPFUNC ConvertComparison(GLenum comparison);
+D3DCOLOR ConvertColor(gl::ColorF color);
+D3DBLEND ConvertBlendFunc(GLenum blend);
+D3DBLENDOP ConvertBlendOp(GLenum blendOp);
+D3DSTENCILOP ConvertStencilOp(GLenum stencilOp);
+D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap);
+D3DCULL ConvertCullMode(gl::CullFaceMode cullFace, GLenum frontFace);
+D3DCUBEMAP_FACES ConvertCubeFace(gl::TextureTarget cubeFace);
+DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha);
+D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy);
+void ConvertMinFilter(GLenum minFilter,
+ D3DTEXTUREFILTERTYPE *d3dMinFilter,
+ D3DTEXTUREFILTERTYPE *d3dMipFilter,
+ float *d3dLodBias,
+ float maxAnisotropy,
+ size_t baseLevel);
+D3DQUERYTYPE ConvertQueryType(gl::QueryType type);
+
+D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples);
+
+} // namespace gl_d3d9
+
+namespace d3d9_gl
+{
+
+unsigned int GetReservedVaryingVectors();
+
+unsigned int GetReservedVertexUniformVectors();
+
+unsigned int GetReservedFragmentUniformVectors();
+
+GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type);
+
+bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format);
+
+void GenerateCaps(IDirect3D9 *d3d9,
+ IDirect3DDevice9 *device,
+ D3DDEVTYPE deviceType,
+ UINT adapter,
+ gl::Caps *caps,
+ gl::TextureCapsMap *textureCapsMap,
+ gl::Extensions *extensions,
+ gl::Limitations *limitations);
+} // namespace d3d9_gl
+
+namespace d3d9
+{
+
+GLuint ComputeBlockSize(D3DFORMAT format, GLuint width, GLuint height);
+
+void MakeValidSize(bool isImage,
+ D3DFORMAT format,
+ GLsizei *requestWidth,
+ GLsizei *requestHeight,
+ int *levelOffset);
+
+inline bool isDeviceLostError(HRESULT errorCode)
+{
+ switch (errorCode)
+ {
+ case D3DERR_DRIVERINTERNALERROR:
+ case D3DERR_DEVICELOST:
+ case D3DERR_DEVICEHUNG:
+ case D3DERR_DEVICEREMOVED:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void InitializeFeatures(angle::FeaturesD3D *features);
+} // namespace d3d9
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskpremultps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskpremultps.h
new file mode 100644
index 0000000000..04868aeb9c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskpremultps.h
@@ -0,0 +1,50 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+// Parameters:
+//
+// float4 add;
+// float4 mult;
+// sampler2D tex;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// mult c0 1
+// add c1 1
+// tex s0 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mul r0.xyz, r0.w, r0
+ mov r1, c0
+ mad r0, r0, r1, c1
+ mov oC0, r0
+
+// approximately 5 instruction slots used (1 texture, 4 arithmetic)
+#endif
+
+const BYTE g_ps20_componentmaskpremultps[] = {
+ 0, 2, 255, 255, 254, 255, 50, 0, 67, 84, 65, 66, 28, 0, 0, 0, 143, 0, 0,
+ 0, 0, 2, 255, 255, 3, 0, 0, 0, 28, 0, 0, 0, 0, 1, 0, 0, 136, 0,
+ 0, 0, 88, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 92, 0, 0, 0, 0,
+ 0, 0, 0, 108, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 113, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 120, 0, 0,
+ 0, 0, 0, 0, 0, 97, 100, 100, 0, 1, 0, 3, 0, 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 109, 117, 108, 116, 0, 116, 101, 120, 0, 171, 171, 171, 4,
+ 0, 12, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 112, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76,
+ 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32,
+ 54, 46, 51, 46, 57, 54, 48, 48, 46, 49, 54, 51, 56, 52, 0, 171, 171, 171, 31,
+ 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228,
+ 160, 5, 0, 0, 3, 0, 0, 7, 128, 0, 0, 255, 128, 0, 0, 228, 128, 1, 0,
+ 0, 2, 1, 0, 15, 128, 0, 0, 228, 160, 4, 0, 0, 4, 0, 0, 15, 128, 0,
+ 0, 228, 128, 1, 0, 228, 128, 1, 0, 228, 160, 1, 0, 0, 2, 0, 8, 15, 128,
+ 0, 0, 228, 128, 255, 255, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h
new file mode 100644
index 0000000000..06673ae5f7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h
@@ -0,0 +1,48 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+// Parameters:
+//
+// float4 add;
+// float4 mult;
+// sampler2D tex;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// mult c0 1
+// add c1 1
+// tex s0 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mov r1, c0
+ mad r0, r0, r1, c1
+ mov oC0, r0
+
+// approximately 4 instruction slots used (1 texture, 3 arithmetic)
+#endif
+
+const BYTE g_ps20_componentmaskps[] = {
+ 0, 2, 255, 255, 254, 255, 50, 0, 67, 84, 65, 66, 28, 0, 0, 0, 143, 0, 0,
+ 0, 0, 2, 255, 255, 3, 0, 0, 0, 28, 0, 0, 0, 0, 1, 0, 0, 136, 0,
+ 0, 0, 88, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 92, 0, 0, 0, 0,
+ 0, 0, 0, 108, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 113, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 120, 0, 0,
+ 0, 0, 0, 0, 0, 97, 100, 100, 0, 1, 0, 3, 0, 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 109, 117, 108, 116, 0, 116, 101, 120, 0, 171, 171, 171, 4,
+ 0, 12, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 112, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76,
+ 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32,
+ 54, 46, 51, 46, 57, 54, 48, 48, 46, 49, 54, 51, 56, 52, 0, 171, 171, 171, 31,
+ 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228,
+ 160, 1, 0, 0, 2, 1, 0, 15, 128, 0, 0, 228, 160, 4, 0, 0, 4, 0, 0,
+ 15, 128, 0, 0, 228, 128, 1, 0, 228, 128, 1, 0, 228, 160, 1, 0, 0, 2, 0,
+ 8, 15, 128, 0, 0, 228, 128, 255, 255, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskunmultps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskunmultps.h
new file mode 100644
index 0000000000..ad15364bb8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskunmultps.h
@@ -0,0 +1,54 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+// Parameters:
+//
+// float4 add;
+// float4 mult;
+// sampler2D tex;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// mult c0 1
+// add c1 1
+// tex s0 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ rcp r1.w, r0.w
+ mul r1.xyz, r0, r1.w
+ cmp r0.xyz, -r0.w, r0, r1
+ mov r1, c0
+ mad r0, r0, r1, c1
+ mov oC0, r0
+
+// approximately 7 instruction slots used (1 texture, 6 arithmetic)
+#endif
+
+const BYTE g_ps20_componentmaskunmultps[] = {
+ 0, 2, 255, 255, 254, 255, 50, 0, 67, 84, 65, 66, 28, 0, 0, 0, 143, 0, 0,
+ 0, 0, 2, 255, 255, 3, 0, 0, 0, 28, 0, 0, 0, 0, 1, 0, 0, 136, 0,
+ 0, 0, 88, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 92, 0, 0, 0, 0,
+ 0, 0, 0, 108, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 113, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 120, 0, 0,
+ 0, 0, 0, 0, 0, 97, 100, 100, 0, 1, 0, 3, 0, 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 109, 117, 108, 116, 0, 116, 101, 120, 0, 171, 171, 171, 4,
+ 0, 12, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 112, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76,
+ 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32,
+ 54, 46, 51, 46, 57, 54, 48, 48, 46, 49, 54, 51, 56, 52, 0, 171, 171, 171, 31,
+ 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228,
+ 160, 6, 0, 0, 2, 1, 0, 8, 128, 0, 0, 255, 128, 5, 0, 0, 3, 1, 0,
+ 7, 128, 0, 0, 228, 128, 1, 0, 255, 128, 88, 0, 0, 4, 0, 0, 7, 128, 0,
+ 0, 255, 129, 0, 0, 228, 128, 1, 0, 228, 128, 1, 0, 0, 2, 1, 0, 15, 128,
+ 0, 0, 228, 160, 4, 0, 0, 4, 0, 0, 15, 128, 0, 0, 228, 128, 1, 0, 228,
+ 128, 1, 0, 228, 160, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 128, 255, 255,
+ 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminancepremultps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminancepremultps.h
new file mode 100644
index 0000000000..274a7824f9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminancepremultps.h
@@ -0,0 +1,50 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+// Parameters:
+//
+// float4 add;
+// float4 mult;
+// sampler2D tex;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// mult c0 1
+// add c1 1
+// tex s0 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mul r0.xyz, r0.w, r0.x
+ mov r1, c0
+ mad r0, r0, r1, c1
+ mov oC0, r0
+
+// approximately 5 instruction slots used (1 texture, 4 arithmetic)
+#endif
+
+const BYTE g_ps20_luminancepremultps[] = {
+ 0, 2, 255, 255, 254, 255, 50, 0, 67, 84, 65, 66, 28, 0, 0, 0, 143, 0, 0,
+ 0, 0, 2, 255, 255, 3, 0, 0, 0, 28, 0, 0, 0, 0, 1, 0, 0, 136, 0,
+ 0, 0, 88, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 92, 0, 0, 0, 0,
+ 0, 0, 0, 108, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 113, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 120, 0, 0,
+ 0, 0, 0, 0, 0, 97, 100, 100, 0, 1, 0, 3, 0, 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 109, 117, 108, 116, 0, 116, 101, 120, 0, 171, 171, 171, 4,
+ 0, 12, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 112, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76,
+ 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32,
+ 54, 46, 51, 46, 57, 54, 48, 48, 46, 49, 54, 51, 56, 52, 0, 171, 171, 171, 31,
+ 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228,
+ 160, 5, 0, 0, 3, 0, 0, 7, 128, 0, 0, 255, 128, 0, 0, 0, 128, 1, 0,
+ 0, 2, 1, 0, 15, 128, 0, 0, 228, 160, 4, 0, 0, 4, 0, 0, 15, 128, 0,
+ 0, 228, 128, 1, 0, 228, 128, 1, 0, 228, 160, 1, 0, 0, 2, 0, 8, 15, 128,
+ 0, 0, 228, 128, 255, 255, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h
new file mode 100644
index 0000000000..0be665c525
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h
@@ -0,0 +1,53 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+// Parameters:
+//
+// float4 add;
+// float4 mult;
+// sampler2D tex;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// mult c0 1
+// add c1 1
+// tex s0 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mov r1.xw, c0
+ mad r0.x, r0.x, r1.x, c1.x
+ mad r0.y, r0.w, r1.w, c1.w
+ mov r1.xyz, r0.x
+ mov r1.w, r0.y
+ mov oC0, r1
+
+// approximately 7 instruction slots used (1 texture, 6 arithmetic)
+#endif
+
+const BYTE g_ps20_luminanceps[] = {
+ 0, 2, 255, 255, 254, 255, 50, 0, 67, 84, 65, 66, 28, 0, 0, 0, 143, 0, 0,
+ 0, 0, 2, 255, 255, 3, 0, 0, 0, 28, 0, 0, 0, 0, 1, 0, 0, 136, 0,
+ 0, 0, 88, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 92, 0, 0, 0, 0,
+ 0, 0, 0, 108, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 113, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 120, 0, 0,
+ 0, 0, 0, 0, 0, 97, 100, 100, 0, 1, 0, 3, 0, 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 109, 117, 108, 116, 0, 116, 101, 120, 0, 171, 171, 171, 4,
+ 0, 12, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 112, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76,
+ 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32,
+ 54, 46, 51, 46, 57, 54, 48, 48, 46, 49, 54, 51, 56, 52, 0, 171, 171, 171, 31,
+ 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228,
+ 160, 1, 0, 0, 2, 1, 0, 9, 128, 0, 0, 228, 160, 4, 0, 0, 4, 0, 0,
+ 1, 128, 0, 0, 0, 128, 1, 0, 0, 128, 1, 0, 0, 160, 4, 0, 0, 4, 0,
+ 0, 2, 128, 0, 0, 255, 128, 1, 0, 255, 128, 1, 0, 255, 160, 1, 0, 0, 2,
+ 1, 0, 7, 128, 0, 0, 0, 128, 1, 0, 0, 2, 1, 0, 8, 128, 0, 0, 85,
+ 128, 1, 0, 0, 2, 0, 8, 15, 128, 1, 0, 228, 128, 255, 255, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceunmultps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceunmultps.h
new file mode 100644
index 0000000000..1100d0b088
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceunmultps.h
@@ -0,0 +1,54 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+// Parameters:
+//
+// float4 add;
+// float4 mult;
+// sampler2D tex;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// mult c0 1
+// add c1 1
+// tex s0 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ rcp r1.w, r0.w
+ mul r1.x, r0.x, r1.w
+ cmp r0.xyz, -r0.w, r0.x, r1.x
+ mov r1, c0
+ mad r0, r0, r1, c1
+ mov oC0, r0
+
+// approximately 7 instruction slots used (1 texture, 6 arithmetic)
+#endif
+
+const BYTE g_ps20_luminanceunmultps[] = {
+ 0, 2, 255, 255, 254, 255, 50, 0, 67, 84, 65, 66, 28, 0, 0, 0, 143, 0, 0,
+ 0, 0, 2, 255, 255, 3, 0, 0, 0, 28, 0, 0, 0, 0, 1, 0, 0, 136, 0,
+ 0, 0, 88, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 92, 0, 0, 0, 0,
+ 0, 0, 0, 108, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 92, 0, 0, 0,
+ 0, 0, 0, 0, 113, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 120, 0, 0,
+ 0, 0, 0, 0, 0, 97, 100, 100, 0, 1, 0, 3, 0, 1, 0, 4, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 109, 117, 108, 116, 0, 116, 101, 120, 0, 171, 171, 171, 4,
+ 0, 12, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 112, 115, 95, 50,
+ 95, 48, 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76,
+ 83, 76, 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32,
+ 54, 46, 51, 46, 57, 54, 48, 48, 46, 49, 54, 51, 56, 52, 0, 171, 171, 171, 31,
+ 0, 0, 2, 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144,
+ 0, 8, 15, 160, 66, 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228,
+ 160, 6, 0, 0, 2, 1, 0, 8, 128, 0, 0, 255, 128, 5, 0, 0, 3, 1, 0,
+ 1, 128, 0, 0, 0, 128, 1, 0, 255, 128, 88, 0, 0, 4, 0, 0, 7, 128, 0,
+ 0, 255, 129, 0, 0, 0, 128, 1, 0, 0, 128, 1, 0, 0, 2, 1, 0, 15, 128,
+ 0, 0, 228, 160, 4, 0, 0, 4, 0, 0, 15, 128, 0, 0, 228, 128, 1, 0, 228,
+ 128, 1, 0, 228, 160, 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 128, 255, 255,
+ 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h
new file mode 100644
index 0000000000..0c17739e17
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h
@@ -0,0 +1,37 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+// Parameters:
+//
+// sampler2D tex;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// ------------ ----- ----
+// tex s0 1
+//
+
+ ps_2_0
+ dcl t0.xy
+ dcl_2d s0
+ texld r0, t0, s0
+ mov oC0, r0
+
+// approximately 2 instruction slots used (1 texture, 1 arithmetic)
+#endif
+
+const BYTE g_ps20_passthroughps[] = {
+ 0, 2, 255, 255, 254, 255, 33, 0, 67, 84, 65, 66, 28, 0, 0, 0, 75, 0,
+ 0, 0, 0, 2, 255, 255, 1, 0, 0, 0, 28, 0, 0, 0, 0, 1, 0, 0,
+ 68, 0, 0, 0, 48, 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 52, 0,
+ 0, 0, 0, 0, 0, 0, 116, 101, 120, 0, 4, 0, 12, 0, 1, 0, 1, 0,
+ 1, 0, 0, 0, 0, 0, 0, 0, 112, 115, 95, 50, 95, 48, 0, 77, 105, 99,
+ 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76, 32, 83, 104,
+ 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 54, 46, 51, 46,
+ 57, 54, 48, 48, 46, 49, 54, 51, 56, 52, 0, 171, 171, 171, 31, 0, 0, 2,
+ 0, 0, 0, 128, 0, 0, 3, 176, 31, 0, 0, 2, 0, 0, 0, 144, 0, 8,
+ 15, 160, 66, 0, 0, 3, 0, 0, 15, 128, 0, 0, 228, 176, 0, 8, 228, 160,
+ 1, 0, 0, 2, 0, 8, 15, 128, 0, 0, 228, 128, 255, 255, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h
new file mode 100644
index 0000000000..e4d7e0e1a8
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h
@@ -0,0 +1,46 @@
+#if 0
+//
+// Generated by Microsoft (R) HLSL Shader Compiler 6.3.9600.16384
+//
+// Parameters:
+//
+// float4 halfPixelSize;
+// float4 texcoordOffset;
+//
+//
+// Registers:
+//
+// Name Reg Size
+// -------------- ----- ----
+// halfPixelSize c0 1
+// texcoordOffset c1 1
+//
+
+ vs_2_0
+ def c2, 0.5, -0.5, 1, 0
+ dcl_position v0
+ add oPos, v0, c0
+ mad r0, v0, c2.xyzz, c2.xxww
+ mov oT0.zw, r0
+ mad oT0.xy, r0, c1.zwzw, c1
+
+// approximately 4 instruction slots used
+#endif
+
+const BYTE g_vs20_standardvs[] = {
+ 0, 2, 254, 255, 254, 255, 44, 0, 67, 84, 65, 66, 28, 0, 0, 0, 122, 0, 0,
+ 0, 0, 2, 254, 255, 2, 0, 0, 0, 28, 0, 0, 0, 0, 1, 0, 0, 115, 0,
+ 0, 0, 68, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 0,
+ 0, 0, 0, 100, 0, 0, 0, 2, 0, 1, 0, 1, 0, 0, 0, 84, 0, 0, 0,
+ 0, 0, 0, 0, 104, 97, 108, 102, 80, 105, 120, 101, 108, 83, 105, 122, 101, 0, 171,
+ 171, 1, 0, 3, 0, 1, 0, 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 116, 101,
+ 120, 99, 111, 111, 114, 100, 79, 102, 102, 115, 101, 116, 0, 118, 115, 95, 50, 95, 48,
+ 0, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 40, 82, 41, 32, 72, 76, 83, 76,
+ 32, 83, 104, 97, 100, 101, 114, 32, 67, 111, 109, 112, 105, 108, 101, 114, 32, 54, 46,
+ 51, 46, 57, 54, 48, 48, 46, 49, 54, 51, 56, 52, 0, 81, 0, 0, 5, 2, 0,
+ 15, 160, 0, 0, 0, 63, 0, 0, 0, 191, 0, 0, 128, 63, 0, 0, 0, 0, 31,
+ 0, 0, 2, 0, 0, 0, 128, 0, 0, 15, 144, 2, 0, 0, 3, 0, 0, 15, 192,
+ 0, 0, 228, 144, 0, 0, 228, 160, 4, 0, 0, 4, 0, 0, 15, 128, 0, 0, 228,
+ 144, 2, 0, 164, 160, 2, 0, 240, 160, 1, 0, 0, 2, 0, 0, 12, 224, 0, 0,
+ 228, 128, 4, 0, 0, 4, 0, 0, 3, 224, 0, 0, 228, 128, 1, 0, 238, 160, 1,
+ 0, 228, 160, 255, 255, 0, 0};
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h
new file mode 100644
index 0000000000..fb172448d1
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h
@@ -0,0 +1,197 @@
+//
+// Copyright 2002 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// vertexconversion.h: A library of vertex conversion classes that can be used to build
+// the FormatConverter objects used by the buffer conversion system.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+
+namespace rx
+{
+
+// Conversion types:
+// static const bool identity: true if this is an identity transform, false otherwise
+// static U convert(T): convert a single element from the input type to the output type
+// typedef ... OutputType: the type produced by this conversion
+
+template <class T>
+struct Identity
+{
+ static const bool identity = true;
+
+ typedef T OutputType;
+
+ static T convert(T x) { return x; }
+};
+
+template <class FromT, class ToT>
+struct Cast
+{
+ static const bool identity = false;
+
+ typedef ToT OutputType;
+
+ static ToT convert(FromT x) { return static_cast<ToT>(x); }
+};
+
+template <class T>
+struct Cast<T, T>
+{
+ static const bool identity = true;
+
+ typedef T OutputType;
+
+ static T convert(T x) { return static_cast<T>(x); }
+};
+
+template <class T>
+struct Normalize
+{
+ static const bool identity = false;
+
+ typedef float OutputType;
+
+ static float convert(T x)
+ {
+ typedef std::numeric_limits<T> NL;
+ float f = static_cast<float>(x);
+
+ if (NL::is_signed)
+ {
+ // const float => VC2008 computes it at compile time
+ // static const float => VC2008 computes it the first time we get here, stores it to
+ // memory with static guard and all that.
+ const float divisor = 1.0f / (2 * static_cast<float>(NL::max()) + 1);
+ return (2 * f + 1) * divisor;
+ }
+ else
+ {
+ return f / NL::max();
+ }
+ }
+};
+
+template <class FromType, std::size_t ScaleBits>
+struct FixedToFloat
+{
+ static const bool identity = false;
+
+ typedef float OutputType;
+
+ static float convert(FromType x)
+ {
+ const float divisor = 1.0f / static_cast<float>(static_cast<FromType>(1) << ScaleBits);
+ return static_cast<float>(x) * divisor;
+ }
+};
+
+// Widen types:
+// static const unsigned int initialWidth: number of components before conversion
+// static const unsigned int finalWidth: number of components after conversion
+
+// Float is supported at any size.
+template <std::size_t N>
+struct NoWiden
+{
+ static const std::size_t initialWidth = N;
+ static const std::size_t finalWidth = N;
+};
+
+// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components
+template <std::size_t N>
+struct WidenToEven
+{
+ static const std::size_t initialWidth = N;
+ static const std::size_t finalWidth = N + (N & 1);
+};
+
+template <std::size_t N>
+struct WidenToFour
+{
+ static const std::size_t initialWidth = N;
+ static const std::size_t finalWidth = 4;
+};
+
+// Most types have 0 and 1 that are just that.
+template <class T>
+struct SimpleDefaultValues
+{
+ static T zero() { return static_cast<T>(0); }
+ static T one() { return static_cast<T>(1); }
+};
+
+// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value.
+template <class T>
+struct NormalizedDefaultValues
+{
+ static T zero() { return static_cast<T>(0); }
+ static T one() { return std::numeric_limits<T>::max(); }
+};
+
+// Converter:
+// static const bool identity: true if this is an identity transform (with no widening)
+// static const std::size_t finalSize: number of bytes per output vertex
+// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert
+// an array of vertices. Input may be strided, but output will be unstrided.
+
+template <class InT,
+ class WidenRule,
+ class Converter,
+ class DefaultValueRule = SimpleDefaultValues<InT>>
+struct VertexDataConverter
+{
+ typedef typename Converter::OutputType OutputType;
+ typedef InT InputType;
+
+ static const bool identity =
+ (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity;
+ static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType);
+
+ static void convertArray(const uint8_t *input, size_t stride, size_t n, uint8_t *output)
+ {
+ OutputType *out = reinterpret_cast<OutputType *>(output);
+
+ for (std::size_t i = 0; i < n; i++)
+ {
+ const InputType *ein = reinterpret_cast<const InputType *>(input + i * stride);
+
+ copyComponent(out, ein, 0, static_cast<OutputType>(DefaultValueRule::zero()));
+ copyComponent(out, ein, 1, static_cast<OutputType>(DefaultValueRule::zero()));
+ copyComponent(out, ein, 2, static_cast<OutputType>(DefaultValueRule::zero()));
+ copyComponent(out, ein, 3, static_cast<OutputType>(DefaultValueRule::one()));
+
+ out += WidenRule::finalWidth;
+ }
+ }
+
+ private:
+ static void copyComponent(OutputType *out,
+ const InputType *in,
+ std::size_t elementindex,
+ OutputType defaultvalue)
+ {
+ if (WidenRule::finalWidth > elementindex)
+ {
+ if (WidenRule::initialWidth > elementindex)
+ {
+ out[elementindex] = Converter::convert(in[elementindex]);
+ }
+ else
+ {
+ out[elementindex] = defaultvalue;
+ }
+ }
+ }
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/driver_utils_d3d.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/driver_utils_d3d.cpp
new file mode 100644
index 0000000000..1709f82868
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/driver_utils_d3d.cpp
@@ -0,0 +1,26 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// driver_utils_d3d.cpp: Information specific to the D3D driver
+
+#include "libANGLE/renderer/d3d/driver_utils_d3d.h"
+
+namespace rx
+{
+
+std::string GetDriverVersionString(LARGE_INTEGER driverVersion)
+{
+ std::stringstream versionString;
+ uint64_t intVersion = driverVersion.QuadPart;
+ constexpr uint64_t kMask16 = std::numeric_limits<uint16_t>::max();
+ versionString << ((intVersion >> 48) & kMask16) << ".";
+ versionString << ((intVersion >> 32) & kMask16) << ".";
+ versionString << ((intVersion >> 16) & kMask16) << ".";
+ versionString << (intVersion & kMask16);
+ return versionString.str();
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/driver_utils_d3d.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/driver_utils_d3d.h
new file mode 100644
index 0000000000..3b217838f9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/driver_utils_d3d.h
@@ -0,0 +1,21 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// driver_utils_d3d.h: Information specific to the D3D driver
+
+#ifndef LIBANGLE_RENDERER_D3D_DRIVER_UTILS_D3D_H_
+#define LIBANGLE_RENDERER_D3D_DRIVER_UTILS_D3D_H_
+
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+
+std::string GetDriverVersionString(LARGE_INTEGER driverVersion);
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_DRIVER_UTILS_D3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/formatutilsD3D.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d/formatutilsD3D.h
new file mode 100644
index 0000000000..f0e876d49d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/formatutilsD3D.h
@@ -0,0 +1,24 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// formatutils9.h: Queries for GL image formats and their translations to D3D
+// formats.
+
+#ifndef LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_
+#define LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_
+
+namespace rx
+{
+enum VertexConversionType
+{
+ VERTEX_CONVERT_NONE = 0,
+ VERTEX_CONVERT_CPU = 1,
+ VERTEX_CONVERT_GPU = 2,
+ VERTEX_CONVERT_BOTH = 3
+};
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d_format.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d_format.cpp
new file mode 100644
index 0000000000..0823b37a5d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d_format.cpp
@@ -0,0 +1,206 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// d3d_format: Describes a D3D9 format. Used by the D3D9 and GL back-ends.
+
+#include "libANGLE/renderer/d3d_format.h"
+
+using namespace angle;
+
+namespace rx
+{
+namespace d3d9
+{
+namespace
+{
+constexpr D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z')));
+constexpr D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L')));
+} // anonymous namespace
+
+D3DFormat::D3DFormat()
+ : pixelBytes(0),
+ blockWidth(0),
+ blockHeight(0),
+ redBits(0),
+ greenBits(0),
+ blueBits(0),
+ alphaBits(0),
+ luminanceBits(0),
+ depthBits(0),
+ stencilBits(0),
+ formatID(angle::FormatID::NONE)
+{}
+
+D3DFormat::D3DFormat(GLuint bits,
+ GLuint blockWidth,
+ GLuint blockHeight,
+ GLuint redBits,
+ GLuint greenBits,
+ GLuint blueBits,
+ GLuint alphaBits,
+ GLuint lumBits,
+ GLuint depthBits,
+ GLuint stencilBits,
+ FormatID formatID)
+ : pixelBytes(bits / 8),
+ blockWidth(blockWidth),
+ blockHeight(blockHeight),
+ redBits(redBits),
+ greenBits(greenBits),
+ blueBits(blueBits),
+ alphaBits(alphaBits),
+ luminanceBits(lumBits),
+ depthBits(depthBits),
+ stencilBits(stencilBits),
+ formatID(formatID)
+{}
+
+const D3DFormat &GetD3DFormatInfo(D3DFORMAT format)
+{
+ if (format == D3DFMT_NULL)
+ {
+ static const D3DFormat info(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FormatID::NONE);
+ return info;
+ }
+
+ if (format == D3DFMT_INTZ)
+ {
+ static const D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 8, FormatID::D24_UNORM_S8_UINT);
+ return info;
+ }
+
+ switch (format)
+ {
+ case D3DFMT_UNKNOWN:
+ {
+ static const D3DFormat info(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FormatID::NONE);
+ return info;
+ }
+
+ case D3DFMT_L8:
+ {
+ static const D3DFormat info(8, 1, 1, 0, 0, 0, 0, 8, 0, 0, FormatID::L8_UNORM);
+ return info;
+ }
+ case D3DFMT_A8:
+ {
+ static const D3DFormat info(8, 1, 1, 0, 0, 0, 8, 0, 0, 0, FormatID::A8_UNORM);
+ return info;
+ }
+ case D3DFMT_A8L8:
+ {
+ static const D3DFormat info(16, 1, 1, 0, 0, 0, 8, 8, 0, 0, FormatID::L8A8_UNORM);
+ return info;
+ }
+
+ case D3DFMT_A4R4G4B4:
+ {
+ static const D3DFormat info(16, 1, 1, 4, 4, 4, 4, 0, 0, 0, FormatID::B4G4R4A4_UNORM);
+ return info;
+ }
+ case D3DFMT_A1R5G5B5:
+ {
+ static const D3DFormat info(16, 1, 1, 5, 5, 5, 1, 0, 0, 0, FormatID::B5G5R5A1_UNORM);
+ return info;
+ }
+ case D3DFMT_R5G6B5:
+ {
+ static const D3DFormat info(16, 1, 1, 5, 6, 5, 0, 0, 0, 0, FormatID::R5G6B5_UNORM);
+ return info;
+ }
+ case D3DFMT_X8R8G8B8:
+ {
+ static const D3DFormat info(32, 1, 1, 8, 8, 8, 0, 0, 0, 0, FormatID::B8G8R8X8_UNORM);
+ return info;
+ }
+ case D3DFMT_A8R8G8B8:
+ {
+ static const D3DFormat info(32, 1, 1, 8, 8, 8, 8, 0, 0, 0, FormatID::B8G8R8A8_UNORM);
+ return info;
+ }
+
+ case D3DFMT_R16F:
+ {
+ static const D3DFormat info(16, 1, 1, 16, 0, 0, 0, 0, 0, 0, FormatID::R16_FLOAT);
+ return info;
+ }
+ case D3DFMT_G16R16F:
+ {
+ static const D3DFormat info(32, 1, 1, 16, 16, 0, 0, 0, 0, 0, FormatID::R16G16_FLOAT);
+ return info;
+ }
+ case D3DFMT_A16B16G16R16F:
+ {
+ static const D3DFormat info(64, 1, 1, 16, 16, 16, 16, 0, 0, 0,
+ FormatID::R16G16B16A16_FLOAT);
+ return info;
+ }
+ case D3DFMT_R32F:
+ {
+ static const D3DFormat info(32, 1, 1, 32, 0, 0, 0, 0, 0, 0, FormatID::R32_FLOAT);
+ return info;
+ }
+ case D3DFMT_G32R32F:
+ {
+ static const D3DFormat info(64, 1, 1, 32, 32, 0, 0, 0, 0, 0, FormatID::R32G32_FLOAT);
+ return info;
+ }
+ case D3DFMT_A32B32G32R32F:
+ {
+ static const D3DFormat info(128, 1, 1, 32, 32, 32, 32, 0, 0, 0,
+ FormatID::R32G32B32A32_FLOAT);
+ return info;
+ }
+
+ case D3DFMT_D16:
+ {
+ static const D3DFormat info(16, 1, 1, 0, 0, 0, 0, 0, 16, 0, FormatID::D16_UNORM);
+ return info;
+ }
+ case D3DFMT_D24S8:
+ {
+ static const D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 8,
+ FormatID::D24_UNORM_S8_UINT);
+ return info;
+ }
+ case D3DFMT_D24X8:
+ {
+ static const D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 24, 0, FormatID::D16_UNORM);
+ return info;
+ }
+ case D3DFMT_D32:
+ {
+ static const D3DFormat info(32, 1, 1, 0, 0, 0, 0, 0, 32, 0, FormatID::D32_UNORM);
+ return info;
+ }
+
+ case D3DFMT_DXT1:
+ {
+ static const D3DFormat info(64, 4, 4, 0, 0, 0, 0, 0, 0, 0,
+ FormatID::BC1_RGBA_UNORM_BLOCK);
+ return info;
+ }
+ case D3DFMT_DXT3:
+ {
+ static const D3DFormat info(128, 4, 4, 0, 0, 0, 0, 0, 0, 0,
+ FormatID::BC2_RGBA_UNORM_BLOCK);
+ return info;
+ }
+ case D3DFMT_DXT5:
+ {
+ static const D3DFormat info(128, 4, 4, 0, 0, 0, 0, 0, 0, 0,
+ FormatID::BC3_RGBA_UNORM_BLOCK);
+ return info;
+ }
+
+ default:
+ {
+ static const D3DFormat defaultInfo;
+ return defaultInfo;
+ }
+ }
+}
+} // namespace d3d9
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d_format.h b/gfx/angle/checkout/src/libANGLE/renderer/d3d_format.h
new file mode 100644
index 0000000000..4554f11460
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d_format.h
@@ -0,0 +1,58 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// d3d_format: Describes a D3D9 format. Used by the D3D9 and GL back-ends.
+
+#ifndef LIBANGLE_RENDERER_D3D_FORMAT_H_
+#define LIBANGLE_RENDERER_D3D_FORMAT_H_
+
+#include "libANGLE/renderer/Format.h"
+
+// We forcibly include the D3D9 header here because this file can be used from 3 different backends.
+#include <d3d9.h>
+
+namespace rx
+{
+namespace d3d9
+{
+struct D3DFormat
+{
+ D3DFormat();
+ D3DFormat(GLuint pixelBytes,
+ GLuint blockWidth,
+ GLuint blockHeight,
+ GLuint redBits,
+ GLuint greenBits,
+ GLuint blueBits,
+ GLuint alphaBits,
+ GLuint luminanceBits,
+ GLuint depthBits,
+ GLuint stencilBits,
+ angle::FormatID formatID);
+
+ const angle::Format &info() const { return angle::Format::Get(formatID); }
+
+ GLuint pixelBytes;
+ GLuint blockWidth;
+ GLuint blockHeight;
+
+ GLuint redBits;
+ GLuint greenBits;
+ GLuint blueBits;
+ GLuint alphaBits;
+ GLuint luminanceBits;
+
+ GLuint depthBits;
+ GLuint stencilBits;
+
+ angle::FormatID formatID;
+};
+
+const D3DFormat &GetD3DFormatInfo(D3DFORMAT format);
+
+} // namespace d3d9
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_D3D_FORMAT_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/driver_utils.cpp b/gfx/angle/checkout/src/libANGLE/renderer/driver_utils.cpp
new file mode 100644
index 0000000000..360a0dd9a2
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/driver_utils.cpp
@@ -0,0 +1,438 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// driver_utils.h : provides more information about current driver.
+
+#include <algorithm>
+
+#include "libANGLE/renderer/driver_utils.h"
+
+#include "common/platform.h"
+#include "common/system_utils.h"
+
+#if defined(ANGLE_PLATFORM_ANDROID)
+# include <sys/system_properties.h>
+#endif
+
+#if defined(ANGLE_PLATFORM_LINUX)
+# include <sys/utsname.h>
+#endif
+
+#if defined(ANGLE_PLATFORM_WINDOWS)
+# include <versionhelpers.h>
+#endif
+
+namespace rx
+{
+// Intel
+// Referenced from
+// https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/include/pci_ids/crocus_pci_ids.h
+// https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/include/pci_ids/iris_pci_ids.h
+namespace
+{
+// gen6
+const uint16_t SandyBridge[] = {
+ 0x0102, 0x0106, 0x010A, // snb_gt1
+ 0x0112, 0x0122, 0x0116, 0x0126 // snb_gt2
+};
+
+// gen7
+const uint16_t IvyBridge[] = {
+ 0x0152, 0x0156, 0x015A, // ivb_gt1
+ 0x0162, 0x0166, 0x016A // ivb_gt2
+};
+
+// gen 7.5
+const uint16_t Haswell[] = {
+ 0x0402, 0x0406, 0x040A, 0x040B, 0x040E, 0x0C02, 0x0C06, 0x0C0A, 0x0C0B, 0x0C0E,
+ 0x0A02, 0x0A06, 0x0A0A, 0x0A0B, 0x0A0E, 0x0D02, 0x0D06, 0x0D0A, 0x0D0B, 0x0D0E, // hsw_gt1
+ 0x0412, 0x0416, 0x041A, 0x041B, 0x041E, 0x0C12, 0x0C16, 0x0C1A, 0x0C1B, 0x0C1E,
+ 0x0A12, 0x0A16, 0x0A1A, 0x0A1B, 0x0A1E, 0x0D12, 0x0D16, 0x0D1A, 0x0D1B, 0x0D1E, // hsw_gt2
+ 0x0422, 0x0426, 0x042A, 0x042B, 0x042E, 0x0C22, 0x0C26, 0x0C2A, 0x0C2B, 0x0C2E,
+ 0x0A22, 0x0A26, 0x0A2A, 0x0A2B, 0x0A2E, 0x0D22, 0x0D26, 0x0D2A, 0x0D2B, 0x0D2E // hsw_gt3
+};
+
+// gen8
+const uint16_t Broadwell[] = {
+ 0x1602, 0x1606, 0x160A, 0x160B, 0x160D, 0x160E, // bdw_gt1
+ 0x1612, 0x1616, 0x161A, 0x161B, 0x161D, 0x161E, // bdw_gt2
+ 0x1622, 0x1626, 0x162A, 0x162B, 0x162D, 0x162E // bdw_gt3
+};
+
+const uint16_t CherryView[] = {0x22B0, 0x22B1, 0x22B2, 0x22B3};
+
+// gen9
+const uint16_t Skylake[] = {
+ 0x1902, 0x1906, 0x190A, 0x190B, 0x190E, // skl_gt1
+ 0x1912, 0x1913, 0x1915, 0x1916, 0x1917, 0x191A, 0x191B, 0x191D, 0x191E, 0x1921, // skl_gt2
+ 0x1923, 0x1926, 0x1927, 0x192B, 0x192D, // skl_gt3
+ 0x192A, 0x1932, 0x193A, 0x193B, 0x193D // skl_gt4
+};
+
+// gen9lp
+const uint16_t Broxton[] = {0x0A84, 0x1A84, 0x1A85, 0x5A84, 0x5A85};
+
+const uint16_t GeminiLake[] = {0x3184, 0x3185};
+
+// gen9p5
+const uint16_t KabyLake[] = {
+ // Kaby Lake
+ 0x5902, 0x5906, 0x5908, 0x590A, 0x590B, 0x590E, // kbl_gt1
+ 0x5913, 0x5915, // kbl_gt1_5
+ 0x5912, 0x5916, 0x5917, 0x591A, 0x591B, 0x591D, 0x591E, 0x5921, // kbl_gt2
+ 0x5923, 0x5926, 0x5927, // kbl_gt3
+ 0x593B, // kbl_gt4
+ // Amber Lake
+ 0x591C, 0x87C0 // kbl_gt2
+};
+
+const uint16_t CoffeeLake[] = {
+ // Amber Lake
+ 0x87CA, // cfl_gt2
+
+ // Coffee Lake
+ 0x3E90, 0x3E93, 0x3E99, 0x3E9C, // cfl_gt1
+ 0x3E91, 0x3E92, 0x3E94, 0x3E96, 0x3E98, 0x3E9A, 0x3E9B, 0x3EA9, // cfl_gt2
+ 0x3EA5, 0x3EA6, 0x3EA7, 0x3EA8, // cfl_gt3
+
+ // Whisky Lake
+ 0x3EA1, 0x3EA4, // cfl_gt1
+ 0x3EA0, 0x3EA3, // cfl_gt2
+ 0x3EA2, // cfl_gt3
+
+ // Comet Lake
+ 0x9B21, 0x9BA0, 0x9BA2, 0x9BA4, 0x9BA5, 0x9BA8, 0x9BAA, 0x9BAB, 0x9BAC, // cfl_gt1
+ 0x9B41, 0x9BC0, 0x9BC2, 0x9BC4, 0x9BC5, 0x9BC6, 0x9BC8, 0x9BCA, 0x9BCB, 0x9BCC, // cfl_gt2
+ 0x9BE6, 0x9BF6 // cfl_gt2
+};
+
+const uint16_t IntelGen11[] = {
+ // Ice Lake
+ 0x8A71, // icl_gt0_5
+ 0x8A56, 0x8A58, 0x8A5B, 0x8A5D, // icl_gt1
+ 0x8A54, 0x8A57, 0x8A59, 0x8A5A, 0x8A5C, // icl_gt1_5
+ 0x8A50, 0x8A51, 0x8A52, 0x8A53, // icl_gt2
+
+ // Elkhart Lake
+ 0x4500, 0x4541, 0x4551, 0x4555, 0x4557, 0x4571,
+
+ // Jasper Lake
+ 0x4E51, 0x4E55, 0x4E57, 0x4E61, 0x4E71};
+
+const uint16_t IntelGen12[] = {
+ // Rocket Lake
+ 0x4C8C, // rkl_gt05
+ 0x4C8A, 0x4C8B, 0x4C90, 0x4C9A, // rkl_gt1
+
+ // Alder Lake
+ 0x4683, 0x4693, // adl_gt05
+ 0x4680, 0x4681, 0x4682, 0x4688, 0x4689, 0x4690, 0x4691, 0x4692, // adl_gt1
+ 0x4626, 0x4628, 0x462A, 0x46A0, 0x46A1, 0x46A2, 0x46A3, 0x46A6, 0x46A8, // adl_gt2
+ 0x46AA, 0x46B0, 0x46B1, 0x46B2, 0x46B3, 0x46C0, 0x46C1, 0x46C2, 0x46C3, // adl_gt2
+ 0x46D0, 0x46D1, 0x46D2, // adl_n
+
+ // Tiger Lake
+ 0x9A60, 0x9A68, 0x9A70, // tgl_gt1
+ 0x9A40, 0x9A49, 0x9A59, 0x9A78, 0x9AC0, 0x9AC9, 0x9AD9, 0x9AF8, // tgl_gt2
+
+ // Raptop Lake
+ 0xA780, 0xA781, 0xA782, 0xA783, 0xA788, 0xA789, // rpl
+ 0xA720, 0xA721, 0xA7A0, 0xA7A1, 0xA7A8, 0xA7A9, // rpl_p
+
+ // DG1
+ 0x4905, 0x4906, 0x4907, 0x4908, 0x4909};
+
+} // anonymous namespace
+
+IntelDriverVersion::IntelDriverVersion(uint32_t buildNumber) : mBuildNumber(buildNumber) {}
+
+bool IntelDriverVersion::operator==(const IntelDriverVersion &version)
+{
+ return mBuildNumber == version.mBuildNumber;
+}
+
+bool IntelDriverVersion::operator!=(const IntelDriverVersion &version)
+{
+ return !(*this == version);
+}
+
+bool IntelDriverVersion::operator<(const IntelDriverVersion &version)
+{
+ return mBuildNumber < version.mBuildNumber;
+}
+
+bool IntelDriverVersion::operator>=(const IntelDriverVersion &version)
+{
+ return !(*this < version);
+}
+
+bool IsSandyBridge(uint32_t DeviceId)
+{
+ return std::find(std::begin(SandyBridge), std::end(SandyBridge), DeviceId) !=
+ std::end(SandyBridge);
+}
+
+bool IsIvyBridge(uint32_t DeviceId)
+{
+ return std::find(std::begin(IvyBridge), std::end(IvyBridge), DeviceId) != std::end(IvyBridge);
+}
+
+bool IsHaswell(uint32_t DeviceId)
+{
+ return std::find(std::begin(Haswell), std::end(Haswell), DeviceId) != std::end(Haswell);
+}
+
+bool IsBroadwell(uint32_t DeviceId)
+{
+ return std::find(std::begin(Broadwell), std::end(Broadwell), DeviceId) != std::end(Broadwell);
+}
+
+bool IsCherryView(uint32_t DeviceId)
+{
+ return std::find(std::begin(CherryView), std::end(CherryView), DeviceId) !=
+ std::end(CherryView);
+}
+
+bool IsSkylake(uint32_t DeviceId)
+{
+ return std::find(std::begin(Skylake), std::end(Skylake), DeviceId) != std::end(Skylake);
+}
+
+bool IsBroxton(uint32_t DeviceId)
+{
+ return std::find(std::begin(Broxton), std::end(Broxton), DeviceId) != std::end(Broxton);
+}
+
+bool IsKabyLake(uint32_t DeviceId)
+{
+ return std::find(std::begin(KabyLake), std::end(KabyLake), DeviceId) != std::end(KabyLake);
+}
+
+bool IsGeminiLake(uint32_t DeviceId)
+{
+ return std::find(std::begin(GeminiLake), std::end(GeminiLake), DeviceId) !=
+ std::end(GeminiLake);
+}
+
+bool IsCoffeeLake(uint32_t DeviceId)
+{
+ return std::find(std::begin(CoffeeLake), std::end(CoffeeLake), DeviceId) !=
+ std::end(CoffeeLake);
+}
+
+bool Is9thGenIntel(uint32_t DeviceId)
+{
+ return IsSkylake(DeviceId) || IsBroxton(DeviceId) || IsKabyLake(DeviceId);
+}
+
+bool Is11thGenIntel(uint32_t DeviceId)
+{
+ return std::find(std::begin(IntelGen11), std::end(IntelGen11), DeviceId) !=
+ std::end(IntelGen11);
+}
+
+bool Is12thGenIntel(uint32_t DeviceId)
+{
+ return std::find(std::begin(IntelGen12), std::end(IntelGen12), DeviceId) !=
+ std::end(IntelGen12);
+}
+
+const char *GetVendorString(uint32_t vendorId)
+{
+ switch (vendorId)
+ {
+ case VENDOR_ID_AMD:
+ return "AMD";
+ case VENDOR_ID_ARM:
+ return "ARM";
+ case VENDOR_ID_APPLE:
+ return "Apple";
+ case VENDOR_ID_BROADCOM:
+ return "Broadcom";
+ case VENDOR_ID_GOOGLE:
+ return "Google";
+ case VENDOR_ID_INTEL:
+ return "Intel";
+ case VENDOR_ID_MESA:
+ return "Mesa";
+ case VENDOR_ID_MICROSOFT:
+ return "Microsoft";
+ case VENDOR_ID_NVIDIA:
+ return "NVIDIA";
+ case VENDOR_ID_POWERVR:
+ return "Imagination Technologies";
+ case VENDOR_ID_QUALCOMM:
+ return "Qualcomm";
+ case VENDOR_ID_SAMSUNG:
+ return "Samsung Electronics Co., Ltd.";
+ case VENDOR_ID_VIVANTE:
+ return "Vivante";
+ case VENDOR_ID_VMWARE:
+ return "VMware";
+ case 0xba5eba11: // Mock vendor ID used for tests.
+ return "Test";
+ case 0:
+ return "NULL";
+ default:
+ // TODO(jmadill): More vendor IDs.
+ UNIMPLEMENTED();
+ return "Unknown";
+ }
+}
+
+MajorMinorPatchVersion::MajorMinorPatchVersion() {}
+MajorMinorPatchVersion::MajorMinorPatchVersion(int major, int minor, int patch)
+ : majorVersion(major), minorVersion(minor), patchVersion(patch)
+{}
+
+bool operator==(const MajorMinorPatchVersion &a, const MajorMinorPatchVersion &b)
+{
+ return std::tie(a.majorVersion, a.minorVersion, a.patchVersion) ==
+ std::tie(b.majorVersion, b.minorVersion, b.patchVersion);
+}
+bool operator!=(const MajorMinorPatchVersion &a, const MajorMinorPatchVersion &b)
+{
+ return std::tie(a.majorVersion, a.minorVersion, a.patchVersion) !=
+ std::tie(b.majorVersion, b.minorVersion, b.patchVersion);
+}
+bool operator<(const MajorMinorPatchVersion &a, const MajorMinorPatchVersion &b)
+{
+ return std::tie(a.majorVersion, a.minorVersion, a.patchVersion) <
+ std::tie(b.majorVersion, b.minorVersion, b.patchVersion);
+}
+bool operator>=(const MajorMinorPatchVersion &a, const MajorMinorPatchVersion &b)
+{
+ return std::tie(a.majorVersion, a.minorVersion, a.patchVersion) >=
+ std::tie(b.majorVersion, b.minorVersion, b.patchVersion);
+}
+
+ARMDriverVersion ParseARMDriverVersion(uint32_t driverVersion)
+{
+ // ARM driver versions are built with the following macro:
+ // ((((uint32_t)(major)) << 22) | (((uint32_t)(minor)) << 12) | ((uint32_t)(patch)))
+ constexpr uint32_t kMinorVersionMask = angle::BitMask<uint32_t>(10);
+ constexpr uint32_t kPatchMask = angle::BitMask<uint32_t>(12);
+ return ARMDriverVersion(driverVersion >> 22, (driverVersion >> 12) & kMinorVersionMask,
+ driverVersion & kPatchMask);
+}
+
+int GetAndroidSDKVersion()
+{
+#if defined(ANGLE_PLATFORM_ANDROID)
+ char apiVersion[PROP_VALUE_MAX];
+ int length = __system_property_get("ro.build.version.sdk", apiVersion);
+ if (length == 0)
+ {
+ return 0;
+ }
+ return atoi(apiVersion);
+#else
+ return 0;
+#endif
+}
+#if !defined(ANGLE_PLATFORM_MACOS)
+OSVersion GetMacOSVersion()
+{
+ // Return a default version
+ return OSVersion(0, 0, 0);
+}
+#endif
+
+#if !defined(ANGLE_PLATFORM_IOS)
+OSVersion GetiOSVersion()
+{
+ // Return a default version
+ return OSVersion(0, 0, 0);
+}
+#endif
+
+#if defined(ANGLE_PLATFORM_LINUX)
+bool ParseLinuxOSVersion(const char *version, int *major, int *minor, int *patch)
+{
+ errno = 0; // reset global error flag.
+ char *next;
+ *major = static_cast<int>(strtol(version, &next, 10));
+ if (next == nullptr || *next != '.' || errno != 0)
+ {
+ return false;
+ }
+
+ *minor = static_cast<int>(strtol(next + 1, &next, 10));
+ if (next == nullptr || *next != '.' || errno != 0)
+ {
+ return false;
+ }
+
+ *patch = static_cast<int>(strtol(next + 1, &next, 10));
+ if (errno != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+#endif
+
+OSVersion GetLinuxOSVersion()
+{
+#if defined(ANGLE_PLATFORM_LINUX)
+ struct utsname uname_info;
+ if (uname(&uname_info) != 0)
+ {
+ return OSVersion(0, 0, 0);
+ }
+
+ int majorVersion = 0, minorVersion = 0, patchVersion = 0;
+ if (ParseLinuxOSVersion(uname_info.release, &majorVersion, &minorVersion, &patchVersion))
+ {
+ return OSVersion(majorVersion, minorVersion, patchVersion);
+ }
+#endif
+
+ return OSVersion(0, 0, 0);
+}
+
+// There are multiple environment variables that may or may not be set during Wayland
+// sessions, including WAYLAND_DISPLAY, XDG_SESSION_TYPE, and DESKTOP_SESSION
+bool IsWayland()
+{
+ static bool checked = false;
+ static bool isWayland = false;
+ if (!checked)
+ {
+ if (IsLinux())
+ {
+ if (!angle::GetEnvironmentVar("WAYLAND_DISPLAY").empty())
+ {
+ isWayland = true;
+ }
+ else if (angle::GetEnvironmentVar("XDG_SESSION_TYPE") == "wayland")
+ {
+ isWayland = true;
+ }
+ else if (angle::GetEnvironmentVar("DESKTOP_SESSION").find("wayland") !=
+ std::string::npos)
+ {
+ isWayland = true;
+ }
+ }
+ checked = true;
+ }
+ return isWayland;
+}
+
+bool IsWin10OrGreater()
+{
+#if defined(ANGLE_ENABLE_WINDOWS_UWP)
+ return true;
+#elif defined(ANGLE_PLATFORM_WINDOWS)
+ return IsWindows10OrGreater();
+#else
+ return false;
+#endif
+}
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/driver_utils.h b/gfx/angle/checkout/src/libANGLE/renderer/driver_utils.h
new file mode 100644
index 0000000000..3addc07ffd
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/driver_utils.h
@@ -0,0 +1,278 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// driver_utils.h : provides more information about current driver.
+
+#ifndef LIBANGLE_RENDERER_DRIVER_UTILS_H_
+#define LIBANGLE_RENDERER_DRIVER_UTILS_H_
+
+#include "common/platform.h"
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+
+enum VendorID : uint32_t
+{
+ VENDOR_ID_UNKNOWN = 0x0,
+ VENDOR_ID_AMD = 0x1002,
+ VENDOR_ID_APPLE = 0x106B,
+ VENDOR_ID_ARM = 0x13B5,
+ // Broadcom devices won't use PCI, but this is their Vulkan vendor id.
+ VENDOR_ID_BROADCOM = 0x14E4,
+ VENDOR_ID_GOOGLE = 0x1AE0,
+ VENDOR_ID_INTEL = 0x8086,
+ VENDOR_ID_MESA = 0x10005,
+ VENDOR_ID_MICROSOFT = 0x1414,
+ VENDOR_ID_NVIDIA = 0x10DE,
+ VENDOR_ID_POWERVR = 0x1010,
+ // This is Qualcomm PCI Vendor ID.
+ // Android doesn't have a PCI bus, but all we need is a unique id.
+ VENDOR_ID_QUALCOMM = 0x5143,
+ VENDOR_ID_SAMSUNG = 0x144D,
+ VENDOR_ID_VIVANTE = 0x9999,
+ VENDOR_ID_VMWARE = 0x15AD,
+};
+
+enum AndroidDeviceID : uint32_t
+{
+ ANDROID_DEVICE_ID_UNKNOWN = 0x0,
+ ANDROID_DEVICE_ID_NEXUS5X = 0x4010800,
+ ANDROID_DEVICE_ID_PIXEL2 = 0x5040001,
+ ANDROID_DEVICE_ID_PIXEL1XL = 0x5030004,
+ ANDROID_DEVICE_ID_PIXEL4 = 0x6040001,
+ ANDROID_DEVICE_ID_SWIFTSHADER = 0xC0DE,
+};
+
+inline bool IsAMD(uint32_t vendorId)
+{
+ return vendorId == VENDOR_ID_AMD;
+}
+
+inline bool IsApple(uint32_t vendorId)
+{
+ return vendorId == VENDOR_ID_APPLE;
+}
+
+inline bool IsARM(uint32_t vendorId)
+{
+ return vendorId == VENDOR_ID_ARM;
+}
+
+inline bool IsBroadcom(uint32_t vendorId)
+{
+ return vendorId == VENDOR_ID_BROADCOM;
+}
+
+inline bool IsIntel(uint32_t vendorId)
+{
+ return vendorId == VENDOR_ID_INTEL;
+}
+
+inline bool IsGoogle(uint32_t vendorId)
+{
+ return vendorId == VENDOR_ID_GOOGLE;
+}
+
+inline bool IsMicrosoft(uint32_t vendorId)
+{
+ return vendorId == VENDOR_ID_MICROSOFT;
+}
+
+inline bool IsNvidia(uint32_t vendorId)
+{
+ return vendorId == VENDOR_ID_NVIDIA;
+}
+
+inline bool IsPowerVR(uint32_t vendorId)
+{
+ return vendorId == VENDOR_ID_POWERVR;
+}
+
+inline bool IsQualcomm(uint32_t vendorId)
+{
+ return vendorId == VENDOR_ID_QUALCOMM;
+}
+
+inline bool IsSamsung(uint32_t vendorId)
+{
+ return vendorId == VENDOR_ID_SAMSUNG;
+}
+
+inline bool IsVivante(uint32_t vendorId)
+{
+ return vendorId == VENDOR_ID_VIVANTE;
+}
+
+inline bool IsVMWare(uint32_t vendorId)
+{
+ return vendorId == VENDOR_ID_VMWARE;
+}
+
+inline bool IsNexus5X(uint32_t vendorId, uint32_t deviceId)
+{
+ return IsQualcomm(vendorId) && deviceId == ANDROID_DEVICE_ID_NEXUS5X;
+}
+
+inline bool IsPixel1XL(uint32_t vendorId, uint32_t deviceId)
+{
+ return IsQualcomm(vendorId) && deviceId == ANDROID_DEVICE_ID_PIXEL1XL;
+}
+
+inline bool IsPixel2(uint32_t vendorId, uint32_t deviceId)
+{
+ return IsQualcomm(vendorId) && deviceId == ANDROID_DEVICE_ID_PIXEL2;
+}
+
+inline bool IsPixel4(uint32_t vendorId, uint32_t deviceId)
+{
+ return IsQualcomm(vendorId) && deviceId == ANDROID_DEVICE_ID_PIXEL4;
+}
+
+inline bool IsSwiftshader(uint32_t vendorId, uint32_t deviceId)
+{
+ return IsGoogle(vendorId) && deviceId == ANDROID_DEVICE_ID_SWIFTSHADER;
+}
+
+const char *GetVendorString(uint32_t vendorId);
+
+// For Linux, Intel graphics driver version is the Mesa version. The version number has three
+// fields: major revision, minor revision and release number.
+// For Windows, The version number includes 3rd and 4th fields. Please refer the details at
+// http://www.intel.com/content/www/us/en/support/graphics-drivers/000005654.html.
+// Current implementation only supports Windows.
+class IntelDriverVersion
+{
+ public:
+ IntelDriverVersion(uint32_t buildNumber);
+ bool operator==(const IntelDriverVersion &);
+ bool operator!=(const IntelDriverVersion &);
+ bool operator<(const IntelDriverVersion &);
+ bool operator>=(const IntelDriverVersion &);
+
+ private:
+ uint32_t mBuildNumber;
+};
+
+bool IsSandyBridge(uint32_t DeviceId);
+bool IsIvyBridge(uint32_t DeviceId);
+bool IsHaswell(uint32_t DeviceId);
+bool IsBroadwell(uint32_t DeviceId);
+bool IsCherryView(uint32_t DeviceId);
+bool IsSkylake(uint32_t DeviceId);
+bool IsBroxton(uint32_t DeviceId);
+bool IsKabyLake(uint32_t DeviceId);
+bool IsGeminiLake(uint32_t DeviceId);
+bool IsCoffeeLake(uint32_t DeviceId);
+bool Is9thGenIntel(uint32_t DeviceId);
+bool Is11thGenIntel(uint32_t DeviceId);
+bool Is12thGenIntel(uint32_t DeviceId);
+
+struct MajorMinorPatchVersion
+{
+ MajorMinorPatchVersion();
+ MajorMinorPatchVersion(int major, int minor, int patch);
+
+ int majorVersion = 0;
+ int minorVersion = 0;
+ int patchVersion = 0;
+};
+bool operator==(const MajorMinorPatchVersion &a, const MajorMinorPatchVersion &b);
+bool operator!=(const MajorMinorPatchVersion &a, const MajorMinorPatchVersion &b);
+bool operator<(const MajorMinorPatchVersion &a, const MajorMinorPatchVersion &b);
+bool operator>=(const MajorMinorPatchVersion &a, const MajorMinorPatchVersion &b);
+
+using ARMDriverVersion = MajorMinorPatchVersion;
+ARMDriverVersion ParseARMDriverVersion(uint32_t driverVersion);
+
+// Platform helpers
+inline bool IsWindows()
+{
+#if defined(ANGLE_PLATFORM_WINDOWS)
+ return true;
+#else
+ return false;
+#endif
+}
+
+inline bool IsLinux()
+{
+#if defined(ANGLE_PLATFORM_LINUX)
+ return true;
+#else
+ return false;
+#endif
+}
+
+inline bool IsChromeOS()
+{
+#if defined(ANGLE_PLATFORM_CHROMEOS)
+ return true;
+#else
+ return false;
+#endif
+}
+
+inline bool IsApple()
+{
+#if defined(ANGLE_PLATFORM_APPLE)
+ return true;
+#else
+ return false;
+#endif
+}
+
+inline bool IsMac()
+{
+#if defined(ANGLE_PLATFORM_APPLE) && defined(ANGLE_PLATFORM_MACOS)
+ return true;
+#else
+ return false;
+#endif
+}
+
+inline bool IsFuchsia()
+{
+#if defined(ANGLE_PLATFORM_FUCHSIA)
+ return true;
+#else
+ return false;
+#endif
+}
+
+inline bool IsIOS()
+{
+#if defined(ANGLE_PLATFORM_IOS)
+ return true;
+#else
+ return false;
+#endif
+}
+
+bool IsWayland();
+bool IsWin10OrGreater();
+
+using OSVersion = MajorMinorPatchVersion;
+
+OSVersion GetMacOSVersion();
+
+OSVersion GetiOSVersion();
+
+OSVersion GetLinuxOSVersion();
+
+inline bool IsAndroid()
+{
+#if defined(ANGLE_PLATFORM_ANDROID)
+ return true;
+#else
+ return false;
+#endif
+}
+
+int GetAndroidSDKVersion();
+
+} // namespace rx
+#endif // LIBANGLE_RENDERER_DRIVER_UTILS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/dxgi_format_map.h b/gfx/angle/checkout/src/libANGLE/renderer/dxgi_format_map.h
new file mode 100644
index 0000000000..711d0d0a0b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/dxgi_format_map.h
@@ -0,0 +1,27 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DXGI format info:
+// Determining metadata about a DXGI format.
+
+#ifndef LIBANGLE_RENDERER_DXGI_FORMAT_MAP_H_
+#define LIBANGLE_RENDERER_DXGI_FORMAT_MAP_H_
+
+#include "common/platform.h"
+
+namespace rx
+{
+namespace d3d11
+{
+GLenum GetComponentType(DXGI_FORMAT dxgiFormat);
+} // namespace d3d11
+
+namespace d3d11_angle
+{
+const angle::Format &GetFormat(DXGI_FORMAT dxgiFormat);
+} // namespace d3d11_angle
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_DXGI_FORMAT_MAP_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/dxgi_format_map_autogen.cpp b/gfx/angle/checkout/src/libANGLE/renderer/dxgi_format_map_autogen.cpp
new file mode 100644
index 0000000000..a46567ae0d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/dxgi_format_map_autogen.cpp
@@ -0,0 +1,516 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_dxgi_format_table.py using data from dxgi_format_data.json.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DXGI format info:
+// Determining metadata about a DXGI format.
+
+#include "libANGLE/renderer/Format.h"
+
+using namespace angle;
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+GLenum GetComponentType(DXGI_FORMAT dxgiFormat)
+{
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_420_OPAQUE:
+ break;
+ case DXGI_FORMAT_A8P8:
+ break;
+ case DXGI_FORMAT_A8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_AI44:
+ break;
+ case DXGI_FORMAT_AYUV:
+ break;
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ break;
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ break;
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC1_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC1_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC2_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC2_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC3_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC3_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC4_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC4_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC4_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC5_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC5_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC5_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC6H_SF16:
+ break;
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC6H_UF16:
+ break;
+ case DXGI_FORMAT_BC7_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC7_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_D16_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ break;
+ case DXGI_FORMAT_D32_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ break;
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_IA44:
+ break;
+ case DXGI_FORMAT_NV11:
+ break;
+ case DXGI_FORMAT_NV12:
+ break;
+ case DXGI_FORMAT_P010:
+ break;
+ case DXGI_FORMAT_P016:
+ break;
+ case DXGI_FORMAT_P8:
+ break;
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ break;
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ break;
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R16G16_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R16G16_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R16G16_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ break;
+ case DXGI_FORMAT_R16G16_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R16G16_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R16_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R16_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R16_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_R16_TYPELESS:
+ break;
+ case DXGI_FORMAT_R16_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R16_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R1_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R32G32B32_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32B32_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R32G32_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R32G32_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32_FLOAT:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ return GL_FLOAT;
+ case DXGI_FORMAT_R32_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R8G8_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R8G8_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R8G8_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R8G8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R8_SINT:
+ return GL_INT;
+ case DXGI_FORMAT_R8_SNORM:
+ return GL_SIGNED_NORMALIZED;
+ case DXGI_FORMAT_R8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R8_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_R8_UNORM:
+ return GL_UNSIGNED_NORMALIZED;
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ return GL_FLOAT;
+ case DXGI_FORMAT_UNKNOWN:
+ break;
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ return GL_UNSIGNED_INT;
+ case DXGI_FORMAT_Y210:
+ break;
+ case DXGI_FORMAT_Y216:
+ break;
+ case DXGI_FORMAT_Y410:
+ break;
+ case DXGI_FORMAT_Y416:
+ break;
+ case DXGI_FORMAT_YUY2:
+ break;
+ default:
+ break;
+ }
+
+ UNREACHABLE();
+ return GL_NONE;
+}
+
+} // namespace d3d11
+
+namespace d3d11_angle
+{
+
+const Format &GetFormat(DXGI_FORMAT dxgiFormat)
+{
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_420_OPAQUE:
+ break;
+ case DXGI_FORMAT_A8P8:
+ break;
+ case DXGI_FORMAT_A8_UNORM:
+ return Format::Get(FormatID::A8_UNORM);
+ case DXGI_FORMAT_AI44:
+ break;
+ case DXGI_FORMAT_AYUV:
+ break;
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ return Format::Get(FormatID::B4G4R4A4_UNORM);
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ return Format::Get(FormatID::B5G5R5A1_UNORM);
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ return Format::Get(FormatID::B5G6R5_UNORM);
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ return Format::Get(FormatID::B8G8R8A8_TYPELESS);
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ return Format::Get(FormatID::B8G8R8A8_UNORM);
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ return Format::Get(FormatID::B8G8R8A8_UNORM_SRGB);
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ break;
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ return Format::Get(FormatID::B8G8R8X8_UNORM);
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ break;
+ case DXGI_FORMAT_BC1_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC1_UNORM:
+ return Format::Get(FormatID::BC1_RGBA_UNORM_BLOCK);
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ return Format::Get(FormatID::BC1_RGBA_UNORM_SRGB_BLOCK);
+ case DXGI_FORMAT_BC2_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC2_UNORM:
+ return Format::Get(FormatID::BC2_RGBA_UNORM_BLOCK);
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ return Format::Get(FormatID::BC2_RGBA_UNORM_SRGB_BLOCK);
+ case DXGI_FORMAT_BC3_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC3_UNORM:
+ return Format::Get(FormatID::BC3_RGBA_UNORM_BLOCK);
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ return Format::Get(FormatID::BC3_RGBA_UNORM_SRGB_BLOCK);
+ case DXGI_FORMAT_BC4_SNORM:
+ return Format::Get(FormatID::BC4_RED_SNORM_BLOCK);
+ case DXGI_FORMAT_BC4_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC4_UNORM:
+ return Format::Get(FormatID::BC4_RED_UNORM_BLOCK);
+ case DXGI_FORMAT_BC5_SNORM:
+ return Format::Get(FormatID::BC5_RG_SNORM_BLOCK);
+ case DXGI_FORMAT_BC5_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC5_UNORM:
+ return Format::Get(FormatID::BC5_RG_UNORM_BLOCK);
+ case DXGI_FORMAT_BC6H_SF16:
+ break;
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC6H_UF16:
+ break;
+ case DXGI_FORMAT_BC7_TYPELESS:
+ break;
+ case DXGI_FORMAT_BC7_UNORM:
+ break;
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ break;
+ case DXGI_FORMAT_D16_UNORM:
+ return Format::Get(FormatID::D16_UNORM);
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ return Format::Get(FormatID::D24_UNORM_S8_UINT);
+ case DXGI_FORMAT_D32_FLOAT:
+ return Format::Get(FormatID::D32_FLOAT);
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ return Format::Get(FormatID::D32_FLOAT_S8X24_UINT);
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ break;
+ case DXGI_FORMAT_IA44:
+ break;
+ case DXGI_FORMAT_NV11:
+ break;
+ case DXGI_FORMAT_NV12:
+ break;
+ case DXGI_FORMAT_P010:
+ break;
+ case DXGI_FORMAT_P016:
+ break;
+ case DXGI_FORMAT_P8:
+ break;
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ break;
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ return Format::Get(FormatID::R10G10B10A2_UINT);
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ return Format::Get(FormatID::R10G10B10A2_UNORM);
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ break;
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ return Format::Get(FormatID::R11G11B10_FLOAT);
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ return Format::Get(FormatID::R16G16B16A16_FLOAT);
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ return Format::Get(FormatID::R16G16B16A16_SINT);
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ return Format::Get(FormatID::R16G16B16A16_SNORM);
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ break;
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ return Format::Get(FormatID::R16G16B16A16_UINT);
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ return Format::Get(FormatID::R16G16B16A16_UNORM);
+ case DXGI_FORMAT_R16G16_FLOAT:
+ return Format::Get(FormatID::R16G16_FLOAT);
+ case DXGI_FORMAT_R16G16_SINT:
+ return Format::Get(FormatID::R16G16_SINT);
+ case DXGI_FORMAT_R16G16_SNORM:
+ return Format::Get(FormatID::R16G16_SNORM);
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ break;
+ case DXGI_FORMAT_R16G16_UINT:
+ return Format::Get(FormatID::R16G16_UINT);
+ case DXGI_FORMAT_R16G16_UNORM:
+ return Format::Get(FormatID::R16G16_UNORM);
+ case DXGI_FORMAT_R16_FLOAT:
+ return Format::Get(FormatID::R16_FLOAT);
+ case DXGI_FORMAT_R16_SINT:
+ return Format::Get(FormatID::R16_SINT);
+ case DXGI_FORMAT_R16_SNORM:
+ return Format::Get(FormatID::R16_SNORM);
+ case DXGI_FORMAT_R16_TYPELESS:
+ break;
+ case DXGI_FORMAT_R16_UINT:
+ return Format::Get(FormatID::R16_UINT);
+ case DXGI_FORMAT_R16_UNORM:
+ return Format::Get(FormatID::R16_UNORM);
+ case DXGI_FORMAT_R1_UNORM:
+ break;
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ return Format::Get(FormatID::R32G32B32A32_FLOAT);
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ return Format::Get(FormatID::R32G32B32A32_SINT);
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ return Format::Get(FormatID::R32G32B32A32_UINT);
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ return Format::Get(FormatID::R32G32B32_FLOAT);
+ case DXGI_FORMAT_R32G32B32_SINT:
+ return Format::Get(FormatID::R32G32B32_SINT);
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32B32_UINT:
+ return Format::Get(FormatID::R32G32B32_UINT);
+ case DXGI_FORMAT_R32G32_FLOAT:
+ return Format::Get(FormatID::R32G32_FLOAT);
+ case DXGI_FORMAT_R32G32_SINT:
+ return Format::Get(FormatID::R32G32_SINT);
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32G32_UINT:
+ return Format::Get(FormatID::R32G32_UINT);
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32_FLOAT:
+ return Format::Get(FormatID::R32_FLOAT);
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32_SINT:
+ return Format::Get(FormatID::R32_SINT);
+ case DXGI_FORMAT_R32_TYPELESS:
+ break;
+ case DXGI_FORMAT_R32_UINT:
+ return Format::Get(FormatID::R32_UINT);
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ return Format::Get(FormatID::R8G8B8A8_SINT);
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ return Format::Get(FormatID::R8G8B8A8_SNORM);
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ return Format::Get(FormatID::R8G8B8A8_TYPELESS);
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ return Format::Get(FormatID::R8G8B8A8_UINT);
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ return Format::Get(FormatID::R8G8B8A8_UNORM);
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ return Format::Get(FormatID::R8G8B8A8_UNORM_SRGB);
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ break;
+ case DXGI_FORMAT_R8G8_SINT:
+ return Format::Get(FormatID::R8G8_SINT);
+ case DXGI_FORMAT_R8G8_SNORM:
+ return Format::Get(FormatID::R8G8_SNORM);
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R8G8_UINT:
+ return Format::Get(FormatID::R8G8_UINT);
+ case DXGI_FORMAT_R8G8_UNORM:
+ return Format::Get(FormatID::R8G8_UNORM);
+ case DXGI_FORMAT_R8_SINT:
+ return Format::Get(FormatID::R8_SINT);
+ case DXGI_FORMAT_R8_SNORM:
+ return Format::Get(FormatID::R8_SNORM);
+ case DXGI_FORMAT_R8_TYPELESS:
+ break;
+ case DXGI_FORMAT_R8_UINT:
+ return Format::Get(FormatID::R8_UINT);
+ case DXGI_FORMAT_R8_UNORM:
+ return Format::Get(FormatID::R8_UNORM);
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ return Format::Get(FormatID::R9G9B9E5_SHAREDEXP);
+ case DXGI_FORMAT_UNKNOWN:
+ return Format::Get(FormatID::NONE);
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ break;
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ break;
+ case DXGI_FORMAT_Y210:
+ break;
+ case DXGI_FORMAT_Y216:
+ break;
+ case DXGI_FORMAT_Y410:
+ break;
+ case DXGI_FORMAT_Y416:
+ break;
+ case DXGI_FORMAT_YUY2:
+ break;
+ default:
+ break;
+ }
+
+ UNREACHABLE();
+ return Format::Get(FormatID::NONE);
+}
+
+} // namespace d3d11_angle
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/dxgi_support_table.h b/gfx/angle/checkout/src/libANGLE/renderer/dxgi_support_table.h
new file mode 100644
index 0000000000..fef57d0a1b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/dxgi_support_table.h
@@ -0,0 +1,43 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// dxgi_support_table:
+// Queries for DXGI support of various texture formats. Depends on DXGI
+// version, D3D feature level, and is sometimes guaranteed or optional.
+//
+
+#ifndef LIBANGLE_RENDERER_DXGI_SUPPORT_TABLE_H_
+#define LIBANGLE_RENDERER_DXGI_SUPPORT_TABLE_H_
+
+#include "common/platform.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+struct DXGISupport
+{
+ DXGISupport() : alwaysSupportedFlags(0), neverSupportedFlags(0), optionallySupportedFlags(0) {}
+
+ DXGISupport(UINT alwaysSupportedIn, UINT neverSupportedIn, UINT optionallySupportedIn)
+ : alwaysSupportedFlags(alwaysSupportedIn),
+ neverSupportedFlags(neverSupportedIn),
+ optionallySupportedFlags(optionallySupportedIn)
+ {}
+
+ UINT alwaysSupportedFlags;
+ UINT neverSupportedFlags;
+ UINT optionallySupportedFlags;
+};
+
+const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel);
+
+} // namespace d3d11
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_DXGI_SUPPORT_TABLE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/dxgi_support_table_autogen.cpp b/gfx/angle/checkout/src/libANGLE/renderer/dxgi_support_table_autogen.cpp
new file mode 100644
index 0000000000..56bbaed0db
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/dxgi_support_table_autogen.cpp
@@ -0,0 +1,3042 @@
+// GENERATED FILE - DO NOT EDIT. See dxgi_support_data.json.
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// dxgi_support_table:
+// Queries for DXGI support of various texture formats. Depends on DXGI
+// version, D3D feature level, and is sometimes guaranteed or optional.
+//
+
+#include "libANGLE/renderer/dxgi_support_table.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+namespace d3d11
+{
+
+#define F_2D D3D11_FORMAT_SUPPORT_TEXTURE2D
+#define F_3D D3D11_FORMAT_SUPPORT_TEXTURE3D
+#define F_CUBE D3D11_FORMAT_SUPPORT_TEXTURECUBE
+#define F_SAMPLE D3D11_FORMAT_SUPPORT_SHADER_SAMPLE
+#define F_RT D3D11_FORMAT_SUPPORT_RENDER_TARGET
+#define F_MS D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET
+#define F_DS D3D11_FORMAT_SUPPORT_DEPTH_STENCIL
+#define F_MIPGEN D3D11_FORMAT_SUPPORT_MIP_AUTOGEN
+
+namespace
+{
+
+const DXGISupport &GetDefaultSupport()
+{
+ static UINT AllSupportFlags =
+ D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURE3D |
+ D3D11_FORMAT_SUPPORT_TEXTURECUBE | D3D11_FORMAT_SUPPORT_SHADER_SAMPLE |
+ D3D11_FORMAT_SUPPORT_RENDER_TARGET | D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET |
+ D3D11_FORMAT_SUPPORT_DEPTH_STENCIL | D3D11_FORMAT_SUPPORT_MIP_AUTOGEN;
+ static const DXGISupport defaultSupport(0, 0, AllSupportFlags);
+ return defaultSupport;
+}
+
+const DXGISupport &GetDXGISupport_9_3(DXGI_FORMAT dxgiFormat)
+{
+ // clang-format off
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_420_OPAQUE:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_A8P8:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_A8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_AI44:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_AYUV:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ {
+ static const DXGISupport info(F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_MIPGEN | F_RT, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_SNORM:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_UNORM:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_SNORM:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_UNORM:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_SF16:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_UF16:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_UNORM:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_D16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_IA44:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_NV11:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_NV12:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P010:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P016:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P8:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ {
+ static const DXGISupport info(0, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ {
+ static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
+ return info;
+ }
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ {
+ static const DXGISupport info(0, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ {
+ static const DXGISupport info(0, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_SINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_UINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_FLOAT:
+ {
+ static const DXGISupport info(0, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_SINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_SNORM:
+ {
+ static const DXGISupport info(0, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16_UINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R1_UNORM:
+ {
+ static const DXGISupport info(F_2D, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_SINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_UINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ {
+ static const DXGISupport info(0, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_SINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_UINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_SINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_UINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_UNORM:
+ {
+ static const DXGISupport info(0, F_DS, F_MS | F_RT | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_R8_SINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_SNORM:
+ {
+ static const DXGISupport info(0, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8_UINT:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y210:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y216:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y410:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y416:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_YUY2:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+
+ default:
+ UNREACHABLE();
+ return GetDefaultSupport();
+ }
+ // clang-format on
+}
+
+const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat)
+{
+ // clang-format off
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_420_OPAQUE:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_A8P8:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_A8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_AI44:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_AYUV:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ {
+ static const DXGISupport info(F_MIPGEN, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_MIPGEN | F_RT, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_SF16:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_UF16:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_UNORM:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_D16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_IA44:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_NV11:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_NV12:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P010:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P016:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P8:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ {
+ static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
+ return info;
+ }
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R1_UNORM:
+ {
+ static const DXGISupport info(F_2D, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_R32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y210:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y216:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y410:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y416:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_YUY2:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+
+ default:
+ UNREACHABLE();
+ return GetDefaultSupport();
+ }
+ // clang-format on
+}
+
+const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat)
+{
+ // clang-format off
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_420_OPAQUE:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_A8P8:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_A8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_AI44:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_AYUV:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ {
+ static const DXGISupport info(F_MIPGEN, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_MIPGEN | F_RT, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_SF16:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_UF16:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_UNORM:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_D16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_IA44:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_NV11:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_NV12:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P010:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P016:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P8:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ {
+ static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
+ return info;
+ }
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R1_UNORM:
+ {
+ static const DXGISupport info(F_2D, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y210:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y216:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y410:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y416:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_YUY2:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+
+ default:
+ UNREACHABLE();
+ return GetDefaultSupport();
+ }
+ // clang-format on
+}
+
+const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat)
+{
+ // clang-format off
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_420_OPAQUE:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_A8P8:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_A8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_AI44:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_AYUV:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ {
+ static const DXGISupport info(F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ {
+ static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_SF16:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_UF16:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_D16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_IA44:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_NV11:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_NV12:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P010:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P016:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P8:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ {
+ static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
+ return info;
+ }
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y210:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y216:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y410:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y416:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_YUY2:
+ {
+ static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+
+ default:
+ UNREACHABLE();
+ return GetDefaultSupport();
+ }
+ // clang-format on
+}
+
+const DXGISupport &GetDXGISupport_11_1(DXGI_FORMAT dxgiFormat)
+{
+ // clang-format off
+ switch (dxgiFormat)
+ {
+ case DXGI_FORMAT_420_OPAQUE:
+ {
+ static const DXGISupport info(F_2D, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_A8P8:
+ {
+ static const DXGISupport info(F_2D, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_A8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_AI44:
+ {
+ static const DXGISupport info(F_2D, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_AYUV:
+ {
+ static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B4G4R4A4_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_B5G5R5A1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_SAMPLE, F_DS, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_B5G6R5_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_UNORM:
+ {
+ static const DXGISupport info(F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_TYPELESS:
+ {
+ static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_UNORM:
+ {
+ static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC4_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC5_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_SF16:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC6H_UF16:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_D16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D24_UNORM_S8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_G8R8_G8B8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_IA44:
+ {
+ static const DXGISupport info(F_2D, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_NV11:
+ {
+ static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_NV12:
+ {
+ static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P010:
+ {
+ static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P016:
+ {
+ static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_P8:
+ {
+ static const DXGISupport info(F_2D, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10A2_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
+ {
+ static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D);
+ return info;
+ }
+ case DXGI_FORMAT_R11G11B10_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16B16A16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16G16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R16_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R16_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R1_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R24G8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32A32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32B32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_SAMPLE, F_MS | F_RT);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32G32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32G8X24_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_FLOAT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R32_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R32_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_B8G8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8G8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_SINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_SNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_TYPELESS:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_R8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | F_SAMPLE, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R8_UNORM:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS);
+ return info;
+ }
+ case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
+ {
+ static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_UNKNOWN:
+ {
+ static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
+ {
+ static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y210:
+ {
+ static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y216:
+ {
+ static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y410:
+ {
+ static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_Y416:
+ {
+ static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+ case DXGI_FORMAT_YUY2:
+ {
+ static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0);
+ return info;
+ }
+
+ default:
+ UNREACHABLE();
+ return GetDefaultSupport();
+ }
+ // clang-format on
+}
+
+} // namespace
+
+#undef F_2D
+#undef F_3D
+#undef F_CUBE
+#undef F_SAMPLE
+#undef F_RT
+#undef F_MS
+#undef F_DS
+#undef F_MIPGEN
+
+const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ case D3D_FEATURE_LEVEL_9_3:
+ return GetDXGISupport_9_3(dxgiFormat);
+ case D3D_FEATURE_LEVEL_10_0:
+ return GetDXGISupport_10_0(dxgiFormat);
+ case D3D_FEATURE_LEVEL_10_1:
+ return GetDXGISupport_10_1(dxgiFormat);
+ case D3D_FEATURE_LEVEL_11_0:
+ return GetDXGISupport_11_0(dxgiFormat);
+ case D3D_FEATURE_LEVEL_11_1:
+ return GetDXGISupport_11_1(dxgiFormat);
+ default:
+ return GetDefaultSupport();
+ }
+}
+
+} // namespace d3d11
+
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/gl/functionsgl_enums.h b/gfx/angle/checkout/src/libANGLE/renderer/gl/functionsgl_enums.h
new file mode 100644
index 0000000000..667436e915
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/gl/functionsgl_enums.h
@@ -0,0 +1,1376 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// functionsgl_enums.h: OpenGL enums for versions 1.0 through 4.5.
+
+#ifndef LIBANGLE_RENDERER_GL_FUNCTIONSGLENUMS_H_
+#define LIBANGLE_RENDERER_GL_FUNCTIONSGLENUMS_H_
+
+// 1.0
+#define GL_ALPHA 0x1906
+#define GL_ALWAYS 0x0207
+#define GL_AND 0x1501
+#define GL_AND_INVERTED 0x1504
+#define GL_AND_REVERSE 0x1502
+#define GL_BACK 0x0405
+#define GL_BACK_LEFT 0x0402
+#define GL_BACK_RIGHT 0x0403
+#define GL_BLEND 0x0BE2
+#define GL_BLEND_DST 0x0BE0
+#define GL_BLEND_SRC 0x0BE1
+#define GL_BLUE 0x1905
+#define GL_BYTE 0x1400
+#define GL_CCW 0x0901
+#define GL_CLEAR 0x1500
+#define GL_COLOR 0x1800
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_COLOR_CLEAR_VALUE 0x0C22
+#define GL_COLOR_LOGIC_OP 0x0BF2
+#define GL_COLOR_WRITEMASK 0x0C23
+#define GL_COPY 0x1503
+#define GL_COPY_INVERTED 0x150C
+#define GL_CULL_FACE 0x0B44
+#define GL_CULL_FACE_MODE 0x0B45
+#define GL_CW 0x0900
+#define GL_DECR 0x1E03
+#define GL_DEPTH 0x1801
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_DEPTH_CLEAR_VALUE 0x0B73
+#define GL_DEPTH_COMPONENT 0x1902
+#define GL_DEPTH_FUNC 0x0B74
+#define GL_DEPTH_RANGE 0x0B70
+#define GL_DEPTH_TEST 0x0B71
+#define GL_DEPTH_WRITEMASK 0x0B72
+#define GL_DITHER 0x0BD0
+#define GL_DONT_CARE 0x1100
+#define GL_DOUBLE 0x140A
+#define GL_DOUBLEBUFFER 0x0C32
+#define GL_DRAW_BUFFER 0x0C01
+#define GL_DST_ALPHA 0x0304
+#define GL_DST_COLOR 0x0306
+#define GL_EQUAL 0x0202
+#define GL_EQUIV 0x1509
+#define GL_EXTENSIONS 0x1F03
+#define GL_FALSE 0
+#define GL_FASTEST 0x1101
+#define GL_FILL 0x1B02
+#define GL_FLOAT 0x1406
+#define GL_FRONT 0x0404
+#define GL_FRONT_AND_BACK 0x0408
+#define GL_FRONT_FACE 0x0B46
+#define GL_FRONT_LEFT 0x0400
+#define GL_FRONT_RIGHT 0x0401
+#define GL_GEQUAL 0x0206
+#define GL_GREATER 0x0204
+#define GL_GREEN 0x1904
+#define GL_INCR 0x1E02
+#define GL_INT 0x1404
+#define GL_INVALID_ENUM 0x0500
+#define GL_INVALID_OPERATION 0x0502
+#define GL_INVALID_VALUE 0x0501
+#define GL_INVERT 0x150A
+#define GL_KEEP 0x1E00
+#define GL_LEFT 0x0406
+#define GL_LEQUAL 0x0203
+#define GL_LESS 0x0201
+#define GL_LINE 0x1B01
+#define GL_LINEAR 0x2601
+#define GL_LINEAR_MIPMAP_LINEAR 0x2703
+#define GL_LINEAR_MIPMAP_NEAREST 0x2701
+#define GL_LINES 0x0001
+#define GL_LINE_LOOP 0x0002
+#define GL_LINE_SMOOTH 0x0B20
+#define GL_LINE_SMOOTH_HINT 0x0C52
+#define GL_LINE_STRIP 0x0003
+#define GL_LINE_WIDTH 0x0B21
+#define GL_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_LINE_WIDTH_RANGE 0x0B22
+#define GL_LOGIC_OP_MODE 0x0BF0
+#define GL_MAX_TEXTURE_SIZE 0x0D33
+#define GL_MAX_VIEWPORT_DIMS 0x0D3A
+#define GL_NAND 0x150E
+#define GL_NEAREST 0x2600
+#define GL_NEAREST_MIPMAP_LINEAR 0x2702
+#define GL_NEAREST_MIPMAP_NEAREST 0x2700
+#define GL_NEVER 0x0200
+#define GL_NICEST 0x1102
+#define GL_NONE 0
+#define GL_NOOP 0x1505
+#define GL_NOR 0x1508
+#define GL_NOTEQUAL 0x0205
+#define GL_NO_ERROR 0
+#define GL_ONE 1
+#define GL_ONE_MINUS_DST_ALPHA 0x0305
+#define GL_ONE_MINUS_DST_COLOR 0x0307
+#define GL_ONE_MINUS_SRC_ALPHA 0x0303
+#define GL_ONE_MINUS_SRC_COLOR 0x0301
+#define GL_OR 0x1507
+#define GL_OR_INVERTED 0x150D
+#define GL_OR_REVERSE 0x150B
+#define GL_OUT_OF_MEMORY 0x0505
+#define GL_PACK_ALIGNMENT 0x0D05
+#define GL_PACK_LSB_FIRST 0x0D01
+#define GL_PACK_ROW_LENGTH 0x0D02
+#define GL_PACK_SKIP_PIXELS 0x0D04
+#define GL_PACK_SKIP_ROWS 0x0D03
+#define GL_PACK_SWAP_BYTES 0x0D00
+#define GL_POINT 0x1B00
+#define GL_POINTS 0x0000
+#define GL_POINT_SIZE 0x0B11
+#define GL_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_POINT_SIZE_RANGE 0x0B12
+#define GL_POLYGON_MODE 0x0B40
+#define GL_POLYGON_OFFSET_FACTOR 0x8038
+#define GL_POLYGON_OFFSET_FILL 0x8037
+#define GL_POLYGON_OFFSET_LINE 0x2A02
+#define GL_POLYGON_OFFSET_POINT 0x2A01
+#define GL_POLYGON_OFFSET_UNITS 0x2A00
+#define GL_POLYGON_SMOOTH 0x0B41
+#define GL_POLYGON_SMOOTH_HINT 0x0C53
+#define GL_PROXY_TEXTURE_1D 0x8063
+#define GL_PROXY_TEXTURE_2D 0x8064
+#define GL_QUADS 0x0007
+#define GL_R3_G3_B2 0x2A10
+#define GL_READ_BUFFER 0x0C02
+#define GL_RED 0x1903
+#define GL_RENDERER 0x1F01
+#define GL_REPEAT 0x2901
+#define GL_REPLACE 0x1E01
+#define GL_RGB 0x1907
+#define GL_RGB10 0x8052
+#define GL_RGB10_A2 0x8059
+#define GL_RGB12 0x8053
+#define GL_RGB16 0x8054
+#define GL_RGB4 0x804F
+#define GL_RGB5 0x8050
+#define GL_RGB5_A1 0x8057
+#define GL_RGB8 0x8051
+#define GL_RGBA 0x1908
+#define GL_RGBA12 0x805A
+#define GL_RGBA16 0x805B
+#define GL_RGBA2 0x8055
+#define GL_RGBA4 0x8056
+#define GL_RGBA8 0x8058
+#define GL_RIGHT 0x0407
+#define GL_SCISSOR_BOX 0x0C10
+#define GL_SCISSOR_TEST 0x0C11
+#define GL_SET 0x150F
+#define GL_SHORT 0x1402
+#define GL_SRC_ALPHA 0x0302
+#define GL_SRC_ALPHA_SATURATE 0x0308
+#define GL_SRC_COLOR 0x0300
+#define GL_STENCIL 0x1802
+#define GL_STENCIL_BUFFER_BIT 0x00000400
+#define GL_STENCIL_CLEAR_VALUE 0x0B91
+#define GL_STENCIL_FAIL 0x0B94
+#define GL_STENCIL_FUNC 0x0B92
+#define GL_STENCIL_INDEX 0x1901
+#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
+#define GL_STENCIL_REF 0x0B97
+#define GL_STENCIL_TEST 0x0B90
+#define GL_STENCIL_VALUE_MASK 0x0B93
+#define GL_STENCIL_WRITEMASK 0x0B98
+#define GL_STEREO 0x0C33
+#define GL_SUBPIXEL_BITS 0x0D50
+#define GL_TEXTURE 0x1702
+#define GL_TEXTURE_1D 0x0DE0
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_TEXTURE_ALPHA_SIZE 0x805F
+#define GL_TEXTURE_BINDING_1D 0x8068
+#define GL_TEXTURE_BINDING_2D 0x8069
+#define GL_TEXTURE_BLUE_SIZE 0x805E
+#define GL_TEXTURE_BORDER_COLOR 0x1004
+#define GL_TEXTURE_GREEN_SIZE 0x805D
+#define GL_TEXTURE_HEIGHT 0x1001
+#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_RED_SIZE 0x805C
+#define GL_TEXTURE_WIDTH 0x1000
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+#define GL_TRIANGLES 0x0004
+#define GL_TRIANGLE_FAN 0x0006
+#define GL_TRIANGLE_STRIP 0x0005
+#define GL_TRUE 1
+#define GL_UNPACK_ALIGNMENT 0x0CF5
+#define GL_UNPACK_LSB_FIRST 0x0CF1
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+#define GL_UNPACK_SKIP_PIXELS 0x0CF4
+#define GL_UNPACK_SKIP_ROWS 0x0CF3
+#define GL_UNPACK_SWAP_BYTES 0x0CF0
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_UNSIGNED_INT 0x1405
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_VENDOR 0x1F00
+#define GL_VERSION 0x1F02
+#define GL_VIEWPORT 0x0BA2
+#define GL_XOR 0x1506
+#define GL_ZERO 0
+
+// 1.2
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_TEXTURE_3D 0x806F
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+
+// 1.2 Extensions
+#define GL_ALL_COMPLETED_NV 0x84F2
+#define GL_FENCE_STATUS_NV 0x84F3
+#define GL_FENCE_CONDITION_NV 0x84F4
+
+// 1.3
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_MULTISAMPLE 0x809D
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+
+// 1.5
+#define GL_BLEND_COLOR 0x8005
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_EQUATION 0x8009
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_DECR_WRAP 0x8508
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_FUNC_ADD 0x8006
+#define GL_FUNC_REVERSE_SUBTRACT 0x800B
+#define GL_FUNC_SUBTRACT 0x800A
+#define GL_INCR_WRAP 0x8507
+#define GL_MAX 0x8008
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_MIN 0x8007
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_TEXTURE_LOD_BIAS 0x8501
+
+// 1.5
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_CURRENT_QUERY 0x8865
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_READ_ONLY 0x88B8
+#define GL_READ_WRITE 0x88BA
+#define GL_SAMPLES_PASSED 0x8914
+#define GL_SRC1_ALPHA 0x8589
+#define GL_STATIC_COPY 0x88E6
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STREAM_COPY 0x88E2
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_WRITE_ONLY 0x88B9
+
+// 2.0
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_BLEND_EQUATION_RGB 0x8009
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_DELETE_STATUS 0x8B80
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_LINK_STATUS 0x8B82
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_POINT_SPRITE 0x8861
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_SHADER 0x8B31
+
+// 2.1
+#define GL_COMPRESSED_SRGB 0x8C48
+#define GL_COMPRESSED_SRGB_ALPHA 0x8C49
+#define GL_FLOAT_MAT2x3 0x8B65
+#define GL_FLOAT_MAT2x4 0x8B66
+#define GL_FLOAT_MAT3x2 0x8B67
+#define GL_FLOAT_MAT3x4 0x8B68
+#define GL_FLOAT_MAT4x2 0x8B69
+#define GL_FLOAT_MAT4x3 0x8B6A
+#define GL_PIXEL_PACK_BUFFER 0x88EB
+#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
+#define GL_SRGB 0x8C40
+#define GL_SRGB8 0x8C41
+#define GL_SRGB8_ALPHA8 0x8C43
+#define GL_SRGB_ALPHA 0x8C42
+
+// 3.0
+#define GL_BGRA_INTEGER 0x8D9B
+#define GL_BGR_INTEGER 0x8D9A
+#define GL_BLUE_INTEGER 0x8D96
+#define GL_BUFFER_ACCESS_FLAGS 0x911F
+#define GL_BUFFER_MAP_LENGTH 0x9120
+#define GL_BUFFER_MAP_OFFSET 0x9121
+#define GL_CLAMP_READ_COLOR 0x891C
+#define GL_CLIP_DISTANCE0 0x3000
+#define GL_CLIP_DISTANCE1 0x3001
+#define GL_CLIP_DISTANCE2 0x3002
+#define GL_CLIP_DISTANCE3 0x3003
+#define GL_CLIP_DISTANCE4 0x3004
+#define GL_CLIP_DISTANCE5 0x3005
+#define GL_CLIP_DISTANCE6 0x3006
+#define GL_CLIP_DISTANCE7 0x3007
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#define GL_COMPARE_REF_TO_TEXTURE 0x884E
+#define GL_COMPRESSED_RED 0x8225
+#define GL_COMPRESSED_RED_RGTC1 0x8DBB
+#define GL_COMPRESSED_RG 0x8226
+#define GL_COMPRESSED_RG_RGTC2 0x8DBD
+#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define GL_CONTEXT_FLAGS 0x821E
+#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001
+#define GL_DEPTH24_STENCIL8 0x88F0
+#define GL_DEPTH32F_STENCIL8 0x8CAD
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#define GL_DEPTH_COMPONENT32F 0x8CAC
+#define GL_DEPTH_STENCIL 0x84F9
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_FIXED_ONLY 0x891D
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD
+#define GL_FRAMEBUFFER 0x8D40
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#define GL_FRAMEBUFFER_DEFAULT 0x8218
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#define GL_FRAMEBUFFER_UNDEFINED 0x8219
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#define GL_GREEN_INTEGER 0x8D95
+#define GL_HALF_FLOAT 0x140B
+#define GL_INTERLEAVED_ATTRIBS 0x8C8C
+#define GL_INT_SAMPLER_1D 0x8DC9
+#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE
+#define GL_INT_SAMPLER_2D 0x8DCA
+#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF
+#define GL_INT_SAMPLER_3D 0x8DCB
+#define GL_INT_SAMPLER_CUBE 0x8DCC
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#define GL_MAJOR_VERSION 0x821B
+#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010
+#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
+#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004
+#define GL_MAP_READ_BIT 0x0001
+#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
+#define GL_MAP_WRITE_BIT 0x0002
+#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
+#define GL_MAX_CLIP_DISTANCES 0x0D32
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#define GL_MAX_SAMPLES 0x8D57
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#define GL_MINOR_VERSION 0x821C
+#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904
+#define GL_NUM_EXTENSIONS 0x821D
+#define GL_PRIMITIVES_GENERATED 0x8C87
+#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19
+#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B
+#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16
+#define GL_QUERY_BY_REGION_WAIT 0x8E15
+#define GL_QUERY_NO_WAIT 0x8E14
+#define GL_QUERY_WAIT 0x8E13
+#define GL_R11F_G11F_B10F 0x8C3A
+#define GL_R16 0x822A
+#define GL_R16F 0x822D
+#define GL_R16I 0x8233
+#define GL_R16UI 0x8234
+#define GL_R32F 0x822E
+#define GL_R32I 0x8235
+#define GL_R32UI 0x8236
+#define GL_R8 0x8229
+#define GL_R8I 0x8231
+#define GL_R8UI 0x8232
+#define GL_RASTERIZER_DISCARD 0x8C89
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
+#define GL_RED_INTEGER 0x8D94
+#define GL_RENDERBUFFER 0x8D41
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#define GL_RENDERBUFFER_HEIGHT 0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#define GL_RG 0x8227
+#define GL_RG16 0x822C
+#define GL_RG16F 0x822F
+#define GL_RG16I 0x8239
+#define GL_RG16UI 0x823A
+#define GL_RG32F 0x8230
+#define GL_RG32I 0x823B
+#define GL_RG32UI 0x823C
+#define GL_RG8 0x822B
+#define GL_RG8I 0x8237
+#define GL_RG8UI 0x8238
+#define GL_RGB16F 0x881B
+#define GL_RGB16I 0x8D89
+#define GL_RGB16UI 0x8D77
+#define GL_RGB32F 0x8815
+#define GL_RGB32I 0x8D83
+#define GL_RGB32UI 0x8D71
+#define GL_RGB8I 0x8D8F
+#define GL_RGB8UI 0x8D7D
+#define GL_RGB9_E5 0x8C3D
+#define GL_RGBA16F 0x881A
+#define GL_RGBA16I 0x8D88
+#define GL_RGBA16UI 0x8D76
+#define GL_RGBA32F 0x8814
+#define GL_RGBA32I 0x8D82
+#define GL_RGBA32UI 0x8D70
+#define GL_RGBA8I 0x8D8E
+#define GL_RGBA8UI 0x8D7C
+#define GL_RGBA_INTEGER 0x8D99
+#define GL_RGB_INTEGER 0x8D98
+#define GL_RG_INTEGER 0x8228
+#define GL_SAMPLER_1D_ARRAY 0x8DC0
+#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3
+#define GL_SAMPLER_2D_ARRAY 0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW 0x8DC5
+#define GL_SEPARATE_ATTRIBS 0x8C8D
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#define GL_STENCIL_INDEX1 0x8D46
+#define GL_STENCIL_INDEX16 0x8D49
+#define GL_STENCIL_INDEX4 0x8D47
+#define GL_STENCIL_INDEX8 0x8D48
+#define GL_TEXTURE_1D_ARRAY 0x8C18
+#define GL_TEXTURE_2D_ARRAY 0x8C1A
+#define GL_TEXTURE_ALPHA_TYPE 0x8C13
+#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
+#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
+#define GL_TEXTURE_BLUE_TYPE 0x8C12
+#define GL_TEXTURE_DEPTH_TYPE 0x8C16
+#define GL_TEXTURE_GREEN_TYPE 0x8C11
+#define GL_TEXTURE_RED_TYPE 0x8C10
+#define GL_TEXTURE_SHARED_SIZE 0x8C3F
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
+#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76
+#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E
+#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1
+#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6
+#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7
+#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4
+#define GL_UNSIGNED_INT_VEC2 0x8DC6
+#define GL_UNSIGNED_INT_VEC3 0x8DC7
+#define GL_UNSIGNED_INT_VEC4 0x8DC8
+#define GL_UNSIGNED_NORMALIZED 0x8C17
+#define GL_VERTEX_ARRAY_BINDING 0x85B5
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD
+
+// 3.1
+#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
+#define GL_COPY_READ_BUFFER 0x8F36
+#define GL_COPY_WRITE_BUFFER 0x8F37
+#define GL_INT_SAMPLER_2D_RECT 0x8DCD
+#define GL_INT_SAMPLER_BUFFER 0x8DD0
+#define GL_INVALID_INDEX 0xFFFFFFFFu
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B
+#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B
+#define GL_PRIMITIVE_RESTART 0x8F9D
+#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#define GL_R16_SNORM 0x8F98
+#define GL_R8_SNORM 0x8F94
+#define GL_RG16_SNORM 0x8F99
+#define GL_RG8_SNORM 0x8F95
+#define GL_RGB16_SNORM 0x8F9A
+#define GL_RGB8_SNORM 0x8F96
+#define GL_RGBA16_SNORM 0x8F9B
+#define GL_RGBA8_SNORM 0x8F97
+#define GL_SAMPLER_2D_RECT 0x8B63
+#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64
+#define GL_SAMPLER_BUFFER 0x8DC2
+#define GL_SIGNED_NORMALIZED 0x8F9C
+#define GL_TEXTURE_BINDING_BUFFER 0x8C2C
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#define GL_TEXTURE_BUFFER 0x8C2A
+#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43
+#define GL_UNIFORM_BLOCK_BINDING 0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40
+#define GL_UNIFORM_BLOCK_INDEX 0x8A3A
+#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
+#define GL_UNIFORM_BUFFER 0x8A11
+#define GL_UNIFORM_BUFFER_BINDING 0x8A28
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34
+#define GL_UNIFORM_BUFFER_SIZE 0x8A2A
+#define GL_UNIFORM_BUFFER_START 0x8A29
+#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E
+#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D
+#define GL_UNIFORM_NAME_LENGTH 0x8A39
+#define GL_UNIFORM_OFFSET 0x8A3B
+#define GL_UNIFORM_SIZE 0x8A38
+#define GL_UNIFORM_TYPE 0x8A37
+#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5
+#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8
+
+// 3.2
+#define GL_ALREADY_SIGNALED 0x911A
+#define GL_CONDITION_SATISFIED 0x911C
+#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002
+#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001
+#define GL_CONTEXT_PROFILE_MASK 0x9126
+#define GL_DEPTH_CLAMP 0x864F
+#define GL_FIRST_VERTEX_CONVENTION 0x8E4D
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#define GL_GEOMETRY_INPUT_TYPE 0x8917
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8918
+#define GL_GEOMETRY_SHADER 0x8DD9
+#define GL_GEOMETRY_VERTICES_OUT 0x8916
+#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109
+#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C
+#define GL_LAST_VERTEX_CONVENTION 0x8E4E
+#define GL_LINES_ADJACENCY 0x000A
+#define GL_LINE_STRIP_ADJACENCY 0x000B
+#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E
+#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125
+#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123
+#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#define GL_MAX_INTEGER_SAMPLES 0x9110
+#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59
+#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122
+#define GL_OBJECT_TYPE 0x9112
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#define GL_PROVOKING_VERTEX 0x8E4F
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101
+#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103
+#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
+#define GL_SAMPLER_2D_MULTISAMPLE 0x9108
+#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B
+#define GL_SAMPLE_MASK 0x8E51
+#define GL_SAMPLE_MASK_VALUE 0x8E52
+#define GL_SAMPLE_POSITION 0x8E50
+#define GL_SIGNALED 0x9119
+#define GL_SYNC_CONDITION 0x9113
+#define GL_SYNC_FENCE 0x9116
+#define GL_SYNC_FLAGS 0x9115
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#define GL_SYNC_STATUS 0x9114
+#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
+#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104
+#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105
+#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F
+#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107
+#define GL_TEXTURE_SAMPLES 0x9106
+#define GL_TIMEOUT_EXPIRED 0x911B
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
+#define GL_TRIANGLES_ADJACENCY 0x000C
+#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D
+#define GL_UNSIGNALED 0x9118
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A
+#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D
+#define GL_WAIT_FAILED 0x911D
+
+// 3.3
+#define GL_ANY_SAMPLES_PASSED 0x8C2F
+#define GL_INT_2_10_10_10_REV 0x8D9F
+#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC
+#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB
+#define GL_ONE_MINUS_SRC1_COLOR 0x88FA
+#define GL_RGB10_A2UI 0x906F
+#define GL_SAMPLER_BINDING 0x8919
+#define GL_SRC1_COLOR 0x88F9
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
+#define GL_TIMESTAMP 0x8E28
+#define GL_TIME_ELAPSED 0x88BF
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
+
+// 4.0
+#define GL_ACTIVE_SUBROUTINES 0x8DE5
+#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48
+#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47
+#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49
+#define GL_COMPATIBLE_SUBROUTINES 0x8E4B
+#define GL_DOUBLE_MAT2 0x8F46
+#define GL_DOUBLE_MAT2x3 0x8F49
+#define GL_DOUBLE_MAT2x4 0x8F4A
+#define GL_DOUBLE_MAT3 0x8F47
+#define GL_DOUBLE_MAT3x2 0x8F4B
+#define GL_DOUBLE_MAT3x4 0x8F4C
+#define GL_DOUBLE_MAT4 0x8F48
+#define GL_DOUBLE_MAT4x2 0x8F4D
+#define GL_DOUBLE_MAT4x3 0x8F4E
+#define GL_DOUBLE_VEC2 0x8FFC
+#define GL_DOUBLE_VEC3 0x8FFD
+#define GL_DOUBLE_VEC4 0x8FFE
+#define GL_DRAW_INDIRECT_BUFFER 0x8F3F
+#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43
+#define GL_FRACTIONAL_EVEN 0x8E7C
+#define GL_FRACTIONAL_ODD 0x8E7B
+#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D
+#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F
+#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
+#define GL_ISOLINES 0x8E7A
+#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
+#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
+#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C
+#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A
+#define GL_MAX_PATCH_VERTICES 0x8E7D
+#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F
+#define GL_MAX_SUBROUTINES 0x8DE7
+#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8
+#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C
+#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83
+#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81
+#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85
+#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89
+#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F
+#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D
+#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86
+#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82
+#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A
+#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80
+#define GL_MAX_TESS_GEN_LEVEL 0x8E7E
+#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84
+#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70
+#define GL_MAX_VERTEX_STREAMS 0x8E71
+#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B
+#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E
+#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37
+#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A
+#define GL_PATCHES 0x000E
+#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73
+#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74
+#define GL_PATCH_VERTICES 0x8E72
+#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B
+#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
+#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
+#define GL_SAMPLE_SHADING 0x8C36
+#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75
+#define GL_TESS_CONTROL_SHADER 0x8E88
+#define GL_TESS_EVALUATION_SHADER 0x8E87
+#define GL_TESS_GEN_MODE 0x8E76
+#define GL_TESS_GEN_POINT_MODE 0x8E79
+#define GL_TESS_GEN_SPACING 0x8E77
+#define GL_TESS_GEN_VERTEX_ORDER 0x8E78
+#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
+#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25
+#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1
+#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
+
+// 4.1
+#define GL_ACTIVE_PROGRAM 0x8259
+#define GL_ALL_SHADER_BITS 0xFFFFFFFF
+#define GL_FIXED 0x140C
+#define GL_FRAGMENT_SHADER_BIT 0x00000002
+#define GL_GEOMETRY_SHADER_BIT 0x00000004
+#define GL_HIGH_FLOAT 0x8DF2
+#define GL_HIGH_INT 0x8DF5
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
+#define GL_LAYER_PROVOKING_VERTEX 0x825E
+#define GL_LOW_FLOAT 0x8DF0
+#define GL_LOW_INT 0x8DF3
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
+#define GL_MAX_VARYING_VECTORS 0x8DFC
+#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
+#define GL_MAX_VIEWPORTS 0x825B
+#define GL_MEDIUM_FLOAT 0x8DF1
+#define GL_MEDIUM_INT 0x8DF4
+#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#define GL_PROGRAM_BINARY_FORMATS 0x87FF
+#define GL_PROGRAM_BINARY_LENGTH 0x8741
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257
+#define GL_PROGRAM_PIPELINE_BINDING 0x825A
+#define GL_PROGRAM_SEPARABLE 0x8258
+#define GL_RGB565 0x8D62
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#define GL_SHADER_COMPILER 0x8DFA
+#define GL_TESS_CONTROL_SHADER_BIT 0x00000008
+#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010
+#define GL_UNDEFINED_VERTEX 0x8260
+#define GL_VERTEX_SHADER_BIT 0x00000001
+#define GL_VIEWPORT_BOUNDS_RANGE 0x825D
+#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F
+#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C
+
+// 4.2
+#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9
+#define GL_ALL_BARRIER_BITS 0xFFFFFFFF
+#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
+#define GL_ATOMIC_COUNTER_BUFFER 0x92C0
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5
+#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6
+#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1
+#define GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7
+#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3
+#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2
+#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200
+#define GL_COMMAND_BARRIER_BIT 0x00000040
+#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
+#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
+#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
+#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
+#define GL_COPY_READ_BUFFER_BINDING 0x8F36
+#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37
+#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002
+#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400
+#define GL_IMAGE_1D 0x904C
+#define GL_IMAGE_1D_ARRAY 0x9052
+#define GL_IMAGE_2D 0x904D
+#define GL_IMAGE_2D_ARRAY 0x9053
+#define GL_IMAGE_2D_MULTISAMPLE 0x9055
+#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056
+#define GL_IMAGE_2D_RECT 0x904F
+#define GL_IMAGE_3D 0x904E
+#define GL_IMAGE_BINDING_ACCESS 0x8F3E
+#define GL_IMAGE_BINDING_FORMAT 0x906E
+#define GL_IMAGE_BINDING_LAYER 0x8F3D
+#define GL_IMAGE_BINDING_LAYERED 0x8F3C
+#define GL_IMAGE_BINDING_LEVEL 0x8F3B
+#define GL_IMAGE_BINDING_NAME 0x8F3A
+#define GL_IMAGE_BUFFER 0x9051
+#define GL_IMAGE_CUBE 0x9050
+#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9
+#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8
+#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7
+#define GL_INT_IMAGE_1D 0x9057
+#define GL_INT_IMAGE_1D_ARRAY 0x905D
+#define GL_INT_IMAGE_2D 0x9058
+#define GL_INT_IMAGE_2D_ARRAY 0x905E
+#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060
+#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061
+#define GL_INT_IMAGE_2D_RECT 0x905A
+#define GL_INT_IMAGE_3D 0x9059
+#define GL_INT_IMAGE_BUFFER 0x905C
+#define GL_INT_IMAGE_CUBE 0x905B
+#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC
+#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8
+#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7
+#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1
+#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
+#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6
+#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0
+#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5
+#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF
+#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD
+#define GL_MAX_IMAGE_SAMPLES 0x906D
+#define GL_MAX_IMAGE_UNITS 0x8F38
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3
+#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD
+#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4
+#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE
+#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC
+#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2
+#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC
+#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA
+#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC
+#define GL_NUM_SAMPLE_COUNTS 0x9380
+#define GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D
+#define GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C
+#define GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E
+#define GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B
+#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080
+#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020
+#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008
+#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F
+#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100
+#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24
+#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800
+#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23
+#define GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA
+#define GL_UNIFORM_BARRIER_BIT 0x00000004
+#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129
+#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128
+#define GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A
+#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127
+#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB
+#define GL_UNSIGNED_INT_IMAGE_1D 0x9062
+#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068
+#define GL_UNSIGNED_INT_IMAGE_2D 0x9063
+#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B
+#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C
+#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065
+#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
+#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067
+#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
+#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
+#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001
+
+// 4.3
+#define GL_ACTIVE_RESOURCES 0x92F5
+#define GL_ACTIVE_VARIABLES 0x9305
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
+#define GL_ARRAY_SIZE 0x92FB
+#define GL_ARRAY_STRIDE 0x92FE
+#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301
+#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
+#define GL_AUTO_GENERATE_MIPMAP 0x8295
+#define GL_BLOCK_INDEX 0x92FD
+#define GL_BUFFER 0x82E0
+#define GL_BUFFER_BINDING 0x9302
+#define GL_BUFFER_DATA_SIZE 0x9303
+#define GL_BUFFER_VARIABLE 0x92E5
+#define GL_CAVEAT_SUPPORT 0x82B8
+#define GL_CLEAR_BUFFER 0x82B4
+#define GL_COLOR_COMPONENTS 0x8283
+#define GL_COLOR_ENCODING 0x8296
+#define GL_COLOR_RENDERABLE 0x8286
+#define GL_COMPRESSED_R11_EAC 0x9270
+#define GL_COMPRESSED_RG11_EAC 0x9272
+#define GL_COMPRESSED_RGB8_ETC2 0x9274
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
+#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
+#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271
+#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279
+#define GL_COMPRESSED_SRGB8_ETC2 0x9275
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
+#define GL_COMPUTE_SHADER 0x91B9
+#define GL_COMPUTE_SHADER_BIT 0x00000020
+#define GL_COMPUTE_SUBROUTINE 0x92ED
+#define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3
+#define GL_COMPUTE_TEXTURE 0x82A0
+#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_OUTPUT 0x92E0
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define GL_DEBUG_SOURCE_API 0x8246
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define GL_DEPTH_COMPONENTS 0x8284
+#define GL_DEPTH_RENDERABLE 0x8287
+#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA
+#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE
+#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF
+#define GL_FILTER 0x829A
+#define GL_FRAGMENT_SUBROUTINE 0x92EC
+#define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2
+#define GL_FRAGMENT_TEXTURE 0x829F
+#define GL_FRAMEBUFFER_BLEND 0x828B
+#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314
+#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311
+#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312
+#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313
+#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310
+#define GL_FRAMEBUFFER_RENDERABLE 0x8289
+#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A
+#define GL_FULL_SUPPORT 0x82B7
+#define GL_GEOMETRY_SUBROUTINE 0x92EB
+#define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1
+#define GL_GEOMETRY_TEXTURE 0x829E
+#define GL_GET_TEXTURE_IMAGE_FORMAT 0x8291
+#define GL_GET_TEXTURE_IMAGE_TYPE 0x8292
+#define GL_IMAGE_CLASS_10_10_10_2 0x82C3
+#define GL_IMAGE_CLASS_11_11_10 0x82C2
+#define GL_IMAGE_CLASS_1_X_16 0x82BE
+#define GL_IMAGE_CLASS_1_X_32 0x82BB
+#define GL_IMAGE_CLASS_1_X_8 0x82C1
+#define GL_IMAGE_CLASS_2_X_16 0x82BD
+#define GL_IMAGE_CLASS_2_X_32 0x82BA
+#define GL_IMAGE_CLASS_2_X_8 0x82C0
+#define GL_IMAGE_CLASS_4_X_16 0x82BC
+#define GL_IMAGE_CLASS_4_X_32 0x82B9
+#define GL_IMAGE_CLASS_4_X_8 0x82BF
+#define GL_IMAGE_COMPATIBILITY_CLASS 0x82A8
+#define GL_IMAGE_PIXEL_FORMAT 0x82A9
+#define GL_IMAGE_PIXEL_TYPE 0x82AA
+#define GL_IMAGE_TEXEL_SIZE 0x82A7
+#define GL_INTERNALFORMAT_ALPHA_SIZE 0x8274
+#define GL_INTERNALFORMAT_ALPHA_TYPE 0x827B
+#define GL_INTERNALFORMAT_BLUE_SIZE 0x8273
+#define GL_INTERNALFORMAT_BLUE_TYPE 0x827A
+#define GL_INTERNALFORMAT_DEPTH_SIZE 0x8275
+#define GL_INTERNALFORMAT_DEPTH_TYPE 0x827C
+#define GL_INTERNALFORMAT_GREEN_SIZE 0x8272
+#define GL_INTERNALFORMAT_GREEN_TYPE 0x8279
+#define GL_INTERNALFORMAT_PREFERRED 0x8270
+#define GL_INTERNALFORMAT_RED_SIZE 0x8271
+#define GL_INTERNALFORMAT_RED_TYPE 0x8278
+#define GL_INTERNALFORMAT_SHARED_SIZE 0x8277
+#define GL_INTERNALFORMAT_STENCIL_SIZE 0x8276
+#define GL_INTERNALFORMAT_STENCIL_TYPE 0x827D
+#define GL_INTERNALFORMAT_SUPPORTED 0x826F
+#define GL_IS_PER_PATCH 0x92E7
+#define GL_IS_ROW_MAJOR 0x9300
+#define GL_LOCATION 0x930E
+#define GL_LOCATION_INDEX 0x930F
+#define GL_MANUAL_GENERATE_MIPMAP 0x8294
+#define GL_MATRIX_STRIDE 0x92FF
+#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266
+#define GL_MAX_COMBINED_DIMENSIONS 0x8282
+#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
+#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
+#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265
+#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264
+#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD
+#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB
+#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262
+#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC
+#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB
+#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263
+#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE
+#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB
+#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define GL_MAX_DEPTH 0x8280
+#define GL_MAX_ELEMENT_INDEX 0x8D6B
+#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA
+#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316
+#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317
+#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318
+#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315
+#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7
+#define GL_MAX_HEIGHT 0x827F
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#define GL_MAX_LAYERS 0x8281
+#define GL_MAX_NAME_LENGTH 0x92F6
+#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7
+#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8
+#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE
+#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD
+#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8
+#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9
+#define GL_MAX_UNIFORM_LOCATIONS 0x826E
+#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA
+#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9
+#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6
+#define GL_MAX_WIDTH 0x827E
+#define GL_MIPMAP 0x8293
+#define GL_NAME_LENGTH 0x92F9
+#define GL_NUM_ACTIVE_VARIABLES 0x9304
+#define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9
+#define GL_OFFSET 0x92FC
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
+#define GL_PROGRAM 0x82E2
+#define GL_PROGRAM_INPUT 0x92E3
+#define GL_PROGRAM_OUTPUT 0x92E4
+#define GL_PROGRAM_PIPELINE 0x82E4
+#define GL_QUERY 0x82E3
+#define GL_READ_PIXELS 0x828C
+#define GL_READ_PIXELS_FORMAT 0x828D
+#define GL_READ_PIXELS_TYPE 0x828E
+#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B
+#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A
+#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309
+#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307
+#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308
+#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306
+#define GL_SAMPLER 0x82E6
+#define GL_SHADER 0x82E1
+#define GL_SHADER_IMAGE_ATOMIC 0x82A6
+#define GL_SHADER_IMAGE_LOAD 0x82A4
+#define GL_SHADER_IMAGE_STORE 0x82A5
+#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000
+#define GL_SHADER_STORAGE_BLOCK 0x92E6
+#define GL_SHADER_STORAGE_BUFFER 0x90D2
+#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3
+#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF
+#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5
+#define GL_SHADER_STORAGE_BUFFER_START 0x90D4
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC
+#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD
+#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF
+#define GL_SRGB_READ 0x8297
+#define GL_SRGB_WRITE 0x8298
+#define GL_STENCIL_COMPONENTS 0x8285
+#define GL_STENCIL_RENDERABLE 0x8288
+#define GL_TESS_CONTROL_SUBROUTINE 0x92E9
+#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF
+#define GL_TESS_CONTROL_TEXTURE 0x829C
+#define GL_TESS_EVALUATION_SUBROUTINE 0x92EA
+#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0
+#define GL_TESS_EVALUATION_TEXTURE 0x829D
+#define GL_TEXTURE_BUFFER_OFFSET 0x919D
+#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F
+#define GL_TEXTURE_BUFFER_SIZE 0x919E
+#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2
+#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3
+#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1
+#define GL_TEXTURE_GATHER 0x82A2
+#define GL_TEXTURE_GATHER_SHADOW 0x82A3
+#define GL_TEXTURE_IMAGE_FORMAT 0x828F
+#define GL_TEXTURE_IMAGE_TYPE 0x8290
+#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF
+#define GL_TEXTURE_SHADOW 0x82A1
+#define GL_TEXTURE_VIEW 0x82B5
+#define GL_TEXTURE_VIEW_MIN_LAYER 0x82DD
+#define GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB
+#define GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE
+#define GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC
+#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C
+#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D
+#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4
+#define GL_TYPE 0x92FA
+#define GL_UNIFORM 0x92E1
+#define GL_UNIFORM_BLOCK 0x92E2
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
+#define GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E
+#define GL_VERTEX_ATTRIB_BINDING 0x82D4
+#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5
+#define GL_VERTEX_BINDING_BUFFER 0x8F4F
+#define GL_VERTEX_BINDING_DIVISOR 0x82D6
+#define GL_VERTEX_BINDING_OFFSET 0x82D7
+#define GL_VERTEX_BINDING_STRIDE 0x82D8
+#define GL_VERTEX_SUBROUTINE 0x92E8
+#define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE
+#define GL_VERTEX_TEXTURE 0x829B
+#define GL_VIEW_CLASS_128_BITS 0x82C4
+#define GL_VIEW_CLASS_16_BITS 0x82CA
+#define GL_VIEW_CLASS_24_BITS 0x82C9
+#define GL_VIEW_CLASS_32_BITS 0x82C8
+#define GL_VIEW_CLASS_48_BITS 0x82C7
+#define GL_VIEW_CLASS_64_BITS 0x82C6
+#define GL_VIEW_CLASS_8_BITS 0x82CB
+#define GL_VIEW_CLASS_96_BITS 0x82C5
+#define GL_VIEW_CLASS_BPTC_FLOAT 0x82D3
+#define GL_VIEW_CLASS_BPTC_UNORM 0x82D2
+#define GL_VIEW_CLASS_RGTC1_RED 0x82D0
+#define GL_VIEW_CLASS_RGTC2_RG 0x82D1
+#define GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC
+#define GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD
+#define GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE
+#define GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF
+#define GL_VIEW_COMPATIBILITY_CLASS 0x82B6
+
+// 4.4
+#define GL_BUFFER_IMMUTABLE_STORAGE 0x821F
+#define GL_BUFFER_STORAGE_FLAGS 0x8220
+#define GL_CLEAR_TEXTURE 0x9365
+#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT 0x00004000
+#define GL_CLIENT_STORAGE_BIT 0x0200
+#define GL_DYNAMIC_STORAGE_BIT 0x0100
+#define GL_LOCATION_COMPONENT 0x934A
+#define GL_MAP_COHERENT_BIT 0x0080
+#define GL_MAP_PERSISTENT_BIT 0x0040
+#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5
+#define GL_MIRROR_CLAMP_TO_EDGE 0x8743
+#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221
+#define GL_QUERY_BUFFER 0x9192
+#define GL_QUERY_BUFFER_BARRIER_BIT 0x00008000
+#define GL_QUERY_BUFFER_BINDING 0x9193
+#define GL_QUERY_RESULT_NO_WAIT 0x9194
+#define GL_TEXTURE_BUFFER_BINDING 0x8C2A
+#define GL_TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B
+#define GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C
+
+// 4.5
+#define GL_CLIP_DEPTH_MODE 0x935D
+#define GL_CLIP_ORIGIN 0x935C
+#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004
+#define GL_CONTEXT_LOST 0x0507
+#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB
+#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC
+#define GL_GUILTY_CONTEXT_RESET 0x8253
+#define GL_INNOCENT_CONTEXT_RESET 0x8254
+#define GL_LOSE_CONTEXT_ON_RESET 0x8252
+#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 0x82FA
+#define GL_MAX_CULL_DISTANCES 0x82F9
+#define GL_NEGATIVE_ONE_TO_ONE 0x935E
+#define GL_NO_RESET_NOTIFICATION 0x8261
+#define GL_QUERY_BY_REGION_NO_WAIT_INVERTED 0x8E1A
+#define GL_QUERY_BY_REGION_WAIT_INVERTED 0x8E19
+#define GL_QUERY_NO_WAIT_INVERTED 0x8E18
+#define GL_QUERY_TARGET 0x82EA
+#define GL_QUERY_WAIT_INVERTED 0x8E17
+#define GL_RESET_NOTIFICATION_STRATEGY 0x8256
+#define GL_TEXTURE_TARGET 0x1006
+#define GL_UNKNOWN_CONTEXT_RESET 0x8255
+#define GL_ZERO_TO_ONE 0x935F
+#define GL_COMPLETION_STATUS 0x91B1
+
+#endif // LIBANGLE_RENDERER_GL_FUNCTIONSGLENUMS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/load_functions_table.h b/gfx/angle/checkout/src/libANGLE/renderer/load_functions_table.h
new file mode 100644
index 0000000000..27eaebc8e7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/load_functions_table.h
@@ -0,0 +1,20 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// load_functions_table:
+// Contains load functions table depending on internal format and ANGLE format.
+//
+
+#ifndef LIBANGLE_RENDERER_LOADFUNCTIONSTABLE_H_
+#define LIBANGLE_RENDERER_LOADFUNCTIONSTABLE_H_
+
+#include "libANGLE/renderer/Format.h"
+
+namespace angle
+{
+rx::LoadFunctionMap GetLoadFunctionsMap(GLenum internalFormat, FormatID angleFormat);
+} // namespace angle
+
+#endif // LIBANGLE_RENDERER_LOADFUNCTIONSTABLE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/load_functions_table_autogen.cpp b/gfx/angle/checkout/src/libANGLE/renderer/load_functions_table_autogen.cpp
new file mode 100644
index 0000000000..11fe60fe0d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/load_functions_table_autogen.cpp
@@ -0,0 +1,5465 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by gen_load_functions_table.py using data from load_functions_data.json
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// load_functions_table:
+// Contains the GetLoadFunctionsMap for texture_format_util.h
+//
+
+#include "libANGLE/renderer/load_functions_table.h"
+
+#include "image_util/copyimage.h"
+#include "image_util/generatemip.h"
+#include "image_util/loadimage.h"
+
+using namespace rx;
+
+namespace angle
+{
+
+namespace
+{
+
+// ES3 image loading functions vary based on:
+// - the GL internal format (supplied to glTex*Image*D)
+// - the GL data type given (supplied to glTex*Image*D)
+// - the target DXGI_FORMAT that the image will be loaded into (which is chosen based on the D3D
+// device's capabilities)
+// This map type determines which loading function to use, based on these three parameters.
+// Source formats and types are taken from Tables 3.2 and 3.3 of the ES 3 spec.
+void UnimplementedLoadFunction(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ UNIMPLEMENTED();
+}
+
+void UnreachableLoadFunction(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch)
+{
+ UNREACHABLE();
+}
+
+LoadImageFunctionInfo A1RGB5_ANGLEX_to_A1R5G5B5_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true);
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA_to_R16G16B16A16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA_to_R32G32B32A32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadA32FToRGBA32F, true);
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA16F_EXT_to_R16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 1>, false);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA16F_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadA16FToRGBA16F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA32F_EXT_to_R32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLfloat, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA32F_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadA32FToRGBA32F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA8_EXT_to_A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA8_EXT_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadA8ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ALPHA8_EXT_to_R8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo BGR10_A2_ANGLEX_to_B10G10R10A2_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo BGR565_ANGLEX_to_B5G6R5_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadRGB8ToBGR565, true);
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return LoadImageFunctionInfo(LoadRGB565ToBGR565, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo BGR5_A1_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true);
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo BGRA4_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ return LoadImageFunctionInfo(LoadRGBA4ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo BGRA8_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo BGRA8_SRGB_ANGLEX_to_B8G8R8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo BGRA_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo BGRX8_ANGLEX_to_B8G8R8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo BGRX8_ANGLEX_to_B8G8R8X8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_R11_EAC_to_EAC_R11_UNORM_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_R11_EAC_to_R16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACR11ToR16F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_R11_EAC_to_R16_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACR11ToR16, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RED_GREEN_RGTC2_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RED_RGTC1_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RG11_EAC_to_EAC_R11G11_UNORM_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RG11_EAC_to_R16G16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACRG11ToRG16F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RG11_EAC_to_R16G16_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACRG11ToRG16, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB8_ETC2_to_ETC2_R8G8B8_UNORM_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB8_ETC2_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2RGB8ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2RGB8ToBC1, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_ETC2_R8G8B8A1_UNORM_BLOCK(
+ GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2RGB8A1ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo
+COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2RGB8A1ToBC1, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA8_ETC2_EAC_to_ETC2_R8G8B8A8_UNORM_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA8_ETC2_EAC_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2RGBA8ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_10x10_KHR_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<10, 10>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_10x10_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<10, 10, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_10x5_KHR_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<10, 5>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_10x5_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<10, 5, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_10x6_KHR_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<10, 6>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_10x6_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<10, 6, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_10x8_KHR_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<10, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_10x8_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<10, 8, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_12x10_KHR_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<12, 10>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_12x10_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<12, 10, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_12x12_KHR_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<12, 12>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_12x12_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<12, 12, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_3x3x3_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<3, 3, 3, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_4x3x3_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 3, 3, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_4x4_KHR_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<4, 4>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_4x4_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_4x4x3_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 3, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_4x4x4_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 4, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_5x4_KHR_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<5, 4>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_5x4_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<5, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_5x4x4_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<5, 4, 4, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_5x5_KHR_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<5, 5>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_5x5_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<5, 5, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_5x5x4_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<5, 5, 4, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_5x5x5_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<5, 5, 5, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_6x5_KHR_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<6, 5>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_6x5_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<6, 5, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_6x5x5_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<6, 5, 5, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_6x6_KHR_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<6, 6>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_6x6_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<6, 6, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_6x6x5_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<6, 6, 5, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_6x6x6_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<6, 6, 6, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_8x5_KHR_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<8, 5>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_8x5_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<8, 5, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_8x6_KHR_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<8, 6>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_8x6_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<8, 6, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_8x8_KHR_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<8, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_ASTC_8x8_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<8, 8, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_BPTC_UNORM_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_S3TC_DXT1_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_S3TC_DXT3_ANGLE_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGBA_S3TC_DXT5_ANGLE_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_RGB_S3TC_DXT1_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SIGNED_R11_EAC_to_EAC_R11_SNORM_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SIGNED_R11_EAC_to_R16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACR11SToR16F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SIGNED_R11_EAC_to_R16_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACR11SToR16, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SIGNED_RED_RGTC1_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SIGNED_RG11_EAC_to_EAC_R11G11_SNORM_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SIGNED_RG11_EAC_to_R16G16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACRG11SToRG16F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SIGNED_RG11_EAC_to_R16G16_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadEACRG11SToRG16, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<10, 10>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<10, 10, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<10, 5>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<10, 5, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<10, 6>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<10, 6, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<10, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<10, 8, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<12, 10>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<12, 10, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<12, 12>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<12, 12, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<3, 3, 3, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 3, 3, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<4, 4>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 3, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 4, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<5, 4>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<5, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<5, 4, 4, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<5, 5>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<5, 5, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<5, 5, 4, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<5, 5, 5, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<6, 5>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<6, 5, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<6, 5, 5, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<6, 6>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<6, 6, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<6, 6, 5, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<6, 6, 6, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<8, 5>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<8, 5, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<8, 6>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<8, 6, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadASTCToRGBA8<8, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<8, 8, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ETC2_EAC_to_ETC2_R8G8B8A8_SRGB_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ALPHA8_ETC2_EAC_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2SRGBA8ToSRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ETC2_to_ETC2_R8G8B8_SRGB_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_ETC2_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2SRGB8ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_SRGB_BLOCK(
+ GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2SRGB8ToBC1, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_ETC2_R8G8B8A1_SRGB_BLOCK(
+ GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2SRGB8A1ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo
+COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_SRGB_BLOCK(
+ GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC2SRGB8A1ToBC1, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 16>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo COMPRESSED_SRGB_S3TC_DXT1_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH24_STENCIL8_to_D24_UNORM_S8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_24_8:
+ return LoadImageFunctionInfo(LoadR32ToR24G8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH24_STENCIL8_to_D32_FLOAT_S8X24_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_24_8:
+ return LoadImageFunctionInfo(LoadD24S8ToD32FS8X24, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH32F_STENCIL8_to_D24_UNORM_S8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ return LoadImageFunctionInfo(LoadD32FS8X24ToD24S8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH32F_STENCIL8_to_D32_FLOAT_S8X24_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ return LoadImageFunctionInfo(LoadD32FS8X24ToD32FS8X24, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT16_to_D16_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadR32ToR16, true);
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT16_to_D32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadUNorm32To32F, true);
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadUNorm16To32F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT24_to_D24_UNORM_S8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadR32ToR24G8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT24_to_D24_UNORM_X8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadR32ToR24G8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT24_to_D32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadD24S8ToD32F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT24_to_D32_FLOAT_S8X24_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadD32ToD32FX32, true);
+ case GL_UNSIGNED_INT_24_8:
+ return LoadImageFunctionInfo(LoadD24S8ToD32FS8X24, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT32F_to_D32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadD32FToD32F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT32_OES_to_D32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadD32ToD32F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo DEPTH_COMPONENT32_OES_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadR32ToR24G8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ETC1_RGB8_LOSSY_DECODE_ANGLE_to_BC1_RGB_UNORM_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC1RGB8ToBC1, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ETC1_RGB8_OES_to_ETC1_R8G8B8_UNORM_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ETC1_RGB8_OES_to_ETC2_R8G8B8_UNORM_BLOCK(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadCompressedToNative<4, 4, 1, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo ETC1_RGB8_OES_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadETC1RGB8ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo G8_B8R8_2PLANE_420_UNORM_ANGLE_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadYuvToNative, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo G8_B8_R8_3PLANE_420_UNORM_ANGLE_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnimplementedLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_to_R16G16B16A16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_to_R32G32B32A32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadL32FToRGBA32F, true);
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE16F_EXT_to_R16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 1>, false);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE16F_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadL16FToRGBA16F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE32F_EXT_to_R32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLfloat, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE32F_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadL32FToRGBA32F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE8_ALPHA8_EXT_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadLA8ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE8_ALPHA8_EXT_to_R8G8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE8_EXT_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadL8ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE8_EXT_to_R8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA_to_R16G16B16A16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA_to_R32G32B32A32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadLA32FToRGBA32F, true);
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA16F_EXT_to_R16G16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 2>, false);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA16F_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadLA16FToRGBA16F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA32F_EXT_to_R32G32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLfloat, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo LUMINANCE_ALPHA32F_EXT_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadLA32FToRGBA32F, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo PALETTE4_R5_G6_B5_OES_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadPalettedToRGBA8<4, 5, 6, 0>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo PALETTE4_RGB5_A1_OES_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadPalettedToRGBA8<4, 5, 5, 1>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo PALETTE4_RGB8_OES_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadPalettedToRGBA8<4, 8, 8, 0>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo PALETTE4_RGBA4_OES_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadPalettedToRGBA8<4, 4, 4, 4>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo PALETTE4_RGBA8_OES_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadPalettedToRGBA8<4, 8, 8, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo PALETTE8_R5_G6_B5_OES_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadPalettedToRGBA8<8, 5, 6, 0>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo PALETTE8_RGB5_A1_OES_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadPalettedToRGBA8<8, 5, 5, 1>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo PALETTE8_RGB8_OES_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadPalettedToRGBA8<8, 8, 8, 0>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo PALETTE8_RGBA4_OES_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadPalettedToRGBA8<8, 4, 4, 4>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo PALETTE8_RGBA8_OES_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadPalettedToRGBA8<8, 8, 8, 8>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R11F_G11F_B10F_to_R11G11B10_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadRGB32FToRG11B10F, true);
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadRGB16FToRG11B10F, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadRGB16FToRG11B10F, true);
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R16F_to_R16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(Load32FTo16F<1>, true);
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 1>, false);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R16I_to_R16_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLshort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R16UI_to_R16_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R16_EXT_to_R16_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R16_SNORM_EXT_to_R16_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R16_SSCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R16_USCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R32F_to_R32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLfloat, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R32I_to_R32_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_INT:
+ return LoadImageFunctionInfo(LoadToNative<GLint, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R32UI_to_R32_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R8_to_R8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R8I_to_R8_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R8UI_to_R8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R8_SNORM_to_R8_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R8_SSCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo R8_USCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG16F_to_R16G16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(Load32FTo16F<2>, true);
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 2>, false);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG16I_to_R16G16_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLshort, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG16UI_to_R16G16_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG16_EXT_to_R16G16_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG16_SNORM_EXT_to_R16G16_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG16_SSCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG16_USCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG32F_to_R32G32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLfloat, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG32I_to_R32G32_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_INT:
+ return LoadImageFunctionInfo(LoadToNative<GLint, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG32UI_to_R32G32_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG8_to_R8G8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG8I_to_R8G8_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG8UI_to_R8G8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG8_SNORM_to_R8G8_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG8_SSCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RG8_USCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB10_A2_to_R10G10B10A2_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB10_A2UI_to_R10G10B10A2_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB10_A2_SINT_ANGLEX_to_R10G10B10A2_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadRGB10A2ToRGBA8, true);
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB10_A2_SNORM_ANGLEX_to_R10G10B10A2_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadRGB10A2ToRGBA8, true);
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB10_A2_SSCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB10_A2_USCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB10_UNORM_ANGLEX_to_R10G10B10A2_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return LoadImageFunctionInfo(LoadRGB10A2ToRGB10X2, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB10_UNORM_ANGLEX_to_R10G10B10X2_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return LoadImageFunctionInfo(LoadRGB10A2ToRGB10X2, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16F_to_R16G16B16A16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadRGB32FToRGBA16F, true);
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLhalf, gl::Float16One>, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLhalf, gl::Float16One>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16F_to_R16G16B16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadRGB32FToRGB16F, true);
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 3>, false);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 3>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16I_to_R16G16B16A16_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLshort, 0x0001>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16I_to_R16G16B16_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLshort, 3>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16UI_to_R16G16B16A16_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLushort, 0x0001>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16UI_to_R16G16B16_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 3>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16_EXT_to_R16G16B16A16_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLushort, 0xFFFF>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16_EXT_to_R16G16B16_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 3>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16_SNORM_EXT_to_R16G16B16A16_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLushort, 0x7FFF>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16_SNORM_EXT_to_R16G16B16_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 3>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16_SSCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB16_USCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB32F_to_R32G32B32A32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLfloat, gl::Float32One>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB32F_to_R32G32B32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLfloat, 3>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB32I_to_R32G32B32A32_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_INT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLint, 0x00000001>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB32I_to_R32G32B32_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_INT:
+ return LoadImageFunctionInfo(LoadToNative<GLint, 3>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB32UI_to_R32G32B32A32_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLuint, 0x00000001>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB32UI_to_R32G32B32_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 3>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB565_to_B5G6R5_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadRGB8ToBGR565, true);
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB565_to_R5G6B5_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadRGB8ToBGR565, true);
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB565_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLubyte, 0xFF>, true);
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return LoadImageFunctionInfo(LoadR5G6B5ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB5_A1_to_A1R5G5B5_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadRGBA8ToBGR5A1, true);
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return LoadImageFunctionInfo(LoadRGB10A2ToBGR5A1, true);
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ return LoadImageFunctionInfo(LoadRGB5A1ToA1RGB5, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB5_A1_to_B5G5R5A1_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadRGBA8ToBGR5A1, true);
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return LoadImageFunctionInfo(LoadRGB10A2ToBGR5A1, true);
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ return LoadImageFunctionInfo(LoadRGB5A1ToA1RGB5, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB5_A1_to_R5G5B5A1_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadRGBA8ToRGB5A1, true);
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return LoadImageFunctionInfo(LoadRGB10A2ToRGB5A1, true);
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB5_A1_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return LoadImageFunctionInfo(LoadRGB10A2ToRGBA8, true);
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ return LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB8_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLubyte, 0xFF>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB8_to_R8G8B8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 3>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB8I_to_R8G8B8A8_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLbyte, 0x01>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB8I_to_R8G8B8_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 3>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB8UI_to_R8G8B8A8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLubyte, 0x01>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB8UI_to_R8G8B8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 3>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB8_SNORM_to_R8G8B8A8_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLbyte, 0x7F>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB8_SNORM_to_R8G8B8_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 3>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB8_SSCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB8_USCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGB9_E5_to_R9G9B9E5_SHAREDEXP(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadRGB32FToRGB9E5, true);
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadRGB16FToRGB9E5, true);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadRGB16FToRGB9E5, true);
+ case GL_UNSIGNED_INT_5_9_9_9_REV:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA16F_to_R16G16B16A16_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(Load32FTo16F<4>, true);
+ case GL_HALF_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 4>, false);
+ case GL_HALF_FLOAT_OES:
+ return LoadImageFunctionInfo(LoadToNative<GLhalf, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA16I_to_R16G16B16A16_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLshort, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA16UI_to_R16G16B16A16_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA16_EXT_to_R16G16B16A16_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA16_SNORM_EXT_to_R16G16B16A16_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_SHORT:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA16_SSCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA16_USCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA32F_to_R32G32B32A32_FLOAT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_FLOAT:
+ return LoadImageFunctionInfo(LoadToNative<GLfloat, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA32I_to_R32G32B32A32_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_INT:
+ return LoadImageFunctionInfo(LoadToNative<GLint, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA32UI_to_R32G32B32A32_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_INT:
+ return LoadImageFunctionInfo(LoadToNative<GLuint, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA4_to_B4G4R4A4_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadRGBA8ToBGRA4, true);
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ return LoadImageFunctionInfo(LoadRGBA4ToARGB4, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA4_to_R4G4B4A4_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadRGBA8ToRGBA4, true);
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ return LoadImageFunctionInfo(LoadToNative<GLushort, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA4_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ return LoadImageFunctionInfo(LoadRGBA4ToRGBA8, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA8_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA8I_to_R8G8B8A8_SINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA8UI_to_R8G8B8A8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA8_SNORM_to_R8G8B8A8_SNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA8_SSCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBA8_USCALED_ANGLEX_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBX8_ANGLE_to_R8G8B8A8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLubyte, 0xFF>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo RGBX8_ANGLE_to_R8G8B8X8_UNORM(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLubyte, 0xFF>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo SR8_EXT_to_R8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo SRG8_EXT_to_R8G8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 2>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo SRGB8_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative3To4<GLubyte, 0xFF>, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo SRGB8_to_R8G8B8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLbyte, 3>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo SRGB8_ALPHA8_to_R8G8B8A8_UNORM_SRGB(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 4>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo STENCIL_INDEX8_to_S8_UINT(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(LoadToNative<GLubyte, 1>, false);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+LoadImageFunctionInfo STENCIL_INDEX8_to_default(GLenum type)
+{
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ return LoadImageFunctionInfo(UnimplementedLoadFunction, true);
+ default:
+ UNREACHABLE();
+ return LoadImageFunctionInfo(UnreachableLoadFunction, true);
+ }
+}
+
+} // namespace
+
+LoadFunctionMap GetLoadFunctionsMap(GLenum internalFormat, FormatID angleFormat)
+{
+ // clang-format off
+ switch (internalFormat)
+ {
+ case GL_A1RGB5_ANGLEX:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::A1R5G5B5_UNORM:
+ return A1RGB5_ANGLEX_to_A1R5G5B5_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_ALPHA:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16B16A16_FLOAT:
+ return ALPHA_to_R16G16B16A16_FLOAT;
+ case FormatID::R32G32B32A32_FLOAT:
+ return ALPHA_to_R32G32B32A32_FLOAT;
+ default:
+ return ALPHA_to_default;
+ }
+ }
+ case GL_ALPHA16F_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16_FLOAT:
+ return ALPHA16F_EXT_to_R16_FLOAT;
+ default:
+ return ALPHA16F_EXT_to_default;
+ }
+ }
+ case GL_ALPHA32F_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R32_FLOAT:
+ return ALPHA32F_EXT_to_R32_FLOAT;
+ default:
+ return ALPHA32F_EXT_to_default;
+ }
+ }
+ case GL_ALPHA8_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::A8_UNORM:
+ return ALPHA8_EXT_to_A8_UNORM;
+ case FormatID::R8G8B8A8_UNORM:
+ return ALPHA8_EXT_to_R8G8B8A8_UNORM;
+ case FormatID::R8_UNORM:
+ return ALPHA8_EXT_to_R8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BGR10_A2_ANGLEX:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::B10G10R10A2_UNORM:
+ return BGR10_A2_ANGLEX_to_B10G10R10A2_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BGR565_ANGLEX:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::B5G6R5_UNORM:
+ return BGR565_ANGLEX_to_B5G6R5_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BGR5_A1_ANGLEX:
+ return BGR5_A1_ANGLEX_to_default;
+ case GL_BGRA4_ANGLEX:
+ return BGRA4_ANGLEX_to_default;
+ case GL_BGRA8_EXT:
+ return BGRA8_EXT_to_default;
+ case GL_BGRA8_SRGB_ANGLEX:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::B8G8R8A8_UNORM_SRGB:
+ return BGRA8_SRGB_ANGLEX_to_B8G8R8A8_UNORM_SRGB;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_BGRA_EXT:
+ return BGRA_EXT_to_default;
+ case GL_BGRX8_ANGLEX:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::B8G8R8A8_UNORM:
+ return BGRX8_ANGLEX_to_B8G8R8A8_UNORM;
+ case FormatID::B8G8R8X8_UNORM:
+ return BGRX8_ANGLEX_to_B8G8R8X8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_COMPRESSED_R11_EAC:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::EAC_R11_UNORM_BLOCK:
+ return COMPRESSED_R11_EAC_to_EAC_R11_UNORM_BLOCK;
+ case FormatID::R16_FLOAT:
+ return COMPRESSED_R11_EAC_to_R16_FLOAT;
+ case FormatID::R16_UNORM:
+ return COMPRESSED_R11_EAC_to_R16_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
+ return COMPRESSED_RED_GREEN_RGTC2_EXT_to_default;
+ case GL_COMPRESSED_RED_RGTC1_EXT:
+ return COMPRESSED_RED_RGTC1_EXT_to_default;
+ case GL_COMPRESSED_RG11_EAC:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::EAC_R11G11_UNORM_BLOCK:
+ return COMPRESSED_RG11_EAC_to_EAC_R11G11_UNORM_BLOCK;
+ case FormatID::R16G16_FLOAT:
+ return COMPRESSED_RG11_EAC_to_R16G16_FLOAT;
+ case FormatID::R16G16_UNORM:
+ return COMPRESSED_RG11_EAC_to_R16G16_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_COMPRESSED_RGB8_ETC2:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::ETC2_R8G8B8_UNORM_BLOCK:
+ return COMPRESSED_RGB8_ETC2_to_ETC2_R8G8B8_UNORM_BLOCK;
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGB8_ETC2_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::BC1_RGB_UNORM_BLOCK:
+ return COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_BLOCK;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::ETC2_R8G8B8A1_UNORM_BLOCK:
+ return COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_ETC2_R8G8B8A1_UNORM_BLOCK;
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::BC1_RGBA_UNORM_BLOCK:
+ return COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_BLOCK;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_COMPRESSED_RGBA8_ETC2_EAC:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::ETC2_R8G8B8A8_UNORM_BLOCK:
+ return COMPRESSED_RGBA8_ETC2_EAC_to_ETC2_R8G8B8A8_UNORM_BLOCK;
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA8_ETC2_EAC_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA_ASTC_10x10_KHR_to_R8G8B8A8_UNORM;
+ default:
+ return COMPRESSED_RGBA_ASTC_10x10_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA_ASTC_10x5_KHR_to_R8G8B8A8_UNORM;
+ default:
+ return COMPRESSED_RGBA_ASTC_10x5_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA_ASTC_10x6_KHR_to_R8G8B8A8_UNORM;
+ default:
+ return COMPRESSED_RGBA_ASTC_10x6_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA_ASTC_10x8_KHR_to_R8G8B8A8_UNORM;
+ default:
+ return COMPRESSED_RGBA_ASTC_10x8_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA_ASTC_12x10_KHR_to_R8G8B8A8_UNORM;
+ default:
+ return COMPRESSED_RGBA_ASTC_12x10_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA_ASTC_12x12_KHR_to_R8G8B8A8_UNORM;
+ default:
+ return COMPRESSED_RGBA_ASTC_12x12_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_RGBA_ASTC_3x3x3_OES:
+ return COMPRESSED_RGBA_ASTC_3x3x3_OES_to_default;
+ case GL_COMPRESSED_RGBA_ASTC_4x3x3_OES:
+ return COMPRESSED_RGBA_ASTC_4x3x3_OES_to_default;
+ case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA_ASTC_4x4_KHR_to_R8G8B8A8_UNORM;
+ default:
+ return COMPRESSED_RGBA_ASTC_4x4_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_RGBA_ASTC_4x4x3_OES:
+ return COMPRESSED_RGBA_ASTC_4x4x3_OES_to_default;
+ case GL_COMPRESSED_RGBA_ASTC_4x4x4_OES:
+ return COMPRESSED_RGBA_ASTC_4x4x4_OES_to_default;
+ case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA_ASTC_5x4_KHR_to_R8G8B8A8_UNORM;
+ default:
+ return COMPRESSED_RGBA_ASTC_5x4_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_RGBA_ASTC_5x4x4_OES:
+ return COMPRESSED_RGBA_ASTC_5x4x4_OES_to_default;
+ case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA_ASTC_5x5_KHR_to_R8G8B8A8_UNORM;
+ default:
+ return COMPRESSED_RGBA_ASTC_5x5_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_RGBA_ASTC_5x5x4_OES:
+ return COMPRESSED_RGBA_ASTC_5x5x4_OES_to_default;
+ case GL_COMPRESSED_RGBA_ASTC_5x5x5_OES:
+ return COMPRESSED_RGBA_ASTC_5x5x5_OES_to_default;
+ case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA_ASTC_6x5_KHR_to_R8G8B8A8_UNORM;
+ default:
+ return COMPRESSED_RGBA_ASTC_6x5_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_RGBA_ASTC_6x5x5_OES:
+ return COMPRESSED_RGBA_ASTC_6x5x5_OES_to_default;
+ case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA_ASTC_6x6_KHR_to_R8G8B8A8_UNORM;
+ default:
+ return COMPRESSED_RGBA_ASTC_6x6_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_RGBA_ASTC_6x6x5_OES:
+ return COMPRESSED_RGBA_ASTC_6x6x5_OES_to_default;
+ case GL_COMPRESSED_RGBA_ASTC_6x6x6_OES:
+ return COMPRESSED_RGBA_ASTC_6x6x6_OES_to_default;
+ case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA_ASTC_8x5_KHR_to_R8G8B8A8_UNORM;
+ default:
+ return COMPRESSED_RGBA_ASTC_8x5_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA_ASTC_8x6_KHR_to_R8G8B8A8_UNORM;
+ default:
+ return COMPRESSED_RGBA_ASTC_8x6_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return COMPRESSED_RGBA_ASTC_8x8_KHR_to_R8G8B8A8_UNORM;
+ default:
+ return COMPRESSED_RGBA_ASTC_8x8_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
+ return COMPRESSED_RGBA_BPTC_UNORM_EXT_to_default;
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return COMPRESSED_RGBA_S3TC_DXT1_EXT_to_default;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ return COMPRESSED_RGBA_S3TC_DXT3_ANGLE_to_default;
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ return COMPRESSED_RGBA_S3TC_DXT5_ANGLE_to_default;
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
+ return COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT_to_default;
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
+ return COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT_to_default;
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ return COMPRESSED_RGB_S3TC_DXT1_EXT_to_default;
+ case GL_COMPRESSED_SIGNED_R11_EAC:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::EAC_R11_SNORM_BLOCK:
+ return COMPRESSED_SIGNED_R11_EAC_to_EAC_R11_SNORM_BLOCK;
+ case FormatID::R16_FLOAT:
+ return COMPRESSED_SIGNED_R11_EAC_to_R16_FLOAT;
+ case FormatID::R16_SNORM:
+ return COMPRESSED_SIGNED_R11_EAC_to_R16_SNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
+ return COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT_to_default;
+ case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
+ return COMPRESSED_SIGNED_RED_RGTC1_EXT_to_default;
+ case GL_COMPRESSED_SIGNED_RG11_EAC:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::EAC_R11G11_SNORM_BLOCK:
+ return COMPRESSED_SIGNED_RG11_EAC_to_EAC_R11G11_SNORM_BLOCK;
+ case FormatID::R16G16_FLOAT:
+ return COMPRESSED_SIGNED_RG11_EAC_to_R16G16_FLOAT;
+ case FormatID::R16G16_SNORM:
+ return COMPRESSED_SIGNED_RG11_EAC_to_R16G16_SNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES_to_default;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES_to_default;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES_to_default;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES_to_default;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES_to_default;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES_to_default;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES_to_default;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES_to_default;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES_to_default;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES_to_default;
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ return COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR_to_default;
+ }
+ }
+ case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::ETC2_R8G8B8A8_SRGB_BLOCK:
+ return COMPRESSED_SRGB8_ALPHA8_ETC2_EAC_to_ETC2_R8G8B8A8_SRGB_BLOCK;
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ALPHA8_ETC2_EAC_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_COMPRESSED_SRGB8_ETC2:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::ETC2_R8G8B8_SRGB_BLOCK:
+ return COMPRESSED_SRGB8_ETC2_to_ETC2_R8G8B8_SRGB_BLOCK;
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_ETC2_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::BC1_RGB_UNORM_SRGB_BLOCK:
+ return COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGB_UNORM_SRGB_BLOCK;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::ETC2_R8G8B8A1_SRGB_BLOCK:
+ return COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_ETC2_R8G8B8A1_SRGB_BLOCK;
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::BC1_RGBA_UNORM_SRGB_BLOCK:
+ return COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE_to_BC1_RGBA_UNORM_SRGB_BLOCK;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
+ return COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT_to_default;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ return COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT_to_default;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ return COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT_to_default;
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ return COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT_to_default;
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ return COMPRESSED_SRGB_S3TC_DXT1_EXT_to_default;
+ case GL_DEPTH24_STENCIL8:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::D24_UNORM_S8_UINT:
+ return DEPTH24_STENCIL8_to_D24_UNORM_S8_UINT;
+ case FormatID::D32_FLOAT_S8X24_UINT:
+ return DEPTH24_STENCIL8_to_D32_FLOAT_S8X24_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_DEPTH32F_STENCIL8:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::D24_UNORM_S8_UINT:
+ return DEPTH32F_STENCIL8_to_D24_UNORM_S8_UINT;
+ case FormatID::D32_FLOAT_S8X24_UINT:
+ return DEPTH32F_STENCIL8_to_D32_FLOAT_S8X24_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_DEPTH_COMPONENT16:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::D16_UNORM:
+ return DEPTH_COMPONENT16_to_D16_UNORM;
+ case FormatID::D32_FLOAT:
+ return DEPTH_COMPONENT16_to_D32_FLOAT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_DEPTH_COMPONENT24:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::D24_UNORM_S8_UINT:
+ return DEPTH_COMPONENT24_to_D24_UNORM_S8_UINT;
+ case FormatID::D24_UNORM_X8_UINT:
+ return DEPTH_COMPONENT24_to_D24_UNORM_X8_UINT;
+ case FormatID::D32_FLOAT:
+ return DEPTH_COMPONENT24_to_D32_FLOAT;
+ case FormatID::D32_FLOAT_S8X24_UINT:
+ return DEPTH_COMPONENT24_to_D32_FLOAT_S8X24_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_DEPTH_COMPONENT32F:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::D32_FLOAT:
+ return DEPTH_COMPONENT32F_to_D32_FLOAT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_DEPTH_COMPONENT32_OES:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::D32_FLOAT:
+ return DEPTH_COMPONENT32_OES_to_D32_FLOAT;
+ default:
+ return DEPTH_COMPONENT32_OES_to_default;
+ }
+ }
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::BC1_RGB_UNORM_BLOCK:
+ return ETC1_RGB8_LOSSY_DECODE_ANGLE_to_BC1_RGB_UNORM_BLOCK;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_ETC1_RGB8_OES:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::ETC1_R8G8B8_UNORM_BLOCK:
+ return ETC1_RGB8_OES_to_ETC1_R8G8B8_UNORM_BLOCK;
+ case FormatID::ETC2_R8G8B8_UNORM_BLOCK:
+ return ETC1_RGB8_OES_to_ETC2_R8G8B8_UNORM_BLOCK;
+ case FormatID::R8G8B8A8_UNORM:
+ return ETC1_RGB8_OES_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE:
+ return G8_B8R8_2PLANE_420_UNORM_ANGLE_to_default;
+ case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE:
+ return G8_B8_R8_3PLANE_420_UNORM_ANGLE_to_default;
+ case GL_LUMINANCE:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16B16A16_FLOAT:
+ return LUMINANCE_to_R16G16B16A16_FLOAT;
+ case FormatID::R32G32B32A32_FLOAT:
+ return LUMINANCE_to_R32G32B32A32_FLOAT;
+ default:
+ return LUMINANCE_to_default;
+ }
+ }
+ case GL_LUMINANCE16F_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16_FLOAT:
+ return LUMINANCE16F_EXT_to_R16_FLOAT;
+ default:
+ return LUMINANCE16F_EXT_to_default;
+ }
+ }
+ case GL_LUMINANCE32F_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R32_FLOAT:
+ return LUMINANCE32F_EXT_to_R32_FLOAT;
+ default:
+ return LUMINANCE32F_EXT_to_default;
+ }
+ }
+ case GL_LUMINANCE8_ALPHA8_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return LUMINANCE8_ALPHA8_EXT_to_R8G8B8A8_UNORM;
+ case FormatID::R8G8_UNORM:
+ return LUMINANCE8_ALPHA8_EXT_to_R8G8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_LUMINANCE8_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return LUMINANCE8_EXT_to_R8G8B8A8_UNORM;
+ case FormatID::R8_UNORM:
+ return LUMINANCE8_EXT_to_R8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_LUMINANCE_ALPHA:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16B16A16_FLOAT:
+ return LUMINANCE_ALPHA_to_R16G16B16A16_FLOAT;
+ case FormatID::R32G32B32A32_FLOAT:
+ return LUMINANCE_ALPHA_to_R32G32B32A32_FLOAT;
+ default:
+ return LUMINANCE_ALPHA_to_default;
+ }
+ }
+ case GL_LUMINANCE_ALPHA16F_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16_FLOAT:
+ return LUMINANCE_ALPHA16F_EXT_to_R16G16_FLOAT;
+ default:
+ return LUMINANCE_ALPHA16F_EXT_to_default;
+ }
+ }
+ case GL_LUMINANCE_ALPHA32F_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R32G32_FLOAT:
+ return LUMINANCE_ALPHA32F_EXT_to_R32G32_FLOAT;
+ default:
+ return LUMINANCE_ALPHA32F_EXT_to_default;
+ }
+ }
+ case GL_PALETTE4_R5_G6_B5_OES:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return PALETTE4_R5_G6_B5_OES_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_PALETTE4_RGB5_A1_OES:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return PALETTE4_RGB5_A1_OES_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_PALETTE4_RGB8_OES:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return PALETTE4_RGB8_OES_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_PALETTE4_RGBA4_OES:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return PALETTE4_RGBA4_OES_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_PALETTE4_RGBA8_OES:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return PALETTE4_RGBA8_OES_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_PALETTE8_R5_G6_B5_OES:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return PALETTE8_R5_G6_B5_OES_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_PALETTE8_RGB5_A1_OES:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return PALETTE8_RGB5_A1_OES_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_PALETTE8_RGB8_OES:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return PALETTE8_RGB8_OES_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_PALETTE8_RGBA4_OES:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return PALETTE8_RGBA4_OES_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_PALETTE8_RGBA8_OES:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return PALETTE8_RGBA8_OES_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_R11F_G11F_B10F:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R11G11B10_FLOAT:
+ return R11F_G11F_B10F_to_R11G11B10_FLOAT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_R16F:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16_FLOAT:
+ return R16F_to_R16_FLOAT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_R16I:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16_SINT:
+ return R16I_to_R16_SINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_R16UI:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16_UINT:
+ return R16UI_to_R16_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_R16_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16_UNORM:
+ return R16_EXT_to_R16_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_R16_SNORM_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16_SNORM:
+ return R16_SNORM_EXT_to_R16_SNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_R16_SSCALED_ANGLEX:
+ return R16_SSCALED_ANGLEX_to_default;
+ case GL_R16_USCALED_ANGLEX:
+ return R16_USCALED_ANGLEX_to_default;
+ case GL_R32F:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R32_FLOAT:
+ return R32F_to_R32_FLOAT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_R32I:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R32_SINT:
+ return R32I_to_R32_SINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_R32UI:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R32_UINT:
+ return R32UI_to_R32_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_R8:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8_UNORM:
+ return R8_to_R8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_R8I:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8_SINT:
+ return R8I_to_R8_SINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_R8UI:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8_UINT:
+ return R8UI_to_R8_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_R8_SNORM:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8_SNORM:
+ return R8_SNORM_to_R8_SNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_R8_SSCALED_ANGLEX:
+ return R8_SSCALED_ANGLEX_to_default;
+ case GL_R8_USCALED_ANGLEX:
+ return R8_USCALED_ANGLEX_to_default;
+ case GL_RG16F:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16_FLOAT:
+ return RG16F_to_R16G16_FLOAT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RG16I:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16_SINT:
+ return RG16I_to_R16G16_SINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RG16UI:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16_UINT:
+ return RG16UI_to_R16G16_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RG16_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16_UNORM:
+ return RG16_EXT_to_R16G16_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RG16_SNORM_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16_SNORM:
+ return RG16_SNORM_EXT_to_R16G16_SNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RG16_SSCALED_ANGLEX:
+ return RG16_SSCALED_ANGLEX_to_default;
+ case GL_RG16_USCALED_ANGLEX:
+ return RG16_USCALED_ANGLEX_to_default;
+ case GL_RG32F:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R32G32_FLOAT:
+ return RG32F_to_R32G32_FLOAT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RG32I:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R32G32_SINT:
+ return RG32I_to_R32G32_SINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RG32UI:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R32G32_UINT:
+ return RG32UI_to_R32G32_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RG8:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8_UNORM:
+ return RG8_to_R8G8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RG8I:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8_SINT:
+ return RG8I_to_R8G8_SINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RG8UI:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8_UINT:
+ return RG8UI_to_R8G8_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RG8_SNORM:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8_SNORM:
+ return RG8_SNORM_to_R8G8_SNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RG8_SSCALED_ANGLEX:
+ return RG8_SSCALED_ANGLEX_to_default;
+ case GL_RG8_USCALED_ANGLEX:
+ return RG8_USCALED_ANGLEX_to_default;
+ case GL_RGB:
+ return RGB_to_default;
+ case GL_RGB10_A2:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R10G10B10A2_UNORM:
+ return RGB10_A2_to_R10G10B10A2_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB10_A2UI:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R10G10B10A2_UINT:
+ return RGB10_A2UI_to_R10G10B10A2_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB10_A2_SINT_ANGLEX:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R10G10B10A2_SINT:
+ return RGB10_A2_SINT_ANGLEX_to_R10G10B10A2_SINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB10_A2_SNORM_ANGLEX:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R10G10B10A2_SNORM:
+ return RGB10_A2_SNORM_ANGLEX_to_R10G10B10A2_SNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB10_A2_SSCALED_ANGLEX:
+ return RGB10_A2_SSCALED_ANGLEX_to_default;
+ case GL_RGB10_A2_USCALED_ANGLEX:
+ return RGB10_A2_USCALED_ANGLEX_to_default;
+ case GL_RGB10_UNORM_ANGLEX:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R10G10B10A2_UNORM:
+ return RGB10_UNORM_ANGLEX_to_R10G10B10A2_UNORM;
+ case FormatID::R10G10B10X2_UNORM:
+ return RGB10_UNORM_ANGLEX_to_R10G10B10X2_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB16F:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16B16A16_FLOAT:
+ return RGB16F_to_R16G16B16A16_FLOAT;
+ case FormatID::R16G16B16_FLOAT:
+ return RGB16F_to_R16G16B16_FLOAT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB16I:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16B16A16_SINT:
+ return RGB16I_to_R16G16B16A16_SINT;
+ case FormatID::R16G16B16_SINT:
+ return RGB16I_to_R16G16B16_SINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB16UI:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16B16A16_UINT:
+ return RGB16UI_to_R16G16B16A16_UINT;
+ case FormatID::R16G16B16_UINT:
+ return RGB16UI_to_R16G16B16_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB16_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16B16A16_UNORM:
+ return RGB16_EXT_to_R16G16B16A16_UNORM;
+ case FormatID::R16G16B16_UNORM:
+ return RGB16_EXT_to_R16G16B16_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB16_SNORM_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16B16A16_SNORM:
+ return RGB16_SNORM_EXT_to_R16G16B16A16_SNORM;
+ case FormatID::R16G16B16_SNORM:
+ return RGB16_SNORM_EXT_to_R16G16B16_SNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB16_SSCALED_ANGLEX:
+ return RGB16_SSCALED_ANGLEX_to_default;
+ case GL_RGB16_USCALED_ANGLEX:
+ return RGB16_USCALED_ANGLEX_to_default;
+ case GL_RGB32F:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R32G32B32A32_FLOAT:
+ return RGB32F_to_R32G32B32A32_FLOAT;
+ case FormatID::R32G32B32_FLOAT:
+ return RGB32F_to_R32G32B32_FLOAT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB32I:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R32G32B32A32_SINT:
+ return RGB32I_to_R32G32B32A32_SINT;
+ case FormatID::R32G32B32_SINT:
+ return RGB32I_to_R32G32B32_SINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB32UI:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R32G32B32A32_UINT:
+ return RGB32UI_to_R32G32B32A32_UINT;
+ case FormatID::R32G32B32_UINT:
+ return RGB32UI_to_R32G32B32_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB565:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::B5G6R5_UNORM:
+ return RGB565_to_B5G6R5_UNORM;
+ case FormatID::R5G6B5_UNORM:
+ return RGB565_to_R5G6B5_UNORM;
+ case FormatID::R8G8B8A8_UNORM:
+ return RGB565_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB5_A1:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::A1R5G5B5_UNORM:
+ return RGB5_A1_to_A1R5G5B5_UNORM;
+ case FormatID::B5G5R5A1_UNORM:
+ return RGB5_A1_to_B5G5R5A1_UNORM;
+ case FormatID::R5G5B5A1_UNORM:
+ return RGB5_A1_to_R5G5B5A1_UNORM;
+ case FormatID::R8G8B8A8_UNORM:
+ return RGB5_A1_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB8:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return RGB8_to_R8G8B8A8_UNORM;
+ case FormatID::R8G8B8_UNORM:
+ return RGB8_to_R8G8B8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB8I:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_SINT:
+ return RGB8I_to_R8G8B8A8_SINT;
+ case FormatID::R8G8B8_SINT:
+ return RGB8I_to_R8G8B8_SINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB8UI:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UINT:
+ return RGB8UI_to_R8G8B8A8_UINT;
+ case FormatID::R8G8B8_UINT:
+ return RGB8UI_to_R8G8B8_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB8_SNORM:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_SNORM:
+ return RGB8_SNORM_to_R8G8B8A8_SNORM;
+ case FormatID::R8G8B8_SNORM:
+ return RGB8_SNORM_to_R8G8B8_SNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGB8_SSCALED_ANGLEX:
+ return RGB8_SSCALED_ANGLEX_to_default;
+ case GL_RGB8_USCALED_ANGLEX:
+ return RGB8_USCALED_ANGLEX_to_default;
+ case GL_RGB9_E5:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R9G9B9E5_SHAREDEXP:
+ return RGB9_E5_to_R9G9B9E5_SHAREDEXP;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGBA:
+ return RGBA_to_default;
+ case GL_RGBA16F:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16B16A16_FLOAT:
+ return RGBA16F_to_R16G16B16A16_FLOAT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGBA16I:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16B16A16_SINT:
+ return RGBA16I_to_R16G16B16A16_SINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGBA16UI:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16B16A16_UINT:
+ return RGBA16UI_to_R16G16B16A16_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGBA16_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16B16A16_UNORM:
+ return RGBA16_EXT_to_R16G16B16A16_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGBA16_SNORM_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R16G16B16A16_SNORM:
+ return RGBA16_SNORM_EXT_to_R16G16B16A16_SNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGBA16_SSCALED_ANGLEX:
+ return RGBA16_SSCALED_ANGLEX_to_default;
+ case GL_RGBA16_USCALED_ANGLEX:
+ return RGBA16_USCALED_ANGLEX_to_default;
+ case GL_RGBA32F:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R32G32B32A32_FLOAT:
+ return RGBA32F_to_R32G32B32A32_FLOAT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGBA32I:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R32G32B32A32_SINT:
+ return RGBA32I_to_R32G32B32A32_SINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGBA32UI:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R32G32B32A32_UINT:
+ return RGBA32UI_to_R32G32B32A32_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGBA4:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::B4G4R4A4_UNORM:
+ return RGBA4_to_B4G4R4A4_UNORM;
+ case FormatID::R4G4B4A4_UNORM:
+ return RGBA4_to_R4G4B4A4_UNORM;
+ case FormatID::R8G8B8A8_UNORM:
+ return RGBA4_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGBA8:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return RGBA8_to_R8G8B8A8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGBA8I:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_SINT:
+ return RGBA8I_to_R8G8B8A8_SINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGBA8UI:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UINT:
+ return RGBA8UI_to_R8G8B8A8_UINT;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGBA8_SNORM:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_SNORM:
+ return RGBA8_SNORM_to_R8G8B8A8_SNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_RGBA8_SSCALED_ANGLEX:
+ return RGBA8_SSCALED_ANGLEX_to_default;
+ case GL_RGBA8_USCALED_ANGLEX:
+ return RGBA8_USCALED_ANGLEX_to_default;
+ case GL_RGBX8_ANGLE:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM:
+ return RGBX8_ANGLE_to_R8G8B8A8_UNORM;
+ case FormatID::R8G8B8X8_UNORM:
+ return RGBX8_ANGLE_to_R8G8B8X8_UNORM;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SR8_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8_UNORM_SRGB:
+ return SR8_EXT_to_R8_UNORM_SRGB;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SRG8_EXT:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8_UNORM_SRGB:
+ return SRG8_EXT_to_R8G8_UNORM_SRGB;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SRGB8:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return SRGB8_to_R8G8B8A8_UNORM_SRGB;
+ case FormatID::R8G8B8_UNORM_SRGB:
+ return SRGB8_to_R8G8B8_UNORM_SRGB;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_SRGB8_ALPHA8:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::R8G8B8A8_UNORM_SRGB:
+ return SRGB8_ALPHA8_to_R8G8B8A8_UNORM_SRGB;
+ default:
+ break;
+ }
+ break;
+ }
+ case GL_STENCIL_INDEX8:
+ {
+ switch (angleFormat)
+ {
+ case FormatID::S8_UINT:
+ return STENCIL_INDEX8_to_S8_UINT;
+ default:
+ return STENCIL_INDEX8_to_default;
+ }
+ }
+
+ default:
+ break;
+ }
+ // clang-format on
+ ASSERT(internalFormat == GL_NONE || angleFormat == angle::FormatID::NONE);
+ static LoadFunctionMap emptyLoadFunctionsMap;
+ return emptyLoadFunctionsMap;
+
+} // GetLoadFunctionsMap
+
+} // namespace angle
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.cpp b/gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.cpp
new file mode 100644
index 0000000000..152de2f25d
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.cpp
@@ -0,0 +1,1583 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// renderer_utils:
+// Helper methods pertaining to most or all back-ends.
+//
+
+#include "libANGLE/renderer/renderer_utils.h"
+
+#include "common/string_utils.h"
+#include "common/system_utils.h"
+#include "common/utilities.h"
+#include "image_util/copyimage.h"
+#include "image_util/imageformats.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Context.inl.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/ContextImpl.h"
+#include "libANGLE/renderer/Format.h"
+#include "platform/Feature.h"
+
+#include <string.h>
+#include <cctype>
+
+namespace angle
+{
+namespace
+{
+// For the sake of feature name matching, underscore is ignored, and the names are matched
+// case-insensitive. This allows feature names to be overriden both in snake_case (previously used
+// by ANGLE) and camelCase. The second string (user-provided name) can end in `*` for wildcard
+// matching.
+bool FeatureNameMatch(const std::string &a, const std::string &b)
+{
+ size_t ai = 0;
+ size_t bi = 0;
+
+ while (ai < a.size() && bi < b.size())
+ {
+ if (a[ai] == '_')
+ {
+ ++ai;
+ }
+ if (b[bi] == '_')
+ {
+ ++bi;
+ }
+ if (b[bi] == '*' && bi + 1 == b.size())
+ {
+ // If selected feature name ends in wildcard, match it.
+ return true;
+ }
+ if (std::tolower(a[ai++]) != std::tolower(b[bi++]))
+ {
+ return false;
+ }
+ }
+
+ return ai == a.size() && bi == b.size();
+}
+} // anonymous namespace
+
+// FeatureSetBase implementation
+void FeatureSetBase::overrideFeatures(const std::vector<std::string> &featureNames, bool enabled)
+{
+ for (const std::string &name : featureNames)
+ {
+ const bool hasWildcard = name.back() == '*';
+ for (auto iter : members)
+ {
+ const std::string &featureName = iter.first;
+ FeatureInfo *feature = iter.second;
+
+ if (!FeatureNameMatch(featureName, name))
+ {
+ continue;
+ }
+
+ feature->enabled = enabled;
+
+ // If name has a wildcard, try to match it with all features. Otherwise, bail on first
+ // match, as names are unique.
+ if (!hasWildcard)
+ {
+ break;
+ }
+ }
+ }
+}
+
+void FeatureSetBase::populateFeatureList(FeatureList *features) const
+{
+ for (FeatureMap::const_iterator it = members.begin(); it != members.end(); it++)
+ {
+ features->push_back(it->second);
+ }
+}
+} // namespace angle
+
+namespace rx
+{
+
+namespace
+{
+// Both D3D and Vulkan support the same set of standard sample positions for 1, 2, 4, 8, and 16
+// samples. See:
+//
+// - https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218.aspx
+//
+// -
+// https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#primsrast-multisampling
+using SamplePositionsArray = std::array<float, 32>;
+constexpr std::array<SamplePositionsArray, 5> kSamplePositions = {
+ {{{0.5f, 0.5f}},
+ {{0.75f, 0.75f, 0.25f, 0.25f}},
+ {{0.375f, 0.125f, 0.875f, 0.375f, 0.125f, 0.625f, 0.625f, 0.875f}},
+ {{0.5625f, 0.3125f, 0.4375f, 0.6875f, 0.8125f, 0.5625f, 0.3125f, 0.1875f, 0.1875f, 0.8125f,
+ 0.0625f, 0.4375f, 0.6875f, 0.9375f, 0.9375f, 0.0625f}},
+ {{0.5625f, 0.5625f, 0.4375f, 0.3125f, 0.3125f, 0.625f, 0.75f, 0.4375f,
+ 0.1875f, 0.375f, 0.625f, 0.8125f, 0.8125f, 0.6875f, 0.6875f, 0.1875f,
+ 0.375f, 0.875f, 0.5f, 0.0625f, 0.25f, 0.125f, 0.125f, 0.75f,
+ 0.0f, 0.5f, 0.9375f, 0.25f, 0.875f, 0.9375f, 0.0625f, 0.0f}}}};
+
+struct IncompleteTextureParameters
+{
+ GLenum sizedInternalFormat;
+ GLenum format;
+ GLenum type;
+ GLubyte clearColor[4];
+};
+
+// Note that for gl::SamplerFormat::Shadow, the clearColor datatype needs to be GLushort and as such
+// we will reinterpret GLubyte[4] as GLushort[2].
+constexpr angle::PackedEnumMap<gl::SamplerFormat, IncompleteTextureParameters>
+ kIncompleteTextureParameters = {
+ {gl::SamplerFormat::Float, {GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, {0, 0, 0, 255}}},
+ {gl::SamplerFormat::Unsigned,
+ {GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, {0, 0, 0, 255}}},
+ {gl::SamplerFormat::Signed, {GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE, {0, 0, 0, 127}}},
+ {gl::SamplerFormat::Shadow,
+ {GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, {0, 0, 0, 0}}}};
+
+void CopyColor(gl::ColorF *color)
+{
+ // No-op
+}
+
+void PremultiplyAlpha(gl::ColorF *color)
+{
+ color->red *= color->alpha;
+ color->green *= color->alpha;
+ color->blue *= color->alpha;
+}
+
+void UnmultiplyAlpha(gl::ColorF *color)
+{
+ if (color->alpha != 0.0f)
+ {
+ float invAlpha = 1.0f / color->alpha;
+ color->red *= invAlpha;
+ color->green *= invAlpha;
+ color->blue *= invAlpha;
+ }
+}
+
+void ClipChannelsR(gl::ColorF *color)
+{
+ color->green = 0.0f;
+ color->blue = 0.0f;
+ color->alpha = 1.0f;
+}
+
+void ClipChannelsRG(gl::ColorF *color)
+{
+ color->blue = 0.0f;
+ color->alpha = 1.0f;
+}
+
+void ClipChannelsRGB(gl::ColorF *color)
+{
+ color->alpha = 1.0f;
+}
+
+void ClipChannelsLuminance(gl::ColorF *color)
+{
+ color->alpha = 1.0f;
+}
+
+void ClipChannelsAlpha(gl::ColorF *color)
+{
+ color->red = 0.0f;
+ color->green = 0.0f;
+ color->blue = 0.0f;
+}
+
+void ClipChannelsNoOp(gl::ColorF *color) {}
+
+void WriteUintColor(const gl::ColorF &color,
+ PixelWriteFunction colorWriteFunction,
+ uint8_t *destPixelData)
+{
+ gl::ColorUI destColor(
+ static_cast<unsigned int>(color.red * 255), static_cast<unsigned int>(color.green * 255),
+ static_cast<unsigned int>(color.blue * 255), static_cast<unsigned int>(color.alpha * 255));
+ colorWriteFunction(reinterpret_cast<const uint8_t *>(&destColor), destPixelData);
+}
+
+void WriteFloatColor(const gl::ColorF &color,
+ PixelWriteFunction colorWriteFunction,
+ uint8_t *destPixelData)
+{
+ colorWriteFunction(reinterpret_cast<const uint8_t *>(&color), destPixelData);
+}
+
+template <int cols, int rows, bool IsColumnMajor>
+inline int GetFlattenedIndex(int col, int row)
+{
+ if (IsColumnMajor)
+ {
+ return col * rows + row;
+ }
+ else
+ {
+ return row * cols + col;
+ }
+}
+
+template <typename T,
+ bool IsSrcColumnMajor,
+ int colsSrc,
+ int rowsSrc,
+ bool IsDstColumnMajor,
+ int colsDst,
+ int rowsDst>
+void ExpandMatrix(T *target, const GLfloat *value)
+{
+ static_assert(colsSrc <= colsDst && rowsSrc <= rowsDst, "Can only expand!");
+
+ constexpr int kDstFlatSize = colsDst * rowsDst;
+ T staging[kDstFlatSize] = {0};
+
+ for (int r = 0; r < rowsSrc; r++)
+ {
+ for (int c = 0; c < colsSrc; c++)
+ {
+ int srcIndex = GetFlattenedIndex<colsSrc, rowsSrc, IsSrcColumnMajor>(c, r);
+ int dstIndex = GetFlattenedIndex<colsDst, rowsDst, IsDstColumnMajor>(c, r);
+
+ staging[dstIndex] = static_cast<T>(value[srcIndex]);
+ }
+ }
+
+ memcpy(target, staging, kDstFlatSize * sizeof(T));
+}
+
+template <bool IsSrcColumMajor,
+ int colsSrc,
+ int rowsSrc,
+ bool IsDstColumnMajor,
+ int colsDst,
+ int rowsDst>
+void SetFloatUniformMatrix(unsigned int arrayElementOffset,
+ unsigned int elementCount,
+ GLsizei countIn,
+ const GLfloat *value,
+ uint8_t *targetData)
+{
+ unsigned int count =
+ std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
+
+ const unsigned int targetMatrixStride = colsDst * rowsDst;
+ GLfloat *target = reinterpret_cast<GLfloat *>(
+ targetData + arrayElementOffset * sizeof(GLfloat) * targetMatrixStride);
+
+ for (unsigned int i = 0; i < count; i++)
+ {
+ ExpandMatrix<GLfloat, IsSrcColumMajor, colsSrc, rowsSrc, IsDstColumnMajor, colsDst,
+ rowsDst>(target, value);
+
+ target += targetMatrixStride;
+ value += colsSrc * rowsSrc;
+ }
+}
+
+void SetFloatUniformMatrixFast(unsigned int arrayElementOffset,
+ unsigned int elementCount,
+ GLsizei countIn,
+ size_t matrixSize,
+ const GLfloat *value,
+ uint8_t *targetData)
+{
+ const unsigned int count =
+ std::min(elementCount - arrayElementOffset, static_cast<unsigned int>(countIn));
+
+ const uint8_t *valueData = reinterpret_cast<const uint8_t *>(value);
+ targetData = targetData + arrayElementOffset * matrixSize;
+
+ memcpy(targetData, valueData, matrixSize * count);
+}
+} // anonymous namespace
+
+bool IsRotatedAspectRatio(SurfaceRotation rotation)
+{
+ switch (rotation)
+ {
+ case SurfaceRotation::Rotated90Degrees:
+ case SurfaceRotation::Rotated270Degrees:
+ case SurfaceRotation::FlippedRotated90Degrees:
+ case SurfaceRotation::FlippedRotated270Degrees:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void RotateRectangle(const SurfaceRotation rotation,
+ const bool flipY,
+ const int framebufferWidth,
+ const int framebufferHeight,
+ const gl::Rectangle &incoming,
+ gl::Rectangle *outgoing)
+{
+ // GLES's y-axis points up; Vulkan's points down.
+ switch (rotation)
+ {
+ case SurfaceRotation::Identity:
+ // Do not rotate gl_Position (surface matches the device's orientation):
+ outgoing->x = incoming.x;
+ outgoing->y = flipY ? framebufferHeight - incoming.y - incoming.height : incoming.y;
+ outgoing->width = incoming.width;
+ outgoing->height = incoming.height;
+ break;
+ case SurfaceRotation::Rotated90Degrees:
+ // Rotate gl_Position 90 degrees:
+ outgoing->x = incoming.y;
+ outgoing->y = flipY ? incoming.x : framebufferWidth - incoming.x - incoming.width;
+ outgoing->width = incoming.height;
+ outgoing->height = incoming.width;
+ break;
+ case SurfaceRotation::Rotated180Degrees:
+ // Rotate gl_Position 180 degrees:
+ outgoing->x = framebufferWidth - incoming.x - incoming.width;
+ outgoing->y = flipY ? incoming.y : framebufferHeight - incoming.y - incoming.height;
+ outgoing->width = incoming.width;
+ outgoing->height = incoming.height;
+ break;
+ case SurfaceRotation::Rotated270Degrees:
+ // Rotate gl_Position 270 degrees:
+ outgoing->x = framebufferHeight - incoming.y - incoming.height;
+ outgoing->y = flipY ? framebufferWidth - incoming.x - incoming.width : incoming.x;
+ outgoing->width = incoming.height;
+ outgoing->height = incoming.width;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+}
+
+PackPixelsParams::PackPixelsParams()
+ : destFormat(nullptr),
+ outputPitch(0),
+ packBuffer(nullptr),
+ offset(0),
+ rotation(SurfaceRotation::Identity)
+{}
+
+PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn,
+ const angle::Format &destFormat,
+ GLuint outputPitchIn,
+ bool reverseRowOrderIn,
+ gl::Buffer *packBufferIn,
+ ptrdiff_t offsetIn)
+ : area(areaIn),
+ destFormat(&destFormat),
+ outputPitch(outputPitchIn),
+ packBuffer(packBufferIn),
+ reverseRowOrder(reverseRowOrderIn),
+ offset(offsetIn),
+ rotation(SurfaceRotation::Identity)
+{}
+
+void PackPixels(const PackPixelsParams &params,
+ const angle::Format &sourceFormat,
+ int inputPitchIn,
+ const uint8_t *sourceIn,
+ uint8_t *destWithoutOffset)
+{
+ uint8_t *destWithOffset = destWithoutOffset + params.offset;
+
+ const uint8_t *source = sourceIn;
+ int inputPitch = inputPitchIn;
+ int destWidth = params.area.width;
+ int destHeight = params.area.height;
+ int xAxisPitch = 0;
+ int yAxisPitch = 0;
+ switch (params.rotation)
+ {
+ case SurfaceRotation::Identity:
+ // The source image is not rotated (i.e. matches the device's orientation), and may or
+ // may not be y-flipped. The image is row-major. Each source row (one step along the
+ // y-axis for each step in the dest y-axis) is inputPitch past the previous row. Along
+ // a row, each source pixel (one step along the x-axis for each step in the dest
+ // x-axis) is sourceFormat.pixelBytes past the previous pixel.
+ xAxisPitch = sourceFormat.pixelBytes;
+ if (params.reverseRowOrder)
+ {
+ // The source image is y-flipped, which means we start at the last row, and each
+ // source row is BEFORE the previous row.
+ source += inputPitchIn * (params.area.height - 1);
+ inputPitch = -inputPitch;
+ yAxisPitch = -inputPitchIn;
+ }
+ else
+ {
+ yAxisPitch = inputPitchIn;
+ }
+ break;
+ case SurfaceRotation::Rotated90Degrees:
+ // The source image is rotated 90 degrees counter-clockwise. Y-flip is always applied
+ // to rotated images. The image is column-major. Each source column (one step along
+ // the source x-axis for each step in the dest y-axis) is inputPitch past the previous
+ // column. Along a column, each source pixel (one step along the y-axis for each step
+ // in the dest x-axis) is sourceFormat.pixelBytes past the previous pixel.
+ xAxisPitch = inputPitchIn;
+ yAxisPitch = sourceFormat.pixelBytes;
+ destWidth = params.area.height;
+ destHeight = params.area.width;
+ break;
+ case SurfaceRotation::Rotated180Degrees:
+ // The source image is rotated 180 degrees. Y-flip is always applied to rotated
+ // images. The image is row-major, but upside down. Each source row (one step along
+ // the y-axis for each step in the dest y-axis) is inputPitch after the previous row.
+ // Along a row, each source pixel (one step along the x-axis for each step in the dest
+ // x-axis) is sourceFormat.pixelBytes BEFORE the previous pixel.
+ xAxisPitch = -static_cast<int>(sourceFormat.pixelBytes);
+ yAxisPitch = inputPitchIn;
+ source += sourceFormat.pixelBytes * (params.area.width - 1);
+ break;
+ case SurfaceRotation::Rotated270Degrees:
+ // The source image is rotated 270 degrees counter-clockwise (or 90 degrees clockwise).
+ // Y-flip is always applied to rotated images. The image is column-major, where each
+ // column (one step in the source x-axis for one step in the dest y-axis) is inputPitch
+ // BEFORE the previous column. Along a column, each source pixel (one step along the
+ // y-axis for each step in the dest x-axis) is sourceFormat.pixelBytes BEFORE the
+ // previous pixel. The first pixel is at the end of the source.
+ xAxisPitch = -inputPitchIn;
+ yAxisPitch = -static_cast<int>(sourceFormat.pixelBytes);
+ destWidth = params.area.height;
+ destHeight = params.area.width;
+ source += inputPitch * (params.area.height - 1) +
+ sourceFormat.pixelBytes * (params.area.width - 1);
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ if (params.rotation == SurfaceRotation::Identity && sourceFormat == *params.destFormat)
+ {
+ // Direct copy possible
+ for (int y = 0; y < params.area.height; ++y)
+ {
+ memcpy(destWithOffset + y * params.outputPitch, source + y * inputPitch,
+ params.area.width * sourceFormat.pixelBytes);
+ }
+ return;
+ }
+
+ FastCopyFunction fastCopyFunc = sourceFormat.fastCopyFunctions.get(params.destFormat->id);
+
+ if (fastCopyFunc)
+ {
+ // Fast copy is possible through some special function
+ fastCopyFunc(source, xAxisPitch, yAxisPitch, destWithOffset, params.destFormat->pixelBytes,
+ params.outputPitch, destWidth, destHeight);
+ return;
+ }
+
+ PixelWriteFunction pixelWriteFunction = params.destFormat->pixelWriteFunction;
+ ASSERT(pixelWriteFunction != nullptr);
+
+ // Maximum size of any Color<T> type used.
+ uint8_t temp[16];
+ static_assert(sizeof(temp) >= sizeof(gl::ColorF) && sizeof(temp) >= sizeof(gl::ColorUI) &&
+ sizeof(temp) >= sizeof(gl::ColorI) &&
+ sizeof(temp) >= sizeof(angle::DepthStencil),
+ "Unexpected size of pixel struct.");
+
+ PixelReadFunction pixelReadFunction = sourceFormat.pixelReadFunction;
+ ASSERT(pixelReadFunction != nullptr);
+
+ for (int y = 0; y < destHeight; ++y)
+ {
+ for (int x = 0; x < destWidth; ++x)
+ {
+ uint8_t *dest =
+ destWithOffset + y * params.outputPitch + x * params.destFormat->pixelBytes;
+ const uint8_t *src = source + y * yAxisPitch + x * xAxisPitch;
+
+ // readFunc and writeFunc will be using the same type of color, CopyTexImage
+ // will not allow the copy otherwise.
+ pixelReadFunction(src, temp);
+ pixelWriteFunction(temp, dest);
+ }
+ }
+}
+
+bool FastCopyFunctionMap::has(angle::FormatID formatID) const
+{
+ return (get(formatID) != nullptr);
+}
+
+namespace
+{
+
+const FastCopyFunctionMap::Entry *getEntry(const FastCopyFunctionMap::Entry *entry,
+ size_t numEntries,
+ angle::FormatID formatID)
+{
+ const FastCopyFunctionMap::Entry *end = entry + numEntries;
+ while (entry != end)
+ {
+ if (entry->formatID == formatID)
+ {
+ return entry;
+ }
+ ++entry;
+ }
+
+ return nullptr;
+}
+
+} // namespace
+
+FastCopyFunction FastCopyFunctionMap::get(angle::FormatID formatID) const
+{
+ const FastCopyFunctionMap::Entry *entry = getEntry(mData, mSize, formatID);
+ return entry ? entry->func : nullptr;
+}
+
+bool ShouldUseDebugLayers(const egl::AttributeMap &attribs)
+{
+ EGLAttrib debugSetting =
+ attribs.get(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE, EGL_DONT_CARE);
+
+ // Prefer to enable debug layers when available.
+#if defined(ANGLE_ENABLE_ASSERTS)
+ return (debugSetting != EGL_FALSE);
+#else
+ return (debugSetting == EGL_TRUE);
+#endif // defined(ANGLE_ENABLE_ASSERTS)
+}
+
+void CopyImageCHROMIUM(const uint8_t *sourceData,
+ size_t sourceRowPitch,
+ size_t sourcePixelBytes,
+ size_t sourceDepthPitch,
+ PixelReadFunction pixelReadFunction,
+ uint8_t *destData,
+ size_t destRowPitch,
+ size_t destPixelBytes,
+ size_t destDepthPitch,
+ PixelWriteFunction pixelWriteFunction,
+ GLenum destUnsizedFormat,
+ GLenum destComponentType,
+ size_t width,
+ size_t height,
+ size_t depth,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha)
+{
+ using ConversionFunction = void (*)(gl::ColorF *);
+ ConversionFunction conversionFunction = CopyColor;
+ if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha)
+ {
+ if (unpackPremultiplyAlpha)
+ {
+ conversionFunction = PremultiplyAlpha;
+ }
+ else
+ {
+ conversionFunction = UnmultiplyAlpha;
+ }
+ }
+
+ auto clipChannelsFunction = ClipChannelsNoOp;
+ switch (destUnsizedFormat)
+ {
+ case GL_RED:
+ clipChannelsFunction = ClipChannelsR;
+ break;
+ case GL_RG:
+ clipChannelsFunction = ClipChannelsRG;
+ break;
+ case GL_RGB:
+ clipChannelsFunction = ClipChannelsRGB;
+ break;
+ case GL_LUMINANCE:
+ clipChannelsFunction = ClipChannelsLuminance;
+ break;
+ case GL_ALPHA:
+ clipChannelsFunction = ClipChannelsAlpha;
+ break;
+ }
+
+ auto writeFunction = (destComponentType == GL_UNSIGNED_INT) ? WriteUintColor : WriteFloatColor;
+
+ for (size_t z = 0; z < depth; z++)
+ {
+ for (size_t y = 0; y < height; y++)
+ {
+ for (size_t x = 0; x < width; x++)
+ {
+ const uint8_t *sourcePixelData =
+ sourceData + y * sourceRowPitch + x * sourcePixelBytes + z * sourceDepthPitch;
+
+ gl::ColorF sourceColor;
+ pixelReadFunction(sourcePixelData, reinterpret_cast<uint8_t *>(&sourceColor));
+
+ conversionFunction(&sourceColor);
+ clipChannelsFunction(&sourceColor);
+
+ size_t destY = 0;
+ if (unpackFlipY)
+ {
+ destY += (height - 1);
+ destY -= y;
+ }
+ else
+ {
+ destY += y;
+ }
+
+ uint8_t *destPixelData =
+ destData + destY * destRowPitch + x * destPixelBytes + z * destDepthPitch;
+ writeFunction(sourceColor, pixelWriteFunction, destPixelData);
+ }
+ }
+ }
+}
+
+// IncompleteTextureSet implementation.
+IncompleteTextureSet::IncompleteTextureSet() : mIncompleteTextureBufferAttachment(nullptr) {}
+
+IncompleteTextureSet::~IncompleteTextureSet() {}
+
+void IncompleteTextureSet::onDestroy(const gl::Context *context)
+{
+ // Clear incomplete textures.
+ for (auto &incompleteTextures : mIncompleteTextures)
+ {
+ for (auto &incompleteTexture : incompleteTextures)
+ {
+ if (incompleteTexture.get() != nullptr)
+ {
+ incompleteTexture->onDestroy(context);
+ incompleteTexture.set(context, nullptr);
+ }
+ }
+ }
+ if (mIncompleteTextureBufferAttachment != nullptr)
+ {
+ mIncompleteTextureBufferAttachment->onDestroy(context);
+ mIncompleteTextureBufferAttachment = nullptr;
+ }
+}
+
+angle::Result IncompleteTextureSet::getIncompleteTexture(
+ const gl::Context *context,
+ gl::TextureType type,
+ gl::SamplerFormat format,
+ MultisampleTextureInitializer *multisampleInitializer,
+ gl::Texture **textureOut)
+{
+ *textureOut = mIncompleteTextures[format][type].get();
+ if (*textureOut != nullptr)
+ {
+ return angle::Result::Continue;
+ }
+
+ ContextImpl *implFactory = context->getImplementation();
+
+ gl::Extents colorSize(1, 1, 1);
+ gl::PixelUnpackState unpack;
+ unpack.alignment = 1;
+ gl::Box area(0, 0, 0, 1, 1, 1);
+ const IncompleteTextureParameters &incompleteTextureParam =
+ kIncompleteTextureParameters[format];
+
+ // Cube map arrays are expected to have layer counts that are multiples of 6
+ constexpr int kCubeMapArraySize = 6;
+ if (type == gl::TextureType::CubeMapArray)
+ {
+ // From the GLES 3.2 spec:
+ // 8.18. IMMUTABLE-FORMAT TEXTURE IMAGES
+ // TexStorage3D Errors
+ // An INVALID_OPERATION error is generated if any of the following conditions hold:
+ // * target is TEXTURE_CUBE_MAP_ARRAY and depth is not a multiple of 6
+ // Since ANGLE treats incomplete textures as immutable, respect that here.
+ colorSize.depth = kCubeMapArraySize;
+ area.depth = kCubeMapArraySize;
+ }
+
+ // If a texture is external use a 2D texture for the incomplete texture
+ gl::TextureType createType = (type == gl::TextureType::External) ? gl::TextureType::_2D : type;
+
+ gl::Texture *tex =
+ new gl::Texture(implFactory, {std::numeric_limits<GLuint>::max()}, createType);
+ angle::UniqueObjectPointer<gl::Texture, gl::Context> t(tex, context);
+
+ // This is a bit of a kludge but is necessary to consume the error.
+ gl::Context *mutableContext = const_cast<gl::Context *>(context);
+
+ if (createType == gl::TextureType::Buffer)
+ {
+ constexpr uint32_t kBufferInitData = 0;
+ mIncompleteTextureBufferAttachment =
+ new gl::Buffer(implFactory, {std::numeric_limits<GLuint>::max()});
+ ANGLE_TRY(mIncompleteTextureBufferAttachment->bufferData(
+ mutableContext, gl::BufferBinding::Texture, &kBufferInitData, sizeof(kBufferInitData),
+ gl::BufferUsage::StaticDraw));
+ }
+ else if (createType == gl::TextureType::_2DMultisample)
+ {
+ ANGLE_TRY(t->setStorageMultisample(mutableContext, createType, 1,
+ incompleteTextureParam.sizedInternalFormat, colorSize,
+ true));
+ }
+ else
+ {
+ ANGLE_TRY(t->setStorage(mutableContext, createType, 1,
+ incompleteTextureParam.sizedInternalFormat, colorSize));
+ }
+
+ if (type == gl::TextureType::CubeMap)
+ {
+ for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
+ {
+ ANGLE_TRY(t->setSubImage(mutableContext, unpack, nullptr, face, 0, area,
+ incompleteTextureParam.format, incompleteTextureParam.type,
+ incompleteTextureParam.clearColor));
+ }
+ }
+ else if (type == gl::TextureType::CubeMapArray)
+ {
+ // We need to provide enough pixel data to fill the array of six faces
+ GLubyte incompleteCubeArrayPixels[kCubeMapArraySize][4];
+ for (int i = 0; i < kCubeMapArraySize; ++i)
+ {
+ incompleteCubeArrayPixels[i][0] = incompleteTextureParam.clearColor[0];
+ incompleteCubeArrayPixels[i][1] = incompleteTextureParam.clearColor[1];
+ incompleteCubeArrayPixels[i][2] = incompleteTextureParam.clearColor[2];
+ incompleteCubeArrayPixels[i][3] = incompleteTextureParam.clearColor[3];
+ }
+
+ ANGLE_TRY(t->setSubImage(mutableContext, unpack, nullptr,
+ gl::NonCubeTextureTypeToTarget(createType), 0, area,
+ incompleteTextureParam.format, incompleteTextureParam.type,
+ *incompleteCubeArrayPixels));
+ }
+ else if (type == gl::TextureType::_2DMultisample)
+ {
+ // Call a specialized clear function to init a multisample texture.
+ ANGLE_TRY(multisampleInitializer->initializeMultisampleTextureToBlack(context, t.get()));
+ }
+ else if (type == gl::TextureType::Buffer)
+ {
+ ANGLE_TRY(t->setBuffer(context, mIncompleteTextureBufferAttachment,
+ incompleteTextureParam.sizedInternalFormat));
+ }
+ else
+ {
+ ANGLE_TRY(t->setSubImage(mutableContext, unpack, nullptr,
+ gl::NonCubeTextureTypeToTarget(createType), 0, area,
+ incompleteTextureParam.format, incompleteTextureParam.type,
+ incompleteTextureParam.clearColor));
+ }
+
+ if (format == gl::SamplerFormat::Shadow)
+ {
+ // To avoid the undefined spec behavior for shadow samplers with a depth texture, we set the
+ // compare mode to GL_COMPARE_REF_TO_TEXTURE
+ ASSERT(!t->hasObservers());
+ t->setCompareMode(context, GL_COMPARE_REF_TO_TEXTURE);
+ }
+
+ ANGLE_TRY(t->syncState(context, gl::Command::Other));
+
+ mIncompleteTextures[format][type].set(context, t.release());
+ *textureOut = mIncompleteTextures[format][type].get();
+ return angle::Result::Continue;
+}
+
+#define ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \
+ template void SetFloatUniformMatrix##api<cols, rows>::Run( \
+ unsigned int, unsigned int, GLsizei, GLboolean, const GLfloat *, uint8_t *)
+
+ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 2);
+ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 3);
+ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 3);
+ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 2);
+ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 2);
+ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 3);
+
+ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 2);
+ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 3);
+ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 3);
+ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 2);
+ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 2, 4);
+ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC(HLSL, 3, 4);
+
+#undef ANGLE_INSTANTIATE_SET_UNIFORM_MATRIX_FUNC
+
+#define ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \
+ template void SetFloatUniformMatrix##api<cols, 4>::Run(unsigned int, unsigned int, GLsizei, \
+ GLboolean, const GLfloat *, uint8_t *)
+
+template <int cols>
+struct SetFloatUniformMatrixGLSL<cols, 4>
+{
+ static void Run(unsigned int arrayElementOffset,
+ unsigned int elementCount,
+ GLsizei countIn,
+ GLboolean transpose,
+ const GLfloat *value,
+ uint8_t *targetData);
+};
+
+ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 2, 4);
+ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 3, 4);
+ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC(GLSL, 4, 4);
+
+#undef ANGLE_SPECIALIZATION_ROWS_SET_UNIFORM_MATRIX_FUNC
+
+#define ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(api, cols, rows) \
+ template void SetFloatUniformMatrix##api<4, rows>::Run(unsigned int, unsigned int, GLsizei, \
+ GLboolean, const GLfloat *, uint8_t *)
+
+template <int rows>
+struct SetFloatUniformMatrixHLSL<4, rows>
+{
+ static void Run(unsigned int arrayElementOffset,
+ unsigned int elementCount,
+ GLsizei countIn,
+ GLboolean transpose,
+ const GLfloat *value,
+ uint8_t *targetData);
+};
+
+ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 2);
+ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 3);
+ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC(HLSL, 4, 4);
+
+#undef ANGLE_SPECIALIZATION_COLS_SET_UNIFORM_MATRIX_FUNC
+
+template <int cols>
+void SetFloatUniformMatrixGLSL<cols, 4>::Run(unsigned int arrayElementOffset,
+ unsigned int elementCount,
+ GLsizei countIn,
+ GLboolean transpose,
+ const GLfloat *value,
+ uint8_t *targetData)
+{
+ const bool isSrcColumnMajor = !transpose;
+ if (isSrcColumnMajor)
+ {
+ // Both src and dst matrixs are has same layout,
+ // a single memcpy updates all the matrices
+ constexpr size_t srcMatrixSize = sizeof(GLfloat) * cols * 4;
+ SetFloatUniformMatrixFast(arrayElementOffset, elementCount, countIn, srcMatrixSize, value,
+ targetData);
+ }
+ else
+ {
+ // fallback to general cases
+ SetFloatUniformMatrix<false, cols, 4, true, cols, 4>(arrayElementOffset, elementCount,
+ countIn, value, targetData);
+ }
+}
+
+template <int cols, int rows>
+void SetFloatUniformMatrixGLSL<cols, rows>::Run(unsigned int arrayElementOffset,
+ unsigned int elementCount,
+ GLsizei countIn,
+ GLboolean transpose,
+ const GLfloat *value,
+ uint8_t *targetData)
+{
+ const bool isSrcColumnMajor = !transpose;
+ // GLSL expects matrix uniforms to be column-major, and each column is padded to 4 rows.
+ if (isSrcColumnMajor)
+ {
+ SetFloatUniformMatrix<true, cols, rows, true, cols, 4>(arrayElementOffset, elementCount,
+ countIn, value, targetData);
+ }
+ else
+ {
+ SetFloatUniformMatrix<false, cols, rows, true, cols, 4>(arrayElementOffset, elementCount,
+ countIn, value, targetData);
+ }
+}
+
+template <int rows>
+void SetFloatUniformMatrixHLSL<4, rows>::Run(unsigned int arrayElementOffset,
+ unsigned int elementCount,
+ GLsizei countIn,
+ GLboolean transpose,
+ const GLfloat *value,
+ uint8_t *targetData)
+{
+ const bool isSrcColumnMajor = !transpose;
+ if (!isSrcColumnMajor)
+ {
+ // Both src and dst matrixs are has same layout,
+ // a single memcpy updates all the matrices
+ constexpr size_t srcMatrixSize = sizeof(GLfloat) * 4 * rows;
+ SetFloatUniformMatrixFast(arrayElementOffset, elementCount, countIn, srcMatrixSize, value,
+ targetData);
+ }
+ else
+ {
+ // fallback to general cases
+ SetFloatUniformMatrix<true, 4, rows, false, 4, rows>(arrayElementOffset, elementCount,
+ countIn, value, targetData);
+ }
+}
+
+template <int cols, int rows>
+void SetFloatUniformMatrixHLSL<cols, rows>::Run(unsigned int arrayElementOffset,
+ unsigned int elementCount,
+ GLsizei countIn,
+ GLboolean transpose,
+ const GLfloat *value,
+ uint8_t *targetData)
+{
+ const bool isSrcColumnMajor = !transpose;
+ // Internally store matrices as row-major to accomodate HLSL matrix indexing. Each row is
+ // padded to 4 columns.
+ if (!isSrcColumnMajor)
+ {
+ SetFloatUniformMatrix<false, cols, rows, false, 4, rows>(arrayElementOffset, elementCount,
+ countIn, value, targetData);
+ }
+ else
+ {
+ SetFloatUniformMatrix<true, cols, rows, false, 4, rows>(arrayElementOffset, elementCount,
+ countIn, value, targetData);
+ }
+}
+
+template void GetMatrixUniform<GLint>(GLenum, GLint *, const GLint *, bool);
+template void GetMatrixUniform<GLuint>(GLenum, GLuint *, const GLuint *, bool);
+
+void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose)
+{
+ int columns = gl::VariableColumnCount(type);
+ int rows = gl::VariableRowCount(type);
+ for (GLint col = 0; col < columns; ++col)
+ {
+ for (GLint row = 0; row < rows; ++row)
+ {
+ GLfloat *outptr = dataOut + ((col * rows) + row);
+ const GLfloat *inptr =
+ transpose ? source + ((row * 4) + col) : source + ((col * 4) + row);
+ *outptr = *inptr;
+ }
+ }
+}
+
+template <typename NonFloatT>
+void GetMatrixUniform(GLenum type, NonFloatT *dataOut, const NonFloatT *source, bool transpose)
+{
+ UNREACHABLE();
+}
+
+const angle::Format &GetFormatFromFormatType(GLenum format, GLenum type)
+{
+ GLenum sizedInternalFormat = gl::GetInternalFormatInfo(format, type).sizedInternalFormat;
+ angle::FormatID angleFormatID = angle::Format::InternalFormatToID(sizedInternalFormat);
+ return angle::Format::Get(angleFormatID);
+}
+
+angle::Result ComputeStartVertex(ContextImpl *contextImpl,
+ const gl::IndexRange &indexRange,
+ GLint baseVertex,
+ GLint *firstVertexOut)
+{
+ // The entire index range should be within the limits of a 32-bit uint because the largest
+ // GL index type is GL_UNSIGNED_INT.
+ ASSERT(indexRange.start <= std::numeric_limits<uint32_t>::max() &&
+ indexRange.end <= std::numeric_limits<uint32_t>::max());
+
+ // The base vertex is only used in DrawElementsIndirect. Given the assertion above and the
+ // type of mBaseVertex (GLint), adding them both as 64-bit ints is safe.
+ int64_t startVertexInt64 =
+ static_cast<int64_t>(baseVertex) + static_cast<int64_t>(indexRange.start);
+
+ // OpenGL ES 3.2 spec section 10.5: "Behavior of DrawElementsOneInstance is undefined if the
+ // vertex ID is negative for any element"
+ ANGLE_CHECK_GL_MATH(contextImpl, startVertexInt64 >= 0);
+
+ // OpenGL ES 3.2 spec section 10.5: "If the vertex ID is larger than the maximum value
+ // representable by type, it should behave as if the calculation were upconverted to 32-bit
+ // unsigned integers(with wrapping on overflow conditions)." ANGLE does not fully handle
+ // these rules, an overflow error is returned if the start vertex cannot be stored in a
+ // 32-bit signed integer.
+ ANGLE_CHECK_GL_MATH(contextImpl, startVertexInt64 <= std::numeric_limits<GLint>::max());
+
+ *firstVertexOut = static_cast<GLint>(startVertexInt64);
+ return angle::Result::Continue;
+}
+
+angle::Result GetVertexRangeInfo(const gl::Context *context,
+ GLint firstVertex,
+ GLsizei vertexOrIndexCount,
+ gl::DrawElementsType indexTypeOrInvalid,
+ const void *indices,
+ GLint baseVertex,
+ GLint *startVertexOut,
+ size_t *vertexCountOut)
+{
+ if (indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum)
+ {
+ gl::IndexRange indexRange;
+ ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(
+ context, indexTypeOrInvalid, vertexOrIndexCount, indices, &indexRange));
+ ANGLE_TRY(ComputeStartVertex(context->getImplementation(), indexRange, baseVertex,
+ startVertexOut));
+ *vertexCountOut = indexRange.vertexCount();
+ }
+ else
+ {
+ *startVertexOut = firstVertex;
+ *vertexCountOut = vertexOrIndexCount;
+ }
+ return angle::Result::Continue;
+}
+
+gl::Rectangle ClipRectToScissor(const gl::State &glState, const gl::Rectangle &rect, bool invertY)
+{
+ // If the scissor test isn't enabled, assume it has infinite size. Its intersection with the
+ // rect would be the rect itself.
+ //
+ // Note that on Vulkan, returning this (as opposed to a fixed max-int-sized rect) could lead to
+ // unnecessary pipeline creations if two otherwise identical pipelines are used on framebuffers
+ // with different sizes. If such usage is observed in an application, we should investigate
+ // possible optimizations.
+ if (!glState.isScissorTestEnabled())
+ {
+ return rect;
+ }
+
+ gl::Rectangle clippedRect;
+ if (!gl::ClipRectangle(glState.getScissor(), rect, &clippedRect))
+ {
+ return gl::Rectangle();
+ }
+
+ if (invertY)
+ {
+ clippedRect.y = rect.height - clippedRect.y - clippedRect.height;
+ }
+
+ return clippedRect;
+}
+
+void LogFeatureStatus(const angle::FeatureSetBase &features,
+ const std::vector<std::string> &featureNames,
+ bool enabled)
+{
+ for (const std::string &name : featureNames)
+ {
+ const bool hasWildcard = name.back() == '*';
+ for (auto iter : features.getFeatures())
+ {
+ const std::string &featureName = iter.first;
+
+ if (!angle::FeatureNameMatch(featureName, name))
+ {
+ continue;
+ }
+
+ INFO() << "Feature: " << featureName << (enabled ? " enabled" : " disabled");
+
+ if (!hasWildcard)
+ {
+ break;
+ }
+ }
+ }
+}
+
+void ApplyFeatureOverrides(angle::FeatureSetBase *features, const egl::DisplayState &state)
+{
+ features->overrideFeatures(state.featureOverridesEnabled, true);
+ features->overrideFeatures(state.featureOverridesDisabled, false);
+
+ // Override with environment as well.
+ constexpr char kAngleFeatureOverridesEnabledEnvName[] = "ANGLE_FEATURE_OVERRIDES_ENABLED";
+ constexpr char kAngleFeatureOverridesDisabledEnvName[] = "ANGLE_FEATURE_OVERRIDES_DISABLED";
+ constexpr char kAngleFeatureOverridesEnabledPropertyName[] =
+ "debug.angle.feature_overrides_enabled";
+ constexpr char kAngleFeatureOverridesDisabledPropertyName[] =
+ "debug.angle.feature_overrides_disabled";
+ std::vector<std::string> overridesEnabled =
+ angle::GetCachedStringsFromEnvironmentVarOrAndroidProperty(
+ kAngleFeatureOverridesEnabledEnvName, kAngleFeatureOverridesEnabledPropertyName, ":");
+ std::vector<std::string> overridesDisabled =
+ angle::GetCachedStringsFromEnvironmentVarOrAndroidProperty(
+ kAngleFeatureOverridesDisabledEnvName, kAngleFeatureOverridesDisabledPropertyName, ":");
+
+ features->overrideFeatures(overridesEnabled, true);
+ LogFeatureStatus(*features, overridesEnabled, true);
+
+ features->overrideFeatures(overridesDisabled, false);
+ LogFeatureStatus(*features, overridesDisabled, false);
+}
+
+void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy)
+{
+ ASSERT(gl::isPow2(sampleCount));
+ if (sampleCount > 16)
+ {
+ // Vulkan (and D3D11) doesn't have standard sample positions for 32 and 64 samples (and no
+ // drivers are known to support that many samples)
+ xy[0] = 0.5f;
+ xy[1] = 0.5f;
+ }
+ else
+ {
+ size_t indexKey = static_cast<size_t>(gl::log2(sampleCount));
+ ASSERT(indexKey < kSamplePositions.size() &&
+ (2 * index + 1) < kSamplePositions[indexKey].size());
+
+ xy[0] = kSamplePositions[indexKey][2 * index];
+ xy[1] = kSamplePositions[indexKey][2 * index + 1];
+ }
+}
+
+// These macros are to avoid code too much duplication for variations of multi draw types
+#define DRAW_ARRAYS__ contextImpl->drawArrays(context, mode, firsts[drawID], counts[drawID])
+#define DRAW_ARRAYS_INSTANCED_ \
+ contextImpl->drawArraysInstanced(context, mode, firsts[drawID], counts[drawID], \
+ instanceCounts[drawID])
+#define DRAW_ELEMENTS__ \
+ contextImpl->drawElements(context, mode, counts[drawID], type, indices[drawID])
+#define DRAW_ELEMENTS_INSTANCED_ \
+ contextImpl->drawElementsInstanced(context, mode, counts[drawID], type, indices[drawID], \
+ instanceCounts[drawID])
+#define DRAW_ARRAYS_INSTANCED_BASE_INSTANCE \
+ contextImpl->drawArraysInstancedBaseInstance(context, mode, firsts[drawID], counts[drawID], \
+ instanceCounts[drawID], baseInstances[drawID])
+#define DRAW_ELEMENTS_INSTANCED_BASE_VERTEX_BASE_INSTANCE \
+ contextImpl->drawElementsInstancedBaseVertexBaseInstance( \
+ context, mode, counts[drawID], type, indices[drawID], instanceCounts[drawID], \
+ baseVertices[drawID], baseInstances[drawID])
+#define DRAW_CALL(drawType, instanced, bvbi) DRAW_##drawType##instanced##bvbi
+
+#define MULTI_DRAW_BLOCK(drawType, instanced, bvbi, hasDrawID, hasBaseVertex, hasBaseInstance) \
+ for (GLsizei drawID = 0; drawID < drawcount; ++drawID) \
+ { \
+ if (ANGLE_NOOP_DRAW(instanced)) \
+ { \
+ ANGLE_TRY(contextImpl->handleNoopDrawEvent()); \
+ continue; \
+ } \
+ ANGLE_SET_DRAW_ID_UNIFORM(hasDrawID)(drawID); \
+ ANGLE_SET_BASE_VERTEX_UNIFORM(hasBaseVertex)(baseVertices[drawID]); \
+ ANGLE_SET_BASE_INSTANCE_UNIFORM(hasBaseInstance)(baseInstances[drawID]); \
+ ANGLE_TRY(DRAW_CALL(drawType, instanced, bvbi)); \
+ ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced); \
+ gl::MarkShaderStorageUsage(context); \
+ }
+
+angle::Result MultiDrawArraysGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ GLsizei drawcount)
+{
+ gl::Program *programObject = context->getState().getLinkedProgram(context);
+ const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
+ if (hasDrawID)
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _, _, 1, 0, 0)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _, _, 0, 0, 0)
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result MultiDrawArraysIndirectGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride)
+{
+ const GLubyte *indirectPtr = static_cast<const GLubyte *>(indirect);
+
+ for (auto count = 0; count < drawcount; count++)
+ {
+ ANGLE_TRY(contextImpl->drawArraysIndirect(
+ context, mode, reinterpret_cast<const gl::DrawArraysIndirectCommand *>(indirectPtr)));
+ if (stride == 0)
+ {
+ indirectPtr += sizeof(gl::DrawArraysIndirectCommand);
+ }
+ else
+ {
+ indirectPtr += stride;
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result MultiDrawArraysInstancedGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount)
+{
+ gl::Program *programObject = context->getState().getLinkedProgram(context);
+ const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
+ if (hasDrawID)
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 1, 0, 0)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 0, 0, 0)
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result MultiDrawElementsGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ GLsizei drawcount)
+{
+ gl::Program *programObject = context->getState().getLinkedProgram(context);
+ const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
+ if (hasDrawID)
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _, _, 1, 0, 0)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _, _, 0, 0, 0)
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result MultiDrawElementsIndirectGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType type,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride)
+{
+ const GLubyte *indirectPtr = static_cast<const GLubyte *>(indirect);
+
+ for (auto count = 0; count < drawcount; count++)
+ {
+ ANGLE_TRY(contextImpl->drawElementsIndirect(
+ context, mode, type,
+ reinterpret_cast<const gl::DrawElementsIndirectCommand *>(indirectPtr)));
+ if (stride == 0)
+ {
+ indirectPtr += sizeof(gl::DrawElementsIndirectCommand);
+ }
+ else
+ {
+ indirectPtr += stride;
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result MultiDrawElementsInstancedGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount)
+{
+ gl::Program *programObject = context->getState().getLinkedProgram(context);
+ const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
+ if (hasDrawID)
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 1, 0, 0)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 0, 0, 0)
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result MultiDrawArraysInstancedBaseInstanceGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ const GLuint *baseInstances,
+ GLsizei drawcount)
+{
+ gl::Program *programObject = context->getState().getLinkedProgram(context);
+ const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
+ const bool hasBaseInstance = programObject && programObject->hasBaseInstanceUniform();
+ ResetBaseVertexBaseInstance resetUniforms(programObject, false, hasBaseInstance);
+
+ if (hasDrawID && hasBaseInstance)
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 1)
+ }
+ else if (hasDrawID)
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 0)
+ }
+ else if (hasBaseInstance)
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 1)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 0)
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result MultiDrawElementsInstancedBaseVertexBaseInstanceGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount)
+{
+ gl::Program *programObject = context->getState().getLinkedProgram(context);
+ const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
+ const bool hasBaseVertex = programObject && programObject->hasBaseVertexUniform();
+ const bool hasBaseInstance = programObject && programObject->hasBaseInstanceUniform();
+ ResetBaseVertexBaseInstance resetUniforms(programObject, hasBaseVertex, hasBaseInstance);
+
+ if (hasDrawID)
+ {
+ if (hasBaseVertex)
+ {
+ if (hasBaseInstance)
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 1)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 0)
+ }
+ }
+ else
+ {
+ if (hasBaseInstance)
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 1)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 0)
+ }
+ }
+ }
+ else
+ {
+ if (hasBaseVertex)
+ {
+ if (hasBaseInstance)
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 1)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 0)
+ }
+ }
+ else
+ {
+ if (hasBaseInstance)
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 1)
+ }
+ else
+ {
+ MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 0)
+ }
+ }
+ }
+
+ return angle::Result::Continue;
+}
+
+ResetBaseVertexBaseInstance::ResetBaseVertexBaseInstance(gl::Program *programObject,
+ bool resetBaseVertex,
+ bool resetBaseInstance)
+ : mProgramObject(programObject),
+ mResetBaseVertex(resetBaseVertex),
+ mResetBaseInstance(resetBaseInstance)
+{}
+
+ResetBaseVertexBaseInstance::~ResetBaseVertexBaseInstance()
+{
+ if (mProgramObject)
+ {
+ // Reset emulated uniforms to zero to avoid affecting other draw calls
+ if (mResetBaseVertex)
+ {
+ mProgramObject->setBaseVertexUniform(0);
+ }
+
+ if (mResetBaseInstance)
+ {
+ mProgramObject->setBaseInstanceUniform(0);
+ }
+ }
+}
+
+angle::FormatID ConvertToSRGB(angle::FormatID formatID)
+{
+ switch (formatID)
+ {
+ case angle::FormatID::R8_UNORM:
+ return angle::FormatID::R8_UNORM_SRGB;
+ case angle::FormatID::R8G8_UNORM:
+ return angle::FormatID::R8G8_UNORM_SRGB;
+ case angle::FormatID::R8G8B8_UNORM:
+ return angle::FormatID::R8G8B8_UNORM_SRGB;
+ case angle::FormatID::R8G8B8A8_UNORM:
+ return angle::FormatID::R8G8B8A8_UNORM_SRGB;
+ case angle::FormatID::B8G8R8A8_UNORM:
+ return angle::FormatID::B8G8R8A8_UNORM_SRGB;
+ case angle::FormatID::BC1_RGB_UNORM_BLOCK:
+ return angle::FormatID::BC1_RGB_UNORM_SRGB_BLOCK;
+ case angle::FormatID::BC1_RGBA_UNORM_BLOCK:
+ return angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK;
+ case angle::FormatID::BC2_RGBA_UNORM_BLOCK:
+ return angle::FormatID::BC2_RGBA_UNORM_SRGB_BLOCK;
+ case angle::FormatID::BC3_RGBA_UNORM_BLOCK:
+ return angle::FormatID::BC3_RGBA_UNORM_SRGB_BLOCK;
+ case angle::FormatID::BC7_RGBA_UNORM_BLOCK:
+ return angle::FormatID::BC7_RGBA_UNORM_SRGB_BLOCK;
+ case angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK:
+ return angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK;
+ case angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK:
+ return angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK;
+ case angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK:
+ return angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK;
+ case angle::FormatID::ASTC_4x4_UNORM_BLOCK:
+ return angle::FormatID::ASTC_4x4_SRGB_BLOCK;
+ case angle::FormatID::ASTC_5x4_UNORM_BLOCK:
+ return angle::FormatID::ASTC_5x4_SRGB_BLOCK;
+ case angle::FormatID::ASTC_5x5_UNORM_BLOCK:
+ return angle::FormatID::ASTC_5x5_SRGB_BLOCK;
+ case angle::FormatID::ASTC_6x5_UNORM_BLOCK:
+ return angle::FormatID::ASTC_6x5_SRGB_BLOCK;
+ case angle::FormatID::ASTC_6x6_UNORM_BLOCK:
+ return angle::FormatID::ASTC_6x6_SRGB_BLOCK;
+ case angle::FormatID::ASTC_8x5_UNORM_BLOCK:
+ return angle::FormatID::ASTC_8x5_SRGB_BLOCK;
+ case angle::FormatID::ASTC_8x6_UNORM_BLOCK:
+ return angle::FormatID::ASTC_8x6_SRGB_BLOCK;
+ case angle::FormatID::ASTC_8x8_UNORM_BLOCK:
+ return angle::FormatID::ASTC_8x8_SRGB_BLOCK;
+ case angle::FormatID::ASTC_10x5_UNORM_BLOCK:
+ return angle::FormatID::ASTC_10x5_SRGB_BLOCK;
+ case angle::FormatID::ASTC_10x6_UNORM_BLOCK:
+ return angle::FormatID::ASTC_10x6_SRGB_BLOCK;
+ case angle::FormatID::ASTC_10x8_UNORM_BLOCK:
+ return angle::FormatID::ASTC_10x8_SRGB_BLOCK;
+ case angle::FormatID::ASTC_10x10_UNORM_BLOCK:
+ return angle::FormatID::ASTC_10x10_SRGB_BLOCK;
+ case angle::FormatID::ASTC_12x10_UNORM_BLOCK:
+ return angle::FormatID::ASTC_12x10_SRGB_BLOCK;
+ case angle::FormatID::ASTC_12x12_UNORM_BLOCK:
+ return angle::FormatID::ASTC_12x12_SRGB_BLOCK;
+ default:
+ return angle::FormatID::NONE;
+ }
+}
+
+angle::FormatID ConvertToLinear(angle::FormatID formatID)
+{
+ switch (formatID)
+ {
+ case angle::FormatID::R8_UNORM_SRGB:
+ return angle::FormatID::R8_UNORM;
+ case angle::FormatID::R8G8_UNORM_SRGB:
+ return angle::FormatID::R8G8_UNORM;
+ case angle::FormatID::R8G8B8_UNORM_SRGB:
+ return angle::FormatID::R8G8B8_UNORM;
+ case angle::FormatID::R8G8B8A8_UNORM_SRGB:
+ return angle::FormatID::R8G8B8A8_UNORM;
+ case angle::FormatID::B8G8R8A8_UNORM_SRGB:
+ return angle::FormatID::B8G8R8A8_UNORM;
+ case angle::FormatID::BC1_RGB_UNORM_SRGB_BLOCK:
+ return angle::FormatID::BC1_RGB_UNORM_BLOCK;
+ case angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK:
+ return angle::FormatID::BC1_RGBA_UNORM_BLOCK;
+ case angle::FormatID::BC2_RGBA_UNORM_SRGB_BLOCK:
+ return angle::FormatID::BC2_RGBA_UNORM_BLOCK;
+ case angle::FormatID::BC3_RGBA_UNORM_SRGB_BLOCK:
+ return angle::FormatID::BC3_RGBA_UNORM_BLOCK;
+ case angle::FormatID::BC7_RGBA_UNORM_SRGB_BLOCK:
+ return angle::FormatID::BC7_RGBA_UNORM_BLOCK;
+ case angle::FormatID::ETC2_R8G8B8_SRGB_BLOCK:
+ return angle::FormatID::ETC2_R8G8B8_UNORM_BLOCK;
+ case angle::FormatID::ETC2_R8G8B8A1_SRGB_BLOCK:
+ return angle::FormatID::ETC2_R8G8B8A1_UNORM_BLOCK;
+ case angle::FormatID::ETC2_R8G8B8A8_SRGB_BLOCK:
+ return angle::FormatID::ETC2_R8G8B8A8_UNORM_BLOCK;
+ case angle::FormatID::ASTC_4x4_SRGB_BLOCK:
+ return angle::FormatID::ASTC_4x4_UNORM_BLOCK;
+ case angle::FormatID::ASTC_5x4_SRGB_BLOCK:
+ return angle::FormatID::ASTC_5x4_UNORM_BLOCK;
+ case angle::FormatID::ASTC_5x5_SRGB_BLOCK:
+ return angle::FormatID::ASTC_5x5_UNORM_BLOCK;
+ case angle::FormatID::ASTC_6x5_SRGB_BLOCK:
+ return angle::FormatID::ASTC_6x5_UNORM_BLOCK;
+ case angle::FormatID::ASTC_6x6_SRGB_BLOCK:
+ return angle::FormatID::ASTC_6x6_UNORM_BLOCK;
+ case angle::FormatID::ASTC_8x5_SRGB_BLOCK:
+ return angle::FormatID::ASTC_8x5_UNORM_BLOCK;
+ case angle::FormatID::ASTC_8x6_SRGB_BLOCK:
+ return angle::FormatID::ASTC_8x6_UNORM_BLOCK;
+ case angle::FormatID::ASTC_8x8_SRGB_BLOCK:
+ return angle::FormatID::ASTC_8x8_UNORM_BLOCK;
+ case angle::FormatID::ASTC_10x5_SRGB_BLOCK:
+ return angle::FormatID::ASTC_10x5_UNORM_BLOCK;
+ case angle::FormatID::ASTC_10x6_SRGB_BLOCK:
+ return angle::FormatID::ASTC_10x6_UNORM_BLOCK;
+ case angle::FormatID::ASTC_10x8_SRGB_BLOCK:
+ return angle::FormatID::ASTC_10x8_UNORM_BLOCK;
+ case angle::FormatID::ASTC_10x10_SRGB_BLOCK:
+ return angle::FormatID::ASTC_10x10_UNORM_BLOCK;
+ case angle::FormatID::ASTC_12x10_SRGB_BLOCK:
+ return angle::FormatID::ASTC_12x10_UNORM_BLOCK;
+ case angle::FormatID::ASTC_12x12_SRGB_BLOCK:
+ return angle::FormatID::ASTC_12x12_UNORM_BLOCK;
+ default:
+ return angle::FormatID::NONE;
+ }
+}
+
+bool IsOverridableLinearFormat(angle::FormatID formatID)
+{
+ return ConvertToSRGB(formatID) != angle::FormatID::NONE;
+}
+} // namespace rx
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.h b/gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.h
new file mode 100644
index 0000000000..92002db56f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/renderer_utils.h
@@ -0,0 +1,499 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// renderer_utils:
+// Helper methods pertaining to most or all back-ends.
+//
+
+#ifndef LIBANGLE_RENDERER_RENDERER_UTILS_H_
+#define LIBANGLE_RENDERER_RENDERER_UTILS_H_
+
+#include <cstdint>
+
+#include <limits>
+#include <map>
+
+#include "GLSLANG/ShaderLang.h"
+#include "common/angleutils.h"
+#include "common/utilities.h"
+#include "libANGLE/angletypes.h"
+
+namespace angle
+{
+struct FeatureSetBase;
+struct Format;
+enum class FormatID;
+} // namespace angle
+
+namespace gl
+{
+struct FormatType;
+struct InternalFormat;
+class State;
+} // namespace gl
+
+namespace egl
+{
+class AttributeMap;
+struct DisplayState;
+} // namespace egl
+
+namespace rx
+{
+class ContextImpl;
+
+// The possible rotations of the surface/draw framebuffer, particularly for the Vulkan back-end on
+// Android.
+enum class SurfaceRotation
+{
+ Identity,
+ Rotated90Degrees,
+ Rotated180Degrees,
+ Rotated270Degrees,
+ FlippedIdentity,
+ FlippedRotated90Degrees,
+ FlippedRotated180Degrees,
+ FlippedRotated270Degrees,
+
+ InvalidEnum,
+ EnumCount = InvalidEnum,
+};
+
+bool IsRotatedAspectRatio(SurfaceRotation rotation);
+
+using SpecConstUsageBits = angle::PackedEnumBitSet<sh::vk::SpecConstUsage, uint32_t>;
+
+void RotateRectangle(const SurfaceRotation rotation,
+ const bool flipY,
+ const int framebufferWidth,
+ const int framebufferHeight,
+ const gl::Rectangle &incoming,
+ gl::Rectangle *outgoing);
+
+using MipGenerationFunction = void (*)(size_t sourceWidth,
+ size_t sourceHeight,
+ size_t sourceDepth,
+ const uint8_t *sourceData,
+ size_t sourceRowPitch,
+ size_t sourceDepthPitch,
+ uint8_t *destData,
+ size_t destRowPitch,
+ size_t destDepthPitch);
+
+typedef void (*PixelReadFunction)(const uint8_t *source, uint8_t *dest);
+typedef void (*PixelWriteFunction)(const uint8_t *source, uint8_t *dest);
+typedef void (*FastCopyFunction)(const uint8_t *source,
+ int srcXAxisPitch,
+ int srcYAxisPitch,
+ uint8_t *dest,
+ int destXAxisPitch,
+ int destYAxisPitch,
+ int width,
+ int height);
+
+class FastCopyFunctionMap
+{
+ public:
+ struct Entry
+ {
+ angle::FormatID formatID;
+ FastCopyFunction func;
+ };
+
+ constexpr FastCopyFunctionMap() : FastCopyFunctionMap(nullptr, 0) {}
+
+ constexpr FastCopyFunctionMap(const Entry *data, size_t size) : mSize(size), mData(data) {}
+
+ bool has(angle::FormatID formatID) const;
+ FastCopyFunction get(angle::FormatID formatID) const;
+
+ private:
+ size_t mSize;
+ const Entry *mData;
+};
+
+struct PackPixelsParams
+{
+ PackPixelsParams();
+ PackPixelsParams(const gl::Rectangle &area,
+ const angle::Format &destFormat,
+ GLuint outputPitch,
+ bool reverseRowOrderIn,
+ gl::Buffer *packBufferIn,
+ ptrdiff_t offset);
+
+ gl::Rectangle area;
+ const angle::Format *destFormat;
+ GLuint outputPitch;
+ gl::Buffer *packBuffer;
+ bool reverseRowOrder;
+ ptrdiff_t offset;
+ SurfaceRotation rotation;
+};
+
+void PackPixels(const PackPixelsParams &params,
+ const angle::Format &sourceFormat,
+ int inputPitch,
+ const uint8_t *source,
+ uint8_t *destination);
+
+using InitializeTextureDataFunction = void (*)(size_t width,
+ size_t height,
+ size_t depth,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+using LoadImageFunction = void (*)(size_t width,
+ size_t height,
+ size_t depth,
+ const uint8_t *input,
+ size_t inputRowPitch,
+ size_t inputDepthPitch,
+ uint8_t *output,
+ size_t outputRowPitch,
+ size_t outputDepthPitch);
+
+struct LoadImageFunctionInfo
+{
+ LoadImageFunctionInfo() : loadFunction(nullptr), requiresConversion(false) {}
+ LoadImageFunctionInfo(LoadImageFunction loadFunction, bool requiresConversion)
+ : loadFunction(loadFunction), requiresConversion(requiresConversion)
+ {}
+
+ LoadImageFunction loadFunction;
+ bool requiresConversion;
+};
+
+using LoadFunctionMap = LoadImageFunctionInfo (*)(GLenum);
+
+bool ShouldUseDebugLayers(const egl::AttributeMap &attribs);
+
+void CopyImageCHROMIUM(const uint8_t *sourceData,
+ size_t sourceRowPitch,
+ size_t sourcePixelBytes,
+ size_t sourceDepthPitch,
+ PixelReadFunction pixelReadFunction,
+ uint8_t *destData,
+ size_t destRowPitch,
+ size_t destPixelBytes,
+ size_t destDepthPitch,
+ PixelWriteFunction pixelWriteFunction,
+ GLenum destUnsizedFormat,
+ GLenum destComponentType,
+ size_t width,
+ size_t height,
+ size_t depth,
+ bool unpackFlipY,
+ bool unpackPremultiplyAlpha,
+ bool unpackUnmultiplyAlpha);
+
+// Incomplete textures are 1x1 textures filled with black, used when samplers are incomplete.
+// This helper class encapsulates handling incomplete textures. Because the GL back-end
+// can take advantage of the driver's incomplete textures, and because clearing multisample
+// textures is so difficult, we can keep an instance of this class in the back-end instead
+// of moving the logic to the Context front-end.
+
+// This interface allows us to call-back to init a multisample texture.
+class MultisampleTextureInitializer
+{
+ public:
+ virtual ~MultisampleTextureInitializer() {}
+ virtual angle::Result initializeMultisampleTextureToBlack(const gl::Context *context,
+ gl::Texture *glTexture) = 0;
+};
+
+class IncompleteTextureSet final : angle::NonCopyable
+{
+ public:
+ IncompleteTextureSet();
+ ~IncompleteTextureSet();
+
+ void onDestroy(const gl::Context *context);
+
+ angle::Result getIncompleteTexture(const gl::Context *context,
+ gl::TextureType type,
+ gl::SamplerFormat format,
+ MultisampleTextureInitializer *multisampleInitializer,
+ gl::Texture **textureOut);
+
+ private:
+ using TextureMapWithSamplerFormat = angle::PackedEnumMap<gl::SamplerFormat, gl::TextureMap>;
+
+ TextureMapWithSamplerFormat mIncompleteTextures;
+ gl::Buffer *mIncompleteTextureBufferAttachment;
+};
+
+// Helpers to set a matrix uniform value based on GLSL or HLSL semantics.
+// The return value indicate if the data was updated or not.
+template <int cols, int rows>
+struct SetFloatUniformMatrixGLSL
+{
+ static void Run(unsigned int arrayElementOffset,
+ unsigned int elementCount,
+ GLsizei countIn,
+ GLboolean transpose,
+ const GLfloat *value,
+ uint8_t *targetData);
+};
+
+template <int cols, int rows>
+struct SetFloatUniformMatrixHLSL
+{
+ static void Run(unsigned int arrayElementOffset,
+ unsigned int elementCount,
+ GLsizei countIn,
+ GLboolean transpose,
+ const GLfloat *value,
+ uint8_t *targetData);
+};
+
+// Helper method to de-tranpose a matrix uniform for an API query.
+void GetMatrixUniform(GLenum type, GLfloat *dataOut, const GLfloat *source, bool transpose);
+
+template <typename NonFloatT>
+void GetMatrixUniform(GLenum type, NonFloatT *dataOut, const NonFloatT *source, bool transpose);
+
+const angle::Format &GetFormatFromFormatType(GLenum format, GLenum type);
+
+angle::Result ComputeStartVertex(ContextImpl *contextImpl,
+ const gl::IndexRange &indexRange,
+ GLint baseVertex,
+ GLint *firstVertexOut);
+
+angle::Result GetVertexRangeInfo(const gl::Context *context,
+ GLint firstVertex,
+ GLsizei vertexOrIndexCount,
+ gl::DrawElementsType indexTypeOrInvalid,
+ const void *indices,
+ GLint baseVertex,
+ GLint *startVertexOut,
+ size_t *vertexCountOut);
+
+gl::Rectangle ClipRectToScissor(const gl::State &glState, const gl::Rectangle &rect, bool invertY);
+
+// Helper method to intialize a FeatureSet with overrides from the DisplayState
+void ApplyFeatureOverrides(angle::FeatureSetBase *features, const egl::DisplayState &state);
+
+template <typename In>
+uint32_t LineLoopRestartIndexCountHelper(GLsizei indexCount, const uint8_t *srcPtr)
+{
+ constexpr In restartIndex = gl::GetPrimitiveRestartIndexFromType<In>();
+ const In *inIndices = reinterpret_cast<const In *>(srcPtr);
+ uint32_t numIndices = 0;
+ // See CopyLineLoopIndicesWithRestart() below for more info on how
+ // numIndices is calculated.
+ GLsizei loopStartIndex = 0;
+ for (GLsizei curIndex = 0; curIndex < indexCount; curIndex++)
+ {
+ In vertex = inIndices[curIndex];
+ if (vertex != restartIndex)
+ {
+ numIndices++;
+ }
+ else
+ {
+ if (curIndex > loopStartIndex)
+ {
+ numIndices += 2;
+ }
+ loopStartIndex = curIndex + 1;
+ }
+ }
+ if (indexCount > loopStartIndex)
+ {
+ numIndices++;
+ }
+ return numIndices;
+}
+
+inline uint32_t GetLineLoopWithRestartIndexCount(gl::DrawElementsType glIndexType,
+ GLsizei indexCount,
+ const uint8_t *srcPtr)
+{
+ switch (glIndexType)
+ {
+ case gl::DrawElementsType::UnsignedByte:
+ return LineLoopRestartIndexCountHelper<uint8_t>(indexCount, srcPtr);
+ case gl::DrawElementsType::UnsignedShort:
+ return LineLoopRestartIndexCountHelper<uint16_t>(indexCount, srcPtr);
+ case gl::DrawElementsType::UnsignedInt:
+ return LineLoopRestartIndexCountHelper<uint32_t>(indexCount, srcPtr);
+ default:
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+// Writes the line-strip vertices for a line loop to outPtr,
+// where outLimit is calculated as in GetPrimitiveRestartIndexCount.
+template <typename In, typename Out>
+void CopyLineLoopIndicesWithRestart(GLsizei indexCount, const uint8_t *srcPtr, uint8_t *outPtr)
+{
+ constexpr In restartIndex = gl::GetPrimitiveRestartIndexFromType<In>();
+ constexpr Out outRestartIndex = gl::GetPrimitiveRestartIndexFromType<Out>();
+ const In *inIndices = reinterpret_cast<const In *>(srcPtr);
+ Out *outIndices = reinterpret_cast<Out *>(outPtr);
+ GLsizei loopStartIndex = 0;
+ for (GLsizei curIndex = 0; curIndex < indexCount; curIndex++)
+ {
+ In vertex = inIndices[curIndex];
+ if (vertex != restartIndex)
+ {
+ *(outIndices++) = static_cast<Out>(vertex);
+ }
+ else
+ {
+ if (curIndex > loopStartIndex)
+ {
+ // Emit an extra vertex only if the loop is not empty.
+ *(outIndices++) = inIndices[loopStartIndex];
+ // Then restart the strip.
+ *(outIndices++) = outRestartIndex;
+ }
+ loopStartIndex = curIndex + 1;
+ }
+ }
+ if (indexCount > loopStartIndex)
+ {
+ // Close the last loop if not empty.
+ *(outIndices++) = inIndices[loopStartIndex];
+ }
+}
+
+void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy);
+
+angle::Result MultiDrawArraysGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ GLsizei drawcount);
+angle::Result MultiDrawArraysIndirectGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride);
+angle::Result MultiDrawArraysInstancedGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount);
+angle::Result MultiDrawElementsGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ GLsizei drawcount);
+angle::Result MultiDrawElementsIndirectGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ gl::DrawElementsType type,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride);
+angle::Result MultiDrawElementsInstancedGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount);
+angle::Result MultiDrawArraysInstancedBaseInstanceGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ const GLuint *baseInstances,
+ GLsizei drawcount);
+angle::Result MultiDrawElementsInstancedBaseVertexBaseInstanceGeneral(ContextImpl *contextImpl,
+ const gl::Context *context,
+ gl::PrimitiveMode mode,
+ const GLsizei *counts,
+ gl::DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount);
+
+// RAII object making sure reset uniforms is called no matter whether there's an error in draw calls
+class ResetBaseVertexBaseInstance : angle::NonCopyable
+{
+ public:
+ ResetBaseVertexBaseInstance(gl::Program *programObject,
+ bool resetBaseVertex,
+ bool resetBaseInstance);
+
+ ~ResetBaseVertexBaseInstance();
+
+ private:
+ gl::Program *mProgramObject;
+ bool mResetBaseVertex;
+ bool mResetBaseInstance;
+};
+
+angle::FormatID ConvertToSRGB(angle::FormatID formatID);
+angle::FormatID ConvertToLinear(angle::FormatID formatID);
+bool IsOverridableLinearFormat(angle::FormatID formatID);
+
+enum class PipelineType
+{
+ Graphics = 0,
+ Compute = 1,
+
+ InvalidEnum = 2,
+ EnumCount = 2,
+};
+} // namespace rx
+
+// MultiDraw macro patterns
+// These macros are to avoid too much code duplication as we don't want to have if detect for
+// hasDrawID/BaseVertex/BaseInstance inside for loop in a multiDrawANGLE call Part of these are put
+// in the header as we want to share with specialized context impl on some platforms for multidraw
+#define ANGLE_SET_DRAW_ID_UNIFORM_0(drawID) \
+ {}
+#define ANGLE_SET_DRAW_ID_UNIFORM_1(drawID) programObject->setDrawIDUniform(drawID)
+#define ANGLE_SET_DRAW_ID_UNIFORM(cond) ANGLE_SET_DRAW_ID_UNIFORM_##cond
+
+#define ANGLE_SET_BASE_VERTEX_UNIFORM_0(baseVertex) \
+ {}
+#define ANGLE_SET_BASE_VERTEX_UNIFORM_1(baseVertex) programObject->setBaseVertexUniform(baseVertex);
+#define ANGLE_SET_BASE_VERTEX_UNIFORM(cond) ANGLE_SET_BASE_VERTEX_UNIFORM_##cond
+
+#define ANGLE_SET_BASE_INSTANCE_UNIFORM_0(baseInstance) \
+ {}
+#define ANGLE_SET_BASE_INSTANCE_UNIFORM_1(baseInstance) \
+ programObject->setBaseInstanceUniform(baseInstance)
+#define ANGLE_SET_BASE_INSTANCE_UNIFORM(cond) ANGLE_SET_BASE_INSTANCE_UNIFORM_##cond
+
+#define ANGLE_NOOP_DRAW_ context->noopDraw(mode, counts[drawID])
+#define ANGLE_NOOP_DRAW_INSTANCED \
+ context->noopDrawInstanced(mode, counts[drawID], instanceCounts[drawID])
+#define ANGLE_NOOP_DRAW(_instanced) ANGLE_NOOP_DRAW##_instanced
+
+#define ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE_ \
+ gl::MarkTransformFeedbackBufferUsage(context, counts[drawID], 1)
+#define ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE_INSTANCED \
+ gl::MarkTransformFeedbackBufferUsage(context, counts[drawID], instanceCounts[drawID])
+#define ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced) \
+ ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE##instanced
+
+// Helper macro that casts to a bitfield type then verifies no bits were dropped.
+#define SetBitField(lhs, rhs) \
+ do \
+ { \
+ auto ANGLE_LOCAL_VAR = rhs; \
+ lhs = static_cast<typename std::decay<decltype(lhs)>::type>(ANGLE_LOCAL_VAR); \
+ ASSERT(static_cast<decltype(ANGLE_LOCAL_VAR)>(lhs) == ANGLE_LOCAL_VAR); \
+ } while (0)
+
+#endif // LIBANGLE_RENDERER_RENDERER_UTILS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/serial_utils.h b/gfx/angle/checkout/src/libANGLE/renderer/serial_utils.h
new file mode 100644
index 0000000000..49a65c4e26
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/serial_utils.h
@@ -0,0 +1,126 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// serial_utils:
+// Utilities for generating unique IDs for resources in ANGLE.
+//
+
+#ifndef LIBANGLE_RENDERER_SERIAL_UTILS_H_
+#define LIBANGLE_RENDERER_SERIAL_UTILS_H_
+
+#include <atomic>
+#include <limits>
+
+#include "common/angleutils.h"
+#include "common/debug.h"
+
+namespace rx
+{
+class ResourceSerial
+{
+ public:
+ constexpr ResourceSerial() : mValue(kDirty) {}
+ explicit constexpr ResourceSerial(uintptr_t value) : mValue(value) {}
+ constexpr bool operator==(ResourceSerial other) const { return mValue == other.mValue; }
+ constexpr bool operator!=(ResourceSerial other) const { return mValue != other.mValue; }
+
+ void dirty() { mValue = kDirty; }
+ void clear() { mValue = kEmpty; }
+
+ constexpr bool valid() const { return mValue != kEmpty && mValue != kDirty; }
+ constexpr bool empty() const { return mValue == kEmpty; }
+
+ private:
+ constexpr static uintptr_t kDirty = std::numeric_limits<uintptr_t>::max();
+ constexpr static uintptr_t kEmpty = 0;
+
+ uintptr_t mValue;
+};
+
+class Serial final
+{
+ public:
+ constexpr Serial() : mValue(kInvalid) {}
+ constexpr Serial(const Serial &other) = default;
+ Serial &operator=(const Serial &other) = default;
+
+ static constexpr Serial Infinite() { return Serial(std::numeric_limits<uint64_t>::max()); }
+
+ constexpr bool operator==(const Serial &other) const
+ {
+ return mValue != kInvalid && mValue == other.mValue;
+ }
+ constexpr bool operator==(uint32_t value) const
+ {
+ return mValue != kInvalid && mValue == static_cast<uint64_t>(value);
+ }
+ constexpr bool operator!=(const Serial &other) const
+ {
+ return mValue == kInvalid || mValue != other.mValue;
+ }
+ constexpr bool operator>(const Serial &other) const { return mValue > other.mValue; }
+ constexpr bool operator>=(const Serial &other) const { return mValue >= other.mValue; }
+ constexpr bool operator<(const Serial &other) const { return mValue < other.mValue; }
+ constexpr bool operator<=(const Serial &other) const { return mValue <= other.mValue; }
+
+ constexpr bool operator<(uint32_t value) const { return mValue < static_cast<uint64_t>(value); }
+
+ // Useful for serialization.
+ constexpr uint64_t getValue() const { return mValue; }
+ constexpr bool valid() const { return mValue != kInvalid; }
+
+ private:
+ template <typename T>
+ friend class SerialFactoryBase;
+ friend class AtomicQueueSerial;
+ constexpr explicit Serial(uint64_t value) : mValue(value) {}
+ uint64_t mValue;
+ static constexpr uint64_t kInvalid = 0;
+};
+
+// Defines class to track the queue serial that can be load/store from multiple threads atomically.
+class AtomicQueueSerial final
+{
+ public:
+ constexpr AtomicQueueSerial() : mValue(kInvalid) { ASSERT(mValue.is_lock_free()); }
+ AtomicQueueSerial &operator=(const Serial &other)
+ {
+ mValue.store(other.mValue, std::memory_order_release);
+ return *this;
+ }
+ Serial getSerial() const { return Serial(mValue.load(std::memory_order_consume)); }
+
+ private:
+ std::atomic<uint64_t> mValue;
+ static constexpr uint64_t kInvalid = 0;
+};
+
+// Used as default/initial serial
+static constexpr Serial kZeroSerial = Serial();
+
+template <typename SerialBaseType>
+class SerialFactoryBase final : angle::NonCopyable
+{
+ public:
+ SerialFactoryBase() : mSerial(1) {}
+
+ Serial generate()
+ {
+ uint64_t current = mSerial++;
+ ASSERT(mSerial > current); // Integer overflow
+ return Serial(current);
+ }
+
+ private:
+ SerialBaseType mSerial;
+};
+
+using SerialFactory = SerialFactoryBase<uint64_t>;
+using AtomicSerialFactory = SerialFactoryBase<std::atomic<uint64_t>>;
+using RenderPassSerialFactory = SerialFactoryBase<uint64_t>;
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_SERIAL_UTILS_H_
diff --git a/gfx/angle/checkout/src/libANGLE/trace.h b/gfx/angle/checkout/src/libANGLE/trace.h
new file mode 100644
index 0000000000..fc8d40c646
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/trace.h
@@ -0,0 +1,26 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// trace.h: Wrappers for ANGLE trace event functions.
+//
+
+#ifndef LIBANGLE_TRACE_H_
+#define LIBANGLE_TRACE_H_
+
+#include <platform/PlatformMethods.h>
+#include "third_party/trace_event/trace_event.h"
+
+// TODO: Pass platform directly to these methods. http://anglebug.com/1892
+#define ANGLE_TRACE_EVENT_BEGIN0(CATEGORY, EVENT) \
+ TRACE_EVENT_BEGIN0(ANGLEPlatformCurrent(), CATEGORY, EVENT)
+#define ANGLE_TRACE_EVENT_END0(CATEGORY, EVENT) \
+ TRACE_EVENT_END0(ANGLEPlatformCurrent(), CATEGORY, EVENT)
+#define ANGLE_TRACE_EVENT_INSTANT0(CATEGORY, EVENT) \
+ TRACE_EVENT_INSTANT0(ANGLEPlatformCurrent(), CATEGORY, EVENT)
+#define ANGLE_TRACE_EVENT0(CATEGORY, EVENT) TRACE_EVENT0(ANGLEPlatformCurrent(), CATEGORY, EVENT)
+#define ANGLE_TRACE_EVENT1(CATEGORY, EVENT, NAME, PARAM) \
+ TRACE_EVENT1(ANGLEPlatformCurrent(), CATEGORY, EVENT, NAME, PARAM)
+
+#endif // LIBANGLE_TRACE_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationEGL.cpp b/gfx/angle/checkout/src/libANGLE/validationEGL.cpp
new file mode 100644
index 0000000000..e73535ab5c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationEGL.cpp
@@ -0,0 +1,6782 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationEGL.cpp: Validation functions for generic EGL entry point parameters
+
+#include "libANGLE/validationEGL_autogen.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Device.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/EGLSync.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Stream.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Thread.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/DisplayImpl.h"
+
+#include <EGL/eglext.h>
+
+namespace egl
+{
+namespace
+{
+size_t GetMaximumMipLevel(const gl::Context *context, gl::TextureType type)
+{
+ const gl::Caps &caps = context->getCaps();
+
+ int maxDimension = 0;
+ switch (type)
+ {
+ case gl::TextureType::_2D:
+ case gl::TextureType::_2DArray:
+ case gl::TextureType::_2DMultisample:
+ maxDimension = caps.max2DTextureSize;
+ break;
+ case gl::TextureType::Rectangle:
+ maxDimension = caps.maxRectangleTextureSize;
+ break;
+ case gl::TextureType::CubeMap:
+ maxDimension = caps.maxCubeMapTextureSize;
+ break;
+ case gl::TextureType::_3D:
+ maxDimension = caps.max3DTextureSize;
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+
+ return gl::log2(maxDimension);
+}
+
+bool TextureHasNonZeroMipLevelsSpecified(const gl::Context *context, const gl::Texture *texture)
+{
+ size_t maxMip = GetMaximumMipLevel(context, texture->getType());
+ for (size_t level = 1; level < maxMip; level++)
+ {
+ if (texture->getType() == gl::TextureType::CubeMap)
+ {
+ for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
+ {
+ if (texture->getFormat(face, level).valid())
+ {
+ return true;
+ }
+ }
+ }
+ else
+ {
+ if (texture->getFormat(gl::NonCubeTextureTypeToTarget(texture->getType()), level)
+ .valid())
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool CubeTextureHasUnspecifiedLevel0Face(const gl::Texture *texture)
+{
+ ASSERT(texture->getType() == gl::TextureType::CubeMap);
+ for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
+ {
+ if (!texture->getFormat(face, 0).valid())
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool ValidateStreamAttribute(const ValidationContext *val,
+ const EGLAttrib attribute,
+ const EGLAttrib value,
+ const DisplayExtensions &extensions)
+{
+ switch (attribute)
+ {
+ case EGL_STREAM_STATE_KHR:
+ case EGL_PRODUCER_FRAME_KHR:
+ case EGL_CONSUMER_FRAME_KHR:
+ val->setError(EGL_BAD_ACCESS, "Attempt to initialize readonly parameter");
+ return false;
+ case EGL_CONSUMER_LATENCY_USEC_KHR:
+ // Technically not in spec but a latency < 0 makes no sense so we check it
+ if (value < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Latency must be positive");
+ return false;
+ }
+ break;
+ case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
+ if (!extensions.streamConsumerGLTexture)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Consumer GL extension not enabled");
+ return false;
+ }
+ // Again not in spec but it should be positive anyways
+ if (value < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Timeout must be positive");
+ return false;
+ }
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid stream attribute");
+ return false;
+ }
+ return true;
+}
+
+bool ValidateCreateImageMipLevelCommon(const ValidationContext *val,
+ const gl::Context *context,
+ const gl::Texture *texture,
+ EGLAttrib level)
+{
+ // Note that the spec EGL_create_image spec does not explicitly specify an error
+ // when the level is outside the base/max level range, but it does mention that the
+ // level "must be a part of the complete texture object <buffer>". It can be argued
+ // that out-of-range levels are not a part of the complete texture.
+ const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
+ if (level > 0 &&
+ (!texture->isMipmapComplete() || static_cast<GLuint>(level) < effectiveBaseLevel ||
+ static_cast<GLuint>(level) > texture->getTextureState().getMipmapMaxLevel()))
+ {
+ val->setError(EGL_BAD_PARAMETER, "texture must be complete if level is non-zero.");
+ return false;
+ }
+
+ if (level == 0 && !texture->isMipmapComplete() &&
+ TextureHasNonZeroMipLevelsSpecified(context, texture))
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "if level is zero and the texture is incomplete, it must "
+ "have no mip levels specified except zero.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateConfigAttribute(const ValidationContext *val,
+ const Display *display,
+ EGLAttrib attribute)
+{
+ switch (attribute)
+ {
+ case EGL_BUFFER_SIZE:
+ case EGL_ALPHA_SIZE:
+ case EGL_BLUE_SIZE:
+ case EGL_GREEN_SIZE:
+ case EGL_RED_SIZE:
+ case EGL_DEPTH_SIZE:
+ case EGL_STENCIL_SIZE:
+ case EGL_CONFIG_CAVEAT:
+ case EGL_CONFIG_ID:
+ case EGL_LEVEL:
+ case EGL_NATIVE_RENDERABLE:
+ case EGL_NATIVE_VISUAL_ID:
+ case EGL_NATIVE_VISUAL_TYPE:
+ case EGL_SAMPLES:
+ case EGL_SAMPLE_BUFFERS:
+ case EGL_SURFACE_TYPE:
+ case EGL_TRANSPARENT_TYPE:
+ case EGL_TRANSPARENT_BLUE_VALUE:
+ case EGL_TRANSPARENT_GREEN_VALUE:
+ case EGL_TRANSPARENT_RED_VALUE:
+ case EGL_BIND_TO_TEXTURE_RGB:
+ case EGL_BIND_TO_TEXTURE_RGBA:
+ case EGL_MIN_SWAP_INTERVAL:
+ case EGL_MAX_SWAP_INTERVAL:
+ case EGL_LUMINANCE_SIZE:
+ case EGL_ALPHA_MASK_SIZE:
+ case EGL_COLOR_BUFFER_TYPE:
+ case EGL_RENDERABLE_TYPE:
+ case EGL_MATCH_NATIVE_PIXMAP:
+ case EGL_CONFORMANT:
+ case EGL_MAX_PBUFFER_WIDTH:
+ case EGL_MAX_PBUFFER_HEIGHT:
+ case EGL_MAX_PBUFFER_PIXELS:
+ break;
+
+ case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
+ if (!display->getExtensions().surfaceOrientation)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_surface_orientation is not enabled.");
+ return false;
+ }
+ break;
+
+ case EGL_COLOR_COMPONENT_TYPE_EXT:
+ if (!display->getExtensions().pixelFormatFloat)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_EXT_pixel_format_float is not enabled.");
+ return false;
+ }
+ break;
+
+ case EGL_RECORDABLE_ANDROID:
+ if (!display->getExtensions().recordable)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANDROID_recordable is not enabled.");
+ return false;
+ }
+ break;
+
+ case EGL_FRAMEBUFFER_TARGET_ANDROID:
+ if (!display->getExtensions().framebufferTargetANDROID)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANDROID_framebuffer_target is not enabled.");
+ return false;
+ }
+ break;
+
+ case EGL_BIND_TO_TEXTURE_TARGET_ANGLE:
+ if (!display->getExtensions().iosurfaceClientBuffer)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_ANGLE_iosurface_client_buffer is not enabled.");
+ return false;
+ }
+ break;
+
+ case EGL_Y_INVERTED_NOK:
+ if (!display->getExtensions().textureFromPixmapNOK)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
+ return false;
+ }
+ break;
+
+ case EGL_MATCH_FORMAT_KHR:
+ if (!display->getExtensions().lockSurface3KHR)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_KHR_lock_surface3 is not enabled.");
+ return false;
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04" PRIxPTR "X", attribute);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateConfigAttributeValue(const ValidationContext *val,
+ const Display *display,
+ EGLAttrib attribute,
+ EGLAttrib value)
+{
+ switch (attribute)
+ {
+
+ case EGL_BIND_TO_TEXTURE_RGB:
+ case EGL_BIND_TO_TEXTURE_RGBA:
+ switch (value)
+ {
+ case EGL_DONT_CARE:
+ case EGL_TRUE:
+ case EGL_FALSE:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_bind_to_texture invalid attribute: 0x%X",
+ static_cast<uint32_t>(value));
+ return false;
+ }
+ break;
+
+ case EGL_COLOR_BUFFER_TYPE:
+ switch (value)
+ {
+ case EGL_RGB_BUFFER:
+ case EGL_LUMINANCE_BUFFER:
+ // EGL_DONT_CARE doesn't match the spec, but does match dEQP usage
+ case EGL_DONT_CARE:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_color_buffer_type invalid attribute: 0x%X",
+ static_cast<uint32_t>(value));
+ return false;
+ }
+ break;
+
+ case EGL_NATIVE_RENDERABLE:
+ switch (value)
+ {
+ case EGL_DONT_CARE:
+ case EGL_TRUE:
+ case EGL_FALSE:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_native_renderable invalid attribute: 0x%X",
+ static_cast<uint32_t>(value));
+ return false;
+ }
+ break;
+
+ case EGL_TRANSPARENT_TYPE:
+ switch (value)
+ {
+ case EGL_NONE:
+ case EGL_TRANSPARENT_RGB:
+ // EGL_DONT_CARE doesn't match the spec, but does match dEQP usage
+ case EGL_DONT_CARE:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_transparent_type invalid attribute: 0x%X",
+ static_cast<uint32_t>(value));
+ return false;
+ }
+ break;
+
+ case EGL_RECORDABLE_ANDROID:
+ switch (value)
+ {
+ case EGL_TRUE:
+ case EGL_FALSE:
+ case EGL_DONT_CARE:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_RECORDABLE_ANDROID invalid attribute: 0x%X",
+ static_cast<uint32_t>(value));
+ return false;
+ }
+ break;
+
+ case EGL_COLOR_COMPONENT_TYPE_EXT:
+ switch (value)
+ {
+ case EGL_COLOR_COMPONENT_TYPE_FIXED_EXT:
+ case EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT:
+ case EGL_DONT_CARE:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_COLOR_COMPONENT_TYPE_EXT invalid attribute: 0x%X",
+ static_cast<uint32_t>(value));
+ return false;
+ }
+ break;
+
+ case EGL_MATCH_FORMAT_KHR:
+ switch (value)
+ {
+ case EGL_FORMAT_RGB_565_KHR:
+ case EGL_FORMAT_RGBA_8888_KHR:
+ case EGL_FORMAT_RGB_565_EXACT_KHR:
+ case EGL_FORMAT_RGBA_8888_EXACT_KHR:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_KHR_lock_surface3 invalid attribute: 0x%X",
+ static_cast<uint32_t>(value));
+ return false;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+bool ValidateConfigAttributes(const ValidationContext *val,
+ const Display *display,
+ const AttributeMap &attributes)
+{
+ ANGLE_VALIDATION_TRY(attributes.validate(val, display, ValidateConfigAttribute));
+
+ for (const auto &attrib : attributes)
+ {
+ EGLAttrib pname = attrib.first;
+ EGLAttrib value = attrib.second;
+ ANGLE_VALIDATION_TRY(ValidateConfigAttributeValue(val, display, pname, value));
+ }
+
+ return true;
+}
+
+bool ValidateColorspaceAttribute(const ValidationContext *val,
+ const DisplayExtensions &displayExtensions,
+ EGLAttrib colorSpace)
+{
+ switch (colorSpace)
+ {
+ case EGL_GL_COLORSPACE_SRGB:
+ break;
+ case EGL_GL_COLORSPACE_LINEAR:
+ break;
+ case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT:
+ if (!displayExtensions.glColorspaceDisplayP3Linear &&
+ !displayExtensions.eglColorspaceAttributePassthroughANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EXT_gl_colorspace_display_p3_linear is not available.");
+ return false;
+ }
+ break;
+ case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
+ if (!displayExtensions.glColorspaceDisplayP3 &&
+ !displayExtensions.eglColorspaceAttributePassthroughANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EXT_gl_colorspace_display_p3 is not available.");
+ return false;
+ }
+ break;
+ case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT:
+ if (!displayExtensions.glColorspaceDisplayP3Passthrough &&
+ !displayExtensions.eglColorspaceAttributePassthroughANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_EXT_gl_colorspace_display_p3_passthrough is not available.");
+ return false;
+ }
+ break;
+ case EGL_GL_COLORSPACE_SCRGB_EXT:
+ if (!displayExtensions.glColorspaceScrgb &&
+ !displayExtensions.eglColorspaceAttributePassthroughANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EXT_gl_colorspace_scrgb is not available.");
+ return false;
+ }
+ break;
+ case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:
+ if (!displayExtensions.glColorspaceScrgbLinear &&
+ !displayExtensions.eglColorspaceAttributePassthroughANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EXT_gl_colorspace_scrgb_linear is not available.");
+ return false;
+ }
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ return true;
+}
+bool ValidatePlatformType(const ValidationContext *val,
+ const ClientExtensions &clientExtensions,
+ EGLAttrib platformType)
+{
+ switch (platformType)
+ {
+ case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
+ case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
+ if (!clientExtensions.platformANGLED3D)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Direct3D platform is unsupported.");
+ return false;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+ if (!clientExtensions.platformANGLEOpenGL)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "OpenGL platform is unsupported.");
+ return false;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
+ if (!clientExtensions.platformANGLENULL)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Display type EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE "
+ "requires EGL_ANGLE_platform_angle_null.");
+ return false;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
+ if (!clientExtensions.platformANGLEVulkan)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Vulkan platform is unsupported.");
+ return false;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE:
+ if (!clientExtensions.platformANGLEMetal)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Metal platform is unsupported.");
+ return false;
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Unknown platform type.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetPlatformDisplayCommon(const ValidationContext *val,
+ EGLenum platform,
+ const void *native_display,
+ const AttributeMap &attribMap)
+{
+ const ClientExtensions &clientExtensions = Display::GetClientExtensions();
+
+ switch (platform)
+ {
+ case EGL_PLATFORM_ANGLE_ANGLE:
+ if (!clientExtensions.platformANGLE)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Platform ANGLE extension is not active");
+ return false;
+ }
+ break;
+ case EGL_PLATFORM_DEVICE_EXT:
+ if (!clientExtensions.platformDevice)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Platform Device extension is not active");
+ return false;
+ }
+ break;
+ case EGL_PLATFORM_GBM_KHR:
+ if (!clientExtensions.platformGbmKHR)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Platform GBM extension is not active");
+ return false;
+ }
+ break;
+ case EGL_PLATFORM_WAYLAND_EXT:
+ if (!clientExtensions.platformWaylandEXT)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Platform Wayland extension is not active");
+ return false;
+ }
+ break;
+ default:
+ val->setError(EGL_BAD_CONFIG, "Bad platform type.");
+ return false;
+ }
+
+ attribMap.initializeWithoutValidation();
+
+ if (platform != EGL_PLATFORM_DEVICE_EXT)
+ {
+ EGLAttrib platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
+ bool enableAutoTrimSpecified = false;
+ bool enableD3D11on12 = false;
+ bool presentPathSpecified = false;
+ bool luidSpecified = false;
+ bool deviceIdSpecified = false;
+
+ Optional<EGLAttrib> majorVersion;
+ Optional<EGLAttrib> minorVersion;
+ Optional<EGLAttrib> deviceType;
+ Optional<EGLAttrib> eglHandle;
+
+ for (const auto &curAttrib : attribMap)
+ {
+ const EGLAttrib value = curAttrib.second;
+
+ switch (curAttrib.first)
+ {
+ case EGL_PLATFORM_ANGLE_TYPE_ANGLE:
+ {
+ ANGLE_VALIDATION_TRY(ValidatePlatformType(val, clientExtensions, value));
+ platformType = value;
+ break;
+ }
+
+ case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE:
+ if (value != EGL_DONT_CARE)
+ {
+ majorVersion = value;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE:
+ if (value != EGL_DONT_CARE)
+ {
+ minorVersion = value;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE:
+ switch (value)
+ {
+ case EGL_TRUE:
+ case EGL_FALSE:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid automatic trim attribute");
+ return false;
+ }
+ enableAutoTrimSpecified = true;
+ break;
+
+ case EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE:
+ if (!clientExtensions.platformANGLED3D ||
+ !clientExtensions.platformANGLED3D11ON12)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE extension not active.");
+ return false;
+ }
+
+ switch (value)
+ {
+ case EGL_TRUE:
+ case EGL_FALSE:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid D3D11on12 attribute");
+ return false;
+ }
+ enableD3D11on12 = true;
+ break;
+
+ case EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE:
+ if (!clientExtensions.experimentalPresentPath)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_ANGLE_experimental_present_path extension not active");
+ return false;
+ }
+
+ switch (value)
+ {
+ case EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE:
+ case EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Invalid value for EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE");
+ return false;
+ }
+ presentPathSpecified = true;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE:
+ switch (value)
+ {
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE:
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
+ if (!clientExtensions.platformANGLED3D)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_ANGLE_platform_angle_d3d is not supported");
+ return false;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE:
+ if (!clientExtensions.platformANGLEDeviceTypeEGLANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_ANGLE_platform_angle_device_type_"
+ "egl_angle is not supported");
+ return false;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE:
+ if (!clientExtensions.platformANGLEDeviceTypeSwiftShader)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_ANGLE_platform_angle_device_type_"
+ "swiftshader is not supported");
+ return false;
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Invalid value for "
+ "EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE "
+ "attrib");
+ return false;
+ }
+ deviceType = value;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE:
+ if (!clientExtensions.platformANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_ANGLE_platform_angle extension not active");
+ return false;
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE && value != EGL_DONT_CARE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE "
+ "must be EGL_TRUE, EGL_FALSE, or "
+ "EGL_DONT_CARE.");
+ return false;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE:
+ if (value != EGL_DONT_CARE)
+ {
+ eglHandle = value;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE:
+ case EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE:
+ luidSpecified = true;
+ break;
+ case EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_EAGL_ANGLE:
+ // The property does not have an effect if it's not active, so do not check
+ // for non-support.
+ switch (value)
+ {
+ case EGL_FALSE:
+ case EGL_TRUE:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Invalid value for "
+ "EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_"
+ "EAGL_ANGLE attrib");
+ return false;
+ }
+ break;
+ case EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_CGL_ANGLE:
+ // The property does not have an effect if it's not active, so do not check
+ // for non-support.
+ switch (value)
+ {
+ case EGL_FALSE:
+ case EGL_TRUE:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Invalid value for "
+ "EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_"
+ "CGL_ANGLE attrib");
+ return false;
+ }
+ break;
+ case EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE:
+ case EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE:
+ if (!clientExtensions.platformANGLEDeviceId)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_ANGLE_platform_angle_device_id is not supported");
+ return false;
+ }
+ deviceIdSpecified = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!majorVersion.valid() && minorVersion.valid())
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Must specify major version if you specify a minor version.");
+ return false;
+ }
+
+ if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE &&
+ platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE requires a "
+ "device type of EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
+ return false;
+ }
+
+ if (enableAutoTrimSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE "
+ "requires a device type of "
+ "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
+ return false;
+ }
+
+ if (enableD3D11on12)
+ {
+ if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE "
+ "requires a platform type of "
+ "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
+ return false;
+ }
+
+ if (deviceType.valid() && deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE &&
+ deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE requires a device "
+ "type of EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE "
+ "or EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE");
+ return false;
+ }
+ }
+
+ if (presentPathSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE requires a "
+ "device type of EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
+ return false;
+ }
+
+ if (luidSpecified)
+ {
+ if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE and "
+ "EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE "
+ "require a platform type of "
+ "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
+ return false;
+ }
+
+ if (attribMap.get(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 0) == 0 &&
+ attribMap.get(EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE, 0) == 0)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "If either EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE "
+ "and/or EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE are "
+ "specified, at least one must non-zero.");
+ return false;
+ }
+ }
+
+ if (deviceIdSpecified)
+ {
+ if (attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0) == 0 &&
+ attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0) == 0)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "If either EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE "
+ "and/or EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE are "
+ "specified, at least one must non-zero.");
+ return false;
+ }
+ }
+
+ if (deviceType.valid())
+ {
+ switch (deviceType.value())
+ {
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE:
+ if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE &&
+ platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "This device type requires a "
+ "platform type of EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE or "
+ "EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE.");
+ return false;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE:
+ if (platformType != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "This device type requires a "
+ "platform type of EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE.");
+ return false;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (platformType == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
+ {
+ if ((majorVersion.valid() && majorVersion.value() != 1) ||
+ (minorVersion.valid() && minorVersion.value() != 0))
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE currently "
+ "only supports Vulkan 1.0.");
+ return false;
+ }
+ }
+
+ if (eglHandle.valid() && platformType != EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE &&
+ platformType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE requires a "
+ "device type of EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE.");
+ return false;
+ }
+ }
+ else
+ {
+ const Device *eglDevice = static_cast<const Device *>(native_display);
+ if (eglDevice == nullptr || !Device::IsValidDevice(eglDevice))
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "native_display should be a valid EGL device if "
+ "platform equals EGL_PLATFORM_DEVICE_EXT");
+ return false;
+ }
+ }
+
+ if (attribMap.contains(EGL_POWER_PREFERENCE_ANGLE))
+ {
+ if (!clientExtensions.displayPowerPreferenceANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_POWER_PREFERENCE_ANGLE "
+ "requires EGL_ANGLE_display_power_preference.");
+ return false;
+ }
+ EGLAttrib value = attribMap.get(EGL_POWER_PREFERENCE_ANGLE, 0);
+ if (value != EGL_LOW_POWER_ANGLE && value != EGL_HIGH_POWER_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_POWER_PREFERENCE_ANGLE must be "
+ "either EGL_LOW_POWER_ANGLE or EGL_HIGH_POWER_ANGLE.");
+ return false;
+ }
+ }
+
+ if (attribMap.contains(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE))
+ {
+ if (!clientExtensions.featureControlANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_feature_control is not supported");
+ return false;
+ }
+ else if (attribMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0) == 0)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_FEATURE_OVERRIDES_ENABLED_ANGLE must be a valid pointer");
+ return false;
+ }
+ }
+ if (attribMap.contains(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE))
+ {
+ if (!clientExtensions.featureControlANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_feature_control is not supported");
+ return false;
+ }
+ else if (attribMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0) == 0)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_FEATURE_OVERRIDES_DISABLED_ANGLE must be a valid pointer");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateStream(const ValidationContext *val, const Display *display, const Stream *stream)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.stream)
+ {
+ val->setError(EGL_BAD_ACCESS, "Stream extension not active");
+ return false;
+ }
+
+ if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+ {
+ val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateLabeledObject(const ValidationContext *val,
+ const Display *display,
+ ObjectType objectType,
+ EGLObjectKHR object,
+ LabeledObject **outLabeledObject)
+{
+ switch (objectType)
+ {
+ case ObjectType::Context:
+ {
+ gl::Context *context = static_cast<gl::Context *>(object);
+ ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
+ *outLabeledObject = context;
+ break;
+ }
+
+ case ObjectType::Display:
+ {
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+ if (display != object)
+ {
+ if (val)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "when object type is EGL_OBJECT_DISPLAY_KHR, the "
+ "object must be the same as the display.");
+ }
+ return false;
+ }
+
+ *outLabeledObject = static_cast<Display *>(object);
+ break;
+ }
+
+ case ObjectType::Image:
+ {
+ Image *image = static_cast<Image *>(object);
+ ANGLE_VALIDATION_TRY(ValidateImage(val, display, image));
+ *outLabeledObject = image;
+ break;
+ }
+
+ case ObjectType::Stream:
+ {
+ Stream *stream = static_cast<Stream *>(object);
+ ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
+ *outLabeledObject = stream;
+ break;
+ }
+
+ case ObjectType::Surface:
+ {
+ Surface *surface = static_cast<Surface *>(object);
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+ *outLabeledObject = surface;
+ break;
+ }
+
+ case ObjectType::Sync:
+ {
+ Sync *sync = static_cast<Sync *>(object);
+ ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
+ *outLabeledObject = sync;
+ break;
+ }
+
+ case ObjectType::Thread:
+ {
+ ASSERT(val);
+ *outLabeledObject = val->eglThread;
+ break;
+ }
+
+ default:
+ if (val)
+ {
+ val->setError(EGL_BAD_PARAMETER, "unknown object type.");
+ }
+ return false;
+ }
+
+ return true;
+}
+
+// This is a common sub-check of Display status that's shared by multiple functions
+bool ValidateDisplayPointer(const ValidationContext *val, const Display *display)
+{
+ if (display == EGL_NO_DISPLAY)
+ {
+ if (val)
+ {
+ val->setError(EGL_BAD_DISPLAY, "display is EGL_NO_DISPLAY.");
+ }
+ return false;
+ }
+
+ if (!Display::isValidDisplay(display))
+ {
+ if (val)
+ {
+ val->setError(EGL_BAD_DISPLAY, "display is not a valid display: 0x%p", display);
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidCompositorTimingName(CompositorTiming name)
+{
+ switch (name)
+ {
+ case CompositorTiming::CompositeDeadline:
+ case CompositorTiming::CompositInterval:
+ case CompositorTiming::CompositToPresentLatency:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidTimestampType(Timestamp timestamp)
+{
+ switch (timestamp)
+ {
+ case Timestamp::RequestedPresentTime:
+ case Timestamp::RenderingCompleteTime:
+ case Timestamp::CompositionLatchTime:
+ case Timestamp::FirstCompositionStartTime:
+ case Timestamp::LastCompositionStartTime:
+ case Timestamp::FirstCompositionGPUFinishedTime:
+ case Timestamp::DisplayPresentTime:
+ case Timestamp::DequeueReadyTime:
+ case Timestamp::ReadsDoneTime:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidateCompatibleSurface(const ValidationContext *val,
+ const Display *display,
+ const gl::Context *context,
+ const Surface *surface)
+{
+ const Config *contextConfig = context->getConfig();
+ const Config *surfaceConfig = surface->getConfig();
+
+ if (context->getClientType() != EGL_OPENGL_API)
+ {
+ // Surface compatible with client API - only OPENGL_ES supported
+ switch (context->getClientMajorVersion())
+ {
+ case 1:
+ if (!(surfaceConfig->renderableType & EGL_OPENGL_ES_BIT))
+ {
+ val->setError(EGL_BAD_MATCH, "Surface not compatible with OpenGL ES 1.x.");
+ return false;
+ }
+ break;
+ case 2:
+ if (!(surfaceConfig->renderableType & EGL_OPENGL_ES2_BIT))
+ {
+ val->setError(EGL_BAD_MATCH, "Surface not compatible with OpenGL ES 2.x.");
+ return false;
+ }
+ break;
+ case 3:
+ if (!(surfaceConfig->renderableType & (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT)))
+ {
+ val->setError(EGL_BAD_MATCH, "Surface not compatible with OpenGL ES 3.x.");
+ return false;
+ }
+ break;
+ default:
+ val->setError(EGL_BAD_MATCH, "Surface not compatible with Context API.");
+ return false;
+ }
+ }
+ else
+ {
+ if (!(surfaceConfig->renderableType & EGL_OPENGL_BIT))
+ {
+ val->setError(EGL_BAD_MATCH, "Surface not compatible with OpenGL Desktop.");
+ return false;
+ }
+ }
+
+ // EGL KHR no config context
+ if (context->getConfig() == EGL_NO_CONFIG_KHR)
+ {
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (displayExtensions.noConfigContext)
+ {
+ return true;
+ }
+ val->setError(EGL_BAD_MATCH, "Context with no config is not supported.");
+ return false;
+ }
+
+ // Config compatibility is defined in section 2.2 of the EGL 1.5 spec
+
+ bool colorBufferCompat = surfaceConfig->colorBufferType == contextConfig->colorBufferType;
+ if (!colorBufferCompat)
+ {
+ val->setError(EGL_BAD_MATCH, "Color buffer types are not compatible.");
+ return false;
+ }
+
+ bool colorCompat = surfaceConfig->redSize == contextConfig->redSize &&
+ surfaceConfig->greenSize == contextConfig->greenSize &&
+ surfaceConfig->blueSize == contextConfig->blueSize &&
+ surfaceConfig->alphaSize == contextConfig->alphaSize &&
+ surfaceConfig->luminanceSize == contextConfig->luminanceSize;
+ if (!colorCompat)
+ {
+ val->setError(EGL_BAD_MATCH, "Color buffer sizes are not compatible.");
+ return false;
+ }
+
+ bool componentTypeCompat =
+ surfaceConfig->colorComponentType == contextConfig->colorComponentType;
+ if (!componentTypeCompat)
+ {
+ val->setError(EGL_BAD_MATCH, "Color buffer component types are not compatible.");
+ return false;
+ }
+
+ bool dsCompat = surfaceConfig->depthSize == contextConfig->depthSize &&
+ surfaceConfig->stencilSize == contextConfig->stencilSize;
+ if (!dsCompat)
+ {
+ val->setError(EGL_BAD_MATCH, "Depth-stencil buffer types are not compatible.");
+ return false;
+ }
+
+ bool surfaceTypeCompat = (surfaceConfig->surfaceType & contextConfig->surfaceType) != 0;
+ if (!surfaceTypeCompat)
+ {
+ val->setError(EGL_BAD_MATCH, "Surface type is not compatible.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCreateSyncBase(const ValidationContext *val,
+ const Display *display,
+ EGLenum type,
+ const AttributeMap &attribs,
+ bool isExt)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ attribs.initializeWithoutValidation();
+
+ gl::Context *currentContext = val->eglThread->getContext();
+ egl::Display *currentDisplay = currentContext ? currentContext->getDisplay() : nullptr;
+
+ switch (type)
+ {
+ case EGL_SYNC_FENCE_KHR:
+ if (!attribs.isEmpty())
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+ return false;
+ }
+
+ if (!display->getExtensions().fenceSync)
+ {
+ val->setError(EGL_BAD_MATCH, "EGL_KHR_fence_sync extension is not available");
+ return false;
+ }
+
+ if (display != currentDisplay)
+ {
+ val->setError(EGL_BAD_MATCH,
+ "CreateSync can only be called on the current display");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateContext(val, currentDisplay, currentContext));
+
+ if (!currentContext->getExtensions().EGLSyncOES)
+ {
+ val->setError(EGL_BAD_MATCH,
+ "EGL_SYNC_FENCE_KHR cannot be used without "
+ "GL_OES_EGL_sync support.");
+ return false;
+ }
+ break;
+
+ case EGL_SYNC_NATIVE_FENCE_ANDROID:
+ if (!display->getExtensions().fenceSync)
+ {
+ val->setError(EGL_BAD_MATCH, "EGL_KHR_fence_sync extension is not available");
+ return false;
+ }
+
+ if (!display->getExtensions().nativeFenceSyncANDROID)
+ {
+ val->setError(EGL_BAD_DISPLAY,
+ "EGL_ANDROID_native_fence_sync extension is not available.");
+ return false;
+ }
+
+ if (display != currentDisplay)
+ {
+ val->setError(EGL_BAD_MATCH,
+ "CreateSync can only be called on the current display");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateContext(val, currentDisplay, currentContext));
+
+ if (!currentContext->getExtensions().EGLSyncOES)
+ {
+ val->setError(EGL_BAD_MATCH,
+ "EGL_SYNC_FENCE_KHR cannot be used without "
+ "GL_OES_EGL_sync support.");
+ return false;
+ }
+
+ for (const auto &attributeIter : attribs)
+ {
+ EGLAttrib attribute = attributeIter.first;
+
+ switch (attribute)
+ {
+ case EGL_SYNC_NATIVE_FENCE_FD_ANDROID:
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+ return false;
+ }
+ }
+ break;
+
+ case EGL_SYNC_REUSABLE_KHR:
+ if (!attribs.isEmpty())
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+ return false;
+ }
+
+ if (!display->getExtensions().reusableSyncKHR)
+ {
+ val->setError(EGL_BAD_MATCH, "EGL_KHR_reusable_sync extension is not available.");
+ return false;
+ }
+ break;
+
+ case EGL_SYNC_METAL_SHARED_EVENT_ANGLE:
+ if (!display->getExtensions().fenceSync)
+ {
+ val->setError(EGL_BAD_MATCH, "EGL_KHR_fence_sync extension is not available");
+ return false;
+ }
+
+ if (!display->getExtensions().mtlSyncSharedEventANGLE)
+ {
+ val->setError(EGL_BAD_DISPLAY,
+ "EGL_ANGLE_metal_shared_event_sync is not available");
+ return false;
+ }
+
+ if (display != currentDisplay)
+ {
+ val->setError(EGL_BAD_MATCH,
+ "CreateSync can only be called on the current display");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateContext(val, currentDisplay, currentContext));
+
+ // This should be implied by exposing EGL_KHR_fence_sync
+ ASSERT(currentContext->getExtensions().EGLSyncOES);
+
+ for (const auto &attributeIter : attribs)
+ {
+ EGLAttrib attribute = attributeIter.first;
+ EGLAttrib value = attributeIter.second;
+
+ switch (attribute)
+ {
+ case EGL_SYNC_METAL_SHARED_EVENT_OBJECT_ANGLE:
+ if (!value)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_SYNC_METAL_SHARED_EVENT_ANGLE can't be NULL");
+ return false;
+ }
+ break;
+
+ case EGL_SYNC_METAL_SHARED_EVENT_SIGNAL_VALUE_LO_ANGLE:
+ case EGL_SYNC_METAL_SHARED_EVENT_SIGNAL_VALUE_HI_ANGLE:
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+ return false;
+ }
+ }
+ break;
+
+ default:
+ if (isExt)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid type parameter");
+ return false;
+ }
+ else
+ {
+ val->setError(EGL_BAD_PARAMETER, "Invalid type parameter");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetSyncAttribBase(const ValidationContext *val,
+ const Display *display,
+ const Sync *sync,
+ EGLint attribute)
+{
+ ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
+
+ switch (attribute)
+ {
+ case EGL_SYNC_CONDITION_KHR:
+ switch (sync->getType())
+ {
+ case EGL_SYNC_FENCE_KHR:
+ case EGL_SYNC_NATIVE_FENCE_ANDROID:
+ case EGL_SYNC_METAL_SHARED_EVENT_ANGLE:
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_SYNC_CONDITION_KHR is not valid for this sync type.");
+ return false;
+ }
+ break;
+
+ // The following attributes are accepted by all types
+ case EGL_SYNC_TYPE_KHR:
+ case EGL_SYNC_STATUS_KHR:
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateQueryDisplayAttribBase(const ValidationContext *val,
+ const Display *display,
+ const EGLint attribute)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ switch (attribute)
+ {
+ case EGL_DEVICE_EXT:
+ if (!Display::GetClientExtensions().deviceQueryEXT)
+ {
+ val->setError(EGL_BAD_DISPLAY, "EGL_EXT_device_query extension is not available.");
+ return false;
+ }
+ break;
+
+ case EGL_FEATURE_COUNT_ANGLE:
+ if (!Display::GetClientExtensions().featureControlANGLE)
+ {
+ val->setError(EGL_BAD_DISPLAY,
+ "EGL_ANGLE_feature_control extension is not available.");
+ return false;
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "attribute is not valid.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCreateContextAttribute(const ValidationContext *val,
+ const Display *display,
+ EGLAttrib attribute)
+{
+ switch (attribute)
+ {
+ case EGL_CONTEXT_CLIENT_VERSION:
+ case EGL_CONTEXT_MINOR_VERSION:
+ case EGL_CONTEXT_FLAGS_KHR:
+ case EGL_CONTEXT_OPENGL_DEBUG:
+ break;
+
+ case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
+ if (val->eglThread->getAPI() != EGL_OPENGL_API)
+ {
+ // Only valid for OpenGL (non-ES) contexts
+ val->setError(EGL_BAD_ATTRIBUTE, "OpenGL profile mask requires an OpenGL context.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
+ if (!display->getExtensions().createContextRobustness)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
+ if (!display->getExtensions().createContextRobustness)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY:
+ {
+ // We either need to have -
+ // 1. EGL 1.5 which added support for this as part of core spec
+ // 2. EGL_KHR_create_context extension which requires EGL 1.4
+ constexpr EGLint kRequiredMajorVersion = 1;
+ constexpr EGLint kRequiredMinorVersion = 5;
+ if ((kEglMajorVersion < kRequiredMajorVersion ||
+ kEglMinorVersion < kRequiredMinorVersion) &&
+ !display->getExtensions().createContext)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+ }
+
+ case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
+ if (!display->getExtensions().createContextNoError)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid Context attribute.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE:
+ if (!display->getExtensions().createContextWebGLCompatibility)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute "
+ "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE requires "
+ "EGL_ANGLE_create_context_webgl_compatibility.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM:
+ if (!display->getExtensions().createContextBindGeneratesResource)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM requires "
+ "EGL_CHROMIUM_create_context_bind_generates_resource.");
+ return false;
+ }
+ break;
+
+ case EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE:
+ if (!display->getExtensions().displayTextureShareGroup)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute "
+ "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE requires "
+ "EGL_ANGLE_display_texture_share_group.");
+ return false;
+ }
+ break;
+
+ case EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE:
+ if (!display->getExtensions().displayTextureShareGroup)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute "
+ "EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE requires "
+ "EGL_ANGLE_display_semaphore_share_group.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE:
+ if (!display->getExtensions().createContextClientArrays)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE requires "
+ "EGL_ANGLE_create_context_client_arrays.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE:
+ if (!display->getExtensions().programCacheControlANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE "
+ "requires EGL_ANGLE_program_cache_control.");
+ return false;
+ }
+ break;
+
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ if (!display->getExtensions().robustResourceInitializationANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
+ "requires EGL_ANGLE_robust_resource_initialization.");
+ return false;
+ }
+ break;
+
+ case EGL_EXTENSIONS_ENABLED_ANGLE:
+ if (!display->getExtensions().createContextExtensionsEnabled)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_EXTENSIONS_ENABLED_ANGLE "
+ "requires EGL_ANGLE_create_context_extensions_enabled.");
+ return false;
+ }
+ break;
+
+ case EGL_POWER_PREFERENCE_ANGLE:
+ if (!display->getExtensions().powerPreference)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_POWER_PREFERENCE_ANGLE "
+ "requires EGL_ANGLE_power_preference.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE:
+ if (!display->getExtensions().createContextBackwardsCompatible)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE "
+ "requires EGL_ANGLE_create_context_backwards_compatible.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
+ if (!display->getExtensions().contextPriority)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG requires "
+ "extension EGL_IMG_context_priority.");
+ return false;
+ }
+ break;
+
+ case EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV:
+ if (!display->getExtensions().robustnessVideoMemoryPurgeNV)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV requires "
+ "extension EGL_NV_robustness_video_memory_purge.");
+ return false;
+ }
+ break;
+
+ case EGL_EXTERNAL_CONTEXT_ANGLE:
+ if (!display->getExtensions().externalContextAndSurface)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute "
+ "EGL_EXTERNAL_CONTEXT_ANGLE requires "
+ "EGL_ANGLE_external_context_and_surface.");
+ return false;
+ }
+ break;
+ case EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE:
+ if (!display->getExtensions().externalContextAndSurface)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute "
+ "EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE requires "
+ "EGL_ANGLE_external_context_and_surface.");
+ return false;
+ }
+ break;
+
+ case EGL_PROTECTED_CONTENT_EXT:
+ if (!display->getExtensions().protectedContentEXT)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
+ "extension EGL_EXT_protected_content.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE:
+ if (!display->getExtensions().contextVirtualizationANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE requires "
+ "extension EGL_ANGLE_context_virtualization.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_METAL_OWNERSHIP_IDENTITY_ANGLE:
+ if (!display->getExtensions().metalCreateContextOwnershipIdentityANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_CONTEXT_METAL_OWNERSHIP_IDENTITY_ANGLE requires "
+ "EGL_ANGLE_metal_create_context_ownership_identity.");
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04" PRIxPTR "X", attribute);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCreateContextAttributeValue(const ValidationContext *val,
+ const Display *display,
+ const gl::Context *shareContext,
+ EGLAttrib attribute,
+ EGLAttrib value)
+{
+ switch (attribute)
+ {
+ case EGL_CONTEXT_CLIENT_VERSION:
+ case EGL_CONTEXT_MINOR_VERSION:
+ case EGL_CONTEXT_OPENGL_DEBUG:
+ case EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE:
+ break;
+
+ case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
+ {
+ constexpr EGLint kValidProfileMaskFlags =
+ (EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT |
+ EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);
+ if ((value & ~kValidProfileMaskFlags) != 0)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid OpenGL profile mask.");
+ return false;
+ }
+ break;
+ }
+
+ case EGL_CONTEXT_FLAGS_KHR:
+ {
+ // Note: EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR does not apply to ES
+ constexpr EGLint kValidContextFlags =
+ (EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);
+ if ((value & ~kValidContextFlags) != 0)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+ }
+
+ case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
+ case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY:
+ if (value != EGL_LOSE_CONTEXT_ON_RESET_EXT && value != EGL_NO_RESET_NOTIFICATION_EXT)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+
+ if (shareContext && shareContext->isResetNotificationEnabled() !=
+ (value == EGL_LOSE_CONTEXT_ON_RESET_EXT))
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Attribute must be EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE:
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE must be "
+ "EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM:
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM "
+ "must be EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE:
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE must be "
+ "EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ if (shareContext &&
+ shareContext->usingDisplayTextureShareGroup() != (value == EGL_TRUE))
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "All contexts within a share group must be "
+ "created with the same value of "
+ "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE.");
+ return false;
+ }
+ break;
+
+ case EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE:
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE must be "
+ "EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ if (shareContext &&
+ shareContext->usingDisplaySemaphoreShareGroup() != (value == EGL_TRUE))
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "All contexts within a share group must be "
+ "created with the same value of "
+ "EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE:
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE must "
+ "be EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE:
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE must "
+ "be EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
+ "either EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_EXTENSIONS_ENABLED_ANGLE:
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_EXTENSIONS_ENABLED_ANGLE must be "
+ "either EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_POWER_PREFERENCE_ANGLE:
+ if (value != EGL_LOW_POWER_ANGLE && value != EGL_HIGH_POWER_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_POWER_PREFERENCE_ANGLE must be "
+ "either EGL_LOW_POWER_ANGLE or EGL_HIGH_POWER_ANGLE.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE:
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE must be "
+ "either EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
+ switch (value)
+ {
+ case EGL_CONTEXT_PRIORITY_LOW_IMG:
+ case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
+ case EGL_CONTEXT_PRIORITY_HIGH_IMG:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG "
+ "must be one of: EGL_CONTEXT_PRIORITY_LOW_IMG, "
+ "EGL_CONTEXT_PRIORITY_MEDIUM_IMG, or "
+ "EGL_CONTEXT_PRIORITY_HIGH_IMG.");
+ return false;
+ }
+ break;
+
+ case EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV:
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV must "
+ "be either EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_EXTERNAL_CONTEXT_ANGLE:
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_EXTERNAL_CONTEXT_ANGLE must "
+ "be either EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ if (shareContext && (value == EGL_TRUE))
+ {
+ val->setError(
+ EGL_BAD_ATTRIBUTE,
+ "EGL_EXTERNAL_CONTEXT_ANGLE doesn't allow creating with sharedContext.");
+ return false;
+ }
+ break;
+ case EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE:
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE must "
+ "be either EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_PROTECTED_CONTENT_EXT:
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_PROTECTED_CONTENT_EXT must "
+ "be either EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_METAL_OWNERSHIP_IDENTITY_ANGLE:
+ if (value == 0)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_CONTEXT_METAL_OWNERSHIP_IDENTITY_ANGLE must"
+ "be non-zero.");
+ return false;
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCreatePbufferSurfaceAttribute(const ValidationContext *val,
+ const Display *display,
+ EGLAttrib attribute)
+{
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+
+ switch (attribute)
+ {
+ case EGL_WIDTH:
+ case EGL_HEIGHT:
+ case EGL_LARGEST_PBUFFER:
+ case EGL_TEXTURE_FORMAT:
+ case EGL_TEXTURE_TARGET:
+ case EGL_MIPMAP_TEXTURE:
+ case EGL_VG_COLORSPACE:
+ case EGL_GL_COLORSPACE:
+ case EGL_VG_ALPHA_FORMAT:
+ break;
+
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ if (!displayExtensions.robustResourceInitializationANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
+ "requires EGL_ANGLE_robust_resource_initialization.");
+ return false;
+ }
+ break;
+
+ case EGL_PROTECTED_CONTENT_EXT:
+ if (!displayExtensions.protectedContentEXT)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
+ "extension EGL_EXT_protected_content.");
+ return false;
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCreatePbufferSurfaceAttributeValue(const ValidationContext *val,
+ const Display *display,
+ EGLAttrib attribute,
+ EGLAttrib value)
+{
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+
+ switch (attribute)
+ {
+ case EGL_WIDTH:
+ case EGL_HEIGHT:
+ if (value < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER);
+ return false;
+ }
+ break;
+
+ case EGL_LARGEST_PBUFFER:
+ break;
+
+ case EGL_TEXTURE_FORMAT:
+ switch (value)
+ {
+ case EGL_NO_TEXTURE:
+ case EGL_TEXTURE_RGB:
+ case EGL_TEXTURE_RGBA:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+
+ case EGL_TEXTURE_TARGET:
+ switch (value)
+ {
+ case EGL_NO_TEXTURE:
+ case EGL_TEXTURE_2D:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+
+ case EGL_MIPMAP_TEXTURE:
+ break;
+
+ case EGL_VG_COLORSPACE:
+ break;
+
+ case EGL_GL_COLORSPACE:
+ ANGLE_VALIDATION_TRY(ValidateColorspaceAttribute(val, displayExtensions, value));
+ break;
+
+ case EGL_VG_ALPHA_FORMAT:
+ break;
+
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ ASSERT(displayExtensions.robustResourceInitializationANGLE);
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
+ "either EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_PROTECTED_CONTENT_EXT:
+ ASSERT(displayExtensions.protectedContentEXT);
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_PROTECTED_CONTENT_EXT must "
+ "be either EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+
+ return true;
+}
+} // anonymous namespace
+
+void ValidationContext::setError(EGLint error) const
+{
+ eglThread->setError(error, entryPoint, labeledObject, nullptr);
+}
+
+void ValidationContext::setError(EGLint error, const char *message...) const
+{
+ ASSERT(message);
+
+ constexpr uint32_t kBufferSize = 1000;
+ char buffer[kBufferSize];
+
+ va_list args;
+ va_start(args, message);
+ vsnprintf(buffer, kBufferSize, message, args);
+
+ eglThread->setError(error, entryPoint, labeledObject, buffer);
+}
+
+bool ValidateDisplay(const ValidationContext *val, const Display *display)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplayPointer(val, display));
+
+ if (!display->isInitialized())
+ {
+ if (val)
+ {
+ val->setError(EGL_NOT_INITIALIZED, "display is not initialized.");
+ }
+ return false;
+ }
+
+ if (display->isDeviceLost())
+ {
+ if (val)
+ {
+ val->setError(EGL_CONTEXT_LOST, "display had a context loss");
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSurface(const ValidationContext *val, const Display *display, const Surface *surface)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->isValidSurface(surface))
+ {
+ if (val)
+ {
+ val->setError(EGL_BAD_SURFACE);
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateConfig(const ValidationContext *val, const Display *display, const Config *config)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->isValidConfig(config))
+ {
+ if (val)
+ {
+ val->setError(EGL_BAD_CONFIG);
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateContext(const ValidationContext *val,
+ const Display *display,
+ const gl::Context *context)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->isValidContext(context))
+ {
+ if (val)
+ {
+ val->setError(EGL_BAD_CONTEXT);
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateImage(const ValidationContext *val, const Display *display, const Image *image)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->isValidImage(image))
+ {
+ if (val)
+ {
+ val->setError(EGL_BAD_PARAMETER, "image is not valid.");
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDevice(const ValidationContext *val, const Device *device)
+{
+ if (device == EGL_NO_DEVICE_EXT)
+ {
+ if (val)
+ {
+ val->setError(EGL_BAD_ACCESS, "device is EGL_NO_DEVICE.");
+ }
+ return false;
+ }
+
+ if (!Device::IsValidDevice(device))
+ {
+ if (val)
+ {
+ val->setError(EGL_BAD_ACCESS, "device is not valid.");
+ }
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSync(const ValidationContext *val, const Display *display, const Sync *sync)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->isValidSync(sync))
+ {
+ if (val)
+ {
+ val->setError(EGL_BAD_PARAMETER, "sync object is not valid.");
+ }
+ return false;
+ }
+
+ return true;
+}
+
+const Thread *GetThreadIfValid(const Thread *thread)
+{
+ // Threads should always be valid
+ return thread;
+}
+
+const Display *GetDisplayIfValid(const Display *display)
+{
+ return ValidateDisplay(nullptr, display) ? display : nullptr;
+}
+
+const Surface *GetSurfaceIfValid(const Display *display, const Surface *surface)
+{
+ return ValidateSurface(nullptr, display, surface) ? surface : nullptr;
+}
+
+const Image *GetImageIfValid(const Display *display, const Image *image)
+{
+ return ValidateImage(nullptr, display, image) ? image : nullptr;
+}
+
+const Stream *GetStreamIfValid(const Display *display, const Stream *stream)
+{
+ return ValidateStream(nullptr, display, stream) ? stream : nullptr;
+}
+
+const gl::Context *GetContextIfValid(const Display *display, const gl::Context *context)
+{
+ return ValidateContext(nullptr, display, context) ? context : nullptr;
+}
+
+const Device *GetDeviceIfValid(const Device *device)
+{
+ return ValidateDevice(nullptr, device) ? device : nullptr;
+}
+
+const Sync *GetSyncIfValid(const Display *display, const Sync *sync)
+{
+ return ValidateSync(nullptr, display, sync) ? sync : nullptr;
+}
+
+LabeledObject *GetLabeledObjectIfValid(Thread *thread,
+ const Display *display,
+ ObjectType objectType,
+ EGLObjectKHR object)
+{
+ if (objectType == ObjectType::Thread)
+ {
+ return thread;
+ }
+
+ LabeledObject *labeledObject = nullptr;
+ if (ValidateLabeledObject(nullptr, display, objectType, object, &labeledObject))
+ {
+ return labeledObject;
+ }
+
+ return nullptr;
+}
+
+bool ValidateInitialize(const ValidationContext *val,
+ const Display *display,
+ const EGLint *major,
+ const EGLint *minor)
+{
+ return ValidateDisplayPointer(val, display);
+}
+
+bool ValidateTerminate(const ValidationContext *val, const Display *display)
+{
+ return ValidateDisplayPointer(val, display);
+}
+
+bool ValidateCreateContext(const ValidationContext *val,
+ const Display *display,
+ const Config *configuration,
+ const gl::Context *shareContext,
+ const AttributeMap &attributes)
+{
+ if (configuration)
+ {
+ ANGLE_VALIDATION_TRY(ValidateConfig(val, display, configuration));
+ }
+ else
+ {
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.noConfigContext)
+ {
+ val->setError(EGL_BAD_CONFIG);
+ return false;
+ }
+ }
+
+ ANGLE_VALIDATION_TRY(attributes.validate(val, display, ValidateCreateContextAttribute));
+
+ for (const auto &attributePair : attributes)
+ {
+ EGLAttrib attribute = attributePair.first;
+ EGLAttrib value = attributePair.second;
+ ANGLE_VALIDATION_TRY(
+ ValidateCreateContextAttributeValue(val, display, shareContext, attribute, value));
+ }
+
+ // Get the requested client version (default is 1) and check it is 2 or 3.
+ EGLAttrib clientMajorVersion = attributes.get(EGL_CONTEXT_CLIENT_VERSION, 1);
+ EGLAttrib clientMinorVersion = attributes.get(EGL_CONTEXT_MINOR_VERSION, 0);
+ EGLenum api = val->eglThread->getAPI();
+
+ switch (api)
+ {
+ case EGL_OPENGL_ES_API:
+ switch (clientMajorVersion)
+ {
+ case 1:
+ if (clientMinorVersion != 0 && clientMinorVersion != 1)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ if (configuration == EGL_NO_CONFIG_KHR)
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+ if ((configuration != EGL_NO_CONFIG_KHR) &&
+ !(configuration->renderableType & EGL_OPENGL_ES_BIT))
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+ break;
+
+ case 2:
+ if (clientMinorVersion != 0)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ if ((configuration != EGL_NO_CONFIG_KHR) &&
+ !(configuration->renderableType & EGL_OPENGL_ES2_BIT))
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+ break;
+ case 3:
+ if (clientMinorVersion < 0 || clientMinorVersion > 2)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ if ((configuration != EGL_NO_CONFIG_KHR) &&
+ !(configuration->renderableType & EGL_OPENGL_ES3_BIT))
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+ if (display->getMaxSupportedESVersion() <
+ gl::Version(static_cast<GLuint>(clientMajorVersion),
+ static_cast<GLuint>(clientMinorVersion)))
+ {
+ gl::Version max = display->getMaxSupportedESVersion();
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Requested GLES version (%" PRIxPTR ".%" PRIxPTR
+ ") is greater than "
+ "max supported (%d, %d).",
+ clientMajorVersion, clientMinorVersion, max.major, max.minor);
+ return false;
+ }
+ if ((attributes.get(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE, EGL_FALSE) ==
+ EGL_TRUE) &&
+ (clientMinorVersion > 1))
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Requested GLES version (%" PRIxPTR ".%" PRIxPTR
+ ") is greater than "
+ "max supported 3.1 for WebGL.",
+ clientMajorVersion, clientMinorVersion);
+ return false;
+ }
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+
+ case EGL_OPENGL_API:
+ // The requested configuration must use EGL_OPENGL_BIT if EGL_OPENGL_BIT is the
+ // currently bound API.
+ if ((configuration != EGL_NO_CONFIG_KHR) &&
+ !(configuration->renderableType & EGL_OPENGL_BIT))
+ {
+ val->setError(EGL_BAD_CONFIG);
+ return false;
+ }
+ // TODO(http://anglebug.com/7533): validate desktop OpenGL versions and profile mask
+ break;
+
+ default:
+ val->setError(EGL_BAD_MATCH, "Unsupported API.");
+ return false;
+ }
+
+ if (shareContext)
+ {
+ // Shared context is invalid or is owned by another display
+ if (!display->isValidContext(shareContext))
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateCreateWindowSurface(const ValidationContext *val,
+ const Display *display,
+ const Config *config,
+ EGLNativeWindowType window,
+ const AttributeMap &attributes)
+{
+ ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
+
+ if (!display->isValidNativeWindow(window))
+ {
+ val->setError(EGL_BAD_NATIVE_WINDOW);
+ return false;
+ }
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+
+ attributes.initializeWithoutValidation();
+
+ for (const auto &attributeIter : attributes)
+ {
+ EGLAttrib attribute = attributeIter.first;
+ EGLAttrib value = attributeIter.second;
+
+ switch (attribute)
+ {
+ case EGL_RENDER_BUFFER:
+ switch (value)
+ {
+ case EGL_BACK_BUFFER:
+ break;
+ case EGL_SINGLE_BUFFER:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+
+ case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+ if (!displayExtensions.postSubBuffer)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+
+ case EGL_WIDTH:
+ case EGL_HEIGHT:
+ if (!displayExtensions.windowFixedSize)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ if (value < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER);
+ return false;
+ }
+ break;
+
+ case EGL_FIXED_SIZE_ANGLE:
+ if (!displayExtensions.windowFixedSize)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+
+ case EGL_SURFACE_ORIENTATION_ANGLE:
+ if (!displayExtensions.surfaceOrientation)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_ANGLE_surface_orientation is not enabled.");
+ return false;
+ }
+ break;
+
+ case EGL_VG_COLORSPACE:
+ if (value != EGL_VG_COLORSPACE_sRGB)
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+ break;
+
+ case EGL_GL_COLORSPACE:
+ ANGLE_VALIDATION_TRY(ValidateColorspaceAttribute(val, displayExtensions, value));
+ break;
+
+ case EGL_VG_ALPHA_FORMAT:
+ val->setError(EGL_BAD_MATCH);
+ return false;
+
+ case EGL_DIRECT_COMPOSITION_ANGLE:
+ if (!displayExtensions.directComposition)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ if (!display->getExtensions().robustResourceInitializationANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
+ "requires EGL_ANGLE_robust_resource_initialization.");
+ return false;
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
+ "either EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_GGP_STREAM_DESCRIPTOR_ANGLE:
+ if (!display->getExtensions().ggpStreamDescriptor)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_GGP_STREAM_DESCRIPTOR_ANGLE requires "
+ "EGL_ANGLE_ggp_stream_descriptor.");
+ return false;
+ }
+ break;
+
+ case EGL_PROTECTED_CONTENT_EXT:
+ if (!displayExtensions.protectedContentEXT)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
+ "extension EGL_EXT_protected_content.");
+ return false;
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_PROTECTED_CONTENT_EXT must "
+ "be either EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_SWAP_INTERVAL_ANGLE:
+ if (!displayExtensions.createSurfaceSwapIntervalANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_SWAP_INTERVAL_ANGLE requires "
+ "extension EGL_ANGLE_create_surface_swap_interval.");
+ return false;
+ }
+ if (value < config->minSwapInterval || value > config->maxSwapInterval)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_SWAP_INTERVAL_ANGLE must "
+ "be within the EGLConfig min and max swap intervals.");
+ return false;
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ }
+
+ if (Display::hasExistingWindowSurface(window))
+ {
+ val->setError(EGL_BAD_ALLOC);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCreatePbufferSurface(const ValidationContext *val,
+ const Display *display,
+ const Config *config,
+ const AttributeMap &attributes)
+{
+ ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
+ ANGLE_VALIDATION_TRY(attributes.validate(val, display, ValidateCreatePbufferSurfaceAttribute));
+
+ for (const auto &attributeIter : attributes)
+ {
+ EGLAttrib attribute = attributeIter.first;
+ EGLAttrib value = attributeIter.second;
+
+ ANGLE_VALIDATION_TRY(
+ ValidateCreatePbufferSurfaceAttributeValue(val, display, attribute, value));
+ }
+
+ if ((config->surfaceType & EGL_PBUFFER_BIT) == 0)
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+
+ const Caps &caps = display->getCaps();
+
+ EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
+ EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
+
+ if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
+ (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+
+ if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
+ (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+
+ EGLint width = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
+ EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
+ if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT &&
+ (!gl::isPow2(width) || !gl::isPow2(height)))
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCreatePbufferFromClientBuffer(const ValidationContext *val,
+ const Display *display,
+ EGLenum buftype,
+ EGLClientBuffer buffer,
+ const Config *config,
+ const AttributeMap &attributes)
+{
+ ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+
+ attributes.initializeWithoutValidation();
+
+ switch (buftype)
+ {
+ case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+ if (!displayExtensions.d3dShareHandleClientBuffer)
+ {
+ val->setError(EGL_BAD_PARAMETER);
+ return false;
+ }
+ if (buffer == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER);
+ return false;
+ }
+ break;
+
+ case EGL_D3D_TEXTURE_ANGLE:
+ if (!displayExtensions.d3dTextureClientBuffer)
+ {
+ val->setError(EGL_BAD_PARAMETER);
+ return false;
+ }
+ if (buffer == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER);
+ return false;
+ }
+ break;
+
+ case EGL_IOSURFACE_ANGLE:
+ if (!displayExtensions.iosurfaceClientBuffer)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "<buftype> EGL_IOSURFACE_ANGLE requires the "
+ "EGL_ANGLE_iosurface_client_buffer extension.");
+ return false;
+ }
+ if (buffer == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "<buffer> must be non null");
+ return false;
+ }
+ break;
+ case EGL_EXTERNAL_SURFACE_ANGLE:
+ if (!display->getExtensions().externalContextAndSurface)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute "
+ "EGL_EXTERNAL_SURFACE_ANGLE requires "
+ "EGL_ANGLE_external_context_and_surface.");
+ return false;
+ }
+ if (buffer != nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "<buffer> must be null");
+ return false;
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_PARAMETER);
+ return false;
+ }
+
+ for (AttributeMap::const_iterator attributeIter = attributes.begin();
+ attributeIter != attributes.end(); attributeIter++)
+ {
+ EGLAttrib attribute = attributeIter->first;
+ EGLAttrib value = attributeIter->second;
+
+ switch (attribute)
+ {
+ case EGL_WIDTH:
+ case EGL_HEIGHT:
+ if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE &&
+ buftype != EGL_D3D_TEXTURE_ANGLE && buftype != EGL_IOSURFACE_ANGLE &&
+ buftype != EGL_EXTERNAL_SURFACE_ANGLE)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "Width and Height are not supported for this <buftype>");
+ return false;
+ }
+ if (value < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Width and Height must be positive");
+ return false;
+ }
+ break;
+
+ case EGL_TEXTURE_FORMAT:
+ switch (value)
+ {
+ case EGL_NO_TEXTURE:
+ case EGL_TEXTURE_RGB:
+ case EGL_TEXTURE_RGBA:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid value for EGL_TEXTURE_FORMAT");
+ return false;
+ }
+ break;
+
+ case EGL_TEXTURE_TARGET:
+ switch (value)
+ {
+ case EGL_NO_TEXTURE:
+ case EGL_TEXTURE_2D:
+ break;
+ case EGL_TEXTURE_RECTANGLE_ANGLE:
+ if (buftype != EGL_IOSURFACE_ANGLE)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "<buftype> doesn't support rectangle texture targets");
+ return false;
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid value for EGL_TEXTURE_TARGET");
+ return false;
+ }
+ break;
+
+ case EGL_MIPMAP_TEXTURE:
+ break;
+
+ case EGL_IOSURFACE_PLANE_ANGLE:
+ if (buftype != EGL_IOSURFACE_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "<buftype> doesn't support iosurface plane");
+ return false;
+ }
+ break;
+
+ case EGL_TEXTURE_TYPE_ANGLE:
+ if (buftype != EGL_IOSURFACE_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "<buftype> doesn't support texture type");
+ return false;
+ }
+ break;
+
+ case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
+ if (buftype != EGL_IOSURFACE_ANGLE && buftype != EGL_D3D_TEXTURE_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "<buftype> doesn't support texture internal format");
+ return false;
+ }
+ break;
+
+ case EGL_GL_COLORSPACE:
+ if (buftype != EGL_D3D_TEXTURE_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "<buftype> doesn't support setting GL colorspace");
+ return false;
+ }
+ break;
+
+ case EGL_IOSURFACE_USAGE_HINT_ANGLE:
+ if (value & ~(EGL_IOSURFACE_READ_HINT_ANGLE | EGL_IOSURFACE_WRITE_HINT_ANGLE))
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "IOSurface usage hint must only contain READ or WRITE");
+ return false;
+ }
+ break;
+
+ case EGL_TEXTURE_OFFSET_X_ANGLE:
+ case EGL_TEXTURE_OFFSET_Y_ANGLE:
+ if (buftype != EGL_D3D_TEXTURE_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "<buftype> doesn't support setting texture offset");
+ return false;
+ }
+ break;
+
+ case EGL_PROTECTED_CONTENT_EXT:
+ if (!displayExtensions.protectedContentEXT)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
+ "extension EGL_EXT_protected_content.");
+ return false;
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_PROTECTED_CONTENT_EXT must "
+ "be either EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ }
+
+ EGLAttrib colorspace = attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR);
+ if (colorspace != EGL_GL_COLORSPACE_LINEAR && colorspace != EGL_GL_COLORSPACE_SRGB)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "invalid GL colorspace");
+ return false;
+ }
+
+ if (!(config->surfaceType & EGL_PBUFFER_BIT))
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+
+ EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
+ EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
+ if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
+ (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+ if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
+ (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
+ {
+ // TODO(cwallez@chromium.org): For IOSurface pbuffers we require that EGL_TEXTURE_RGBA is
+ // set so that eglBindTexImage works. Normally this is only allowed if the config exposes
+ // the bindToTextureRGB/RGBA flag. This issue is that enabling this flags means that
+ // eglBindTexImage should also work for regular pbuffers which isn't implemented on macOS.
+ // Instead of adding the flag we special case the check here to be ignored for IOSurfaces.
+ // The TODO is to find a proper solution for this, maybe by implementing eglBindTexImage on
+ // OSX?
+ if (buftype != EGL_IOSURFACE_ANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ }
+
+ if (buftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
+ {
+ EGLint width = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
+ EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
+
+ if (width == 0 || height == 0)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+
+ const Caps &caps = display->getCaps();
+ if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT &&
+ (!gl::isPow2(width) || !gl::isPow2(height)))
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+ }
+
+ if (buftype == EGL_IOSURFACE_ANGLE)
+ {
+ if (static_cast<EGLenum>(textureTarget) != config->bindToTextureTarget)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_IOSURFACE requires the texture target to match the config");
+ return false;
+ }
+ if (textureFormat != EGL_TEXTURE_RGBA)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_IOSURFACE requires the EGL_TEXTURE_RGBA format");
+ return false;
+ }
+
+ if (!attributes.contains(EGL_WIDTH) || !attributes.contains(EGL_HEIGHT) ||
+ !attributes.contains(EGL_TEXTURE_FORMAT) ||
+ !attributes.contains(EGL_TEXTURE_TYPE_ANGLE) ||
+ !attributes.contains(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE) ||
+ !attributes.contains(EGL_IOSURFACE_PLANE_ANGLE))
+ {
+ val->setError(EGL_BAD_PARAMETER, "Missing required attribute for EGL_IOSURFACE");
+ return false;
+ }
+ }
+
+ ANGLE_EGL_TRY_RETURN(val->eglThread,
+ display->validateClientBuffer(config, buftype, buffer, attributes),
+ val->entryPoint, val->labeledObject, false);
+
+ return true;
+}
+
+bool ValidateCreatePixmapSurface(const ValidationContext *val,
+ const Display *display,
+ const Config *config,
+ EGLNativePixmapType pixmap,
+ const AttributeMap &attributes)
+{
+ ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+
+ attributes.initializeWithoutValidation();
+
+ for (const auto &attributePair : attributes)
+ {
+ EGLAttrib attribute = attributePair.first;
+ EGLAttrib value = attributePair.second;
+
+ switch (attribute)
+ {
+ case EGL_GL_COLORSPACE:
+ ANGLE_VALIDATION_TRY(ValidateColorspaceAttribute(val, displayExtensions, value));
+ break;
+
+ case EGL_VG_COLORSPACE:
+ break;
+ case EGL_VG_ALPHA_FORMAT:
+ break;
+
+ case EGL_TEXTURE_FORMAT:
+ if (!displayExtensions.textureFromPixmapNOK)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
+ return false;
+ }
+ switch (value)
+ {
+ case EGL_NO_TEXTURE:
+ case EGL_TEXTURE_RGB:
+ case EGL_TEXTURE_RGBA:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+
+ case EGL_TEXTURE_TARGET:
+ if (!displayExtensions.textureFromPixmapNOK)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
+ return false;
+ }
+ switch (value)
+ {
+ case EGL_NO_TEXTURE:
+ case EGL_TEXTURE_2D:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+
+ case EGL_MIPMAP_TEXTURE:
+ if (!displayExtensions.textureFromPixmapNOK)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
+ return false;
+ }
+ break;
+
+ case EGL_PROTECTED_CONTENT_EXT:
+ if (!displayExtensions.protectedContentEXT)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
+ "extension EGL_EXT_protected_content.");
+ return false;
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_PROTECTED_CONTENT_EXT must "
+ "be either EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04" PRIxPTR, attribute);
+ return false;
+ }
+ }
+
+ if (!(config->surfaceType & EGL_PIXMAP_BIT))
+ {
+ val->setError(EGL_BAD_MATCH, "Congfig does not suport pixmaps.");
+ return false;
+ }
+
+ ANGLE_EGL_TRY_RETURN(val->eglThread, display->valdiatePixmap(config, pixmap, attributes),
+ val->entryPoint, val->labeledObject, false);
+
+ return true;
+}
+
+bool ValidateMakeCurrent(const ValidationContext *val,
+ const Display *display,
+ const Surface *draw,
+ const Surface *read,
+ const gl::Context *context)
+{
+ if (context == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
+ {
+ val->setError(EGL_BAD_MATCH, "If ctx is EGL_NO_CONTEXT, surfaces must be EGL_NO_SURFACE");
+ return false;
+ }
+
+ // If ctx is EGL_NO_CONTEXT and either draw or read are not EGL_NO_SURFACE, an EGL_BAD_MATCH
+ // error is generated. EGL_KHR_surfaceless_context allows both surfaces to be EGL_NO_SURFACE.
+ if (context != EGL_NO_CONTEXT && (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE))
+ {
+ if (display->getExtensions().surfacelessContext)
+ {
+ if ((draw == EGL_NO_SURFACE) != (read == EGL_NO_SURFACE))
+ {
+ val->setError(EGL_BAD_MATCH,
+ "If ctx is not EGL_NOT_CONTEXT, draw or read must "
+ "both be EGL_NO_SURFACE, or both not");
+ return false;
+ }
+ }
+ else
+ {
+ val->setError(EGL_BAD_MATCH,
+ "If ctx is not EGL_NO_CONTEXT, surfaces must not be EGL_NO_SURFACE");
+ return false;
+ }
+ }
+
+ // If either of draw or read is a valid surface and the other is EGL_NO_SURFACE, an
+ // EGL_BAD_MATCH error is generated.
+ if ((read == EGL_NO_SURFACE) != (draw == EGL_NO_SURFACE))
+ {
+ val->setError(EGL_BAD_MATCH,
+ "read and draw must both be valid surfaces, or both be EGL_NO_SURFACE");
+ return false;
+ }
+
+ if (display == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
+ {
+ val->setError(EGL_BAD_DISPLAY, "'dpy' not a valid EGLDisplay handle");
+ return false;
+ }
+
+ // EGL 1.5 spec: dpy can be uninitialized if all other parameters are null
+ if (!display->isInitialized() &&
+ (context != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
+ {
+ val->setError(EGL_NOT_INITIALIZED, "'dpy' not initialized");
+ return false;
+ }
+
+ if (context != EGL_NO_CONTEXT)
+ {
+ ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
+ }
+
+ if (display->isInitialized() && display->isDeviceLost())
+ {
+ val->setError(EGL_CONTEXT_LOST);
+ return false;
+ }
+
+ if (draw != EGL_NO_SURFACE)
+ {
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, draw));
+ }
+
+ if (read != EGL_NO_SURFACE)
+ {
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, read));
+ ANGLE_VALIDATION_TRY(ValidateCompatibleSurface(val, display, context, read));
+ }
+
+ if (draw != read)
+ {
+ if (draw)
+ {
+ ANGLE_VALIDATION_TRY(ValidateCompatibleSurface(val, display, context, draw));
+ }
+ if (read)
+ {
+ ANGLE_VALIDATION_TRY(ValidateCompatibleSurface(val, display, context, read));
+ }
+ }
+ return true;
+}
+
+bool ValidateCreateImage(const ValidationContext *val,
+ const Display *display,
+ const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const AttributeMap &attributes)
+{
+
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ attributes.initializeWithoutValidation();
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+
+ // TODO(geofflang): Complete validation from EGL_KHR_image_base:
+ // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and <attrib_list> is itself an
+ // EGLImage sibling, the error EGL_BAD_ACCESS is generated.
+
+ for (AttributeMap::const_iterator attributeIter = attributes.begin();
+ attributeIter != attributes.end(); attributeIter++)
+ {
+ EGLAttrib attribute = attributeIter->first;
+ EGLAttrib value = attributeIter->second;
+
+ switch (attribute)
+ {
+ case EGL_IMAGE_PRESERVED:
+ switch (value)
+ {
+ case EGL_TRUE:
+ case EGL_FALSE:
+ break;
+
+ default:
+ val->setError(EGL_BAD_PARAMETER,
+ "EGL_IMAGE_PRESERVED must be EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_GL_TEXTURE_LEVEL:
+ if (!displayExtensions.glTexture2DImage &&
+ !displayExtensions.glTextureCubemapImage && !displayExtensions.glTexture3DImage)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "EGL_GL_TEXTURE_LEVEL cannot be used "
+ "without KHR_gl_texture_*_image support.");
+ return false;
+ }
+
+ if (value < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "EGL_GL_TEXTURE_LEVEL cannot be negative.");
+ return false;
+ }
+ break;
+
+ case EGL_GL_TEXTURE_ZOFFSET:
+ if (!displayExtensions.glTexture3DImage)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "EGL_GL_TEXTURE_ZOFFSET cannot be used "
+ "without KHR_gl_texture_3D_image support.");
+ return false;
+ }
+ break;
+
+ case EGL_GL_COLORSPACE:
+ if (!displayExtensions.glColorspace)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "EGL_GL_COLORSPACE cannot be used "
+ "without EGL_KHR_gl_colorspace support.");
+ return false;
+ }
+ switch (value)
+ {
+ case EGL_GL_COLORSPACE_DEFAULT_EXT:
+ break;
+ default:
+ ANGLE_VALIDATION_TRY(
+ ValidateColorspaceAttribute(val, displayExtensions, value));
+ break;
+ }
+ break;
+
+ case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
+ if (!displayExtensions.imageD3D11Texture && !displayExtensions.vulkanImageANGLE)
+ {
+ val->setError(
+ EGL_BAD_PARAMETER,
+ "EGL_TEXTURE_INTERNAL_FORMAT_ANGLE cannot be used without "
+ "EGL_ANGLE_image_d3d11_texture or EGL_ANGLE_vulkan_image support.");
+ return false;
+ }
+ break;
+
+ case EGL_D3D11_TEXTURE_PLANE_ANGLE:
+ if (!displayExtensions.imageD3D11Texture)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_D3D11_TEXTURE_PLANE_ANGLE cannot be used without "
+ "EGL_ANGLE_image_d3d11_texture support.");
+ return false;
+ }
+ break;
+
+ case EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE:
+ if (!displayExtensions.imageD3D11Texture)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE cannot be used without "
+ "EGL_ANGLE_image_d3d11_texture support.");
+ return false;
+ }
+ break;
+
+ case EGL_WIDTH:
+ case EGL_HEIGHT:
+ if (target != EGL_LINUX_DMA_BUF_EXT)
+ {
+ val->setError(
+ EGL_BAD_PARAMETER,
+ "Parameter cannot be used if target is not EGL_LINUX_DMA_BUF_EXT");
+ return false;
+ }
+ break;
+
+ case EGL_LINUX_DRM_FOURCC_EXT:
+ case EGL_DMA_BUF_PLANE0_FD_EXT:
+ case EGL_DMA_BUF_PLANE0_OFFSET_EXT:
+ case EGL_DMA_BUF_PLANE0_PITCH_EXT:
+ case EGL_DMA_BUF_PLANE1_FD_EXT:
+ case EGL_DMA_BUF_PLANE1_OFFSET_EXT:
+ case EGL_DMA_BUF_PLANE1_PITCH_EXT:
+ case EGL_DMA_BUF_PLANE2_FD_EXT:
+ case EGL_DMA_BUF_PLANE2_OFFSET_EXT:
+ case EGL_DMA_BUF_PLANE2_PITCH_EXT:
+ if (!displayExtensions.imageDmaBufImportEXT)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "Parameter cannot be used without "
+ "EGL_EXT_image_dma_buf_import support.");
+ return false;
+ }
+ break;
+
+ case EGL_YUV_COLOR_SPACE_HINT_EXT:
+ if (!displayExtensions.imageDmaBufImportEXT)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "Parameter cannot be used without "
+ "EGL_EXT_image_dma_buf_import support.");
+ return false;
+ }
+
+ switch (value)
+ {
+ case EGL_ITU_REC601_EXT:
+ case EGL_ITU_REC709_EXT:
+ case EGL_ITU_REC2020_EXT:
+ break;
+
+ default:
+ val->setError(EGL_BAD_PARAMETER,
+ "Invalid value for EGL_YUV_COLOR_SPACE_HINT_EXT.");
+ return false;
+ }
+ break;
+
+ case EGL_SAMPLE_RANGE_HINT_EXT:
+ if (!displayExtensions.imageDmaBufImportEXT)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "Parameter cannot be used without "
+ "EGL_EXT_image_dma_buf_import support.");
+ return false;
+ }
+
+ switch (value)
+ {
+ case EGL_YUV_FULL_RANGE_EXT:
+ case EGL_YUV_NARROW_RANGE_EXT:
+ break;
+
+ default:
+ val->setError(EGL_BAD_PARAMETER,
+ "Invalid value for EGL_SAMPLE_RANGE_HINT_EXT.");
+ return false;
+ }
+ break;
+
+ case EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT:
+ case EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT:
+ if (!displayExtensions.imageDmaBufImportEXT)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "Parameter cannot be used without "
+ "EGL_EXT_image_dma_buf_import support.");
+ return false;
+ }
+
+ switch (value)
+ {
+ case EGL_YUV_CHROMA_SITING_0_EXT:
+ case EGL_YUV_CHROMA_SITING_0_5_EXT:
+ break;
+
+ default:
+ val->setError(
+ EGL_BAD_PARAMETER,
+ "Invalid value for EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT or "
+ "EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT.");
+ return false;
+ }
+ break;
+
+ case EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT:
+ case EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT:
+ case EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT:
+ case EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT:
+ case EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT:
+ case EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT:
+ case EGL_DMA_BUF_PLANE3_FD_EXT:
+ case EGL_DMA_BUF_PLANE3_OFFSET_EXT:
+ case EGL_DMA_BUF_PLANE3_PITCH_EXT:
+ case EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT:
+ case EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT:
+ if (!displayExtensions.imageDmaBufImportModifiersEXT)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "Parameter cannot be used without "
+ "EGL_EXT_image_dma_buf_import_modifiers support.");
+ return false;
+ }
+ break;
+
+ case EGL_PROTECTED_CONTENT_EXT:
+ if (!displayExtensions.protectedContentEXT)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
+ "extension EGL_EXT_protected_content.");
+ return false;
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_PROTECTED_CONTENT_EXT must "
+ "be either EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+
+ case EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE:
+ case EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE:
+ if (!displayExtensions.vulkanImageANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_VULKAN_IMAGE_CREATE_INFO_{HI,LO}_ANGLE require "
+ "extension EGL_ANGLE_vulkan_image.");
+ return false;
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_PARAMETER, "invalid attribute: 0x%04" PRIxPTR "X", attribute);
+ return false;
+ }
+ }
+
+ switch (target)
+ {
+ case EGL_GL_TEXTURE_2D:
+ {
+ if (!displayExtensions.glTexture2DImage)
+ {
+ val->setError(EGL_BAD_PARAMETER, "KHR_gl_texture_2D_image not supported.");
+ return false;
+ }
+
+ if (buffer == 0)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "buffer cannot reference a 2D texture with the name 0.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
+ const gl::Texture *texture =
+ context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
+ if (texture == nullptr || texture->getType() != gl::TextureType::_2D)
+ {
+ val->setError(EGL_BAD_PARAMETER, "target is not a 2D texture.");
+ return false;
+ }
+
+ if (texture->getBoundSurface() != nullptr)
+ {
+ val->setError(EGL_BAD_ACCESS, "texture has a surface bound to it.");
+ return false;
+ }
+
+ EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
+ if (texture->getWidth(gl::TextureTarget::_2D, static_cast<size_t>(level)) == 0 ||
+ texture->getHeight(gl::TextureTarget::_2D, static_cast<size_t>(level)) == 0)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "target 2D texture does not have a valid size at specified level.");
+ return false;
+ }
+
+ bool protectedContentAttrib =
+ (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
+ if (protectedContentAttrib != texture->hasProtectedContent())
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
+ "of target.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
+ }
+ break;
+
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ {
+ if (!displayExtensions.glTextureCubemapImage)
+ {
+ val->setError(EGL_BAD_PARAMETER, "KHR_gl_texture_cubemap_image not supported.");
+ return false;
+ }
+
+ if (buffer == 0)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "buffer cannot reference a cubemap texture with the name 0.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
+ const gl::Texture *texture =
+ context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
+ if (texture == nullptr || texture->getType() != gl::TextureType::CubeMap)
+ {
+ val->setError(EGL_BAD_PARAMETER, "target is not a cubemap texture.");
+ return false;
+ }
+
+ if (texture->getBoundSurface() != nullptr)
+ {
+ val->setError(EGL_BAD_ACCESS, "texture has a surface bound to it.");
+ return false;
+ }
+
+ EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
+ gl::TextureTarget cubeMapFace = egl_gl::EGLCubeMapTargetToCubeMapTarget(target);
+ if (texture->getWidth(cubeMapFace, static_cast<size_t>(level)) == 0 ||
+ texture->getHeight(cubeMapFace, static_cast<size_t>(level)) == 0)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "target cubemap texture does not have a valid "
+ "size at specified level and face.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
+
+ if (level == 0 && !texture->isMipmapComplete() &&
+ CubeTextureHasUnspecifiedLevel0Face(texture))
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "if level is zero and the texture is incomplete, "
+ "it must have all of its faces specified at level "
+ "zero.");
+ return false;
+ }
+
+ bool protectedContentAttrib =
+ (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
+ if (protectedContentAttrib != texture->hasProtectedContent())
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
+ "of target.");
+ return false;
+ }
+ }
+ break;
+
+ case EGL_GL_TEXTURE_3D:
+ {
+ if (!displayExtensions.glTexture3DImage)
+ {
+ val->setError(EGL_BAD_PARAMETER, "KHR_gl_texture_3D_image not supported.");
+ return false;
+ }
+
+ if (buffer == 0)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "buffer cannot reference a 3D texture with the name 0.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
+ const gl::Texture *texture =
+ context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
+ if (texture == nullptr || texture->getType() != gl::TextureType::_3D)
+ {
+ val->setError(EGL_BAD_PARAMETER, "target is not a 3D texture.");
+ return false;
+ }
+
+ if (texture->getBoundSurface() != nullptr)
+ {
+ val->setError(EGL_BAD_ACCESS, "texture has a surface bound to it.");
+ return false;
+ }
+
+ EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
+ EGLAttrib zOffset = attributes.get(EGL_GL_TEXTURE_ZOFFSET, 0);
+ if (texture->getWidth(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0 ||
+ texture->getHeight(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0 ||
+ texture->getDepth(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "target 3D texture does not have a valid size at specified level.");
+ return false;
+ }
+
+ if (static_cast<size_t>(zOffset) >=
+ texture->getDepth(gl::TextureTarget::_3D, static_cast<size_t>(level)))
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "target 3D texture does not have enough layers "
+ "for the specified Z offset at the specified "
+ "level.");
+ return false;
+ }
+
+ bool protectedContentAttrib =
+ (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
+ if (protectedContentAttrib != texture->hasProtectedContent())
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
+ "of target.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
+ }
+ break;
+
+ case EGL_GL_RENDERBUFFER:
+ {
+ if (!displayExtensions.glRenderbufferImage)
+ {
+ val->setError(EGL_BAD_PARAMETER, "KHR_gl_renderbuffer_image not supported.");
+ return false;
+ }
+
+ if (attributes.contains(EGL_GL_TEXTURE_LEVEL))
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "EGL_GL_TEXTURE_LEVEL cannot be used in "
+ "conjunction with a renderbuffer target.");
+ return false;
+ }
+
+ if (buffer == 0)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "buffer cannot reference a renderbuffer with the name 0.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
+ const gl::Renderbuffer *renderbuffer =
+ context->getRenderbuffer({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
+ if (renderbuffer == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "target is not a renderbuffer.");
+ return false;
+ }
+
+ if (renderbuffer->getSamples() > 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "target renderbuffer cannot be multisampled.");
+ return false;
+ }
+
+ bool protectedContentAttrib =
+ (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
+ if (protectedContentAttrib != renderbuffer->hasProtectedContent())
+ {
+ val->setError(EGL_BAD_ACCESS,
+ "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
+ "of target.");
+ return false;
+ }
+ }
+ break;
+
+ case EGL_NATIVE_BUFFER_ANDROID:
+ {
+ if (!displayExtensions.imageNativeBuffer)
+ {
+ val->setError(EGL_BAD_PARAMETER, "EGL_ANDROID_image_native_buffer not supported.");
+ return false;
+ }
+
+ if (context != nullptr)
+ {
+ val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
+ return false;
+ }
+
+ ANGLE_EGL_TRY_RETURN(
+ val->eglThread,
+ display->validateImageClientBuffer(context, target, buffer, attributes),
+ val->entryPoint, val->labeledObject, false);
+ }
+ break;
+
+ case EGL_D3D11_TEXTURE_ANGLE:
+ if (!displayExtensions.imageD3D11Texture)
+ {
+ val->setError(EGL_BAD_PARAMETER, "EGL_ANGLE_image_d3d11_texture not supported.");
+ return false;
+ }
+
+ if (context != nullptr)
+ {
+ val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
+ return false;
+ }
+
+ ANGLE_EGL_TRY_RETURN(
+ val->eglThread,
+ display->validateImageClientBuffer(context, target, buffer, attributes),
+ val->entryPoint, val->labeledObject, false);
+ break;
+
+ case EGL_LINUX_DMA_BUF_EXT:
+ if (!displayExtensions.imageDmaBufImportEXT)
+ {
+ val->setError(EGL_BAD_PARAMETER, "EGL_EXT_image_dma_buf_import not supported.");
+ return false;
+ }
+
+ if (context != nullptr)
+ {
+ val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
+ return false;
+ }
+
+ if (buffer != nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "buffer must be NULL.");
+ return false;
+ }
+
+ {
+ EGLenum kRequiredParameters[] = {EGL_WIDTH,
+ EGL_HEIGHT,
+ EGL_LINUX_DRM_FOURCC_EXT,
+ EGL_DMA_BUF_PLANE0_FD_EXT,
+ EGL_DMA_BUF_PLANE0_OFFSET_EXT,
+ EGL_DMA_BUF_PLANE0_PITCH_EXT};
+ for (EGLenum requiredParameter : kRequiredParameters)
+ {
+ if (!attributes.contains(requiredParameter))
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "Missing required parameter 0x%X for image target "
+ "EGL_LINUX_DMA_BUF_EXT.",
+ requiredParameter);
+ return false;
+ }
+ }
+
+ bool containPlane0ModifierLo =
+ attributes.contains(EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT);
+ bool containPlane0ModifierHi =
+ attributes.contains(EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT);
+ bool containPlane1ModifierLo =
+ attributes.contains(EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT);
+ bool containPlane1ModifierHi =
+ attributes.contains(EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT);
+ bool containPlane2ModifierLo =
+ attributes.contains(EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT);
+ bool containPlane2ModifierHi =
+ attributes.contains(EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT);
+ bool containPlane3ModifierLo =
+ attributes.contains(EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT);
+ bool containPlane3ModifierHi =
+ attributes.contains(EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT);
+ if ((containPlane0ModifierLo ^ containPlane0ModifierHi) ||
+ (containPlane1ModifierLo ^ containPlane1ModifierHi) ||
+ (containPlane2ModifierLo ^ containPlane2ModifierHi) ||
+ (containPlane3ModifierLo ^ containPlane3ModifierHi))
+ {
+ val->setError(
+ EGL_BAD_PARAMETER,
+ "the list of attributes contains EGL_DMA_BUF_PLANE*_MODIFIER_LO_EXT "
+ "but not EGL_DMA_BUF_PLANE*_MODIFIER_HI_EXT or vice versa.");
+ return false;
+ }
+ }
+ break;
+
+ case EGL_METAL_TEXTURE_ANGLE:
+ if (!displayExtensions.mtlTextureClientBuffer)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "EGL_ANGLE_metal_texture_client_buffer not supported.");
+ return false;
+ }
+
+ if (context != nullptr)
+ {
+ val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
+ return false;
+ }
+
+ ANGLE_EGL_TRY_RETURN(
+ val->eglThread,
+ display->validateImageClientBuffer(context, target, buffer, attributes),
+ val->entryPoint, val->labeledObject, false);
+ break;
+ case EGL_VULKAN_IMAGE_ANGLE:
+ if (!displayExtensions.vulkanImageANGLE)
+ {
+ val->setError(EGL_BAD_PARAMETER, "EGL_ANGLE_vulkan_image not supported.");
+ return false;
+ }
+
+ if (context != nullptr)
+ {
+ val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
+ return false;
+ }
+
+ {
+ const EGLenum kRequiredParameters[] = {
+ EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE,
+ EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE,
+ };
+ for (EGLenum requiredParameter : kRequiredParameters)
+ {
+ if (!attributes.contains(requiredParameter))
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "Missing required parameter 0x%X for image target "
+ "EGL_VULKAN_IMAGE_ANGLE.",
+ requiredParameter);
+ return false;
+ }
+ }
+ }
+
+ ANGLE_EGL_TRY_RETURN(
+ val->eglThread,
+ display->validateImageClientBuffer(context, target, buffer, attributes),
+ val->entryPoint, val->labeledObject, false);
+ break;
+ default:
+ val->setError(EGL_BAD_PARAMETER, "invalid target: 0x%X", target);
+ return false;
+ }
+
+ if (attributes.contains(EGL_GL_TEXTURE_ZOFFSET) && target != EGL_GL_TEXTURE_3D)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "EGL_GL_TEXTURE_ZOFFSET must be used with a 3D texture target.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDestroyImage(const ValidationContext *val, const Display *display, const Image *image)
+{
+ ANGLE_VALIDATION_TRY(ValidateImage(val, display, image));
+
+ return true;
+}
+
+bool ValidateCreateImageKHR(const ValidationContext *val,
+ const Display *display,
+ const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const AttributeMap &attributes)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().imageBase && !display->getExtensions().image)
+ {
+ // It is out of spec what happens when calling an extension function when the extension is
+ // not available.
+ // EGL_BAD_DISPLAY seems like a reasonable error.
+ val->setError(EGL_BAD_DISPLAY, "EGL_KHR_image not supported.");
+ return false;
+ }
+
+ return ValidateCreateImage(val, display, context, target, buffer, attributes);
+}
+
+bool ValidateDestroyImageKHR(const ValidationContext *val,
+ const Display *display,
+ const Image *image)
+{
+ ANGLE_VALIDATION_TRY(ValidateImage(val, display, image));
+
+ if (!display->getExtensions().imageBase && !display->getExtensions().image)
+ {
+ // It is out of spec what happens when calling an extension function when the extension is
+ // not available.
+ // EGL_BAD_DISPLAY seems like a reasonable error.
+ val->setError(EGL_BAD_DISPLAY);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCreateDeviceANGLE(const ValidationContext *val,
+ EGLint device_type,
+ const void *native_device,
+ const EGLAttrib *attrib_list)
+{
+ const ClientExtensions &clientExtensions = Display::GetClientExtensions();
+ if (!clientExtensions.deviceCreation)
+ {
+ val->setError(EGL_BAD_ACCESS, "Device creation extension not active");
+ return false;
+ }
+
+ if (attrib_list != nullptr && attrib_list[0] != EGL_NONE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid attrib_list parameter");
+ return false;
+ }
+
+ switch (device_type)
+ {
+ case EGL_D3D11_DEVICE_ANGLE:
+ if (!clientExtensions.deviceCreationD3D11)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "D3D11 device creation extension not active");
+ return false;
+ }
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid device_type parameter");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateReleaseDeviceANGLE(const ValidationContext *val, const Device *device)
+{
+ const ClientExtensions &clientExtensions = Display::GetClientExtensions();
+ if (!clientExtensions.deviceCreation)
+ {
+ val->setError(EGL_BAD_ACCESS, "Device creation extension not active");
+ return false;
+ }
+
+ if (device == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(device))
+ {
+ val->setError(EGL_BAD_DEVICE_EXT, "Invalid device parameter");
+ return false;
+ }
+
+ Display *owningDisplay = device->getOwningDisplay();
+ if (owningDisplay != nullptr)
+ {
+ val->setError(EGL_BAD_DEVICE_EXT, "Device must have been created using eglCreateDevice");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCreateSync(const ValidationContext *val,
+ const Display *display,
+ EGLenum type,
+ const AttributeMap &attribs)
+{
+ return ValidateCreateSyncBase(val, display, type, attribs, false);
+}
+
+bool ValidateCreateSyncKHR(const ValidationContext *val,
+ const Display *display,
+ EGLenum type,
+ const AttributeMap &attribs)
+{
+ return ValidateCreateSyncBase(val, display, type, attribs, true);
+}
+
+bool ValidateDestroySync(const ValidationContext *val, const Display *display, const Sync *sync)
+{
+ ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
+ return true;
+}
+
+bool ValidateDestroySyncKHR(const ValidationContext *val,
+ const Display *dpyPacked,
+ const Sync *syncPacked)
+{
+ return ValidateDestroySync(val, dpyPacked, syncPacked);
+}
+
+bool ValidateClientWaitSync(const ValidationContext *val,
+ const Display *display,
+ const Sync *sync,
+ EGLint flags,
+ EGLTime timeout)
+{
+ ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
+ return true;
+}
+
+bool ValidateClientWaitSyncKHR(const ValidationContext *val,
+ const Display *dpyPacked,
+ const Sync *syncPacked,
+ EGLint flags,
+ EGLTimeKHR timeout)
+{
+ return ValidateClientWaitSync(val, dpyPacked, syncPacked, flags, timeout);
+}
+
+bool ValidateWaitSync(const ValidationContext *val,
+ const Display *display,
+ const Sync *sync,
+ EGLint flags)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ const DisplayExtensions &extensions = display->getExtensions();
+ if (!extensions.waitSync)
+ {
+ val->setError(EGL_BAD_ACCESS, "EGL_KHR_wait_sync extension is not available");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
+
+ gl::Context *context = val->eglThread->getContext();
+ if (context == nullptr)
+ {
+ val->setError(EGL_BAD_MATCH, "No context is current.");
+ return false;
+ }
+
+ if (!context->getExtensions().EGLSyncOES)
+ {
+ val->setError(EGL_BAD_MATCH,
+ "Server-side waits cannot be performed without "
+ "GL_OES_EGL_sync support.");
+ return false;
+ }
+
+ if (flags != 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "flags must be zero");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateWaitSyncKHR(const ValidationContext *val,
+ const Display *dpyPacked,
+ const Sync *syncPacked,
+ EGLint flags)
+{
+ return ValidateWaitSync(val, dpyPacked, syncPacked, flags);
+}
+
+bool ValidateGetSyncAttrib(const ValidationContext *val,
+ const Display *display,
+ const Sync *sync,
+ EGLint attribute,
+ const EGLAttrib *value)
+{
+ if (value == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Invalid value parameter");
+ return false;
+ }
+ return ValidateGetSyncAttribBase(val, display, sync, attribute);
+}
+
+bool ValidateGetSyncAttribKHR(const ValidationContext *val,
+ const Display *display,
+ const Sync *sync,
+ EGLint attribute,
+ const EGLint *value)
+{
+ if (value == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Invalid value parameter");
+ return false;
+ }
+ return ValidateGetSyncAttribBase(val, display, sync, attribute);
+}
+
+bool ValidateCreateStreamKHR(const ValidationContext *val,
+ const Display *display,
+ const AttributeMap &attributes)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.stream)
+ {
+ val->setError(EGL_BAD_ALLOC, "Stream extension not active");
+ return false;
+ }
+
+ attributes.initializeWithoutValidation();
+
+ for (const auto &attributeIter : attributes)
+ {
+ EGLAttrib attribute = attributeIter.first;
+ EGLAttrib value = attributeIter.second;
+
+ ANGLE_VALIDATION_TRY(ValidateStreamAttribute(val, attribute, value, displayExtensions));
+ }
+
+ return true;
+}
+
+bool ValidateDestroyStreamKHR(const ValidationContext *val,
+ const Display *display,
+ const Stream *stream)
+{
+ ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
+ return true;
+}
+
+bool ValidateStreamAttribKHR(const ValidationContext *val,
+ const Display *display,
+ const Stream *stream,
+ EGLenum attribute,
+ EGLint value)
+{
+ ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
+
+ if (stream->getState() == EGL_STREAM_STATE_DISCONNECTED_KHR)
+ {
+ val->setError(EGL_BAD_STATE_KHR, "Bad stream state");
+ return false;
+ }
+
+ return ValidateStreamAttribute(val, attribute, value, display->getExtensions());
+}
+
+bool ValidateQueryStreamKHR(const ValidationContext *val,
+ const Display *display,
+ const Stream *stream,
+ EGLenum attribute,
+ const EGLint *value)
+{
+ ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
+
+ switch (attribute)
+ {
+ case EGL_STREAM_STATE_KHR:
+ case EGL_CONSUMER_LATENCY_USEC_KHR:
+ break;
+ case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
+ if (!display->getExtensions().streamConsumerGLTexture)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Consumer GLTexture extension not active");
+ return false;
+ }
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateQueryStreamu64KHR(const ValidationContext *val,
+ const Display *display,
+ const Stream *stream,
+ EGLenum attribute,
+ const EGLuint64KHR *value)
+{
+ ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
+
+ switch (attribute)
+ {
+ case EGL_CONSUMER_FRAME_KHR:
+ case EGL_PRODUCER_FRAME_KHR:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStreamConsumerGLTextureExternalKHR(const ValidationContext *val,
+ const Display *display,
+ const Stream *stream)
+{
+ gl::Context *context = val->eglThread->getContext();
+ ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamConsumerGLTexture)
+ {
+ val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
+ return false;
+ }
+
+ if (!context->getExtensions().EGLStreamConsumerExternalNV)
+ {
+ val->setError(EGL_BAD_ACCESS, "EGL stream consumer external GL extension not enabled");
+ return false;
+ }
+
+ if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+ {
+ val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
+ return false;
+ }
+
+ if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
+ {
+ val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
+ return false;
+ }
+
+ // Lookup the texture and ensure it is correct
+ gl::Texture *texture = context->getState().getTargetTexture(gl::TextureType::External);
+ if (texture == nullptr || texture->id().value == 0)
+ {
+ val->setError(EGL_BAD_ACCESS, "No external texture bound");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStreamConsumerAcquireKHR(const ValidationContext *val,
+ const Display *display,
+ const Stream *stream)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamConsumerGLTexture)
+ {
+ val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
+ return false;
+ }
+
+ if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+ {
+ val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
+ return false;
+ }
+
+ gl::Context *context = val->eglThread->getContext();
+ if (!context)
+ {
+ val->setError(EGL_BAD_ACCESS, "No GL context current to calling thread.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
+
+ if (!stream->isConsumerBoundToContext(context))
+ {
+ val->setError(EGL_BAD_ACCESS, "Current GL context not associated with stream consumer");
+ return false;
+ }
+
+ if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
+ stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
+ {
+ val->setError(EGL_BAD_ACCESS, "Invalid stream consumer type");
+ return false;
+ }
+
+ // Note: technically EGL_STREAM_STATE_EMPTY_KHR is a valid state when the timeout is non-zero.
+ // However, the timeout is effectively ignored since it has no useful functionality with the
+ // current producers that are implemented, so we don't allow that state
+ if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
+ stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
+ {
+ val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStreamConsumerReleaseKHR(const ValidationContext *val,
+ const Display *display,
+ const Stream *stream)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamConsumerGLTexture)
+ {
+ val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
+ return false;
+ }
+
+ if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+ {
+ val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
+ return false;
+ }
+
+ gl::Context *context = val->eglThread->getContext();
+ if (!context)
+ {
+ val->setError(EGL_BAD_ACCESS, "No GL context current to calling thread.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
+
+ if (!stream->isConsumerBoundToContext(context))
+ {
+ val->setError(EGL_BAD_ACCESS, "Current GL context not associated with stream consumer");
+ return false;
+ }
+
+ if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
+ stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
+ {
+ val->setError(EGL_BAD_ACCESS, "Invalid stream consumer type");
+ return false;
+ }
+
+ if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
+ stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
+ {
+ val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStreamConsumerGLTextureExternalAttribsNV(const ValidationContext *val,
+ const Display *display,
+ const Stream *stream,
+ const AttributeMap &attribs)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamConsumerGLTexture)
+ {
+ val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
+ return false;
+ }
+
+ gl::Context *context = val->eglThread->getContext();
+ ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
+
+ // Although technically not a requirement in spec, the context needs to be checked for support
+ // for external textures or future logic will cause assertations. This extension is also
+ // effectively useless without external textures.
+ if (!context->getExtensions().EGLStreamConsumerExternalNV)
+ {
+ val->setError(EGL_BAD_ACCESS, "EGL stream consumer external GL extension not enabled");
+ return false;
+ }
+
+ if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
+ {
+ val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
+ return false;
+ }
+
+ if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
+ {
+ val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
+ return false;
+ }
+
+ const gl::Caps &glCaps = context->getCaps();
+
+ EGLAttrib colorBufferType = EGL_RGB_BUFFER;
+ EGLAttrib planeCount = -1;
+ EGLAttrib plane[3];
+ for (int i = 0; i < 3; i++)
+ {
+ plane[i] = -1;
+ }
+
+ attribs.initializeWithoutValidation();
+
+ for (const auto &attributeIter : attribs)
+ {
+ EGLAttrib attribute = attributeIter.first;
+ EGLAttrib value = attributeIter.second;
+
+ switch (attribute)
+ {
+ case EGL_COLOR_BUFFER_TYPE:
+ if (value != EGL_RGB_BUFFER && value != EGL_YUV_BUFFER_EXT)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Invalid color buffer type");
+ return false;
+ }
+ colorBufferType = value;
+ break;
+ case EGL_YUV_NUMBER_OF_PLANES_EXT:
+ // planeCount = -1 is a tag for the default plane count so the value must be checked
+ // to be positive here to ensure future logic doesn't break on invalid negative
+ // inputs
+ if (value < 0)
+ {
+ val->setError(EGL_BAD_MATCH, "Invalid plane count");
+ return false;
+ }
+ planeCount = value;
+ break;
+ default:
+ if (attribute >= EGL_YUV_PLANE0_TEXTURE_UNIT_NV &&
+ attribute <= EGL_YUV_PLANE2_TEXTURE_UNIT_NV)
+ {
+ if ((value < 0 ||
+ value >= static_cast<EGLAttrib>(glCaps.maxCombinedTextureImageUnits)) &&
+ value != EGL_NONE)
+ {
+ val->setError(EGL_BAD_ACCESS, "Invalid texture unit");
+ return false;
+ }
+ plane[attribute - EGL_YUV_PLANE0_TEXTURE_UNIT_NV] = value;
+ }
+ else
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+ return false;
+ }
+ }
+ }
+
+ if (colorBufferType == EGL_RGB_BUFFER)
+ {
+ if (planeCount > 0)
+ {
+ val->setError(EGL_BAD_MATCH, "Plane count must be 0 for RGB buffer");
+ return false;
+ }
+ for (int i = 0; i < 3; i++)
+ {
+ if (plane[i] != -1)
+ {
+ val->setError(EGL_BAD_MATCH, "Planes cannot be specified");
+ return false;
+ }
+ }
+
+ // Lookup the texture and ensure it is correct
+ gl::Texture *texture = context->getState().getTargetTexture(gl::TextureType::External);
+ if (texture == nullptr || texture->id().value == 0)
+ {
+ val->setError(EGL_BAD_ACCESS, "No external texture bound");
+ return false;
+ }
+ }
+ else
+ {
+ if (planeCount == -1)
+ {
+ planeCount = 2;
+ }
+ if (planeCount < 1 || planeCount > 3)
+ {
+ val->setError(EGL_BAD_MATCH, "Invalid YUV plane count");
+ return false;
+ }
+ for (EGLAttrib i = planeCount; i < 3; i++)
+ {
+ if (plane[i] != -1)
+ {
+ val->setError(EGL_BAD_MATCH, "Invalid plane specified");
+ return false;
+ }
+ }
+
+ // Set to ensure no texture is referenced more than once
+ std::set<gl::Texture *> textureSet;
+ for (EGLAttrib i = 0; i < planeCount; i++)
+ {
+ if (plane[i] == -1)
+ {
+ val->setError(EGL_BAD_MATCH, "Not all planes specified");
+ return false;
+ }
+ if (plane[i] != EGL_NONE)
+ {
+ gl::Texture *texture = context->getState().getSamplerTexture(
+ static_cast<unsigned int>(plane[i]), gl::TextureType::External);
+ if (texture == nullptr || texture->id().value == 0)
+ {
+ val->setError(
+ EGL_BAD_ACCESS,
+ "No external texture bound at one or more specified texture units");
+ return false;
+ }
+ if (textureSet.find(texture) != textureSet.end())
+ {
+ val->setError(EGL_BAD_ACCESS, "Multiple planes bound to same texture object");
+ return false;
+ }
+ textureSet.insert(texture);
+ }
+ }
+ }
+
+ return true;
+}
+
+bool ValidateCreateStreamProducerD3DTextureANGLE(const ValidationContext *val,
+ const Display *display,
+ const Stream *stream,
+ const AttributeMap &attribs)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamProducerD3DTexture)
+ {
+ val->setError(EGL_BAD_ACCESS, "Stream producer extension not active");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
+
+ attribs.initializeWithoutValidation();
+
+ if (!attribs.isEmpty())
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+ return false;
+ }
+
+ if (stream->getState() != EGL_STREAM_STATE_CONNECTING_KHR)
+ {
+ val->setError(EGL_BAD_STATE_KHR, "Stream not in connecting state");
+ return false;
+ }
+
+ switch (stream->getConsumerType())
+ {
+ case Stream::ConsumerType::GLTextureYUV:
+ if (stream->getPlaneCount() != 2)
+ {
+ val->setError(EGL_BAD_MATCH, "Incompatible stream consumer type");
+ return false;
+ }
+ break;
+
+ case Stream::ConsumerType::GLTextureRGB:
+ if (stream->getPlaneCount() != 1)
+ {
+ val->setError(EGL_BAD_MATCH, "Incompatible stream consumer type");
+ return false;
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_MATCH, "Incompatible stream consumer type");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStreamPostD3DTextureANGLE(const ValidationContext *val,
+ const Display *display,
+ const Stream *stream,
+ const void *texture,
+ const AttributeMap &attribs)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.streamProducerD3DTexture)
+ {
+ val->setError(EGL_BAD_ACCESS, "Stream producer extension not active");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
+
+ attribs.initializeWithoutValidation();
+
+ for (auto &attributeIter : attribs)
+ {
+ EGLAttrib attribute = attributeIter.first;
+ EGLAttrib value = attributeIter.second;
+
+ switch (attribute)
+ {
+ case EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE:
+ if (value < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Invalid subresource index");
+ return false;
+ }
+ break;
+ case EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG:
+ if (value < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Invalid plane offset");
+ return false;
+ }
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
+ return false;
+ }
+ }
+
+ if (stream->getState() != EGL_STREAM_STATE_EMPTY_KHR &&
+ stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
+ stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
+ {
+ val->setError(EGL_BAD_STATE_KHR, "Stream not fully configured");
+ return false;
+ }
+
+ if (stream->getProducerType() != Stream::ProducerType::D3D11Texture)
+ {
+ val->setError(EGL_BAD_MATCH, "Incompatible stream producer");
+ return false;
+ }
+
+ if (texture == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Texture is null");
+ return false;
+ }
+
+ ANGLE_EGL_TRY_RETURN(val->eglThread, stream->validateD3D11Texture(texture, attribs),
+ val->entryPoint, val->labeledObject, false);
+
+ return true;
+}
+
+bool ValidateSyncControlCHROMIUM(const ValidationContext *val,
+ const Display *display,
+ const Surface *eglSurface)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.syncControlCHROMIUM)
+ {
+ val->setError(EGL_BAD_ACCESS, "syncControlCHROMIUM extension not active");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSyncControlRateANGLE(const ValidationContext *val,
+ const Display *display,
+ const Surface *eglSurface)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+ if (!displayExtensions.syncControlRateANGLE)
+ {
+ val->setError(EGL_BAD_ACCESS, "syncControlRateANGLE extension not active");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetMscRateANGLE(const ValidationContext *val,
+ const Display *display,
+ const Surface *eglSurface,
+ const EGLint *numerator,
+ const EGLint *denominator)
+{
+ ANGLE_VALIDATION_TRY(ValidateSyncControlRateANGLE(val, display, eglSurface));
+
+ if (numerator == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "numerator is null");
+ return false;
+ }
+ if (denominator == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "denominator is null");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetSyncValuesCHROMIUM(const ValidationContext *val,
+ const Display *display,
+ const Surface *eglSurface,
+ const EGLuint64KHR *ust,
+ const EGLuint64KHR *msc,
+ const EGLuint64KHR *sbc)
+{
+ ANGLE_VALIDATION_TRY(ValidateSyncControlCHROMIUM(val, display, eglSurface));
+
+ if (ust == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "ust is null");
+ return false;
+ }
+ if (msc == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "msc is null");
+ return false;
+ }
+ if (sbc == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "sbc is null");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDestroySurface(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface)
+{
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+ return true;
+}
+
+bool ValidateDestroyContext(const ValidationContext *val,
+ const Display *display,
+ const gl::Context *glCtx)
+{
+ ANGLE_VALIDATION_TRY(ValidateContext(val, display, glCtx));
+ return true;
+}
+
+bool ValidateSwapBuffers(const ValidationContext *val,
+ const Display *display,
+ const Surface *eglSurface)
+{
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
+
+ if (display->isDeviceLost())
+ {
+ val->setError(EGL_CONTEXT_LOST);
+ return false;
+ }
+
+ if (eglSurface->isLocked())
+ {
+ val->setError(EGL_BAD_ACCESS);
+ return false;
+ }
+
+ if (eglSurface == EGL_NO_SURFACE || !val->eglThread->getContext() ||
+ val->eglThread->getCurrentDrawSurface() != eglSurface)
+ {
+ val->setError(EGL_BAD_SURFACE);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSwapBuffersWithDamageKHR(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface,
+ const EGLint *rects,
+ EGLint n_rects)
+{
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+
+ if (!display->getExtensions().swapBuffersWithDamage)
+ {
+ // It is out of spec what happens when calling an extension function when the extension is
+ // not available. EGL_BAD_DISPLAY seems like a reasonable error.
+ val->setError(EGL_BAD_DISPLAY, "EGL_KHR_swap_buffers_with_damage is not available.");
+ return false;
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ val->setError(EGL_BAD_SURFACE, "Swap surface cannot be EGL_NO_SURFACE.");
+ return false;
+ }
+
+ if (n_rects < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "n_rects cannot be negative.");
+ return false;
+ }
+
+ if (n_rects > 0 && rects == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "n_rects cannot be greater than zero when rects is NULL.");
+ return false;
+ }
+
+ if (surface->isLocked())
+ {
+ val->setError(EGL_BAD_ACCESS);
+ return false;
+ }
+
+ // TODO(jmadill): Validate Surface is bound to the thread.
+
+ return true;
+}
+
+bool ValidateWaitNative(const ValidationContext *val, const EGLint engine)
+{
+ if (val->eglThread->getDisplay() == nullptr)
+ {
+ // EGL spec says this about eglWaitNative -
+ // eglWaitNative is ignored if there is no current EGL rendering context.
+ return true;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, val->eglThread->getDisplay()));
+
+ if (engine != EGL_CORE_NATIVE_ENGINE)
+ {
+ val->setError(EGL_BAD_PARAMETER, "the 'engine' parameter has an unrecognized value");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopyBuffers(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface,
+ EGLNativePixmapType target)
+{
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+
+ if (display->isDeviceLost())
+ {
+ val->setError(EGL_CONTEXT_LOST);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindTexImage(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface,
+ const EGLint buffer)
+{
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+
+ if (buffer != EGL_BACK_BUFFER)
+ {
+ val->setError(EGL_BAD_PARAMETER);
+ return false;
+ }
+
+ if (surface->getType() == EGL_WINDOW_BIT)
+ {
+ val->setError(EGL_BAD_SURFACE);
+ return false;
+ }
+
+ if (surface->getBoundTexture())
+ {
+ val->setError(EGL_BAD_ACCESS);
+ return false;
+ }
+
+ if (surface->getTextureFormat() == TextureFormat::NoTexture)
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+
+ if (surface->isLocked())
+ {
+ val->setError(EGL_BAD_ACCESS);
+ return false;
+ }
+
+ gl::Context *context = val->eglThread->getContext();
+ if (context && !context->isContextLost())
+ {
+ gl::TextureType type = egl_gl::EGLTextureTargetToTextureType(surface->getTextureTarget());
+ gl::Texture *textureObject = context->getTextureByType(type);
+ ASSERT(textureObject != nullptr);
+
+ if (textureObject->getImmutableFormat())
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateReleaseTexImage(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface,
+ const EGLint buffer)
+{
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+
+ if (buffer != EGL_BACK_BUFFER)
+ {
+ val->setError(EGL_BAD_PARAMETER);
+ return false;
+ }
+
+ if (surface->getType() == EGL_WINDOW_BIT)
+ {
+ val->setError(EGL_BAD_SURFACE);
+ return false;
+ }
+
+ if (surface->getTextureFormat() == TextureFormat::NoTexture)
+ {
+ val->setError(EGL_BAD_MATCH);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSwapInterval(const ValidationContext *val, const Display *display, EGLint interval)
+{
+ const gl::Context *context = val->eglThread->getContext();
+ ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
+
+ Surface *drawSurface = val->eglThread->getCurrentDrawSurface();
+ if (drawSurface == nullptr)
+ {
+ val->setError(EGL_BAD_SURFACE);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindAPI(const ValidationContext *val, const EGLenum api)
+{
+ switch (api)
+ {
+ case EGL_OPENGL_ES_API:
+ case EGL_OPENGL_API:
+ break;
+ case EGL_OPENVG_API:
+ val->setError(EGL_BAD_PARAMETER);
+ return false; // Not supported by this implementation
+ default:
+ val->setError(EGL_BAD_PARAMETER);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePresentationTimeANDROID(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface,
+ EGLnsecsANDROID time)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().presentationTime)
+ {
+ // It is out of spec what happens when calling an extension function when the extension is
+ // not available. EGL_BAD_DISPLAY seems like a reasonable error.
+ val->setError(EGL_BAD_DISPLAY, "EGL_ANDROID_presentation_time is not available.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+
+ return true;
+}
+
+bool ValidateSetBlobCacheFuncsANDROID(const ValidationContext *val,
+ const Display *display,
+ EGLSetBlobFuncANDROID set,
+ EGLGetBlobFuncANDROID get)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (display->areBlobCacheFuncsSet())
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "Blob cache functions can only be set once in the lifetime of a Display");
+ return false;
+ }
+
+ if (set == nullptr || get == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Blob cache callbacks cannot be null.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetConfigAttrib(const ValidationContext *val,
+ const Display *display,
+ const Config *config,
+ EGLint attribute,
+ const EGLint *value)
+{
+ ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
+ ANGLE_TRY(ValidateConfigAttribute(val, display, static_cast<EGLAttrib>(attribute)));
+ return true;
+}
+
+bool ValidateChooseConfig(const ValidationContext *val,
+ const Display *display,
+ const AttributeMap &attribs,
+ const EGLConfig *configs,
+ EGLint configSize,
+ const EGLint *numConfig)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+ ANGLE_VALIDATION_TRY(ValidateConfigAttributes(val, display, attribs));
+
+ if (numConfig == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "num_config cannot be null.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetConfigs(const ValidationContext *val,
+ const Display *display,
+ const EGLConfig *configs,
+ EGLint configSize,
+ const EGLint *numConfig)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (numConfig == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "num_config cannot be null.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetPlatformDisplay(const ValidationContext *val,
+ EGLenum platform,
+ const void *native_display,
+ const AttributeMap &attribMap)
+{
+ return ValidateGetPlatformDisplayCommon(val, platform, native_display, attribMap);
+}
+
+bool ValidateGetPlatformDisplayEXT(const ValidationContext *val,
+ EGLenum platform,
+ const void *native_display,
+ const AttributeMap &attribMap)
+{
+ return ValidateGetPlatformDisplayCommon(val, platform, native_display, attribMap);
+}
+
+bool ValidateCreatePlatformWindowSurfaceEXT(const ValidationContext *val,
+ const Display *display,
+ const Config *configuration,
+ const void *nativeWindow,
+ const AttributeMap &attributes)
+{
+ if (!Display::GetClientExtensions().platformBase)
+ {
+ val->setError(EGL_BAD_ACCESS, "EGL_EXT_platform_base not supported");
+ return false;
+ }
+
+ const void *actualNativeWindow = display->getImplementation()->isX11()
+ ? *reinterpret_cast<const void *const *>(nativeWindow)
+ : nativeWindow;
+
+ return ValidateCreatePlatformWindowSurface(val, display, configuration, actualNativeWindow,
+ attributes);
+}
+
+bool ValidateCreatePlatformPixmapSurfaceEXT(const ValidationContext *val,
+ const Display *display,
+ const Config *configuration,
+ const void *nativePixmap,
+ const AttributeMap &attributes)
+{
+ if (!Display::GetClientExtensions().platformBase)
+ {
+ val->setError(EGL_BAD_ACCESS, "EGL_EXT_platform_base not supported");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateConfig(val, display, configuration));
+
+ val->setError(EGL_BAD_DISPLAY, "ValidateCreatePlatformPixmapSurfaceEXT unimplemented.");
+ return false;
+}
+
+bool ValidateProgramCacheGetAttribANGLE(const ValidationContext *val,
+ const Display *display,
+ EGLenum attrib)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().programCacheControlANGLE)
+ {
+ val->setError(EGL_BAD_ACCESS, "Extension not supported");
+ return false;
+ }
+
+ switch (attrib)
+ {
+ case EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE:
+ case EGL_PROGRAM_CACHE_SIZE_ANGLE:
+ break;
+
+ default:
+ val->setError(EGL_BAD_PARAMETER, "Invalid program cache attribute.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateProgramCacheQueryANGLE(const ValidationContext *val,
+ const Display *display,
+ EGLint index,
+ const void *key,
+ const EGLint *keysize,
+ const void *binary,
+ const EGLint *binarysize)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().programCacheControlANGLE)
+ {
+ val->setError(EGL_BAD_ACCESS, "Extension not supported");
+ return false;
+ }
+
+ if (index < 0 || index >= display->programCacheGetAttrib(EGL_PROGRAM_CACHE_SIZE_ANGLE))
+ {
+ val->setError(EGL_BAD_PARAMETER, "Program index out of range.");
+ return false;
+ }
+
+ if (keysize == nullptr || binarysize == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "keysize and binarysize must always be valid pointers.");
+ return false;
+ }
+
+ if (binary && *keysize != static_cast<EGLint>(egl::BlobCache::kKeyLength))
+ {
+ val->setError(EGL_BAD_PARAMETER, "Invalid program key size.");
+ return false;
+ }
+
+ if ((key == nullptr) != (binary == nullptr))
+ {
+ val->setError(EGL_BAD_PARAMETER, "key and binary must both be null or both non-null.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateProgramCachePopulateANGLE(const ValidationContext *val,
+ const Display *display,
+ const void *key,
+ EGLint keysize,
+ const void *binary,
+ EGLint binarysize)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().programCacheControlANGLE)
+ {
+ val->setError(EGL_BAD_ACCESS, "Extension not supported");
+ return false;
+ }
+
+ if (keysize != static_cast<EGLint>(egl::BlobCache::kKeyLength))
+ {
+ val->setError(EGL_BAD_PARAMETER, "Invalid program key size.");
+ return false;
+ }
+
+ if (key == nullptr || binary == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "null pointer in arguments.");
+ return false;
+ }
+
+ // Upper bound for binarysize is arbitrary.
+ if (binarysize <= 0 || binarysize > egl::kProgramCacheSizeAbsoluteMax)
+ {
+ val->setError(EGL_BAD_PARAMETER, "binarysize out of valid range.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateProgramCacheResizeANGLE(const ValidationContext *val,
+ const Display *display,
+ EGLint limit,
+ EGLint mode)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().programCacheControlANGLE)
+ {
+ val->setError(EGL_BAD_ACCESS, "Extension not supported");
+ return false;
+ }
+
+ if (limit < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "limit must be non-negative.");
+ return false;
+ }
+
+ switch (mode)
+ {
+ case EGL_PROGRAM_CACHE_RESIZE_ANGLE:
+ case EGL_PROGRAM_CACHE_TRIM_ANGLE:
+ break;
+
+ default:
+ val->setError(EGL_BAD_PARAMETER, "Invalid cache resize mode.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSurfaceAttrib(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface,
+ EGLint attribute,
+ EGLint value)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ val->setError(EGL_BAD_SURFACE, "Surface cannot be EGL_NO_SURFACE.");
+ return false;
+ }
+
+ switch (attribute)
+ {
+ case EGL_MIPMAP_LEVEL:
+ break;
+
+ case EGL_MULTISAMPLE_RESOLVE:
+ switch (value)
+ {
+ case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
+ break;
+
+ case EGL_MULTISAMPLE_RESOLVE_BOX:
+ if ((surface->getConfig()->surfaceType & EGL_MULTISAMPLE_RESOLVE_BOX_BIT) == 0)
+ {
+ val->setError(EGL_BAD_MATCH,
+ "Surface does not support EGL_MULTISAMPLE_RESOLVE_BOX.");
+ return false;
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid multisample resolve type.");
+ return false;
+ }
+ break;
+
+ case EGL_SWAP_BEHAVIOR:
+ switch (value)
+ {
+ case EGL_BUFFER_PRESERVED:
+ if ((surface->getConfig()->surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) == 0)
+ {
+ val->setError(EGL_BAD_MATCH,
+ "Surface does not support EGL_SWAP_BEHAVIOR_PRESERVED.");
+ return false;
+ }
+ break;
+
+ case EGL_BUFFER_DESTROYED:
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid swap behaviour.");
+ return false;
+ }
+ break;
+
+ case EGL_WIDTH:
+ case EGL_HEIGHT:
+ if (!display->getExtensions().windowFixedSize)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_WIDTH or EGL_HEIGHT cannot be set without "
+ "EGL_ANGLE_window_fixed_size support.");
+ return false;
+ }
+ if (!surface->isFixedSize())
+ {
+ val->setError(EGL_BAD_MATCH,
+ "EGL_WIDTH or EGL_HEIGHT cannot be set without "
+ "EGL_FIXED_SIZE_ANGLE being enabled on the surface.");
+ return false;
+ }
+ break;
+
+ case EGL_TIMESTAMPS_ANDROID:
+ if (!display->getExtensions().getFrameTimestamps &&
+ !display->getExtensions().timestampSurfaceAttributeANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_TIMESTAMPS_ANDROID cannot be used without "
+ "EGL_ANDROID_get_frame_timestamps support.");
+ return false;
+ }
+ switch (value)
+ {
+ case EGL_TRUE:
+ case EGL_FALSE:
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid value.");
+ return false;
+ }
+ break;
+
+ case EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID:
+ ASSERT(value == EGL_TRUE || value == EGL_FALSE);
+ break;
+
+ case EGL_RENDER_BUFFER:
+ if (value != EGL_BACK_BUFFER && value != EGL_SINGLE_BUFFER)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_RENDER_BUFFER must be EGL_BACK_BUFFER or EGL_SINGLE_BUFFER.");
+ return false;
+ }
+
+ if (value == EGL_SINGLE_BUFFER)
+ {
+ if (!display->getExtensions().mutableRenderBufferKHR)
+ {
+ val->setError(
+ EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_RENDER_BUFFER requires EGL_KHR_mutable_render_buffer.");
+ return false;
+ }
+
+ if ((surface->getConfig()->surfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR) == 0)
+ {
+ val->setError(EGL_BAD_MATCH,
+ "EGL_RENDER_BUFFER requires the surface type bit "
+ "EGL_MUTABLE_RENDER_BUFFER_BIT_KHR.");
+ return false;
+ }
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid surface attribute: 0x%04X", attribute);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateQuerySurface(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface,
+ EGLint attribute,
+ const EGLint *value)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ val->setError(EGL_BAD_SURFACE, "Surface cannot be EGL_NO_SURFACE.");
+ return false;
+ }
+
+ switch (attribute)
+ {
+ case EGL_GL_COLORSPACE:
+ case EGL_VG_ALPHA_FORMAT:
+ case EGL_VG_COLORSPACE:
+ case EGL_CONFIG_ID:
+ case EGL_HEIGHT:
+ case EGL_HORIZONTAL_RESOLUTION:
+ case EGL_LARGEST_PBUFFER:
+ case EGL_MIPMAP_TEXTURE:
+ case EGL_MIPMAP_LEVEL:
+ case EGL_MULTISAMPLE_RESOLVE:
+ case EGL_PIXEL_ASPECT_RATIO:
+ case EGL_RENDER_BUFFER:
+ case EGL_SWAP_BEHAVIOR:
+ case EGL_TEXTURE_FORMAT:
+ case EGL_TEXTURE_TARGET:
+ case EGL_VERTICAL_RESOLUTION:
+ case EGL_WIDTH:
+ break;
+
+ case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+ if (!display->getExtensions().postSubBuffer)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_POST_SUB_BUFFER_SUPPORTED_NV cannot be used "
+ "without EGL_ANGLE_surface_orientation support.");
+ return false;
+ }
+ break;
+
+ case EGL_FIXED_SIZE_ANGLE:
+ if (!display->getExtensions().windowFixedSize)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_FIXED_SIZE_ANGLE cannot be used without "
+ "EGL_ANGLE_window_fixed_size support.");
+ return false;
+ }
+ break;
+
+ case EGL_SURFACE_ORIENTATION_ANGLE:
+ if (!display->getExtensions().surfaceOrientation)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_SURFACE_ORIENTATION_ANGLE cannot be "
+ "queried without "
+ "EGL_ANGLE_surface_orientation support.");
+ return false;
+ }
+ break;
+
+ case EGL_DIRECT_COMPOSITION_ANGLE:
+ if (!display->getExtensions().directComposition)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_DIRECT_COMPOSITION_ANGLE cannot be "
+ "used without "
+ "EGL_ANGLE_direct_composition support.");
+ return false;
+ }
+ break;
+
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ if (!display->getExtensions().robustResourceInitializationANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
+ "used without EGL_ANGLE_robust_resource_initialization "
+ "support.");
+ return false;
+ }
+ break;
+
+ case EGL_TIMESTAMPS_ANDROID:
+ if (!display->getExtensions().getFrameTimestamps &&
+ !display->getExtensions().timestampSurfaceAttributeANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_TIMESTAMPS_ANDROID cannot be used without "
+ "EGL_ANDROID_get_frame_timestamps support.");
+ return false;
+ }
+ break;
+
+ case EGL_BUFFER_AGE_EXT:
+ {
+ if (!display->getExtensions().bufferAgeEXT)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_BUFFER_AGE_EXT cannot be used without "
+ "EGL_EXT_buffer_age support.");
+ return false;
+ }
+ gl::Context *context = val->eglThread->getContext();
+ if ((context == nullptr) || (context->getCurrentDrawSurface() != surface))
+ {
+ val->setError(EGL_BAD_SURFACE,
+ "The surface must be current to the current context "
+ "in order to query buffer age per extension "
+ "EGL_EXT_buffer_age.");
+ return false;
+ }
+ }
+ break;
+
+ case EGL_BITMAP_PITCH_KHR:
+ case EGL_BITMAP_ORIGIN_KHR:
+ case EGL_BITMAP_PIXEL_RED_OFFSET_KHR:
+ case EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR:
+ case EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR:
+ case EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR:
+ case EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR:
+ case EGL_BITMAP_PIXEL_SIZE_KHR:
+ if (!display->getExtensions().lockSurface3KHR)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_KHR_lock_surface3 is not supported.");
+ return false;
+ }
+ break;
+
+ case EGL_PROTECTED_CONTENT_EXT:
+ if (!display->getExtensions().protectedContentEXT)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_EXT_protected_content not supported");
+ return false;
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid surface attribute: 0x%04X", attribute);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateQueryContext(const ValidationContext *val,
+ const Display *display,
+ const gl::Context *context,
+ EGLint attribute,
+ const EGLint *value)
+{
+ ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
+
+ switch (attribute)
+ {
+ case EGL_CONFIG_ID:
+ case EGL_CONTEXT_CLIENT_TYPE:
+ case EGL_CONTEXT_CLIENT_VERSION:
+ case EGL_RENDER_BUFFER:
+ break;
+
+ case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ if (!display->getExtensions().robustResourceInitializationANGLE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
+ "used without EGL_ANGLE_robust_resource_initialization "
+ "support.");
+ return false;
+ }
+ break;
+
+ case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
+ if (!display->getExtensions().contextPriority)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG requires "
+ "extension EGL_IMG_context_priority.");
+ return false;
+ }
+ break;
+
+ case EGL_PROTECTED_CONTENT_EXT:
+ if (!display->getExtensions().protectedContentEXT)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "EGL_EXT_protected_content not supported");
+ return false;
+ }
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid context attribute: 0x%04X", attribute);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDebugMessageControlKHR(const ValidationContext *val,
+ EGLDEBUGPROCKHR callback,
+ const AttributeMap &attribs)
+{
+ const ClientExtensions &clientExtensions = Display::GetClientExtensions();
+ if (!clientExtensions.debug)
+ {
+ val->setError(EGL_BAD_ACCESS, "EGL_KHR_debug extension is not available.");
+ return false;
+ }
+
+ attribs.initializeWithoutValidation();
+
+ for (const auto &attrib : attribs)
+ {
+ switch (attrib.first)
+ {
+ case EGL_DEBUG_MSG_CRITICAL_KHR:
+ case EGL_DEBUG_MSG_ERROR_KHR:
+ case EGL_DEBUG_MSG_WARN_KHR:
+ case EGL_DEBUG_MSG_INFO_KHR:
+ if (attrib.second != EGL_TRUE && attrib.second != EGL_FALSE)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE,
+ "message controls must be EGL_TRUE or EGL_FALSE.");
+ return false;
+ }
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateQueryDebugKHR(const ValidationContext *val, EGLint attribute, const EGLAttrib *value)
+{
+ const ClientExtensions &clientExtensions = Display::GetClientExtensions();
+ if (!clientExtensions.debug)
+ {
+ val->setError(EGL_BAD_ACCESS, "EGL_KHR_debug extension is not available.");
+ return false;
+ }
+
+ switch (attribute)
+ {
+ case EGL_DEBUG_MSG_CRITICAL_KHR:
+ case EGL_DEBUG_MSG_ERROR_KHR:
+ case EGL_DEBUG_MSG_WARN_KHR:
+ case EGL_DEBUG_MSG_INFO_KHR:
+ case EGL_DEBUG_CALLBACK_KHR:
+ break;
+
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04X", attribute);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateLabelObjectKHR(const ValidationContext *val,
+ const Display *display,
+ ObjectType objectType,
+ EGLObjectKHR object,
+ EGLLabelKHR label)
+{
+ const ClientExtensions &clientExtensions = Display::GetClientExtensions();
+ if (!clientExtensions.debug)
+ {
+ val->setError(EGL_BAD_ACCESS, "EGL_KHR_debug extension is not available.");
+ return false;
+ }
+
+ LabeledObject *labeledObject = nullptr;
+ ANGLE_VALIDATION_TRY(ValidateLabeledObject(val, display, objectType, object, &labeledObject));
+
+ return true;
+}
+
+bool ValidateGetCompositorTimingSupportedANDROID(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface,
+ CompositorTiming name)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().getFrameTimestamps)
+ {
+ val->setError(EGL_BAD_DISPLAY,
+ "EGL_ANDROID_get_frame_timestamps extension is not available.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+
+ if (!ValidCompositorTimingName(name))
+ {
+ val->setError(EGL_BAD_PARAMETER, "invalid timing name.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetCompositorTimingANDROID(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface,
+ EGLint numTimestamps,
+ const EGLint *names,
+ const EGLnsecsANDROID *values)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().getFrameTimestamps)
+ {
+ val->setError(EGL_BAD_DISPLAY,
+ "EGL_ANDROID_get_frame_timestamps extension is not available.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+
+ if (names == nullptr && numTimestamps > 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "names is NULL.");
+ return false;
+ }
+
+ if (values == nullptr && numTimestamps > 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "values is NULL.");
+ return false;
+ }
+
+ if (numTimestamps < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "numTimestamps must be at least 0.");
+ return false;
+ }
+
+ for (EGLint i = 0; i < numTimestamps; i++)
+ {
+ CompositorTiming name = FromEGLenum<CompositorTiming>(names[i]);
+
+ if (!ValidCompositorTimingName(name))
+ {
+ val->setError(EGL_BAD_PARAMETER, "invalid compositor timing.");
+ return false;
+ }
+
+ if (!surface->getSupportedCompositorTimings().test(name))
+ {
+ val->setError(EGL_BAD_PARAMETER, "compositor timing not supported by surface.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetNextFrameIdANDROID(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface,
+ const EGLuint64KHR *frameId)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().getFrameTimestamps)
+ {
+ val->setError(EGL_BAD_DISPLAY,
+ "EGL_ANDROID_get_frame_timestamps extension is not available.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+
+ if (frameId == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "frameId is NULL.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetFrameTimestampSupportedANDROID(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface,
+ Timestamp timestamp)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().getFrameTimestamps)
+ {
+ val->setError(EGL_BAD_DISPLAY,
+ "EGL_ANDROID_get_frame_timestamps extension is not available.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+
+ if (!ValidTimestampType(timestamp))
+ {
+ val->setError(EGL_BAD_PARAMETER, "invalid timestamp type.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetFrameTimestampsANDROID(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface,
+ EGLuint64KHR frameId,
+ EGLint numTimestamps,
+ const EGLint *timestamps,
+ const EGLnsecsANDROID *values)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().getFrameTimestamps)
+ {
+ val->setError(EGL_BAD_DISPLAY,
+ "EGL_ANDROID_get_frame_timestamps extension is not available.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+
+ if (!surface->isTimestampsEnabled())
+ {
+ val->setError(EGL_BAD_SURFACE, "timestamp collection is not enabled for this surface.");
+ return false;
+ }
+
+ if (timestamps == nullptr && numTimestamps > 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "timestamps is NULL.");
+ return false;
+ }
+
+ if (values == nullptr && numTimestamps > 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "values is NULL.");
+ return false;
+ }
+
+ if (numTimestamps < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "numTimestamps must be at least 0.");
+ return false;
+ }
+
+ for (EGLint i = 0; i < numTimestamps; i++)
+ {
+ Timestamp timestamp = FromEGLenum<Timestamp>(timestamps[i]);
+
+ if (!ValidTimestampType(timestamp))
+ {
+ val->setError(EGL_BAD_PARAMETER, "invalid timestamp type.");
+ return false;
+ }
+
+ if (!surface->getSupportedTimestamps().test(timestamp))
+ {
+ val->setError(EGL_BAD_PARAMETER, "timestamp not supported by surface.");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateQueryStringiANGLE(const ValidationContext *val,
+ const Display *display,
+ EGLint name,
+ EGLint index)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!Display::GetClientExtensions().featureControlANGLE)
+ {
+ val->setError(EGL_BAD_DISPLAY, "EGL_ANGLE_feature_control extension is not available.");
+ return false;
+ }
+
+ if (index < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "index is negative.");
+ return false;
+ }
+
+ switch (name)
+ {
+ case EGL_FEATURE_NAME_ANGLE:
+ case EGL_FEATURE_CATEGORY_ANGLE:
+ case EGL_FEATURE_DESCRIPTION_ANGLE:
+ case EGL_FEATURE_BUG_ANGLE:
+ case EGL_FEATURE_STATUS_ANGLE:
+ case EGL_FEATURE_CONDITION_ANGLE:
+ break;
+ default:
+ val->setError(EGL_BAD_PARAMETER, "name is not valid.");
+ return false;
+ }
+
+ if (static_cast<size_t>(index) >= display->getFeatures().size())
+ {
+ val->setError(EGL_BAD_PARAMETER, "index is too big.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateQueryDisplayAttribEXT(const ValidationContext *val,
+ const Display *display,
+ const EGLint attribute,
+ const EGLAttrib *value)
+{
+ ANGLE_VALIDATION_TRY(ValidateQueryDisplayAttribBase(val, display, attribute));
+ return true;
+}
+
+bool ValidateQueryDisplayAttribANGLE(const ValidationContext *val,
+ const Display *display,
+ const EGLint attribute,
+ const EGLAttrib *value)
+{
+ ANGLE_VALIDATION_TRY(ValidateQueryDisplayAttribBase(val, display, attribute));
+ return true;
+}
+
+bool ValidateGetNativeClientBufferANDROID(const ValidationContext *val,
+ const AHardwareBuffer *buffer)
+{
+ // No extension check is done because no display is passed to eglGetNativeClientBufferANDROID
+ // despite it being a display extension. No display is needed for the implementation though.
+ if (buffer == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "NULL buffer.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCreateNativeClientBufferANDROID(const ValidationContext *val,
+ const egl::AttributeMap &attribMap)
+{
+ attribMap.initializeWithoutValidation();
+
+ if (attribMap.isEmpty() || attribMap.begin()->second == EGL_NONE)
+ {
+ val->setError(EGL_BAD_PARAMETER, "invalid attribute list.");
+ return false;
+ }
+
+ int width = attribMap.getAsInt(EGL_WIDTH, 0);
+ int height = attribMap.getAsInt(EGL_HEIGHT, 0);
+ int redSize = attribMap.getAsInt(EGL_RED_SIZE, 0);
+ int greenSize = attribMap.getAsInt(EGL_GREEN_SIZE, 0);
+ int blueSize = attribMap.getAsInt(EGL_BLUE_SIZE, 0);
+ int alphaSize = attribMap.getAsInt(EGL_ALPHA_SIZE, 0);
+ int usage = attribMap.getAsInt(EGL_NATIVE_BUFFER_USAGE_ANDROID, 0);
+
+ for (AttributeMap::const_iterator attributeIter = attribMap.begin();
+ attributeIter != attribMap.end(); attributeIter++)
+ {
+ EGLAttrib attribute = attributeIter->first;
+ switch (attribute)
+ {
+ case EGL_WIDTH:
+ case EGL_HEIGHT:
+ // Validation done after the switch statement
+ break;
+ case EGL_RED_SIZE:
+ case EGL_GREEN_SIZE:
+ case EGL_BLUE_SIZE:
+ case EGL_ALPHA_SIZE:
+ if (redSize < 0 || greenSize < 0 || blueSize < 0 || alphaSize < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "incorrect channel size requested");
+ return false;
+ }
+ break;
+ case EGL_NATIVE_BUFFER_USAGE_ANDROID:
+ // The buffer must be used for either a texture or a renderbuffer.
+ if ((usage & ~(EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID |
+ EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID |
+ EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) != 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "invalid usage flag");
+ return false;
+ }
+ break;
+ case EGL_NONE:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "invalid attribute");
+ return false;
+ }
+ }
+
+ // Validate EGL_WIDTH and EGL_HEIGHT values passed in. Done here to account
+ // for the case where EGL_WIDTH and EGL_HEIGHT were not part of the attribute list.
+ if (width <= 0 || height <= 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "incorrect buffer dimensions requested");
+ return false;
+ }
+
+ if (gl::GetAndroidHardwareBufferFormatFromChannelSizes(attribMap) == 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "unsupported format");
+ return false;
+ }
+ return true;
+}
+
+bool ValidateCopyMetalSharedEventANGLE(const ValidationContext *val,
+ const Display *display,
+ const Sync *sync)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().mtlSyncSharedEventANGLE)
+ {
+ val->setError(EGL_BAD_DISPLAY, "EGL_ANGLE_metal_shared_event_sync is not available.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
+
+ return true;
+}
+
+bool ValidateDupNativeFenceFDANDROID(const ValidationContext *val,
+ const Display *display,
+ const Sync *sync)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().nativeFenceSyncANDROID)
+ {
+ val->setError(EGL_BAD_DISPLAY, "EGL_ANDROID_native_fence_sync extension is not available.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
+
+ return true;
+}
+
+bool ValidateSwapBuffersWithFrameTokenANGLE(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface,
+ EGLFrameTokenANGLE frametoken)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().swapWithFrameToken)
+ {
+ val->setError(EGL_BAD_DISPLAY, "EGL_ANGLE_swap_buffers_with_frame_token is not available.");
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+
+ return true;
+}
+
+bool ValidatePrepareSwapBuffersANGLE(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface)
+{
+ return ValidateSwapBuffers(val, display, surface);
+}
+
+bool ValidateSignalSyncKHR(const ValidationContext *val,
+ const Display *display,
+ const Sync *sync,
+ EGLenum mode)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
+
+ if (sync->getType() == EGL_SYNC_REUSABLE_KHR)
+ {
+ if (!display->getExtensions().reusableSyncKHR)
+ {
+ val->setError(EGL_BAD_MATCH, "EGL_KHR_reusable_sync extension is not available.");
+ return false;
+ }
+
+ if ((mode != EGL_SIGNALED_KHR) && (mode != EGL_UNSIGNALED_KHR))
+ {
+ val->setError(EGL_BAD_PARAMETER, "eglSignalSyncKHR invalid mode.");
+ return false;
+ }
+
+ return true;
+ }
+
+ val->setError(EGL_BAD_MATCH);
+ return false;
+}
+
+bool ValidateQuerySurfacePointerANGLE(const ValidationContext *val,
+ const Display *display,
+ const Surface *eglSurface,
+ EGLint attribute,
+ void *const *value)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().querySurfacePointer)
+ {
+ val->setError(EGL_BAD_ACCESS);
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
+
+ // validate the attribute parameter
+ switch (attribute)
+ {
+ case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+ if (!display->getExtensions().surfaceD3DTexture2DShareHandle)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+ case EGL_DXGI_KEYED_MUTEX_ANGLE:
+ if (!display->getExtensions().keyedMutex)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePostSubBufferNV(const ValidationContext *val,
+ const Display *display,
+ const Surface *eglSurface,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+
+ if (!display->getExtensions().postSubBuffer)
+ {
+ val->setError(EGL_BAD_ACCESS);
+ return false;
+ }
+
+ if (x < 0 || y < 0 || width < 0 || height < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER);
+ return false;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
+
+ if (display->isDeviceLost())
+ {
+ val->setError(EGL_CONTEXT_LOST);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateQueryDeviceAttribEXT(const ValidationContext *val,
+ const Device *device,
+ EGLint attribute,
+ const EGLAttrib *value)
+{
+ ANGLE_VALIDATION_TRY(ValidateDevice(val, device));
+
+ if (!Display::GetClientExtensions().deviceQueryEXT)
+ {
+ val->setError(EGL_BAD_ACCESS, "EGL_EXT_device_query not supported.");
+ return false;
+ }
+
+ // validate the attribute parameter
+ switch (attribute)
+ {
+ case EGL_D3D11_DEVICE_ANGLE:
+ case EGL_D3D9_DEVICE_ANGLE:
+ if (!device->getExtensions().deviceD3D || device->getType() != attribute)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+ case EGL_EAGL_CONTEXT_ANGLE:
+ if (!device->getExtensions().deviceEAGL)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+ case EGL_METAL_DEVICE_ANGLE:
+ if (!device->getExtensions().deviceMetal)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+ case EGL_VULKAN_VERSION_ANGLE:
+ case EGL_VULKAN_INSTANCE_ANGLE:
+ case EGL_VULKAN_INSTANCE_EXTENSIONS_ANGLE:
+ case EGL_VULKAN_PHYSICAL_DEVICE_ANGLE:
+ case EGL_VULKAN_DEVICE_ANGLE:
+ case EGL_VULKAN_DEVICE_EXTENSIONS_ANGLE:
+ case EGL_VULKAN_FEATURES_ANGLE:
+ case EGL_VULKAN_QUEUE_ANGLE:
+ case EGL_VULKAN_QUEUE_FAMILIY_INDEX_ANGLE:
+ case EGL_VULKAN_GET_INSTANCE_PROC_ADDR:
+ if (!device->getExtensions().deviceVulkan)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+ case EGL_CGL_CONTEXT_ANGLE:
+ case EGL_CGL_PIXEL_FORMAT_ANGLE:
+ if (!device->getExtensions().deviceCGL)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateQueryDeviceStringEXT(const ValidationContext *val, const Device *device, EGLint name)
+{
+ ANGLE_VALIDATION_TRY(ValidateDevice(val, device));
+ return true;
+}
+
+bool ValidateReleaseHighPowerGPUANGLE(const ValidationContext *val,
+ const Display *display,
+ const gl::Context *context)
+{
+ ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
+ return true;
+}
+
+bool ValidateReacquireHighPowerGPUANGLE(const ValidationContext *val,
+ const Display *display,
+ const gl::Context *context)
+{
+ ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
+ return true;
+}
+
+bool ValidateHandleGPUSwitchANGLE(const ValidationContext *val, const Display *display)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+ return true;
+}
+
+bool ValidateForceGPUSwitchANGLE(const ValidationContext *val,
+ const Display *display,
+ EGLint gpuIDHigh,
+ EGLint gpuIDLow)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+ return true;
+}
+
+bool ValidateGetCurrentDisplay(const ValidationContext *val)
+{
+ return true;
+}
+
+bool ValidateGetCurrentSurface(const ValidationContext *val, EGLint readdraw)
+{
+ return true;
+}
+
+bool ValidateGetDisplay(const ValidationContext *val, EGLNativeDisplayType display_id)
+{
+ return true;
+}
+
+bool ValidateGetError(const ValidationContext *val)
+{
+ return true;
+}
+
+bool ValidateGetProcAddress(const ValidationContext *val, const char *procname)
+{
+ return true;
+}
+
+bool ValidateQueryString(const ValidationContext *val, const Display *dpyPacked, EGLint name)
+{
+ // The only situation where EGL_NO_DISPLAY is allowed is when querying
+ // EGL_EXTENSIONS or EGL_VERSION.
+ const bool canQueryWithoutDisplay = (name == EGL_VERSION || name == EGL_EXTENSIONS);
+
+ if (dpyPacked != nullptr || !canQueryWithoutDisplay)
+ {
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpyPacked));
+ }
+
+ switch (name)
+ {
+ case EGL_CLIENT_APIS:
+ case EGL_EXTENSIONS:
+ case EGL_VENDOR:
+ case EGL_VERSION:
+ break;
+ default:
+ val->setError(EGL_BAD_PARAMETER);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateWaitGL(const ValidationContext *val)
+{
+ if (val->eglThread->getDisplay() == nullptr)
+ {
+ // EGL spec says this about eglWaitGL -
+ // eglWaitGL is ignored if there is no current EGL rendering context for OpenGL ES.
+ return true;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, val->eglThread->getDisplay()));
+ return true;
+}
+
+bool ValidateQueryAPI(const ValidationContext *val)
+{
+ return true;
+}
+
+bool ValidateReleaseThread(const ValidationContext *val)
+{
+ return true;
+}
+
+bool ValidateWaitClient(const ValidationContext *val)
+{
+ if (val->eglThread->getDisplay() == nullptr)
+ {
+ // EGL spec says this about eglWaitClient -
+ // If there is no current context for the current rendering API,
+ // the function has no effect but still returns EGL_TRUE.
+ return true;
+ }
+
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, val->eglThread->getDisplay()));
+ return true;
+}
+
+bool ValidateGetCurrentContext(const ValidationContext *val)
+{
+ return true;
+}
+
+bool ValidateCreatePlatformPixmapSurface(const ValidationContext *val,
+ const Display *dpyPacked,
+ const Config *configPacked,
+ const void *native_pixmap,
+ const AttributeMap &attrib_listPacked)
+{
+ EGLNativePixmapType nativePixmap =
+ reinterpret_cast<EGLNativePixmapType>(const_cast<void *>(native_pixmap));
+ return ValidateCreatePixmapSurface(val, dpyPacked, configPacked, nativePixmap,
+ attrib_listPacked);
+}
+
+bool ValidateCreatePlatformWindowSurface(const ValidationContext *val,
+ const Display *dpyPacked,
+ const Config *configPacked,
+ const void *native_window,
+ const AttributeMap &attrib_listPacked)
+{
+ EGLNativeWindowType nativeWindow =
+ reinterpret_cast<EGLNativeWindowType>(const_cast<void *>(native_window));
+ return ValidateCreateWindowSurface(val, dpyPacked, configPacked, nativeWindow,
+ attrib_listPacked);
+}
+
+bool ValidateLockSurfaceKHR(const ValidationContext *val,
+ const egl::Display *dpy,
+ const Surface *surface,
+ const AttributeMap &attributes)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, dpy, surface));
+
+ if (!dpy->getExtensions().lockSurface3KHR)
+ {
+ val->setError(EGL_BAD_ACCESS);
+ return false;
+ }
+
+ if (surface->isLocked())
+ {
+ val->setError(EGL_BAD_ACCESS);
+ return false;
+ }
+
+ if ((surface->getConfig()->surfaceType & EGL_LOCK_SURFACE_BIT_KHR) == false)
+ {
+ val->setError(EGL_BAD_ACCESS, "Config does not support EGL_LOCK_SURFACE_BIT");
+ return false;
+ }
+
+ if (surface->isCurrentOnAnyContext())
+ {
+ val->setError(EGL_BAD_ACCESS,
+ "Surface cannot be current to a context for eglLockSurface()");
+ return false;
+ }
+
+ if (surface->hasProtectedContent())
+ {
+ val->setError(EGL_BAD_ACCESS, "Surface cannot be protected content for eglLockSurface()");
+ return false;
+ }
+
+ attributes.initializeWithoutValidation();
+
+ for (const auto &attributeIter : attributes)
+ {
+ EGLAttrib attribute = attributeIter.first;
+ EGLAttrib value = attributeIter.second;
+
+ switch (attribute)
+ {
+ case EGL_MAP_PRESERVE_PIXELS_KHR:
+ if (!((value == EGL_FALSE) || (value == EGL_TRUE)))
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid EGL_MAP_PRESERVE_PIXELS_KHR value");
+ return false;
+ }
+ break;
+ case EGL_LOCK_USAGE_HINT_KHR:
+ if ((value & (EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR)) != value)
+ {
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid EGL_LOCK_USAGE_HINT_KHR value");
+ return false;
+ }
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid query surface64 attribute");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateQuerySurface64KHR(const ValidationContext *val,
+ const egl::Display *dpy,
+ const Surface *surface,
+ EGLint attribute,
+ const EGLAttribKHR *value)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, dpy, surface));
+
+ if (!dpy->getExtensions().lockSurface3KHR)
+ {
+ val->setError(EGL_BAD_ACCESS);
+ return false;
+ }
+
+ switch (attribute)
+ {
+ case EGL_BITMAP_PITCH_KHR:
+ case EGL_BITMAP_ORIGIN_KHR:
+ case EGL_BITMAP_PIXEL_RED_OFFSET_KHR:
+ case EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR:
+ case EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR:
+ case EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR:
+ case EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR:
+ case EGL_BITMAP_PIXEL_SIZE_KHR:
+ case EGL_BITMAP_POINTER_KHR:
+ break;
+ default:
+ val->setError(EGL_BAD_ATTRIBUTE, "Invalid eglQuerySurface64 attribute");
+ return false;
+ }
+
+ if (value == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "value is NULL.");
+ return false;
+ }
+
+ if (!surface->isLocked())
+ {
+ val->setError(EGL_BAD_ACCESS, "Surface is not locked");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateUnlockSurfaceKHR(const ValidationContext *val,
+ const egl::Display *dpy,
+ const Surface *surface)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, dpy, surface));
+
+ if (!dpy->getExtensions().lockSurface3KHR)
+ {
+ val->setError(EGL_BAD_ACCESS);
+ return false;
+ }
+
+ if (!surface->isLocked())
+ {
+ val->setError(EGL_BAD_PARAMETER, "Surface is not locked.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateExportVkImageANGLE(const ValidationContext *val,
+ const Display *dpy,
+ const Image *image,
+ const void *vkImage,
+ const void *vkImageCreateInfo)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
+ ANGLE_VALIDATION_TRY(ValidateImage(val, dpy, image));
+
+ if (!dpy->getExtensions().vulkanImageANGLE)
+ {
+ val->setError(EGL_BAD_ACCESS);
+ return false;
+ }
+
+ if (!vkImage)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Output VkImage pointer is null.");
+ return false;
+ }
+
+ if (!vkImageCreateInfo)
+ {
+ val->setError(EGL_BAD_PARAMETER, "Output VkImageCreateInfo pointer is null.");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSetDamageRegionKHR(const ValidationContext *val,
+ const Display *display,
+ const Surface *surface,
+ const EGLint *rects,
+ EGLint n_rects)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
+ ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
+
+ if (!(surface->getType() & EGL_WINDOW_BIT))
+ {
+ val->setError(EGL_BAD_MATCH, "surface is not a postable surface");
+ return false;
+ }
+
+ if (surface != val->eglThread->getCurrentDrawSurface())
+ {
+ val->setError(EGL_BAD_MATCH,
+ "surface is not the current draw surface for the calling thread");
+ return false;
+ }
+
+ if (surface->getSwapBehavior() != EGL_BUFFER_DESTROYED)
+ {
+ val->setError(EGL_BAD_MATCH, "surface's swap behavior is not EGL_BUFFER_DESTROYED");
+ return false;
+ }
+
+ if (surface->isDamageRegionSet())
+ {
+ val->setError(
+ EGL_BAD_ACCESS,
+ "damage region has already been set on surface since the most recent frame boundary");
+ return false;
+ }
+
+ if (!surface->bufferAgeQueriedSinceLastSwap())
+ {
+ val->setError(EGL_BAD_ACCESS,
+ "EGL_BUFFER_AGE_KHR attribute of surface has not been queried since the most "
+ "recent frame boundary");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateQueryDmaBufFormatsEXT(ValidationContext const *val,
+ Display const *dpy,
+ EGLint max_formats,
+ const EGLint *formats,
+ const EGLint *num_formats)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
+
+ if (!dpy->getExtensions().imageDmaBufImportModifiersEXT)
+ {
+ val->setError(EGL_BAD_ACCESS, "EGL_EXT_dma_buf_import_modfier not supported");
+ return false;
+ }
+
+ if (max_formats < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "max_formats should not be negative");
+ return false;
+ }
+
+ if (max_formats > 0 && formats == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER, "if max_formats is positive, formats should not be NULL");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateQueryDmaBufModifiersEXT(ValidationContext const *val,
+ Display const *dpy,
+ EGLint format,
+ EGLint max_modifiers,
+ const EGLuint64KHR *modifiers,
+ const EGLBoolean *external_only,
+ const EGLint *num_modifiers)
+{
+ ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
+
+ if (!dpy->getExtensions().imageDmaBufImportModifiersEXT)
+ {
+ val->setError(EGL_BAD_ACCESS, "EGL_EXT_dma_buf_import_modfier not supported");
+ return false;
+ }
+
+ if (max_modifiers < 0)
+ {
+ val->setError(EGL_BAD_PARAMETER, "max_modifiers should not be negative");
+ return false;
+ }
+
+ if (max_modifiers > 0 && modifiers == nullptr)
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "if max_modifiers is positive, modifiers should not be NULL");
+ return false;
+ }
+
+ if (!dpy->supportsDmaBufFormat(format))
+ {
+ val->setError(EGL_BAD_PARAMETER,
+ "format should be one of the formats advertised by QueryDmaBufFormatsEXT");
+ return false;
+ }
+ return true;
+}
+
+} // namespace egl
diff --git a/gfx/angle/checkout/src/libANGLE/validationEGL.h b/gfx/angle/checkout/src/libANGLE/validationEGL.h
new file mode 100644
index 0000000000..8f04de288f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationEGL.h
@@ -0,0 +1,201 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationEGL.h: Validation functions for generic EGL entry point parameters
+
+#ifndef LIBANGLE_VALIDATIONEGL_H_
+#define LIBANGLE_VALIDATIONEGL_H_
+
+#include "common/PackedEnums.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Thread.h"
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+namespace gl
+{
+class Context;
+}
+
+namespace egl
+{
+constexpr EGLint kEglMajorVersion = 1;
+constexpr EGLint kEglMinorVersion = 5;
+
+class AttributeMap;
+struct ClientExtensions;
+struct Config;
+class Device;
+class Display;
+class Image;
+class Stream;
+class Surface;
+class Sync;
+class Thread;
+class LabeledObject;
+
+struct ValidationContext
+{
+ ValidationContext(Thread *threadIn, const char *entryPointIn, const LabeledObject *objectIn)
+ : eglThread(threadIn), entryPoint(entryPointIn), labeledObject(objectIn)
+ {}
+
+ // We should remove the message-less overload once we have messages for all EGL errors.
+ void setError(EGLint error) const;
+ ANGLE_FORMAT_PRINTF(3, 4)
+ void setError(EGLint error, const char *message...) const;
+
+ Thread *eglThread;
+ const char *entryPoint;
+ const LabeledObject *labeledObject;
+};
+
+// Object validation
+bool ValidateDisplay(const ValidationContext *val, const Display *display);
+bool ValidateSurface(const ValidationContext *val, const Display *display, const Surface *surface);
+bool ValidateConfig(const ValidationContext *val, const Display *display, const Config *config);
+bool ValidateContext(const ValidationContext *val,
+ const Display *display,
+ const gl::Context *context);
+bool ValidateImage(const ValidationContext *val, const Display *display, const Image *image);
+bool ValidateDevice(const ValidationContext *val, const Device *device);
+bool ValidateSync(const ValidationContext *val, const Display *display, const Sync *sync);
+
+// Return the requested object only if it is valid (otherwise nullptr)
+const Thread *GetThreadIfValid(const Thread *thread);
+const Display *GetDisplayIfValid(const Display *display);
+const Surface *GetSurfaceIfValid(const Display *display, const Surface *surface);
+const Image *GetImageIfValid(const Display *display, const Image *image);
+const Stream *GetStreamIfValid(const Display *display, const Stream *stream);
+const gl::Context *GetContextIfValid(const Display *display, const gl::Context *context);
+const Device *GetDeviceIfValid(const Device *device);
+const Sync *GetSyncIfValid(const Display *display, const Sync *sync);
+LabeledObject *GetLabeledObjectIfValid(Thread *thread,
+ const Display *display,
+ ObjectType objectType,
+ EGLObjectKHR object);
+
+// A template struct for determining the default value to return for each entry point.
+template <angle::EntryPoint EP, typename ReturnType>
+struct DefaultReturnValue
+{
+ static constexpr ReturnType kValue = static_cast<ReturnType>(0);
+};
+
+template <angle::EntryPoint EP, typename ReturnType>
+ReturnType GetDefaultReturnValue(Thread *thread);
+
+template <>
+ANGLE_INLINE EGLint
+GetDefaultReturnValue<angle::EntryPoint::EGLLabelObjectKHR, EGLint>(Thread *thread)
+{
+ return thread->getError();
+}
+
+template <angle::EntryPoint EP, typename ReturnType>
+ANGLE_INLINE ReturnType GetDefaultReturnValue(Thread *thread)
+{
+ return DefaultReturnValue<EP, ReturnType>::kValue;
+}
+
+// First case: handling packed enums.
+template <typename PackedT, typename FromT>
+typename std::enable_if<std::is_enum<PackedT>::value, PackedT>::type PackParam(FromT from)
+{
+ return FromEGLenum<PackedT>(from);
+}
+
+// This and the next 2 template specializations handle distinguishing between EGLint, EGLAttrib
+// and other. This is needed because on some architectures EGLint and EGLAttrib are not the same
+// base type. Previously the code conditionally compiled 2 specializations on 64 bit but it turns
+// out on WatchOS the assumption about 32/64 bit and if EGLint and ELGAttrib are the same or
+// different did not hold.
+template <typename PackedT,
+ typename FromT,
+ typename std::enable_if<!std::is_enum<PackedT>::value>::type * = nullptr,
+ typename std::enable_if<std::is_same<FromT, const EGLint *>::value>::type * = nullptr>
+typename std::remove_reference<PackedT>::type PackParam(FromT attribs)
+{
+ return AttributeMap::CreateFromIntArray(attribs);
+}
+
+template <typename PackedT,
+ typename FromT,
+ typename std::enable_if<!std::is_enum<PackedT>::value>::type * = nullptr,
+ typename std::enable_if<!std::is_same<FromT, const EGLint *>::value>::type * = nullptr,
+ typename std::enable_if<std::is_same<FromT, const EGLAttrib *>::value>::type * = nullptr>
+typename std::remove_reference<PackedT>::type PackParam(FromT attribs)
+{
+ return AttributeMap::CreateFromAttribArray(attribs);
+}
+
+template <typename PackedT,
+ typename FromT,
+ typename std::enable_if<!std::is_enum<PackedT>::value>::type * = nullptr,
+ typename std::enable_if<!std::is_same<FromT, const EGLint *>::value>::type * = nullptr,
+ typename std::enable_if<!std::is_same<FromT, const EGLAttrib *>::value>::type * = nullptr>
+typename std::remove_reference<PackedT>::type PackParam(FromT attribs)
+{
+ return static_cast<PackedT>(attribs);
+}
+
+} // namespace egl
+
+#define ANGLE_EGL_VALIDATE(THREAD, EP, OBJ, RETURN_TYPE, ...) \
+ do \
+ { \
+ const char *epname = "egl" #EP; \
+ ValidationContext vctx(THREAD, epname, OBJ); \
+ auto ANGLE_LOCAL_VAR = (Validate##EP(&vctx, ##__VA_ARGS__)); \
+ if (!ANGLE_LOCAL_VAR) \
+ { \
+ return GetDefaultReturnValue<angle::EntryPoint::EGL##EP, RETURN_TYPE>(THREAD); \
+ } \
+ } while (0)
+
+#define ANGLE_EGL_VALIDATE_VOID(THREAD, EP, OBJ, ...) \
+ do \
+ { \
+ const char *epname = "egl" #EP; \
+ ValidationContext vctx(THREAD, epname, OBJ); \
+ auto ANGLE_LOCAL_VAR = (Validate##EP(&vctx, ##__VA_ARGS__)); \
+ if (!ANGLE_LOCAL_VAR) \
+ { \
+ return; \
+ } \
+ } while (0)
+
+#define ANGLE_EGL_TRY(THREAD, EXPR, FUNCNAME, LABELOBJECT) \
+ do \
+ { \
+ auto ANGLE_LOCAL_VAR = (EXPR); \
+ if (ANGLE_LOCAL_VAR.isError()) \
+ return THREAD->setError(ANGLE_LOCAL_VAR, FUNCNAME, LABELOBJECT); \
+ } while (0)
+
+#define ANGLE_EGL_TRY_RETURN(THREAD, EXPR, FUNCNAME, LABELOBJECT, RETVAL) \
+ do \
+ { \
+ auto ANGLE_LOCAL_VAR = (EXPR); \
+ if (ANGLE_LOCAL_VAR.isError()) \
+ { \
+ THREAD->setError(ANGLE_LOCAL_VAR, FUNCNAME, LABELOBJECT); \
+ return RETVAL; \
+ } \
+ } while (0)
+
+#define ANGLE_EGLBOOLEAN_TRY(EXPR) \
+ do \
+ { \
+ EGLBoolean ANGLE_LOCAL_VAR = (EXPR); \
+ if (ANGLE_LOCAL_VAR != EGL_TRUE) \
+ { \
+ return ANGLE_LOCAL_VAR; \
+ } \
+ } while (0)
+
+#endif // LIBANGLE_VALIDATIONEGL_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationEGL_autogen.h b/gfx/angle/checkout/src/libANGLE/validationEGL_autogen.h
new file mode 100644
index 0000000000..57bd334227
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationEGL_autogen.h
@@ -0,0 +1,510 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from egl.xml and egl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationEGL_autogen.h:
+// Validation functions for the EGL entry points.
+
+#ifndef LIBANGLE_VALIDATION_EGL_AUTOGEN_H_
+#define LIBANGLE_VALIDATION_EGL_AUTOGEN_H_
+
+#include "libANGLE/validationEGL.h"
+
+namespace egl
+{
+
+// EGL 1.0
+bool ValidateChooseConfig(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const AttributeMap &attrib_listPacked,
+ const EGLConfig *configs,
+ EGLint config_size,
+ const EGLint *num_config);
+bool ValidateCopyBuffers(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ EGLNativePixmapType target);
+bool ValidateCreateContext(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Config *configPacked,
+ const gl::Context *share_contextPacked,
+ const AttributeMap &attrib_listPacked);
+bool ValidateCreatePbufferSurface(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Config *configPacked,
+ const AttributeMap &attrib_listPacked);
+bool ValidateCreatePixmapSurface(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Config *configPacked,
+ EGLNativePixmapType pixmap,
+ const AttributeMap &attrib_listPacked);
+bool ValidateCreateWindowSurface(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Config *configPacked,
+ EGLNativeWindowType win,
+ const AttributeMap &attrib_listPacked);
+bool ValidateDestroyContext(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const gl::Context *ctxPacked);
+bool ValidateDestroySurface(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked);
+bool ValidateGetConfigAttrib(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Config *configPacked,
+ EGLint attribute,
+ const EGLint *value);
+bool ValidateGetConfigs(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const EGLConfig *configs,
+ EGLint config_size,
+ const EGLint *num_config);
+bool ValidateGetCurrentDisplay(const ValidationContext *val);
+bool ValidateGetCurrentSurface(const ValidationContext *val, EGLint readdraw);
+bool ValidateGetDisplay(const ValidationContext *val, EGLNativeDisplayType display_id);
+bool ValidateGetError(const ValidationContext *val);
+bool ValidateGetProcAddress(const ValidationContext *val, const char *procname);
+bool ValidateInitialize(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const EGLint *major,
+ const EGLint *minor);
+bool ValidateMakeCurrent(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *drawPacked,
+ const Surface *readPacked,
+ const gl::Context *ctxPacked);
+bool ValidateQueryContext(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const gl::Context *ctxPacked,
+ EGLint attribute,
+ const EGLint *value);
+bool ValidateQueryString(const ValidationContext *val, const egl::Display *dpyPacked, EGLint name);
+bool ValidateQuerySurface(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ EGLint attribute,
+ const EGLint *value);
+bool ValidateSwapBuffers(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked);
+bool ValidateTerminate(const ValidationContext *val, const egl::Display *dpyPacked);
+bool ValidateWaitGL(const ValidationContext *val);
+bool ValidateWaitNative(const ValidationContext *val, EGLint engine);
+
+// EGL 1.1
+bool ValidateBindTexImage(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ EGLint buffer);
+bool ValidateReleaseTexImage(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ EGLint buffer);
+bool ValidateSurfaceAttrib(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ EGLint attribute,
+ EGLint value);
+bool ValidateSwapInterval(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ EGLint interval);
+
+// EGL 1.2
+bool ValidateBindAPI(const ValidationContext *val, EGLenum api);
+bool ValidateCreatePbufferFromClientBuffer(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ EGLenum buftype,
+ EGLClientBuffer buffer,
+ const Config *configPacked,
+ const AttributeMap &attrib_listPacked);
+bool ValidateQueryAPI(const ValidationContext *val);
+bool ValidateReleaseThread(const ValidationContext *val);
+bool ValidateWaitClient(const ValidationContext *val);
+
+// EGL 1.4
+bool ValidateGetCurrentContext(const ValidationContext *val);
+
+// EGL 1.5
+bool ValidateClientWaitSync(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Sync *syncPacked,
+ EGLint flags,
+ EGLTime timeout);
+bool ValidateCreateImage(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const gl::Context *ctxPacked,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const AttributeMap &attrib_listPacked);
+bool ValidateCreatePlatformPixmapSurface(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Config *configPacked,
+ const void *native_pixmap,
+ const AttributeMap &attrib_listPacked);
+bool ValidateCreatePlatformWindowSurface(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Config *configPacked,
+ const void *native_window,
+ const AttributeMap &attrib_listPacked);
+bool ValidateCreateSync(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ EGLenum type,
+ const AttributeMap &attrib_listPacked);
+bool ValidateDestroyImage(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Image *imagePacked);
+bool ValidateDestroySync(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Sync *syncPacked);
+bool ValidateGetPlatformDisplay(const ValidationContext *val,
+ EGLenum platform,
+ const void *native_display,
+ const AttributeMap &attrib_listPacked);
+bool ValidateGetSyncAttrib(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Sync *syncPacked,
+ EGLint attribute,
+ const EGLAttrib *value);
+bool ValidateWaitSync(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Sync *syncPacked,
+ EGLint flags);
+
+// EGL_ANDROID_blob_cache
+bool ValidateSetBlobCacheFuncsANDROID(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ EGLSetBlobFuncANDROID set,
+ EGLGetBlobFuncANDROID get);
+
+// EGL_ANDROID_create_native_client_buffer
+bool ValidateCreateNativeClientBufferANDROID(const ValidationContext *val,
+ const AttributeMap &attrib_listPacked);
+
+// EGL_ANDROID_get_frame_timestamps
+bool ValidateGetCompositorTimingSupportedANDROID(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ CompositorTiming namePacked);
+bool ValidateGetCompositorTimingANDROID(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ EGLint numTimestamps,
+ const EGLint *names,
+ const EGLnsecsANDROID *values);
+bool ValidateGetNextFrameIdANDROID(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ const EGLuint64KHR *frameId);
+bool ValidateGetFrameTimestampSupportedANDROID(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ Timestamp timestampPacked);
+bool ValidateGetFrameTimestampsANDROID(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ EGLuint64KHR frameId,
+ EGLint numTimestamps,
+ const EGLint *timestamps,
+ const EGLnsecsANDROID *values);
+
+// EGL_ANDROID_get_native_client_buffer
+bool ValidateGetNativeClientBufferANDROID(const ValidationContext *val,
+ const struct AHardwareBuffer *buffer);
+
+// EGL_ANDROID_native_fence_sync
+bool ValidateDupNativeFenceFDANDROID(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Sync *syncPacked);
+
+// EGL_ANDROID_presentation_time
+bool ValidatePresentationTimeANDROID(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ EGLnsecsANDROID time);
+
+// EGL_ANGLE_device_creation
+bool ValidateCreateDeviceANGLE(const ValidationContext *val,
+ EGLint device_type,
+ const void *native_device,
+ const EGLAttrib *attrib_list);
+bool ValidateReleaseDeviceANGLE(const ValidationContext *val, const Device *devicePacked);
+
+// EGL_ANGLE_feature_control
+bool ValidateQueryStringiANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ EGLint name,
+ EGLint index);
+bool ValidateQueryDisplayAttribANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ EGLint attribute,
+ const EGLAttrib *value);
+
+// EGL_ANGLE_metal_shared_event_sync
+bool ValidateCopyMetalSharedEventANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Sync *syncPacked);
+
+// EGL_ANGLE_power_preference
+bool ValidateReleaseHighPowerGPUANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const gl::Context *ctxPacked);
+bool ValidateReacquireHighPowerGPUANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const gl::Context *ctxPacked);
+bool ValidateHandleGPUSwitchANGLE(const ValidationContext *val, const egl::Display *dpyPacked);
+bool ValidateForceGPUSwitchANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ EGLint gpuIDHigh,
+ EGLint gpuIDLow);
+
+// EGL_ANGLE_prepare_swap_buffers
+bool ValidatePrepareSwapBuffersANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked);
+
+// EGL_ANGLE_program_cache_control
+bool ValidateProgramCacheGetAttribANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ EGLenum attrib);
+bool ValidateProgramCacheQueryANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ EGLint index,
+ const void *key,
+ const EGLint *keysize,
+ const void *binary,
+ const EGLint *binarysize);
+bool ValidateProgramCachePopulateANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const void *key,
+ EGLint keysize,
+ const void *binary,
+ EGLint binarysize);
+bool ValidateProgramCacheResizeANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ EGLint limit,
+ EGLint mode);
+
+// EGL_ANGLE_query_surface_pointer
+bool ValidateQuerySurfacePointerANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ EGLint attribute,
+ void *const *value);
+
+// EGL_ANGLE_stream_producer_d3d_texture
+bool ValidateCreateStreamProducerD3DTextureANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Stream *streamPacked,
+ const AttributeMap &attrib_listPacked);
+bool ValidateStreamPostD3DTextureANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Stream *streamPacked,
+ const void *texture,
+ const AttributeMap &attrib_listPacked);
+
+// EGL_ANGLE_swap_with_frame_token
+bool ValidateSwapBuffersWithFrameTokenANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ EGLFrameTokenANGLE frametoken);
+
+// EGL_ANGLE_sync_control_rate
+bool ValidateGetMscRateANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ const EGLint *numerator,
+ const EGLint *denominator);
+
+// EGL_ANGLE_vulkan_image
+bool ValidateExportVkImageANGLE(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Image *imagePacked,
+ const void *vk_image,
+ const void *vk_image_create_info);
+
+// EGL_CHROMIUM_sync_control
+bool ValidateGetSyncValuesCHROMIUM(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ const EGLuint64KHR *ust,
+ const EGLuint64KHR *msc,
+ const EGLuint64KHR *sbc);
+
+// EGL_EXT_device_query
+bool ValidateQueryDeviceAttribEXT(const ValidationContext *val,
+ const Device *devicePacked,
+ EGLint attribute,
+ const EGLAttrib *value);
+bool ValidateQueryDeviceStringEXT(const ValidationContext *val,
+ const Device *devicePacked,
+ EGLint name);
+bool ValidateQueryDisplayAttribEXT(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ EGLint attribute,
+ const EGLAttrib *value);
+
+// EGL_EXT_image_dma_buf_import_modifiers
+bool ValidateQueryDmaBufFormatsEXT(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ EGLint max_formats,
+ const EGLint *formats,
+ const EGLint *num_formats);
+bool ValidateQueryDmaBufModifiersEXT(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ EGLint format,
+ EGLint max_modifiers,
+ const EGLuint64KHR *modifiers,
+ const EGLBoolean *external_only,
+ const EGLint *num_modifiers);
+
+// EGL_EXT_platform_base
+bool ValidateCreatePlatformPixmapSurfaceEXT(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Config *configPacked,
+ const void *native_pixmap,
+ const AttributeMap &attrib_listPacked);
+bool ValidateCreatePlatformWindowSurfaceEXT(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Config *configPacked,
+ const void *native_window,
+ const AttributeMap &attrib_listPacked);
+bool ValidateGetPlatformDisplayEXT(const ValidationContext *val,
+ EGLenum platform,
+ const void *native_display,
+ const AttributeMap &attrib_listPacked);
+
+// EGL_KHR_debug
+bool ValidateDebugMessageControlKHR(const ValidationContext *val,
+ EGLDEBUGPROCKHR callback,
+ const AttributeMap &attrib_listPacked);
+bool ValidateLabelObjectKHR(const ValidationContext *val,
+ const egl::Display *displayPacked,
+ ObjectType objectTypePacked,
+ EGLObjectKHR object,
+ EGLLabelKHR label);
+bool ValidateQueryDebugKHR(const ValidationContext *val, EGLint attribute, const EGLAttrib *value);
+
+// EGL_KHR_fence_sync
+bool ValidateClientWaitSyncKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Sync *syncPacked,
+ EGLint flags,
+ EGLTimeKHR timeout);
+bool ValidateCreateSyncKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ EGLenum type,
+ const AttributeMap &attrib_listPacked);
+bool ValidateDestroySyncKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Sync *syncPacked);
+bool ValidateGetSyncAttribKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Sync *syncPacked,
+ EGLint attribute,
+ const EGLint *value);
+
+// EGL_KHR_image
+bool ValidateCreateImageKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const gl::Context *ctxPacked,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const AttributeMap &attrib_listPacked);
+bool ValidateDestroyImageKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Image *imagePacked);
+
+// EGL_KHR_lock_surface3
+bool ValidateLockSurfaceKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ const AttributeMap &attrib_listPacked);
+bool ValidateQuerySurface64KHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ EGLint attribute,
+ const EGLAttribKHR *value);
+bool ValidateUnlockSurfaceKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked);
+
+// EGL_KHR_partial_update
+bool ValidateSetDamageRegionKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ const EGLint *rects,
+ EGLint n_rects);
+
+// EGL_KHR_reusable_sync
+bool ValidateSignalSyncKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Sync *syncPacked,
+ EGLenum mode);
+
+// EGL_KHR_stream
+bool ValidateCreateStreamKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const AttributeMap &attrib_listPacked);
+bool ValidateDestroyStreamKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Stream *streamPacked);
+bool ValidateQueryStreamKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Stream *streamPacked,
+ EGLenum attribute,
+ const EGLint *value);
+bool ValidateQueryStreamu64KHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Stream *streamPacked,
+ EGLenum attribute,
+ const EGLuint64KHR *value);
+bool ValidateStreamAttribKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Stream *streamPacked,
+ EGLenum attribute,
+ EGLint value);
+
+// EGL_KHR_stream_consumer_gltexture
+bool ValidateStreamConsumerAcquireKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Stream *streamPacked);
+bool ValidateStreamConsumerGLTextureExternalKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Stream *streamPacked);
+bool ValidateStreamConsumerReleaseKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Stream *streamPacked);
+
+// EGL_KHR_swap_buffers_with_damage
+bool ValidateSwapBuffersWithDamageKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ const EGLint *rects,
+ EGLint n_rects);
+
+// EGL_KHR_wait_sync
+bool ValidateWaitSyncKHR(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Sync *syncPacked,
+ EGLint flags);
+
+// EGL_NV_post_sub_buffer
+bool ValidatePostSubBufferNV(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Surface *surfacePacked,
+ EGLint x,
+ EGLint y,
+ EGLint width,
+ EGLint height);
+
+// EGL_NV_stream_consumer_gltexture_yuv
+bool ValidateStreamConsumerGLTextureExternalAttribsNV(const ValidationContext *val,
+ const egl::Display *dpyPacked,
+ const Stream *streamPacked,
+ const AttributeMap &attrib_listPacked);
+} // namespace egl
+
+#endif // LIBANGLE_VALIDATION_EGL_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationES.cpp b/gfx/angle/checkout/src/libANGLE/validationES.cpp
new file mode 100644
index 0000000000..ddc586b1ad
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES.cpp
@@ -0,0 +1,8666 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationES.h: Validation functions for generic OpenGL ES entry point parameters
+
+#include "libANGLE/validationES.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/queryutils.h"
+#include "libANGLE/validationES2.h"
+#include "libANGLE/validationES3.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+
+using namespace angle;
+
+namespace gl
+{
+using namespace err;
+
+namespace
+{
+bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
+{
+ // List of compressed format that require that the texture size is smaller than or a multiple of
+ // the compressed block size.
+ switch (internalFormat)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
+ case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
+ case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
+ case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
+ case GL_COMPRESSED_RED_RGTC1_EXT:
+ case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
+ case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
+ case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
+ case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
+ return true;
+
+ default:
+ return false;
+ }
+}
+bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
+{
+ // Compressed sub textures have additional formats that requires exact size.
+ // ES 3.1, Section 8.7, Page 171
+ return CompressedTextureFormatRequiresExactSize(internalFormat) ||
+ IsETC2EACFormat(internalFormat) || IsASTC2DFormat(internalFormat);
+}
+
+bool DifferenceCanOverflow(GLint a, GLint b)
+{
+ CheckedNumeric<GLint> checkedA(a);
+ checkedA -= b;
+ // Use negation to make sure that the difference can't overflow regardless of the order.
+ checkedA = -checkedA;
+ return !checkedA.IsValid();
+}
+
+bool ValidReadPixelsTypeEnum(const Context *context, GLenum type)
+{
+ switch (type)
+ {
+ // Types referenced in Table 3.4 of the ES 2.0.25 spec
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return context->getClientVersion() >= ES_2_0;
+
+ // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
+ case GL_BYTE:
+ case GL_INT:
+ case GL_SHORT:
+ case GL_UNSIGNED_INT:
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_5_9_9_9_REV:
+ case GL_UNSIGNED_SHORT:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ return context->getClientVersion() >= ES_3_0;
+
+ case GL_FLOAT:
+ return context->getClientVersion() >= ES_3_0 ||
+ context->getExtensions().textureFloatOES ||
+ context->getExtensions().colorBufferHalfFloatEXT;
+
+ case GL_HALF_FLOAT:
+ return context->getClientVersion() >= ES_3_0 ||
+ context->getExtensions().textureHalfFloatOES;
+
+ case GL_HALF_FLOAT_OES:
+ return context->getExtensions().colorBufferHalfFloatEXT;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidReadPixelsFormatEnum(const Context *context, GLenum format)
+{
+ switch (format)
+ {
+ // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
+ case GL_RGBA:
+ case GL_RGB:
+ case GL_ALPHA:
+ return context->getClientVersion() >= ES_2_0;
+
+ // Formats referenced in Table 3.2 of the ES 3.0.5 spec
+ case GL_RG:
+ case GL_RED:
+ case GL_RGBA_INTEGER:
+ case GL_RGB_INTEGER:
+ case GL_RG_INTEGER:
+ case GL_RED_INTEGER:
+ return context->getClientVersion() >= ES_3_0;
+
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB_EXT:
+ return context->getExtensions().sRGBEXT;
+
+ case GL_BGRA_EXT:
+ return context->getExtensions().readFormatBgraEXT;
+
+ case GL_RGBX8_ANGLE:
+ return context->getExtensions().rgbxInternalFormatANGLE;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidReadPixelsUnsignedNormalizedDepthType(const Context *context,
+ const gl::InternalFormat *info,
+ GLenum type)
+{
+ bool supportsReadDepthNV = context->getExtensions().readDepthNV && (info->depthBits > 0);
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ case GL_UNSIGNED_INT:
+ case GL_UNSIGNED_INT_24_8:
+ return supportsReadDepthNV;
+ default:
+ return false;
+ }
+}
+
+bool ValidReadPixelsFloatDepthType(const Context *context,
+ const gl::InternalFormat *info,
+ GLenum type)
+{
+ return context->getExtensions().readDepthNV && (type == GL_FLOAT) &&
+ context->getExtensions().depthBufferFloat2NV;
+}
+
+bool ValidReadPixelsFormatType(const Context *context,
+ const gl::InternalFormat *info,
+ GLenum format,
+ GLenum type)
+{
+ switch (info->componentType)
+ {
+ case GL_UNSIGNED_NORMALIZED:
+ // TODO(geofflang): Don't accept BGRA here. Some chrome internals appear to try to use
+ // ReadPixels with BGRA even if the extension is not present
+ switch (format)
+ {
+ case GL_RGBA:
+ return ((type == GL_UNSIGNED_BYTE) && info->pixelBytes >= 1) ||
+ (context->getExtensions().textureNorm16EXT &&
+ (type == GL_UNSIGNED_SHORT) && info->pixelBytes >= 2);
+ case GL_BGRA_EXT:
+ return context->getExtensions().readFormatBgraEXT && (type == GL_UNSIGNED_BYTE);
+ case GL_STENCIL_INDEX_OES:
+ return context->getExtensions().readStencilNV && (type == GL_UNSIGNED_BYTE);
+ case GL_DEPTH_COMPONENT:
+ return ValidReadPixelsUnsignedNormalizedDepthType(context, info, type);
+ case GL_DEPTH_STENCIL_OES:
+ return context->getExtensions().readDepthStencilNV &&
+ (type == GL_UNSIGNED_INT_24_8_OES) && info->stencilBits > 0;
+ case GL_RGBX8_ANGLE:
+ return context->getExtensions().rgbxInternalFormatANGLE &&
+ (type == GL_UNSIGNED_BYTE);
+ default:
+ return false;
+ }
+ case GL_SIGNED_NORMALIZED:
+ return (format == GL_RGBA && type == GL_BYTE && info->pixelBytes >= 1) ||
+ (context->getExtensions().textureNorm16EXT && format == GL_RGBA &&
+ type == GL_UNSIGNED_SHORT && info->pixelBytes >= 2);
+
+ case GL_INT:
+ return (format == GL_RGBA_INTEGER && type == GL_INT);
+
+ case GL_UNSIGNED_INT:
+ return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
+
+ case GL_FLOAT:
+ switch (format)
+ {
+ case GL_RGBA:
+ return (type == GL_FLOAT);
+ case GL_DEPTH_COMPONENT:
+ return ValidReadPixelsFloatDepthType(context, info, type);
+ case GL_DEPTH_STENCIL_OES:
+ return context->getExtensions().readDepthStencilNV &&
+ type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV && info->stencilBits > 0;
+ default:
+ return false;
+ }
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+template <typename ParamType>
+bool ValidateTextureWrapModeValue(const Context *context,
+ angle::EntryPoint entryPoint,
+ const ParamType *params,
+ bool restrictedWrapModes)
+{
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_CLAMP_TO_EDGE:
+ break;
+
+ case GL_CLAMP_TO_BORDER:
+ if (!context->getExtensions().textureBorderClampAny() &&
+ context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ case GL_REPEAT:
+ case GL_MIRRORED_REPEAT:
+ if (restrictedWrapModes)
+ {
+ // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidWrapModeTexture);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureWrap);
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureMinFilterValue(const Context *context,
+ angle::EntryPoint entryPoint,
+ const ParamType *params,
+ bool restrictedMinFilter)
+{
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ break;
+
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ if (restrictedMinFilter)
+ {
+ // OES_EGL_image_external specifies this error.
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFilterTexture);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureFilterParam);
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureMagFilterValue(const Context *context,
+ angle::EntryPoint entryPoint,
+ const ParamType *params)
+{
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureFilterParam);
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureCompareModeValue(const Context *context,
+ angle::EntryPoint entryPoint,
+ const ParamType *params)
+{
+ // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_NONE:
+ case GL_COMPARE_REF_TO_TEXTURE:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kUnknownParameter);
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureCompareFuncValue(const Context *context,
+ angle::EntryPoint entryPoint,
+ const ParamType *params)
+{
+ // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_LEQUAL:
+ case GL_GEQUAL:
+ case GL_LESS:
+ case GL_GREATER:
+ case GL_EQUAL:
+ case GL_NOTEQUAL:
+ case GL_ALWAYS:
+ case GL_NEVER:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kUnknownParameter);
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureSRGBDecodeValue(const Context *context,
+ angle::EntryPoint entryPoint,
+ const ParamType *params)
+{
+ if (!context->getExtensions().textureSRGBDecodeEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ return false;
+ }
+
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_DECODE_EXT:
+ case GL_SKIP_DECODE_EXT:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kUnknownParameter);
+ return false;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTextureSRGBOverrideValue(const Context *context,
+ angle::EntryPoint entryPoint,
+ const ParamType *params)
+{
+ if (!context->getExtensions().textureFormatSRGBOverrideEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ return false;
+ }
+
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_SRGB:
+ case GL_NONE:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kUnknownParameter);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTextureMaxAnisotropyExtensionEnabled(const Context *context,
+ angle::EntryPoint entryPoint)
+{
+ if (!context->getExtensions().textureFilterAnisotropicEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTextureMaxAnisotropyValue(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat paramValue)
+{
+ if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint))
+ {
+ return false;
+ }
+
+ GLfloat largest = context->getCaps().maxTextureAnisotropy;
+
+ if (paramValue < 1 || paramValue > largest)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kOutsideOfBounds);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFragmentShaderColorBufferMaskMatch(const Context *context)
+{
+ const auto &glState = context->getState();
+ const Program *program = context->getActiveLinkedProgram();
+ const Framebuffer *framebuffer = glState.getDrawFramebuffer();
+
+ auto drawBufferMask =
+ framebuffer->getDrawBufferMask() & glState.getBlendStateExt().compareColorMask(0);
+ auto fragmentOutputMask = program->getExecutable().getActiveOutputVariablesMask();
+
+ return drawBufferMask == (drawBufferMask & fragmentOutputMask);
+}
+
+bool ValidateFragmentShaderColorBufferTypeMatch(const Context *context)
+{
+ const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
+ const Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
+
+ return ValidateComponentTypeMasks(executable->getFragmentOutputsTypeMask().to_ulong(),
+ framebuffer->getDrawBufferTypeMask().to_ulong(),
+ executable->getActiveOutputVariablesMask().to_ulong(),
+ framebuffer->getDrawBufferMask().to_ulong());
+}
+
+bool ValidateVertexShaderAttributeTypeMatch(const Context *context)
+{
+ const auto &glState = context->getState();
+ const Program *program = context->getActiveLinkedProgram();
+ const VertexArray *vao = context->getState().getVertexArray();
+
+ if (!program)
+ {
+ return false;
+ }
+
+ unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
+ unsigned long vaoAttribTypeBits = vao->getAttributesTypeMask().to_ulong();
+ unsigned long vaoAttribEnabledMask = vao->getAttributesMask().to_ulong();
+
+ vaoAttribEnabledMask |= vaoAttribEnabledMask << kMaxComponentTypeMaskIndex;
+ vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
+ vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
+
+ const ProgramExecutable &executable = program->getExecutable();
+ return ValidateComponentTypeMasks(executable.getAttributesTypeMask().to_ulong(),
+ vaoAttribTypeBits, executable.getAttributesMask().to_ulong(),
+ 0xFFFF);
+}
+
+bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
+ PrimitiveMode geometryShaderInputPrimitiveType)
+{
+ // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
+ switch (drawMode)
+ {
+ case PrimitiveMode::Points:
+ return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
+ case PrimitiveMode::Lines:
+ case PrimitiveMode::LineStrip:
+ case PrimitiveMode::LineLoop:
+ return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
+ case PrimitiveMode::LinesAdjacency:
+ case PrimitiveMode::LineStripAdjacency:
+ return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
+ case PrimitiveMode::Triangles:
+ case PrimitiveMode::TriangleFan:
+ case PrimitiveMode::TriangleStrip:
+ return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
+ case PrimitiveMode::TrianglesAdjacency:
+ case PrimitiveMode::TriangleStripAdjacency:
+ return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+// GLES1 texture parameters are a small subset of the others
+bool IsValidGLES1TextureParameter(GLenum pname)
+{
+ switch (pname)
+ {
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ case GL_GENERATE_MIPMAP:
+ case GL_TEXTURE_CROP_RECT_OES:
+ return true;
+ default:
+ return false;
+ }
+}
+
+unsigned int GetSamplerParameterCount(GLenum pname)
+{
+ return pname == GL_TEXTURE_BORDER_COLOR ? 4 : 1;
+}
+
+const char *ValidateProgramDrawAdvancedBlendState(const Context *context, Program *program)
+{
+ const State &state = context->getState();
+ const BlendEquationBitSet &supportedBlendEquations =
+ program->getExecutable().getAdvancedBlendEquations();
+ const DrawBufferMask &enabledDrawBufferMask = state.getBlendStateExt().getEnabledMask();
+
+ for (size_t blendEnabledBufferIndex : enabledDrawBufferMask)
+ {
+ const gl::BlendEquationType &enabledBlendEquation = gl::FromGLenum<gl::BlendEquationType>(
+ state.getBlendStateExt().getEquationColorIndexed(blendEnabledBufferIndex));
+
+ if (enabledBlendEquation < gl::BlendEquationType::Multiply ||
+ enabledBlendEquation > gl::BlendEquationType::HslLuminosity)
+ {
+ continue;
+ }
+
+ if (!supportedBlendEquations.test(enabledBlendEquation))
+ {
+ return gl::err::kBlendEquationNotEnabled;
+ }
+ }
+
+ return nullptr;
+}
+
+ANGLE_INLINE const char *ValidateProgramDrawStates(const Context *context,
+ const Extensions &extensions,
+ Program *program)
+{
+ const State &state = context->getState();
+ if (extensions.multiviewOVR || extensions.multiview2OVR)
+ {
+ const int programNumViews = program->usesMultiview() ? program->getNumViews() : 1;
+ Framebuffer *framebuffer = state.getDrawFramebuffer();
+ const int framebufferNumViews = framebuffer->getNumViews();
+
+ if (framebufferNumViews != programNumViews)
+ {
+ return gl::err::kMultiviewMismatch;
+ }
+
+ if (state.isTransformFeedbackActiveUnpaused() && framebufferNumViews > 1)
+ {
+ return gl::err::kMultiviewTransformFeedback;
+ }
+
+ if (extensions.disjointTimerQueryEXT && framebufferNumViews > 1 &&
+ state.isQueryActive(QueryType::TimeElapsed))
+ {
+ return gl::err::kMultiviewTimerQuery;
+ }
+ }
+
+ // Uniform buffer validation
+ for (unsigned int uniformBlockIndex = 0;
+ uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
+ {
+ const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
+ GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
+ const OffsetBindingPointer<Buffer> &uniformBuffer =
+ state.getIndexedUniformBuffer(blockBinding);
+
+ if (uniformBuffer.get() == nullptr && context->isWebGL())
+ {
+ // undefined behaviour
+ return gl::err::kUniformBufferUnbound;
+ }
+
+ size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
+ if (uniformBufferSize < uniformBlock.dataSize &&
+ (context->isWebGL() || context->isBufferAccessValidationEnabled()))
+ {
+ // undefined behaviour
+ return gl::err::kUniformBufferTooSmall;
+ }
+
+ if (uniformBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
+ {
+ return gl::err::kUniformBufferBoundForTransformFeedback;
+ }
+ }
+
+ // Enabled blend equation validation
+ const char *errorString = nullptr;
+
+ if (extensions.blendEquationAdvancedKHR)
+ {
+ errorString = ValidateProgramDrawAdvancedBlendState(context, program);
+ }
+
+ return errorString;
+}
+} // anonymous namespace
+
+void SetRobustLengthParam(const GLsizei *length, GLsizei value)
+{
+ if (length)
+ {
+ // Currently we modify robust length parameters in the validation layer. We should be only
+ // doing this in the Context instead.
+ // TODO(http://anglebug.com/4406): Remove when possible.
+ *const_cast<GLsizei *>(length) = value;
+ }
+}
+
+bool ValidTextureTarget(const Context *context, TextureType type)
+{
+ switch (type)
+ {
+ case TextureType::_2D:
+ case TextureType::CubeMap:
+ return true;
+
+ case TextureType::Rectangle:
+ return context->getExtensions().textureRectangleANGLE;
+
+ case TextureType::_3D:
+ return ((context->getClientMajorVersion() >= 3) ||
+ context->getExtensions().texture3DOES);
+
+ case TextureType::_2DArray:
+ return (context->getClientMajorVersion() >= 3);
+
+ case TextureType::_2DMultisample:
+ return (context->getClientVersion() >= Version(3, 1) ||
+ context->getExtensions().textureMultisampleANGLE);
+ case TextureType::_2DMultisampleArray:
+ return context->getExtensions().textureStorageMultisample2dArrayOES;
+
+ case TextureType::CubeMapArray:
+ return (context->getClientVersion() >= Version(3, 2) ||
+ context->getExtensions().textureCubeMapArrayAny());
+
+ case TextureType::VideoImage:
+ return context->getExtensions().videoTextureWEBGL;
+
+ case TextureType::Buffer:
+ return (context->getClientVersion() >= Version(3, 2) ||
+ context->getExtensions().textureBufferAny());
+
+ default:
+ return false;
+ }
+}
+
+bool ValidTexture2DTarget(const Context *context, TextureType type)
+{
+ switch (type)
+ {
+ case TextureType::_2D:
+ case TextureType::CubeMap:
+ return true;
+
+ case TextureType::Rectangle:
+ return context->getExtensions().textureRectangleANGLE;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidTexture3DTarget(const Context *context, TextureType target)
+{
+ switch (target)
+ {
+ case TextureType::_3D:
+ case TextureType::_2DArray:
+ return (context->getClientMajorVersion() >= 3);
+
+ case TextureType::CubeMapArray:
+ return (context->getClientVersion() >= Version(3, 2) ||
+ context->getExtensions().textureCubeMapArrayAny());
+
+ default:
+ return false;
+ }
+}
+
+// Most texture GL calls are not compatible with external textures, so we have a separate validation
+// function for use in the GL calls that do
+bool ValidTextureExternalTarget(const Context *context, TextureType target)
+{
+ return (target == TextureType::External) &&
+ (context->getExtensions().EGLImageExternalOES ||
+ context->getExtensions().EGLStreamConsumerExternalNV);
+}
+
+bool ValidTextureExternalTarget(const Context *context, TextureTarget target)
+{
+ return (target == TextureTarget::External) &&
+ ValidTextureExternalTarget(context, TextureType::External);
+}
+
+// This function differs from ValidTextureTarget in that the target must be
+// usable as the destination of a 2D operation-- so a cube face is valid, but
+// GL_TEXTURE_CUBE_MAP is not.
+// Note: duplicate of IsInternalTextureTarget
+bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
+{
+ switch (target)
+ {
+ case TextureTarget::_2D:
+ case TextureTarget::CubeMapNegativeX:
+ case TextureTarget::CubeMapNegativeY:
+ case TextureTarget::CubeMapNegativeZ:
+ case TextureTarget::CubeMapPositiveX:
+ case TextureTarget::CubeMapPositiveY:
+ case TextureTarget::CubeMapPositiveZ:
+ return true;
+ case TextureTarget::Rectangle:
+ return context->getExtensions().textureRectangleANGLE;
+ case TextureTarget::VideoImage:
+ return context->getExtensions().videoTextureWEBGL;
+ default:
+ return false;
+ }
+}
+
+bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode transformFeedbackPrimitiveMode,
+ PrimitiveMode renderPrimitiveMode)
+{
+ ASSERT(context);
+
+ if ((!context->getExtensions().geometryShaderAny() ||
+ !context->getExtensions().tessellationShaderEXT) &&
+ context->getClientVersion() < ES_3_2)
+ {
+ // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
+ // that does not match the current transform feedback object's draw mode (if transform
+ // feedback is active), (3.0.2, section 2.14, pg 86)
+ return transformFeedbackPrimitiveMode == renderPrimitiveMode;
+ }
+
+ const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
+ ASSERT(executable);
+ if (executable->hasLinkedShaderStage(ShaderType::Geometry))
+ {
+ // If geometry shader is active, transform feedback mode must match what is output from this
+ // stage.
+ renderPrimitiveMode = executable->getGeometryShaderOutputPrimitiveType();
+ }
+ else if (executable->hasLinkedShaderStage(ShaderType::TessEvaluation))
+ {
+ // Similarly with tessellation shaders, but only if no geometry shader is present. With
+ // tessellation shaders, only triangles are possibly output.
+ return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles &&
+ executable->getTessGenMode() == GL_TRIANGLES;
+ }
+
+ // [GL_EXT_geometry_shader] Table 12.1gs
+ switch (renderPrimitiveMode)
+ {
+ case PrimitiveMode::Points:
+ return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
+ case PrimitiveMode::Lines:
+ case PrimitiveMode::LineStrip:
+ case PrimitiveMode::LineLoop:
+ return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
+ case PrimitiveMode::Triangles:
+ case PrimitiveMode::TriangleFan:
+ case PrimitiveMode::TriangleStrip:
+ return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
+ case PrimitiveMode::Patches:
+ return transformFeedbackPrimitiveMode == PrimitiveMode::Patches;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool ValidateDrawElementsInstancedBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei primcount)
+{
+ if (primcount <= 0)
+ {
+ if (primcount < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativePrimcount);
+ return false;
+ }
+
+ // Early exit.
+ return ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices,
+ primcount);
+ }
+
+ if (!ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, primcount))
+ {
+ return false;
+ }
+
+ if (count == 0)
+ {
+ // Early exit.
+ return true;
+ }
+
+ return ValidateDrawInstancedAttribs(context, entryPoint, primcount);
+}
+
+bool ValidateDrawArraysInstancedBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount)
+{
+ if (primcount <= 0)
+ {
+ if (primcount < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativePrimcount);
+ return false;
+ }
+
+ // Early exit.
+ return ValidateDrawArraysCommon(context, entryPoint, mode, first, count, primcount);
+ }
+
+ if (!ValidateDrawArraysCommon(context, entryPoint, mode, first, count, primcount))
+ {
+ return false;
+ }
+
+ if (count == 0)
+ {
+ // Early exit.
+ return true;
+ }
+
+ return ValidateDrawInstancedAttribs(context, entryPoint, primcount);
+}
+
+bool ValidateDrawInstancedANGLE(const Context *context, angle::EntryPoint entryPoint)
+{
+ // Verify there is at least one active attribute with a divisor of zero
+ const State &state = context->getState();
+ const ProgramExecutable *executable = state.getLinkedProgramExecutable(context);
+
+ if (!executable)
+ {
+ // No executable means there is no Program/PPO bound, which is undefined behavior, but isn't
+ // an error.
+ context->getState().getDebug().insertMessage(
+ GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, 0, GL_DEBUG_SEVERITY_HIGH,
+ std::string("Attempting to draw without a program"), gl::LOG_WARN, entryPoint);
+ return true;
+ }
+
+ const auto &attribs = state.getVertexArray()->getVertexAttributes();
+ const auto &bindings = state.getVertexArray()->getVertexBindings();
+ for (size_t attributeIndex = 0; attributeIndex < attribs.size(); attributeIndex++)
+ {
+ const VertexAttribute &attrib = attribs[attributeIndex];
+ const VertexBinding &binding = bindings[attrib.bindingIndex];
+ if (executable->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
+ {
+ return true;
+ }
+ }
+
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kNoZeroDivisor);
+ return false;
+}
+
+bool ValidTexture3DDestinationTarget(const Context *context, TextureTarget target)
+{
+ switch (target)
+ {
+ case TextureTarget::_3D:
+ case TextureTarget::_2DArray:
+ return true;
+ case TextureTarget::CubeMapArray:
+ return (context->getClientVersion() >= Version(3, 2) ||
+ context->getExtensions().textureCubeMapArrayAny());
+ default:
+ return false;
+ }
+}
+
+bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
+{
+ switch (type)
+ {
+ case TextureType::_2D:
+ case TextureType::_2DArray:
+ case TextureType::_2DMultisample:
+ case TextureType::CubeMap:
+ case TextureType::_3D:
+ return true;
+ case TextureType::CubeMapArray:
+ return (context->getClientVersion() >= Version(3, 2) ||
+ context->getExtensions().textureCubeMapArrayAny());
+ case TextureType::Rectangle:
+ return context->getExtensions().textureRectangleANGLE;
+ case TextureType::_2DMultisampleArray:
+ return context->getExtensions().textureStorageMultisample2dArrayOES;
+ case TextureType::Buffer:
+ return (context->getClientVersion() >= Version(3, 2) ||
+ context->getExtensions().textureBufferAny());
+ default:
+ return false;
+ }
+}
+
+bool ValidFramebufferTarget(const Context *context, GLenum target)
+{
+ static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
+ GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
+ "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
+
+ switch (target)
+ {
+ case GL_FRAMEBUFFER:
+ return true;
+
+ case GL_READ_FRAMEBUFFER:
+ case GL_DRAW_FRAMEBUFFER:
+ return (context->getExtensions().framebufferBlitAny() ||
+ context->getClientMajorVersion() >= 3);
+
+ default:
+ return false;
+ }
+}
+
+bool ValidMipLevel(const Context *context, TextureType type, GLint level)
+{
+ const auto &caps = context->getCaps();
+ int maxDimension = 0;
+ switch (type)
+ {
+ case TextureType::_2D:
+ case TextureType::_2DArray:
+ case TextureType::_2DMultisample:
+ case TextureType::_2DMultisampleArray:
+ // TODO(http://anglebug.com/2775): It's a bit unclear what the "maximum allowable
+ // level-of-detail" for multisample textures should be. Could maybe make it zero.
+ maxDimension = caps.max2DTextureSize;
+ break;
+
+ case TextureType::CubeMap:
+ case TextureType::CubeMapArray:
+ maxDimension = caps.maxCubeMapTextureSize;
+ break;
+
+ case TextureType::External:
+ case TextureType::Rectangle:
+ case TextureType::VideoImage:
+ case TextureType::Buffer:
+ return level == 0;
+
+ case TextureType::_3D:
+ maxDimension = caps.max3DTextureSize;
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+
+ return level <= log2(maxDimension) && level >= 0;
+}
+
+bool ValidImageSizeParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLint level,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ bool isSubImage)
+{
+ if (width < 0 || height < 0 || depth < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
+ return false;
+ }
+ // TexSubImage parameters can be NPOT without textureNPOT extension,
+ // as long as the destination texture is POT.
+ bool hasNPOTSupport =
+ context->getExtensions().textureNpotOES || context->getClientVersion() >= Version(3, 0);
+ if (!isSubImage && !hasNPOTSupport &&
+ (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kTextureNotPow2);
+ return false;
+ }
+
+ if (!ValidMipLevel(context, target, level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidCompressedBaseLevel(GLsizei size, GLuint blockSize, GLint level)
+{
+ // Already checked in ValidMipLevel.
+ ASSERT(level < 32);
+ // This function is used only for 4x4 BC formats.
+ ASSERT(blockSize == 4);
+ // Use the constant value to avoid division.
+ return ((size << level) % 4) == 0;
+}
+
+bool ValidCompressedImageSize(const Context *context,
+ GLenum internalFormat,
+ GLint level,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ if (width < 0 || height < 0)
+ {
+ return false;
+ }
+
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
+
+ if (!formatInfo.compressed && !formatInfo.paletted)
+ {
+ return false;
+ }
+
+ // A texture format can not be both block-compressed and paletted
+ ASSERT(!(formatInfo.compressed && formatInfo.paletted));
+
+ if (formatInfo.compressed)
+ {
+ // Only PVRTC1 requires dimensions to be powers of two
+ if (IsPVRTC1Format(internalFormat))
+ {
+ if (!isPow2(width) || !isPow2(height))
+ {
+ return false;
+ }
+
+ if (context->getLimitations().squarePvrtc1)
+ {
+ if (width != height)
+ {
+ return false;
+ }
+ }
+ }
+
+ if (CompressedTextureFormatRequiresExactSize(internalFormat))
+ {
+ // In WebGL compatibility mode and D3D, enforce that the base level implied
+ // by the compressed texture's mip level would conform to the block
+ // size.
+ if (context->isWebGL() ||
+ context->getLimitations().compressedBaseMipLevelMultipleOfFour)
+ {
+ // This check is performed only for BC formats.
+ ASSERT(formatInfo.compressedBlockDepth == 1);
+ if (!ValidCompressedBaseLevel(width, formatInfo.compressedBlockWidth, level) ||
+ !ValidCompressedBaseLevel(height, formatInfo.compressedBlockHeight, level))
+ {
+ return false;
+ }
+ }
+ // non-WebGL and non-D3D check is not necessary for the following formats
+ // From EXT_texture_compression_s3tc specification:
+ // If the width or height is not a multiple of four, there will be 4x4 blocks at the
+ // edge of the image that contain "extra" texels that are not part of the image. From
+ // EXT_texture_compression_bptc & EXT_texture_compression_rgtc specification: If an
+ // RGTC/BPTC image has a width or height that is not a multiple of four, the data
+ // corresponding to texels outside the image are irrelevant and undefined.
+ }
+ }
+
+ if (formatInfo.paletted)
+ {
+ // TODO(http://anglebug.com/7688): multi-level paletted images
+ if (level != 0)
+ {
+ return false;
+ }
+
+ if (!isPow2(width) || !isPow2(height))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidCompressedSubImageSize(const Context *context,
+ GLenum internalFormat,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ size_t textureWidth,
+ size_t textureHeight,
+ size_t textureDepth)
+{
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
+ if (!formatInfo.compressed)
+ {
+ return false;
+ }
+
+ if (xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0 || depth < 0)
+ {
+ return false;
+ }
+
+ // ANGLE does not support compressed 3D blocks (provided exclusively by ASTC 3D formats), so
+ // there is no need to check the depth here. Only width and height determine whether a 2D array
+ // element or a 2D slice of a sliced 3D texture fill the entire level.
+ bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
+ static_cast<size_t>(width) == textureWidth &&
+ static_cast<size_t>(height) == textureHeight;
+
+ if (CompressedFormatRequiresWholeImage(internalFormat))
+ {
+ return fillsEntireMip;
+ }
+
+ if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
+ {
+ if (xoffset % formatInfo.compressedBlockWidth != 0 ||
+ yoffset % formatInfo.compressedBlockHeight != 0 ||
+ zoffset % formatInfo.compressedBlockDepth != 0)
+ {
+ return false;
+ }
+
+ // Allowed to either have data that is a multiple of block size or is smaller than the block
+ // size but fills the entire mip
+ bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
+ (height % formatInfo.compressedBlockHeight) == 0 &&
+ (depth % formatInfo.compressedBlockDepth) == 0;
+ if (!sizeMultipleOfBlockSize && !fillsEntireMip)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidImageDataSize(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType texType,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ GLsizei imageSize)
+{
+ Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
+ if (pixelUnpackBuffer == nullptr && imageSize < 0)
+ {
+ // Checks are not required
+ return true;
+ }
+
+ // ...the data would be unpacked from the buffer object such that the memory reads required
+ // would exceed the data store size.
+ const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
+ ASSERT(formatInfo.internalFormat != GL_NONE);
+ const Extents size(width, height, depth);
+ const auto &unpack = context->getState().getUnpackState();
+
+ bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
+ GLuint endByte = 0;
+ if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
+ return false;
+ }
+
+ if (pixelUnpackBuffer)
+ {
+ CheckedNumeric<size_t> checkedEndByte(endByte);
+ CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
+ checkedEndByte += checkedOffset;
+
+ if (!checkedEndByte.IsValid() ||
+ (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
+ {
+ // Overflow past the end of the buffer
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
+ return false;
+ }
+ if (pixelUnpackBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kPixelUnpackBufferBoundForTransformFeedback);
+ return false;
+ }
+ }
+ else
+ {
+ ASSERT(imageSize >= 0);
+ if (pixels == nullptr && imageSize != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kImageSizeMustBeZero);
+ return false;
+ }
+
+ if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kImageSizeTooSmall);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidQueryType(const Context *context, QueryType queryType)
+{
+ switch (queryType)
+ {
+ case QueryType::AnySamples:
+ case QueryType::AnySamplesConservative:
+ return context->getClientMajorVersion() >= 3 ||
+ context->getExtensions().occlusionQueryBooleanEXT;
+ case QueryType::TransformFeedbackPrimitivesWritten:
+ return (context->getClientMajorVersion() >= 3);
+ case QueryType::TimeElapsed:
+ return context->getExtensions().disjointTimerQueryEXT;
+ case QueryType::CommandsCompleted:
+ return context->getExtensions().syncQueryCHROMIUM;
+ case QueryType::PrimitivesGenerated:
+ return context->getClientVersion() >= ES_3_2 ||
+ context->getExtensions().geometryShaderAny();
+ default:
+ return false;
+ }
+}
+
+bool ValidateWebGLVertexAttribPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexAttribType type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *ptr,
+ bool pureInteger)
+{
+ ASSERT(context->isWebGL());
+ // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
+ // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
+ // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
+ // parameter exceeds 255.
+ constexpr GLsizei kMaxWebGLStride = 255;
+ if (stride > kMaxWebGLStride)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kStrideExceedsWebGLLimit);
+ return false;
+ }
+
+ // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
+ // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
+ // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
+ // or an INVALID_OPERATION error is generated.
+ angle::FormatID internalType = GetVertexFormatID(type, normalized, 1, pureInteger);
+ size_t typeSize = GetVertexFormatSize(internalType);
+
+ ASSERT(isPow2(typeSize) && typeSize > 0);
+ size_t sizeMask = (typeSize - 1);
+ if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kOffsetMustBeMultipleOfType);
+ return false;
+ }
+
+ if ((stride & sizeMask) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kStrideMustBeMultipleOfType);
+ return false;
+ }
+
+ return true;
+}
+
+Program *GetValidProgramNoResolve(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID id)
+{
+ // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
+ // generate the error INVALID_VALUE if the provided name is not the name of either a shader
+ // or program object and INVALID_OPERATION if the provided name identifies an object
+ // that is not the expected type."
+
+ Program *validProgram = context->getProgramNoResolveLink(id);
+
+ if (!validProgram)
+ {
+ if (context->getShader(id))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExpectedProgramName);
+ }
+ else
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramName);
+ }
+ }
+
+ return validProgram;
+}
+
+Program *GetValidProgram(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id)
+{
+ Program *program = GetValidProgramNoResolve(context, entryPoint, id);
+ if (program)
+ {
+ program->resolveLink(context);
+ }
+ return program;
+}
+
+Shader *GetValidShader(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id)
+{
+ // See ValidProgram for spec details.
+
+ Shader *validShader = context->getShader(id);
+
+ if (!validShader)
+ {
+ if (context->getProgramNoResolveLink(id))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExpectedShaderName);
+ }
+ else
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidShaderName);
+ }
+ }
+
+ return validShader;
+}
+
+bool ValidateAttachmentTarget(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum attachment)
+{
+ if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+ {
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffersEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
+ return false;
+ }
+
+ // Color attachment 0 is validated below because it is always valid
+ const int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
+ if (colorAttachment >= context->getCaps().maxColorAttachments)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAttachment);
+ return false;
+ }
+ }
+ else
+ {
+ switch (attachment)
+ {
+ case GL_COLOR_ATTACHMENT0:
+ case GL_DEPTH_ATTACHMENT:
+ case GL_STENCIL_ATTACHMENT:
+ break;
+
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (!context->isWebGL() && context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateRenderbufferStorageParametersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ switch (target)
+ {
+ case GL_RENDERBUFFER:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget);
+ return false;
+ }
+
+ if (width < 0 || height < 0 || samples < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidRenderbufferWidthHeight);
+ return false;
+ }
+
+ // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
+ GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
+
+ const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
+ if (!formatCaps.renderbuffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
+ return false;
+ }
+
+ // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
+ // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
+ // only sized internal formats.
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
+ if (formatInfo.internalFormat == GL_NONE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
+ return false;
+ }
+
+ if (std::max(width, height) > context->getCaps().maxRenderbufferSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxRenderbufferSize);
+ return false;
+ }
+
+ RenderbufferID id = context->getState().getRenderbufferId();
+ if (id.value == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBlitFramebufferParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter)
+{
+ switch (filter)
+ {
+ case GL_NEAREST:
+ break;
+ case GL_LINEAR:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kBlitInvalidFilter);
+ return false;
+ }
+
+ if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kBlitInvalidMask);
+ return false;
+ }
+
+ // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
+ // color buffer, leaving only nearest being unfiltered from above
+ if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitOnlyNearestForNonColor);
+ return false;
+ }
+
+ const auto &glState = context->getState();
+ Framebuffer *readFramebuffer = glState.getReadFramebuffer();
+ Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
+
+ if (!readFramebuffer || !drawFramebuffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION,
+ kBlitFramebufferMissing);
+ return false;
+ }
+
+ if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer))
+ {
+ return false;
+ }
+
+ if (!ValidateFramebufferComplete(context, entryPoint, drawFramebuffer))
+ {
+ return false;
+ }
+
+ // EXT_YUV_target disallows blitting to or from a YUV framebuffer
+ if ((mask & GL_COLOR_BUFFER_BIT) != 0 &&
+ (readFramebuffer->hasYUVAttachment() || drawFramebuffer->hasYUVAttachment()))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitYUVFramebuffer);
+ return false;
+ }
+
+ // The draw and read framebuffers can only match if:
+ // - They are the default framebuffer AND
+ // - The read/draw surfaces are different
+ if ((readFramebuffer->id() == drawFramebuffer->id()) &&
+ ((drawFramebuffer->id() != Framebuffer::kDefaultDrawFramebufferHandle) ||
+ (context->getCurrentDrawSurface() == context->getCurrentReadSurface())))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitFeedbackLoop);
+ return false;
+ }
+
+ // Not allow blitting to MS buffers, therefore if renderToTextureSamples exist,
+ // consider it MS. checkReadBufferResourceSamples = false
+ if (!ValidateFramebufferNotMultisampled(context, entryPoint, drawFramebuffer, false))
+ {
+ return false;
+ }
+
+ // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
+ // always run it in order to avoid triggering driver bugs.
+ if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
+ DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kBlitDimensionsOutOfRange);
+ return false;
+ }
+
+ bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
+
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorAttachment();
+ const Extensions &extensions = context->getExtensions();
+
+ if (readColorBuffer)
+ {
+ const Format &readFormat = readColorBuffer->getFormat();
+
+ for (size_t drawbufferIdx = 0;
+ drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
+ {
+ const FramebufferAttachment *attachment =
+ drawFramebuffer->getDrawBuffer(drawbufferIdx);
+ if (attachment)
+ {
+ const Format &drawFormat = attachment->getFormat();
+
+ // The GL ES 3.0.2 spec (pg 193) states that:
+ // 1) If the read buffer is fixed point format, the draw buffer must be as well
+ // 2) If the read buffer is an unsigned integer format, the draw buffer must be
+ // as well
+ // 3) If the read buffer is a signed integer format, the draw buffer must be as
+ // well
+ // Changes with EXT_color_buffer_float:
+ // Case 1) is changed to fixed point OR floating point
+ GLenum readComponentType = readFormat.info->componentType;
+ GLenum drawComponentType = drawFormat.info->componentType;
+ bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED ||
+ readComponentType == GL_SIGNED_NORMALIZED);
+ bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
+ drawComponentType == GL_SIGNED_NORMALIZED);
+
+ if (extensions.colorBufferFloatEXT)
+ {
+ bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
+ bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
+
+ if (readFixedOrFloat != drawFixedOrFloat)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitTypeMismatchFixedOrFloat);
+ return false;
+ }
+ }
+ else if (readFixedPoint != drawFixedPoint)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitTypeMismatchFixedPoint);
+ return false;
+ }
+
+ if (readComponentType == GL_UNSIGNED_INT &&
+ drawComponentType != GL_UNSIGNED_INT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitTypeMismatchUnsignedInteger);
+ return false;
+ }
+
+ if (readComponentType == GL_INT && drawComponentType != GL_INT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitTypeMismatchSignedInteger);
+ return false;
+ }
+
+ if (readColorBuffer->getResourceSamples() > 0 &&
+ (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitMultisampledFormatOrBoundsMismatch);
+ return false;
+ }
+
+ if (context->isWebGL() && *readColorBuffer == *attachment)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitSameImageColor);
+ return false;
+ }
+ }
+ }
+
+ if (readFormat.info->isInt() && filter == GL_LINEAR)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitIntegerWithLinearFilter);
+ return false;
+ }
+ }
+ // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
+ // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
+ // attachment and WebGL defines it to be an error. We do the check unconditionally as the
+ // situation is an application error that would lead to a crash in ANGLE.
+ else if (drawFramebuffer->hasEnabledDrawBuffer())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitMissingColor);
+ return false;
+ }
+ }
+
+ GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
+ GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
+ for (size_t i = 0; i < 2; i++)
+ {
+ if (mask & masks[i])
+ {
+ const FramebufferAttachment *readBuffer =
+ readFramebuffer->getAttachment(context, attachments[i]);
+ const FramebufferAttachment *drawBuffer =
+ drawFramebuffer->getAttachment(context, attachments[i]);
+
+ if (readBuffer && drawBuffer)
+ {
+ if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitDepthOrStencilFormatMismatch);
+ return false;
+ }
+
+ if (readBuffer->getResourceSamples() > 0 && !sameBounds)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitMultisampledBoundsMismatch);
+ return false;
+ }
+
+ if (context->isWebGL() && *readBuffer == *drawBuffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitSameImageDepthOrStencil);
+ return false;
+ }
+ }
+ // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
+ else if (drawBuffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitMissingDepthOrStencil);
+ return false;
+ }
+ }
+ }
+
+ // OVR_multiview2:
+ // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
+ // current draw framebuffer isMultiview() or the number of
+ // views in the current read framebuffer is more than one.
+ if (readFramebuffer->readDisallowedByMultiview())
+ {
+ context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFromMultiview);
+ return false;
+ }
+ if (drawFramebuffer->isMultiview())
+ {
+ context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION, kBlitToMultiview);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindFramebufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ FramebufferID framebuffer)
+{
+ if (!ValidFramebufferTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
+ return false;
+ }
+
+ if (!context->getState().isBindGeneratesResourceEnabled() &&
+ !context->isFramebufferGenerated(framebuffer))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindRenderbufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ RenderbufferID renderbuffer)
+{
+ if (target != GL_RENDERBUFFER)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget);
+ return false;
+ }
+
+ if (!context->getState().isBindGeneratesResourceEnabled() &&
+ !context->isRenderbufferGenerated(renderbuffer))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferParameteriBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ GLint param)
+{
+ if (!ValidFramebufferTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+ {
+ GLint maxWidth = context->getCaps().maxFramebufferWidth;
+ if (param < 0 || param > maxWidth)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsFramebufferWidth);
+ return false;
+ }
+ break;
+ }
+ case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+ {
+ GLint maxHeight = context->getCaps().maxFramebufferHeight;
+ if (param < 0 || param > maxHeight)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsFramebufferHeight);
+ return false;
+ }
+ break;
+ }
+ case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+ {
+ GLint maxSamples = context->getCaps().maxFramebufferSamples;
+ if (param < 0 || param > maxSamples)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsFramebufferSamples);
+ return false;
+ }
+ break;
+ }
+ case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+ {
+ break;
+ }
+ case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
+ {
+ if (!context->getExtensions().geometryShaderAny() &&
+ context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kGeometryShaderExtensionNotEnabled);
+ return false;
+ }
+ GLint maxLayers = context->getCaps().maxFramebufferLayers;
+ if (param < 0 || param > maxLayers)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFramebufferLayer);
+ return false;
+ }
+ break;
+ }
+ case GL_FRAMEBUFFER_FLIP_Y_MESA:
+ {
+ if (!context->getExtensions().framebufferFlipYMESA)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+ break;
+ }
+ default:
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+ }
+
+ const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+ if (framebuffer->isDefault())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultFramebuffer);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateFramebufferRenderbufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ RenderbufferID renderbuffer)
+{
+ if (!ValidFramebufferTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
+ return false;
+ }
+
+ if (renderbuffertarget != GL_RENDERBUFFER)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget);
+ return false;
+ }
+
+ Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+
+ ASSERT(framebuffer);
+ if (framebuffer->isDefault())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultFramebufferTarget);
+ return false;
+ }
+
+ if (!ValidateAttachmentTarget(context, entryPoint, attachment))
+ {
+ return false;
+ }
+
+ // [OpenGL ES 2.0.25] Section 4.4.3 page 112
+ // [OpenGL ES 3.0.2] Section 4.4.2 page 201
+ // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
+ // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
+ if (renderbuffer.value != 0)
+ {
+ if (!context->getRenderbuffer(renderbuffer))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferTextureBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureID texture,
+ GLint level)
+{
+ if (!ValidFramebufferTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
+ return false;
+ }
+
+ if (!ValidateAttachmentTarget(context, entryPoint, attachment))
+ {
+ return false;
+ }
+
+ if (texture.value != 0)
+ {
+ Texture *tex = context->getTexture(texture);
+
+ if (tex == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingTexture);
+ return false;
+ }
+
+ if (level < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+
+ // GLES spec 3.1, Section 9.2.8 "Attaching Texture Images to a Framebuffer"
+ // An INVALID_VALUE error is generated if texture is not zero and level is
+ // not a supported texture level for textarget
+
+ // Common criteria for not supported texture levels(other criteria are handled case by case
+ // in non base functions): If texture refers to an immutable-format texture, level must be
+ // greater than or equal to zero and smaller than the value of TEXTURE_IMMUTABLE_LEVELS for
+ // texture.
+ if (tex->getImmutableFormat() && context->getClientVersion() >= ES_3_1)
+ {
+ if (level >= static_cast<GLint>(tex->getImmutableLevels()))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+ }
+
+ // GLES spec 3.2, Section 9.2.8 "Attaching Texture Images to a Framebuffer"
+ // An INVALID_OPERATION error is generated if <texture> is the name of a buffer texture.
+ if ((context->getClientVersion() >= ES_3_2 ||
+ context->getExtensions().textureBufferAny()) &&
+ tex->getType() == TextureType::Buffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureTarget);
+ return false;
+ }
+
+ if (tex->getState().hasProtectedContent() != context->getState().hasProtectedContent())
+ {
+ context->validationError(
+ entryPoint, GL_INVALID_OPERATION,
+ "Mismatch between Texture and Context Protected Content state");
+ return false;
+ }
+ }
+
+ const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (framebuffer->isDefault())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultFramebufferTarget);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGenerateMipmapBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target)
+{
+ if (!ValidTextureTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ Texture *texture = context->getTextureByType(target);
+
+ if (texture == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureNotBound);
+ return false;
+ }
+
+ const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
+
+ // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
+ // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
+ if (effectiveBaseLevel >= IMPLEMENTATION_MAX_TEXTURE_LEVELS)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBaseLevelOutOfRange);
+ return false;
+ }
+
+ TextureTarget baseTarget = (target == TextureType::CubeMap)
+ ? TextureTarget::CubeMapPositiveX
+ : NonCubeTextureTypeToTarget(target);
+ const auto &format = *(texture->getFormat(baseTarget, effectiveBaseLevel).info);
+ if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 ||
+ format.stencilBits > 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
+ return false;
+ }
+
+ // GenerateMipmap accepts formats that are unsized or both color renderable and filterable.
+ bool formatUnsized = !format.sized;
+ bool formatColorRenderableAndFilterable =
+ format.filterSupport(context->getClientVersion(), context->getExtensions()) &&
+ format.textureAttachmentSupport(context->getClientVersion(), context->getExtensions());
+ if (!formatUnsized && !formatColorRenderableAndFilterable)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
+ return false;
+ }
+
+ // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap
+ // generation
+ if (format.colorEncoding == GL_SRGB && format.format == GL_RGB)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
+ return false;
+ }
+
+ // According to the OpenGL extension spec EXT_sRGB.txt, EXT_SRGB is based on ES 2.0 and
+ // generateMipmap is not allowed if texture format is SRGB_EXT or SRGB_ALPHA_EXT.
+ if (context->getClientVersion() < Version(3, 0) && format.colorEncoding == GL_SRGB)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
+ return false;
+ }
+
+ // Non-power of 2 ES2 check
+ if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNpotOES &&
+ (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
+ !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
+ {
+ ASSERT(target == TextureType::_2D || target == TextureType::Rectangle ||
+ target == TextureType::CubeMap);
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureNotPow2);
+ return false;
+ }
+
+ // Cube completeness check
+ if (target == TextureType::CubeMap && !texture->getTextureState().isCubeComplete())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kCubemapIncomplete);
+ return false;
+ }
+
+ if (context->isWebGL() && (texture->getWidth(baseTarget, effectiveBaseLevel) == 0 ||
+ texture->getHeight(baseTarget, effectiveBaseLevel) == 0))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kGenerateMipmapZeroSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateReadPixelsRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLsizei *columns,
+ const GLsizei *rows,
+ const void *pixels)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei writeLength = 0;
+ GLsizei writeColumns = 0;
+ GLsizei writeRows = 0;
+
+ if (!ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize,
+ &writeLength, &writeColumns, &writeRows, pixels))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, writeLength);
+ SetRobustLengthParam(columns, writeColumns);
+ SetRobustLengthParam(rows, writeRows);
+
+ return true;
+}
+
+bool ValidateReadnPixelsEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ if (bufSize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ return ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize,
+ nullptr, nullptr, nullptr, pixels);
+}
+
+bool ValidateReadnPixelsRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLsizei *columns,
+ const GLsizei *rows,
+ const void *data)
+{
+ GLsizei writeLength = 0;
+ GLsizei writeColumns = 0;
+ GLsizei writeRows = 0;
+
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize,
+ &writeLength, &writeColumns, &writeRows, data))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, writeLength);
+ SetRobustLengthParam(columns, writeColumns);
+ SetRobustLengthParam(rows, writeRows);
+
+ return true;
+}
+
+bool ValidateGenQueriesEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const QueryID *ids)
+{
+ if (!context->getExtensions().occlusionQueryBooleanEXT &&
+ !context->getExtensions().disjointTimerQueryEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateDeleteQueriesEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const QueryID *ids)
+{
+ if (!context->getExtensions().occlusionQueryBooleanEXT &&
+ !context->getExtensions().disjointTimerQueryEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateIsQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryID id)
+{
+ if (!context->getExtensions().occlusionQueryBooleanEXT &&
+ !context->getExtensions().disjointTimerQueryEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBeginQueryBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType target,
+ QueryID id)
+{
+ if (!ValidQueryType(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidQueryType);
+ return false;
+ }
+
+ if (id.value == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidQueryId);
+ return false;
+ }
+
+ // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
+ // of zero, if the active query object name for <target> is non-zero (for the
+ // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
+ // the active query for either target is non-zero), if <id> is the name of an
+ // existing query object whose type does not match <target>, or if <id> is the
+ // active query object name for any query type, the error INVALID_OPERATION is
+ // generated.
+
+ // Ensure no other queries are active
+ // NOTE: If other queries than occlusion are supported, we will need to check
+ // separately that:
+ // a) The query ID passed is not the current active query for any target/type
+ // b) There are no active queries for the requested target (and in the case
+ // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
+ // no query may be active for either if glBeginQuery targets either.
+
+ if (context->getState().isQueryActive(target))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kOtherQueryActive);
+ return false;
+ }
+
+ // check that name was obtained with glGenQueries
+ if (!context->isQueryGenerated(id))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidQueryId);
+ return false;
+ }
+
+ // Check for type mismatch. If query is not yet started we're good to go.
+ Query *queryObject = context->getQuery(id);
+ if (queryObject && queryObject->getType() != target)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryTargetMismatch);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBeginQueryEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType target,
+ QueryID id)
+{
+ if (!context->getExtensions().occlusionQueryBooleanEXT &&
+ !context->getExtensions().disjointTimerQueryEXT &&
+ !context->getExtensions().syncQueryCHROMIUM)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateBeginQueryBase(context, entryPoint, target, id);
+}
+
+bool ValidateEndQueryBase(const Context *context, angle::EntryPoint entryPoint, QueryType target)
+{
+ if (!ValidQueryType(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidQueryType);
+ return false;
+ }
+
+ const Query *queryObject = context->getState().getActiveQuery(target);
+
+ if (queryObject == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryInactive);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateEndQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryType target)
+{
+ if (!context->getExtensions().occlusionQueryBooleanEXT &&
+ !context->getExtensions().disjointTimerQueryEXT &&
+ !context->getExtensions().syncQueryCHROMIUM)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateEndQueryBase(context, entryPoint, target);
+}
+
+bool ValidateQueryCounterEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ QueryType target)
+{
+ if (!context->getExtensions().disjointTimerQueryEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (target != QueryType::Timestamp)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidQueryTarget);
+ return false;
+ }
+
+ if (!context->isQueryGenerated(id))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidQueryId);
+ return false;
+ }
+
+ // If query object is not started, that's fine.
+ Query *queryObject = context->getQuery(id);
+ if (queryObject && context->getState().isQueryActive(queryObject))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryActive);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetQueryivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType target,
+ GLenum pname,
+ GLsizei *numParams)
+{
+ if (numParams)
+ {
+ *numParams = 0;
+ }
+
+ if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidQueryType);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_CURRENT_QUERY_EXT:
+ if (target == QueryType::Timestamp)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidQueryTarget);
+ return false;
+ }
+ break;
+ case GL_QUERY_COUNTER_BITS_EXT:
+ if (!context->getExtensions().disjointTimerQueryEXT ||
+ (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+
+ if (numParams)
+ {
+ // All queries return only one value
+ *numParams = 1;
+ }
+
+ return true;
+}
+
+bool ValidateGetQueryivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType target,
+ GLenum pname,
+ const GLint *params)
+{
+ if (!context->getExtensions().occlusionQueryBooleanEXT &&
+ !context->getExtensions().disjointTimerQueryEXT &&
+ !context->getExtensions().syncQueryCHROMIUM)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGetQueryivBase(context, entryPoint, target, pname, nullptr);
+}
+
+bool ValidateGetQueryivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateGetQueryivBase(context, entryPoint, target, pname, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateGetQueryObjectValueBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ GLsizei *numParams)
+{
+ if (numParams)
+ {
+ *numParams = 1;
+ }
+
+ if (context->isContextLost())
+ {
+ context->validationError(entryPoint, GL_CONTEXT_LOST, kContextLost);
+
+ if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
+ {
+ // Generate an error but still return true, the context still needs to return a
+ // value in this case.
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ Query *queryObject = context->getQuery(id);
+
+ if (!queryObject)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidQueryId);
+ return false;
+ }
+
+ if (context->getState().isQueryActive(queryObject))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryActive);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_QUERY_RESULT_EXT:
+ case GL_QUERY_RESULT_AVAILABLE_EXT:
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetQueryObjectivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ const GLint *params)
+{
+ if (!context->getExtensions().disjointTimerQueryEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ if (!context->getExtensions().disjointTimerQueryEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateGetQueryObjectuivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ const GLuint *params)
+{
+ if (!context->getExtensions().disjointTimerQueryEXT &&
+ !context->getExtensions().occlusionQueryBooleanEXT &&
+ !context->getExtensions().syncQueryCHROMIUM)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint *params)
+{
+ if (!context->getExtensions().disjointTimerQueryEXT &&
+ !context->getExtensions().occlusionQueryBooleanEXT &&
+ !context->getExtensions().syncQueryCHROMIUM)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateGetQueryObjecti64vEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ GLint64 *params)
+{
+ if (!context->getExtensions().disjointTimerQueryEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjecti64vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ GLint64 *params)
+{
+ if (!context->getExtensions().disjointTimerQueryEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateGetQueryObjectui64vEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ GLuint64 *params)
+{
+ if (!context->getExtensions().disjointTimerQueryEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ GLuint64 *params)
+{
+ if (!context->getExtensions().disjointTimerQueryEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateUniformCommonBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ const Program *program,
+ UniformLocation location,
+ GLsizei count,
+ const LinkedUniform **uniformOut)
+{
+ // TODO(Jiajia): Add image uniform check in future.
+ if (count < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
+ return false;
+ }
+
+ if (!program)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidProgramName);
+ return false;
+ }
+
+ if (!program->isLinked())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
+ return false;
+ }
+
+ if (location.value == -1)
+ {
+ // Silently ignore the uniform command
+ return false;
+ }
+
+ const auto &uniformLocations = program->getUniformLocations();
+ size_t castedLocation = static_cast<size_t>(location.value);
+ if (castedLocation >= uniformLocations.size())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidUniformLocation);
+ return false;
+ }
+
+ const auto &uniformLocation = uniformLocations[castedLocation];
+ if (uniformLocation.ignored)
+ {
+ // Silently ignore the uniform command
+ return false;
+ }
+
+ if (!uniformLocation.used())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidUniformLocation);
+ return false;
+ }
+
+ const auto &uniform = program->getUniformByIndex(uniformLocation.index);
+
+ // attempting to write an array to a non-array uniform is an INVALID_OPERATION
+ if (count > 1 && !uniform.isArray())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidUniformCount);
+ return false;
+ }
+
+ *uniformOut = &uniform;
+ return true;
+}
+
+bool ValidateUniform1ivValue(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum uniformType,
+ GLsizei count,
+ const GLint *value)
+{
+ // Value type is GL_INT, because we only get here from glUniform1i{v}.
+ // It is compatible with INT or BOOL.
+ // Do these cheap tests first, for a little extra speed.
+ if (GL_INT == uniformType || GL_BOOL == uniformType)
+ {
+ return true;
+ }
+
+ if (IsSamplerType(uniformType))
+ {
+ // Check that the values are in range.
+ const GLint max = context->getCaps().maxCombinedTextureImageUnits;
+ for (GLsizei i = 0; i < count; ++i)
+ {
+ if (value[i] < 0 || value[i] >= max)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kSamplerUniformValueOutOfRange);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kUniformTypeMismatch);
+ return false;
+}
+
+bool ValidateUniformMatrixValue(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum valueType,
+ GLenum uniformType)
+{
+ // Check that the value type is compatible with uniform type.
+ if (valueType == uniformType)
+ {
+ return true;
+ }
+
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kUniformTypeMismatch);
+ return false;
+}
+
+bool ValidateUniform(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum valueType,
+ UniformLocation location,
+ GLsizei count)
+{
+ const LinkedUniform *uniform = nullptr;
+ Program *programObject = context->getActiveLinkedProgram();
+ return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
+ &uniform) &&
+ ValidateUniformValue(context, entryPoint, valueType, uniform->type);
+}
+
+bool ValidateUniform1iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLint *value)
+{
+ const LinkedUniform *uniform = nullptr;
+ Program *programObject = context->getActiveLinkedProgram();
+ return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
+ &uniform) &&
+ ValidateUniform1ivValue(context, entryPoint, uniform->type, count, value);
+}
+
+bool ValidateUniformMatrix(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum valueType,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose)
+{
+ if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kES3Required);
+ return false;
+ }
+
+ const LinkedUniform *uniform = nullptr;
+ Program *programObject = context->getActiveLinkedProgram();
+ return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
+ &uniform) &&
+ ValidateUniformMatrixValue(context, entryPoint, valueType, uniform->type);
+}
+
+bool ValidateStateQuery(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLenum *nativeType,
+ unsigned int *numParams)
+{
+ if (!context->getQueryParameterInfo(pname, nativeType, numParams))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+
+ if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
+ {
+ int colorAttachment = (pname - GL_DRAW_BUFFER0);
+
+ if (colorAttachment >= caps.maxDrawBuffers)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kIndexExceedsMaxDrawBuffer);
+ return false;
+ }
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_BINDING_2D:
+ case GL_TEXTURE_BINDING_CUBE_MAP:
+ case GL_TEXTURE_BINDING_3D:
+ case GL_TEXTURE_BINDING_2D_ARRAY:
+ case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
+ break;
+ case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
+ if (!context->getExtensions().textureStorageMultisample2dArrayOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kMultisampleArrayExtensionRequired);
+ return false;
+ }
+ break;
+ case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
+ if (!context->getExtensions().textureRectangleANGLE)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+ case GL_TEXTURE_BINDING_EXTERNAL_OES:
+ if (!context->getExtensions().EGLStreamConsumerExternalNV &&
+ !context->getExtensions().EGLImageExternalOES)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+ case GL_TEXTURE_BUFFER_BINDING:
+ case GL_TEXTURE_BINDING_BUFFER:
+ case GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
+ case GL_MAX_TEXTURE_BUFFER_SIZE:
+ if (context->getClientVersion() < Version(3, 2) &&
+ !context->getExtensions().textureBufferAny())
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kTextureBufferExtensionNotAvailable);
+ return false;
+ }
+ break;
+
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+ {
+ Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
+ ASSERT(readFramebuffer);
+
+ if (!ValidateFramebufferComplete<GL_INVALID_OPERATION>(context, entryPoint,
+ readFramebuffer))
+ {
+ return false;
+ }
+
+ if (readFramebuffer->getReadBufferState() == GL_NONE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kReadBufferNone);
+ return false;
+ }
+
+ const FramebufferAttachment *attachment = readFramebuffer->getReadColorAttachment();
+ if (!attachment)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kReadBufferNotAttached);
+ return false;
+ }
+ }
+ break;
+
+ case GL_PRIMITIVE_BOUNDING_BOX:
+ if (!context->getExtensions().primitiveBoundingBoxAny())
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ case GL_SHADING_RATE_QCOM:
+ if (!context->getExtensions().shadingRateQCOM)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // pname is valid, but there are no parameters to return
+ if (*numParams == 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBooleanvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLboolean *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+
+ if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateGetFloatvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+
+ if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateGetIntegervRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *data)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+
+ if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateGetInteger64vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ GLint64 *data)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+
+ if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
+ {
+ return false;
+ }
+
+ if (nativeType == GL_INT_64_ANGLEX)
+ {
+ CastStateValues(context, nativeType, pname, numParams, data);
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+ return true;
+}
+
+bool ValidateRobustStateQuery(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ GLenum *nativeType,
+ unsigned int *numParams)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateStateQuery(context, entryPoint, pname, nativeType, numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, *numParams))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopyImageSubDataTarget(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint name,
+ GLenum target)
+{
+ // From EXT_copy_image: INVALID_ENUM is generated if either <srcTarget> or <dstTarget> is not
+ // RENDERBUFFER or a valid non - proxy texture target, is TEXTURE_BUFFER, or is one of the
+ // cubemap face selectors described in table 3.17, or if the target does not match the type of
+ // the object. INVALID_VALUE is generated if either <srcName> or <dstName> does not correspond
+ // to a valid renderbuffer or texture object according to the corresponding target parameter.
+ switch (target)
+ {
+ case GL_RENDERBUFFER:
+ {
+ RenderbufferID renderbuffer = PackParam<RenderbufferID>(name);
+ if (!context->isRenderbuffer(renderbuffer))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidRenderbufferName);
+ return false;
+ }
+ break;
+ }
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_CUBE_MAP_ARRAY_EXT:
+ {
+ TextureID texture = PackParam<TextureID>(name);
+ if (!context->isTexture(texture))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidTextureName);
+ return false;
+ }
+
+ Texture *textureObject = context->getTexture(texture);
+ if (textureObject && textureObject->getType() != PackParam<TextureType>(target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, err::kTextureTypeMismatch);
+ return false;
+ }
+ break;
+ }
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTarget);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopyImageSubDataLevel(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint level)
+{
+ switch (target)
+ {
+ case GL_RENDERBUFFER:
+ {
+ if (level != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+ break;
+ }
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_CUBE_MAP_ARRAY_EXT:
+ {
+ if (!ValidMipLevel(context, PackParam<TextureType>(target), level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+ break;
+ }
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTarget);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopyImageSubDataTargetRegion(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint name,
+ GLenum target,
+ GLint level,
+ GLint offsetX,
+ GLint offsetY,
+ GLint offsetZ,
+ GLsizei width,
+ GLsizei height,
+ GLsizei *samples)
+{
+ // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the boundaries
+ // of the corresponding image object.
+ if (offsetX < 0 || offsetY < 0 || offsetZ < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
+ return false;
+ }
+
+ if (target == GL_RENDERBUFFER)
+ {
+ // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the
+ // boundaries of the corresponding image object
+ Renderbuffer *buffer = context->getRenderbuffer(PackParam<RenderbufferID>(name));
+ if ((buffer->getWidth() - offsetX < width) || (buffer->getHeight() - offsetY < height))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kSourceTextureTooSmall);
+ return false;
+ }
+ }
+ else
+ {
+ Texture *texture = context->getTexture(PackParam<TextureID>(name));
+
+ // INVALID_OPERATION is generated if either object is a texture and the texture is not
+ // complete
+ // This will handle the texture completeness check. Note that this ignores format-based
+ // compleness rules.
+ if (!texture->isSamplerCompleteForCopyImage(context, nullptr))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kNotTextureComplete);
+ return false;
+ }
+
+ GLenum textureTargetToUse = target;
+ if (target == GL_TEXTURE_CUBE_MAP)
+ {
+ // Use GL_TEXTURE_CUBE_MAP_POSITIVE_X to properly gather the textureWidth/textureHeight
+ textureTargetToUse = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ }
+
+ const GLsizei textureWidth = static_cast<GLsizei>(
+ texture->getWidth(PackParam<TextureTarget>(textureTargetToUse), level));
+ const GLsizei textureHeight = static_cast<GLsizei>(
+ texture->getHeight(PackParam<TextureTarget>(textureTargetToUse), level));
+
+ // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the
+ // boundaries of the corresponding image object
+ if ((textureWidth - offsetX < width) || (textureHeight - offsetY < height))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kSourceTextureTooSmall);
+ return false;
+ }
+
+ *samples = texture->getSamples(PackParam<TextureTarget>(textureTargetToUse), level);
+ *samples = (*samples == 0) ? 1 : *samples;
+ }
+
+ return true;
+}
+
+bool ValidateCompressedRegion(const Context *context,
+ angle::EntryPoint entryPoint,
+ const InternalFormat &formatInfo,
+ GLsizei width,
+ GLsizei height)
+{
+ ASSERT(formatInfo.compressed);
+
+ // INVALID_VALUE is generated if the image format is compressed and the dimensions of the
+ // subregion fail to meet the alignment constraints of the format.
+ if ((width % formatInfo.compressedBlockWidth != 0) ||
+ (height % formatInfo.compressedBlockHeight != 0))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidCompressedRegionSize);
+ return false;
+ }
+
+ return true;
+}
+
+const InternalFormat &GetTargetFormatInfo(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint name,
+ GLenum target,
+ GLint level)
+{
+ static const InternalFormat defaultInternalFormat;
+
+ switch (target)
+ {
+ case GL_RENDERBUFFER:
+ {
+ Renderbuffer *buffer = context->getRenderbuffer(PackParam<RenderbufferID>(name));
+ return *buffer->getFormat().info;
+ }
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ case GL_TEXTURE_CUBE_MAP:
+ case GL_TEXTURE_CUBE_MAP_ARRAY_EXT:
+ {
+ Texture *texture = context->getTexture(PackParam<TextureID>(name));
+ GLenum textureTargetToUse = target;
+
+ if (target == GL_TEXTURE_CUBE_MAP)
+ {
+ // Use GL_TEXTURE_CUBE_MAP_POSITIVE_X to properly gather the
+ // textureWidth/textureHeight
+ textureTargetToUse = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+ }
+ return *texture->getFormat(PackParam<TextureTarget>(textureTargetToUse), level).info;
+ }
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTarget);
+ return defaultInternalFormat;
+ }
+}
+
+bool ValidateCopyMixedFormatCompatible(GLenum uncompressedFormat, GLenum compressedFormat)
+{
+ // Validates mixed format compatibility (uncompressed and compressed) from Table 4.X.1 of the
+ // EXT_copy_image spec.
+ switch (compressedFormat)
+ {
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
+ case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
+ case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
+ case GL_COMPRESSED_RGBA8_ETC2_EAC:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+ case GL_COMPRESSED_RG11_EAC:
+ case GL_COMPRESSED_SIGNED_RG11_EAC:
+ case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
+ case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
+ case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
+ case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
+ case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
+ case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
+ case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
+ case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
+ case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
+ case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
+ case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
+ case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
+ case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
+ case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+ case GL_COMPRESSED_RGBA_ASTC_3x3x3_OES:
+ case GL_COMPRESSED_RGBA_ASTC_4x3x3_OES:
+ case GL_COMPRESSED_RGBA_ASTC_4x4x3_OES:
+ case GL_COMPRESSED_RGBA_ASTC_4x4x4_OES:
+ case GL_COMPRESSED_RGBA_ASTC_5x4x4_OES:
+ case GL_COMPRESSED_RGBA_ASTC_5x5x4_OES:
+ case GL_COMPRESSED_RGBA_ASTC_5x5x5_OES:
+ case GL_COMPRESSED_RGBA_ASTC_6x5x5_OES:
+ case GL_COMPRESSED_RGBA_ASTC_6x6x5_OES:
+ case GL_COMPRESSED_RGBA_ASTC_6x6x6_OES:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES:
+ case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES:
+ {
+ switch (uncompressedFormat)
+ {
+ case GL_RGBA32UI:
+ case GL_RGBA32I:
+ case GL_RGBA32F:
+ return true;
+ default:
+ return false;
+ }
+ }
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RED_RGTC1_EXT:
+ case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
+ case GL_COMPRESSED_RGB8_ETC2:
+ case GL_COMPRESSED_SRGB8_ETC2:
+ case GL_COMPRESSED_R11_EAC:
+ case GL_COMPRESSED_SIGNED_R11_EAC:
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ {
+ switch (uncompressedFormat)
+ {
+ case GL_RGBA16UI:
+ case GL_RGBA16I:
+ case GL_RGBA16F:
+ case GL_RG32UI:
+ case GL_RG32I:
+ case GL_RG32F:
+ return true;
+ default:
+ return false;
+ }
+ }
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool ValidateCopyCompressedFormatCompatible(const InternalFormat &srcFormatInfo,
+ const InternalFormat &dstFormatInfo)
+{
+ // Validates compressed format compatibility from Table 4.X.2 of the EXT_copy_image spec.
+
+ ASSERT(srcFormatInfo.internalFormat != dstFormatInfo.internalFormat);
+
+ const GLenum srcFormat = srcFormatInfo.internalFormat;
+ const GLenum dstFormat = dstFormatInfo.internalFormat;
+
+ switch (srcFormat)
+ {
+ case GL_COMPRESSED_RED_RGTC1_EXT:
+ return (dstFormat == GL_COMPRESSED_SIGNED_RED_RGTC1_EXT);
+ case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
+ return (dstFormat == GL_COMPRESSED_RED_RGTC1_EXT);
+ case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
+ return (dstFormat == GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT);
+ case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
+ return (dstFormat == GL_COMPRESSED_RED_GREEN_RGTC2_EXT);
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
+ return (dstFormat == GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT);
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
+ return (dstFormat == GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT);
+ case GL_COMPRESSED_R11_EAC:
+ return (dstFormat == GL_COMPRESSED_SIGNED_R11_EAC);
+ case GL_COMPRESSED_SIGNED_R11_EAC:
+ return (dstFormat == GL_COMPRESSED_R11_EAC);
+ case GL_COMPRESSED_RG11_EAC:
+ return (dstFormat == GL_COMPRESSED_SIGNED_RG11_EAC);
+ case GL_COMPRESSED_SIGNED_RG11_EAC:
+ return (dstFormat == GL_COMPRESSED_RG11_EAC);
+ default:
+ break;
+ }
+
+ // Since they can't be the same format and are both compressed formats, one must be linear and
+ // the other nonlinear.
+ if (srcFormatInfo.colorEncoding == dstFormatInfo.colorEncoding)
+ {
+ return false;
+ }
+
+ const GLenum linearFormat = (srcFormatInfo.colorEncoding == GL_LINEAR) ? srcFormat : dstFormat;
+ const GLenum nonLinearFormat =
+ (srcFormatInfo.colorEncoding != GL_LINEAR) ? srcFormat : dstFormat;
+
+ switch (linearFormat)
+ {
+ case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT);
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT);
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT);
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT);
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT);
+ case GL_COMPRESSED_RGB8_ETC2:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ETC2);
+ case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
+ case GL_COMPRESSED_RGBA8_ETC2_EAC:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
+ case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR);
+ case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR);
+ case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR);
+ case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR);
+ case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR);
+ case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR);
+ case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR);
+ case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR);
+ case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR);
+ case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR);
+ case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR);
+ case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR);
+ case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR);
+ case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR);
+ case GL_COMPRESSED_RGBA_ASTC_3x3x3_OES:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES);
+ case GL_COMPRESSED_RGBA_ASTC_4x3x3_OES:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES);
+ case GL_COMPRESSED_RGBA_ASTC_4x4x3_OES:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES);
+ case GL_COMPRESSED_RGBA_ASTC_4x4x4_OES:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES);
+ case GL_COMPRESSED_RGBA_ASTC_5x4x4_OES:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES);
+ case GL_COMPRESSED_RGBA_ASTC_5x5x4_OES:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES);
+ case GL_COMPRESSED_RGBA_ASTC_5x5x5_OES:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES);
+ case GL_COMPRESSED_RGBA_ASTC_6x5x5_OES:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES);
+ case GL_COMPRESSED_RGBA_ASTC_6x6x5_OES:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES);
+ case GL_COMPRESSED_RGBA_ASTC_6x6x6_OES:
+ return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES);
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool ValidateCopyFormatCompatible(const InternalFormat &srcFormatInfo,
+ const InternalFormat &dstFormatInfo)
+{
+ // Matching source and destination formats are compatible.
+ if (srcFormatInfo.internalFormat == dstFormatInfo.internalFormat)
+ {
+ return true;
+ }
+
+ if (srcFormatInfo.compressed != dstFormatInfo.compressed)
+ {
+ GLenum uncompressedFormat = (!srcFormatInfo.compressed) ? srcFormatInfo.internalFormat
+ : dstFormatInfo.internalFormat;
+ GLenum compressedFormat = (srcFormatInfo.compressed) ? srcFormatInfo.internalFormat
+ : dstFormatInfo.internalFormat;
+
+ return ValidateCopyMixedFormatCompatible(uncompressedFormat, compressedFormat);
+ }
+
+ if (!srcFormatInfo.compressed)
+ {
+ // Source and destination are uncompressed formats.
+ return (srcFormatInfo.pixelBytes == dstFormatInfo.pixelBytes);
+ }
+
+ return ValidateCopyCompressedFormatCompatible(srcFormatInfo, dstFormatInfo);
+}
+
+bool ValidateCopyImageSubDataBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint srcName,
+ GLenum srcTarget,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLuint dstName,
+ GLenum dstTarget,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth)
+{
+ // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the boundaries
+ // of the corresponding image object
+ if ((srcWidth < 0) || (srcHeight < 0) || (srcDepth < 0))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
+ return false;
+ }
+
+ if (!ValidateCopyImageSubDataTarget(context, entryPoint, srcName, srcTarget))
+ {
+ return false;
+ }
+ if (!ValidateCopyImageSubDataTarget(context, entryPoint, dstName, dstTarget))
+ {
+ return false;
+ }
+
+ if (!ValidateCopyImageSubDataLevel(context, entryPoint, srcTarget, srcLevel))
+ {
+ return false;
+ }
+ if (!ValidateCopyImageSubDataLevel(context, entryPoint, dstTarget, dstLevel))
+ {
+ return false;
+ }
+
+ const InternalFormat &srcFormatInfo =
+ GetTargetFormatInfo(context, entryPoint, srcName, srcTarget, srcLevel);
+ const InternalFormat &dstFormatInfo =
+ GetTargetFormatInfo(context, entryPoint, dstName, dstTarget, dstLevel);
+ GLsizei dstWidth = srcWidth;
+ GLsizei dstHeight = srcHeight;
+ GLsizei srcSamples = 1;
+ GLsizei dstSamples = 1;
+
+ if (srcFormatInfo.internalFormat == GL_NONE || dstFormatInfo.internalFormat == GL_NONE)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidTextureLevel);
+ return false;
+ }
+
+ if (!ValidateCopyImageSubDataTargetRegion(context, entryPoint, srcName, srcTarget, srcLevel,
+ srcX, srcY, srcZ, srcWidth, srcHeight, &srcSamples))
+ {
+ return false;
+ }
+
+ // When copying from a compressed image to an uncompressed image the image texel dimensions
+ // written to the uncompressed image will be source extent divided by the compressed texel block
+ // dimensions.
+ if ((srcFormatInfo.compressed) && (!dstFormatInfo.compressed))
+ {
+ ASSERT(srcFormatInfo.compressedBlockWidth != 0);
+ ASSERT(srcFormatInfo.compressedBlockHeight != 0);
+
+ dstWidth /= srcFormatInfo.compressedBlockWidth;
+ dstHeight /= srcFormatInfo.compressedBlockHeight;
+ }
+ // When copying from an uncompressed image to a compressed image the image texel dimensions
+ // written to the compressed image will be the source extent multiplied by the compressed texel
+ // block dimensions.
+ else if ((!srcFormatInfo.compressed) && (dstFormatInfo.compressed))
+ {
+ dstWidth *= dstFormatInfo.compressedBlockWidth;
+ dstHeight *= dstFormatInfo.compressedBlockHeight;
+ }
+
+ if (!ValidateCopyImageSubDataTargetRegion(context, entryPoint, dstName, dstTarget, dstLevel,
+ dstX, dstY, dstZ, dstWidth, dstHeight, &dstSamples))
+ {
+ return false;
+ }
+
+ bool fillsEntireMip = false;
+ gl::Texture *dstTexture = context->getTexture({dstName});
+ gl::TextureTarget dstTargetPacked = gl::PackParam<gl::TextureTarget>(dstTarget);
+ // TODO(http://anglebug.com/5643): Some targets (e.g., GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER) are
+ // unsupported when used with compressed formats due to gl::PackParam() returning
+ // TextureTarget::InvalidEnum.
+ if (dstTargetPacked != gl::TextureTarget::InvalidEnum)
+ {
+ const gl::Extents &dstExtents = dstTexture->getExtents(dstTargetPacked, dstLevel);
+ fillsEntireMip = dstX == 0 && dstY == 0 && dstZ == 0 && srcWidth == dstExtents.width &&
+ srcHeight == dstExtents.height && srcDepth == dstExtents.depth;
+ }
+
+ if (srcFormatInfo.compressed && !fillsEntireMip &&
+ !ValidateCompressedRegion(context, entryPoint, srcFormatInfo, srcWidth, srcHeight))
+ {
+ return false;
+ }
+
+ if (dstFormatInfo.compressed && !fillsEntireMip &&
+ !ValidateCompressedRegion(context, entryPoint, dstFormatInfo, dstWidth, dstHeight))
+ {
+ return false;
+ }
+
+ // From EXT_copy_image: INVALID_OPERATION is generated if the source and destination formats
+ // are not compatible, if one image is compressed and the other is uncompressed and the block
+ // size of compressed image is not equal to the texel size of the compressed image.
+ if (!ValidateCopyFormatCompatible(srcFormatInfo, dstFormatInfo))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kIncompatibleTextures);
+ return false;
+ }
+
+ // INVALID_OPERATION is generated if the source and destination number of samples do not match
+ if (srcSamples != dstSamples)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kSamplesOutOfRange);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopyTexImageParametersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ Format *textureFormatOut)
+{
+ TextureType texType = TextureTargetToType(target);
+
+ if (xoffset < 0 || yoffset < 0 || zoffset < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
+ return false;
+ }
+
+ if (width < 0 || height < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
+ return false;
+ }
+
+ if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
+ std::numeric_limits<GLsizei>::max() - yoffset < height)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow);
+ return false;
+ }
+
+ if (std::numeric_limits<GLint>::max() - width < x ||
+ std::numeric_limits<GLint>::max() - height < y)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIntegerOverflow);
+ return false;
+ }
+
+ if (border != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBorder);
+ return false;
+ }
+
+ if (!ValidMipLevel(context, texType, level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+
+ const State &state = context->getState();
+ Framebuffer *readFramebuffer = state.getReadFramebuffer();
+ if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer))
+ {
+ return false;
+ }
+
+ // checkReadBufferResourceSamples = true. Treat renderToTexture textures as single sample since
+ // they will be resolved before copying.
+ if (!readFramebuffer->isDefault() &&
+ !ValidateFramebufferNotMultisampled(context, entryPoint, readFramebuffer, true))
+ {
+ return false;
+ }
+
+ if (readFramebuffer->getReadBufferState() == GL_NONE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kReadBufferNone);
+ return false;
+ }
+
+ // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
+ // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
+ // attachment and WebGL defines it to be an error. We do the check unconditionally as the
+ // situation is an application error that would lead to a crash in ANGLE.
+ const FramebufferAttachment *source = readFramebuffer->getReadColorAttachment();
+ if (source == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingReadAttachment);
+ return false;
+ }
+
+ if (source->isYUV())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kCopyFromYUVFramebuffer);
+ return false;
+ }
+
+ // ANGLE_multiview spec, Revision 1:
+ // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
+ // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
+ // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
+ // framebuffer is more than one.
+ if (readFramebuffer->readDisallowedByMultiview())
+ {
+ context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION,
+ kMultiviewReadFramebuffer);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+
+ GLint maxDimension = 0;
+ switch (texType)
+ {
+ case TextureType::_2D:
+ maxDimension = caps.max2DTextureSize;
+ break;
+
+ case TextureType::CubeMap:
+ case TextureType::CubeMapArray:
+ maxDimension = caps.maxCubeMapTextureSize;
+ break;
+
+ case TextureType::Rectangle:
+ maxDimension = caps.maxRectangleTextureSize;
+ break;
+
+ case TextureType::_2DArray:
+ maxDimension = caps.max2DTextureSize;
+ break;
+
+ case TextureType::_3D:
+ maxDimension = caps.max3DTextureSize;
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ Texture *texture = state.getTargetTexture(texType);
+ if (!texture)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureNotBound);
+ return false;
+ }
+
+ if (texture->getImmutableFormat() && !isSubImage)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsImmutable);
+ return false;
+ }
+
+ const InternalFormat &formatInfo =
+ isSubImage ? *texture->getFormat(target, level).info
+ : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
+
+ if (formatInfo.depthBits > 0 || formatInfo.compressed)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+
+ if (isSubImage)
+ {
+ if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
+ static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
+ static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow);
+ return false;
+ }
+ }
+ else
+ {
+ if ((texType == TextureType::CubeMap || texType == TextureType::CubeMapArray) &&
+ width != height)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kCubemapIncomplete);
+ return false;
+ }
+
+ if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ internalformat);
+ return false;
+ }
+
+ int maxLevelDimension = (maxDimension >> level);
+ if (static_cast<int>(width) > maxLevelDimension ||
+ static_cast<int>(height) > maxLevelDimension)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ }
+
+ // Do not leak the previous texture format for non-subImage case.
+ if (textureFormatOut && isSubImage)
+ {
+ *textureFormatOut = texture->getFormat(target, level);
+ }
+
+ // Detect texture copying feedback loops for WebGL.
+ if (context->isWebGL())
+ {
+ if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kFeedbackLoop);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+const char *ValidateProgramPipelineDrawStates(const Context *context,
+ const Extensions &extensions,
+ ProgramPipeline *programPipeline)
+{
+ for (const ShaderType shaderType : gl::AllShaderTypes())
+ {
+ Program *program = programPipeline->getShaderProgram(shaderType);
+ if (program)
+ {
+ const char *errorMsg = ValidateProgramDrawStates(context, extensions, program);
+ if (errorMsg)
+ {
+ return errorMsg;
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline)
+{
+ // An INVALID_OPERATION error is generated by any command that transfers vertices to the
+ // GL or launches compute work if the current set of active
+ // program objects cannot be executed, for reasons including:
+ // - There is no current program object specified by UseProgram, there is a current program
+ // pipeline object, and that object is empty (no executable code is installed for any stage).
+ // - A program object is active for at least one, but not all of the shader
+ // stages that were present when the program was linked.
+ if (!programPipeline->getExecutable().getLinkedShaderStages().any())
+ {
+ return gl::err::kNoExecutableCodeInstalled;
+ }
+ for (const ShaderType shaderType : gl::AllShaderTypes())
+ {
+ Program *shaderProgram = programPipeline->getShaderProgram(shaderType);
+ if (shaderProgram)
+ {
+ ProgramExecutable &executable = shaderProgram->getExecutable();
+ for (const ShaderType programShaderType : executable.getLinkedShaderStages())
+ {
+ if (shaderProgram != programPipeline->getShaderProgram(programShaderType))
+ {
+ return gl::err::kNotAllStagesOfSeparableProgramUsed;
+ }
+ }
+ }
+ }
+
+ // [EXT_geometry_shader] Section 11.1.gs Geometry Shaders
+ // A non-separable program object or program pipeline object that includes
+ // a geometry shader must also include a vertex shader.
+ // An INVALID_OPERATION error is generated by any command that transfers
+ // vertices to the GL if the current program state has a geometry shader
+ // but no vertex shader.
+ if (!programPipeline->getShaderProgram(ShaderType::Vertex) &&
+ programPipeline->getShaderProgram(ShaderType::Geometry))
+ {
+ return gl::err::kNoActiveGraphicsShaderStage;
+ }
+
+ return nullptr;
+}
+
+// Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
+// completeness check.
+const char *ValidateDrawStates(const Context *context)
+{
+ const Extensions &extensions = context->getExtensions();
+ const State &state = context->getState();
+
+ // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
+ // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
+ // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
+ VertexArray *vertexArray = state.getVertexArray();
+ ASSERT(vertexArray);
+
+ if (!extensions.webglCompatibilityANGLE && vertexArray->hasInvalidMappedArrayBuffer())
+ {
+ return kBufferMapped;
+ }
+
+ // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
+ // Section 6.10 of the WebGL 1.0 spec.
+ Framebuffer *framebuffer = state.getDrawFramebuffer();
+ ASSERT(framebuffer);
+
+ if (context->getLimitations().noSeparateStencilRefsAndMasks ||
+ extensions.webglCompatibilityANGLE)
+ {
+ ASSERT(framebuffer);
+ const FramebufferAttachment *dsAttachment =
+ framebuffer->getStencilOrDepthStencilAttachment();
+ const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
+ ASSERT(stencilBits <= 8);
+
+ const DepthStencilState &depthStencilState = state.getDepthStencilState();
+ if (depthStencilState.stencilTest && stencilBits > 0)
+ {
+ GLuint maxStencilValue = (1 << stencilBits) - 1;
+
+ bool differentRefs =
+ clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
+ clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
+ bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
+ (depthStencilState.stencilBackWritemask & maxStencilValue);
+ bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
+ (depthStencilState.stencilBackMask & maxStencilValue);
+
+ if (differentRefs || differentWritemasks || differentMasks)
+ {
+ if (!extensions.webglCompatibilityANGLE)
+ {
+ WARN() << "This ANGLE implementation does not support separate front/back "
+ "stencil writemasks, reference values, or stencil mask values.";
+ }
+ return kStencilReferenceMaskOrMismatch;
+ }
+ }
+ }
+
+ if (!extensions.floatBlendEXT)
+ {
+ const DrawBufferMask blendEnabledActiveFloat32ColorAttachmentDrawBufferMask =
+ state.getBlendEnabledDrawBufferMask() &
+ framebuffer->getActiveFloat32ColorAttachmentDrawBufferMask();
+ if (blendEnabledActiveFloat32ColorAttachmentDrawBufferMask.any())
+ {
+ return kUnsupportedFloatBlending;
+ }
+ }
+
+ if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
+ extensions.webglCompatibilityANGLE)
+ {
+ if (state.hasSimultaneousConstantColorAndAlphaBlendFunc())
+ {
+ if (extensions.webglCompatibilityANGLE)
+ {
+ return kInvalidConstantColor;
+ }
+
+ WARN() << kConstantColorAlphaLimitation;
+ return kConstantColorAlphaLimitation;
+ }
+ }
+
+ if (!framebuffer->isComplete(context))
+ {
+ // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
+ return kDrawFramebufferIncomplete;
+ }
+
+ bool framebufferIsYUV = framebuffer->hasYUVAttachment();
+ if (framebufferIsYUV)
+ {
+ const BlendState &blendState = state.getBlendState();
+ if (!blendState.colorMaskRed || !blendState.colorMaskGreen || !blendState.colorMaskBlue)
+ {
+ // When rendering into a YUV framebuffer, the color mask must have r g and b set to
+ // true.
+ return kInvalidColorMaskForYUV;
+ }
+
+ if (blendState.blend)
+ {
+ // When rendering into a YUV framebuffer, blending must be disabled.
+ return kInvalidBlendStateForYUV;
+ }
+ }
+ else
+ {
+ if (framebuffer->hasExternalTextureAttachment())
+ {
+ // It is an error to render into an external texture that is not YUV.
+ return kExternalTextureAttachmentNotYUV;
+ }
+ }
+
+ // Advanced blend equation can only be enabled for a single render target.
+ const BlendStateExt &blendStateExt = state.getBlendStateExt();
+ if (blendStateExt.getUsesAdvancedBlendEquationMask().any())
+ {
+ const size_t drawBufferCount = framebuffer->getDrawbufferStateCount();
+ uint32_t advancedBlendRenderTargetCount = 0;
+
+ for (size_t drawBufferIndex : blendStateExt.getUsesAdvancedBlendEquationMask())
+ {
+ if (drawBufferIndex < drawBufferCount &&
+ framebuffer->getDrawBufferState(drawBufferIndex) != GL_NONE &&
+ blendStateExt.getEnabledMask().test(drawBufferIndex) &&
+ blendStateExt.getUsesAdvancedBlendEquationMask().test(drawBufferIndex))
+ {
+ ++advancedBlendRenderTargetCount;
+ }
+ }
+
+ if (advancedBlendRenderTargetCount > 1)
+ {
+ return kAdvancedBlendEquationWithMRT;
+ }
+ }
+
+ if (context->getStateCache().hasAnyEnabledClientAttrib())
+ {
+ if (extensions.webglCompatibilityANGLE || !state.areClientArraysEnabled())
+ {
+ // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
+ // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
+ // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
+ // to drawArrays or drawElements will generate an INVALID_OPERATION error.
+ return kVertexArrayNoBuffer;
+ }
+
+ if (state.getVertexArray()->hasEnabledNullPointerClientArray())
+ {
+ // This is an application error that would normally result in a crash, but we catch it
+ // and return an error
+ return kVertexArrayNoBufferPointer;
+ }
+ }
+
+ // If we are running GLES1, there is no current program.
+ if (context->getClientVersion() >= Version(2, 0))
+ {
+ Program *program = state.getLinkedProgram(context);
+ ProgramPipeline *programPipeline = state.getLinkedProgramPipeline(context);
+ const ProgramExecutable *executable = state.getProgramExecutable();
+
+ bool programIsYUVOutput = false;
+
+ if (program)
+ {
+ const char *errorMsg = ValidateProgramDrawStates(context, extensions, program);
+ if (errorMsg)
+ {
+ return errorMsg;
+ }
+
+ programIsYUVOutput = executable->isYUVOutput();
+ }
+ else if (programPipeline)
+ {
+ const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline);
+ if (errorMsg)
+ {
+ return errorMsg;
+ }
+
+ errorMsg = ValidateProgramPipelineDrawStates(context, extensions, programPipeline);
+ if (errorMsg)
+ {
+ return errorMsg;
+ }
+
+ if (!programPipeline->isLinked())
+ {
+ return kProgramPipelineLinkFailed;
+ }
+
+ programIsYUVOutput = executable->isYUVOutput();
+ }
+
+ if (executable)
+ {
+ if (!executable->validateSamplers(nullptr, context->getCaps()))
+ {
+ return kTextureTypeConflict;
+ }
+
+ if (executable->hasLinkedTessellationShader())
+ {
+ if (!executable->hasLinkedShaderStage(ShaderType::Vertex))
+ {
+ return kTessellationShaderRequiresVertexShader;
+ }
+
+ if (!executable->hasLinkedShaderStage(ShaderType::TessControl) ||
+ !executable->hasLinkedShaderStage(ShaderType::TessEvaluation))
+ {
+ return kTessellationShaderRequiresBothControlAndEvaluation;
+ }
+ }
+
+ if (state.isTransformFeedbackActive())
+ {
+ if (!ValidateProgramExecutableXFBBuffersPresent(context, executable))
+ {
+ return kTransformFeedbackBufferMissing;
+ }
+ }
+ }
+
+ if (programIsYUVOutput != framebufferIsYUV)
+ {
+ // Both the program and framebuffer must match in YUV output state.
+ return kYUVOutputMissmatch;
+ }
+
+ if (!state.validateSamplerFormats())
+ {
+ return kSamplerFormatMismatch;
+ }
+
+ // Do some additional WebGL-specific validation
+ if (extensions.webglCompatibilityANGLE)
+ {
+ const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
+ if (state.isTransformFeedbackActive() &&
+ transformFeedbackObject->buffersBoundForOtherUseInWebGL())
+ {
+ return kTransformFeedbackBufferDoubleBound;
+ }
+
+ // Detect rendering feedback loops for WebGL.
+ if (framebuffer->formsRenderingFeedbackLoopWith(context))
+ {
+ return kFeedbackLoop;
+ }
+
+ // Detect that the vertex shader input types match the attribute types
+ if (!ValidateVertexShaderAttributeTypeMatch(context))
+ {
+ return kVertexShaderTypeMismatch;
+ }
+
+ if (!context->getState().getRasterizerState().rasterizerDiscard &&
+ !context->getState().allActiveDrawBufferChannelsMasked())
+ {
+ // Detect that if there's active color buffer without fragment shader output
+ if (!ValidateFragmentShaderColorBufferMaskMatch(context))
+ {
+ return kDrawBufferMaskMismatch;
+ }
+
+ // Detect that the color buffer types match the fragment shader output types
+ if (!ValidateFragmentShaderColorBufferTypeMatch(context))
+ {
+ return kDrawBufferTypeMismatch;
+ }
+ }
+
+ const VertexArray *vao = context->getState().getVertexArray();
+ if (vao->hasTransformFeedbackBindingConflict(context))
+ {
+ return kVertexBufferBoundForTransformFeedback;
+ }
+
+ // Validate that we are rendering with a linked program.
+ if (!program->isLinked())
+ {
+ return kProgramNotLinked;
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+const char *ValidateProgramPipeline(const Context *context)
+{
+ const State &state = context->getState();
+ // If we are running GLES1, there is no current program.
+ if (context->getClientVersion() >= Version(2, 0))
+ {
+ ProgramPipeline *programPipeline = state.getProgramPipeline();
+ if (programPipeline)
+ {
+ const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline);
+ if (errorMsg)
+ {
+ return errorMsg;
+ }
+ }
+ }
+ return nullptr;
+}
+
+void RecordDrawModeError(const Context *context, angle::EntryPoint entryPoint, PrimitiveMode mode)
+{
+ const State &state = context->getState();
+ TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
+ if (state.isTransformFeedbackActiveUnpaused())
+ {
+ if (!ValidateTransformFeedbackPrimitiveMode(context, entryPoint,
+ curTransformFeedback->getPrimitiveMode(), mode))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidDrawModeTransformFeedback);
+ return;
+ }
+ }
+
+ const Extensions &extensions = context->getExtensions();
+
+ switch (mode)
+ {
+ case PrimitiveMode::Points:
+ case PrimitiveMode::Lines:
+ case PrimitiveMode::LineLoop:
+ case PrimitiveMode::LineStrip:
+ case PrimitiveMode::Triangles:
+ case PrimitiveMode::TriangleStrip:
+ case PrimitiveMode::TriangleFan:
+ break;
+
+ case PrimitiveMode::LinesAdjacency:
+ case PrimitiveMode::LineStripAdjacency:
+ case PrimitiveMode::TrianglesAdjacency:
+ case PrimitiveMode::TriangleStripAdjacency:
+ if (!extensions.geometryShaderAny() && context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kGeometryShaderExtensionNotEnabled);
+ return;
+ }
+ break;
+
+ case PrimitiveMode::Patches:
+ if (!extensions.tessellationShaderEXT && context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kTessellationShaderExtensionNotEnabled);
+ return;
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDrawMode);
+ return;
+ }
+
+ // If we are running GLES1, there is no current program.
+ if (context->getClientVersion() >= Version(2, 0))
+ {
+ const ProgramExecutable *executable = state.getProgramExecutable();
+ ASSERT(executable);
+
+ // Do geometry shader specific validations
+ if (executable->hasLinkedShaderStage(ShaderType::Geometry))
+ {
+ if (!IsCompatibleDrawModeWithGeometryShader(
+ mode, executable->getGeometryShaderInputPrimitiveType()))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kIncompatibleDrawModeAgainstGeometryShader);
+ return;
+ }
+ }
+
+ if (executable->hasLinkedTessellationShader() && mode != PrimitiveMode::Patches)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kIncompatibleDrawModeWithTessellationShader);
+ return;
+ }
+
+ if (!executable->hasLinkedTessellationShader() && mode == PrimitiveMode::Patches)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kIncompatibleDrawModeWithoutTessellationShader);
+ return;
+ }
+ }
+
+ // An error should be recorded.
+ UNREACHABLE();
+}
+
+bool ValidateDrawArraysInstancedANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount)
+{
+ if (!context->getExtensions().instancedArraysANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount))
+ {
+ return false;
+ }
+
+ return ValidateDrawInstancedANGLE(context, entryPoint);
+}
+
+bool ValidateDrawArraysInstancedEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount)
+{
+ if (!context->getExtensions().instancedArraysEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+const char *ValidateDrawElementsStates(const Context *context)
+{
+ const State &state = context->getState();
+
+ if (context->getStateCache().isTransformFeedbackActiveUnpaused())
+ {
+ // EXT_geometry_shader allows transform feedback to work with all draw commands.
+ // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
+ if (!context->getExtensions().geometryShaderAny() && context->getClientVersion() < ES_3_2)
+ {
+ // It is an invalid operation to call DrawElements, DrawRangeElements or
+ // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
+ // 86)
+ return kUnsupportedDrawModeForTransformFeedback;
+ }
+ }
+
+ const VertexArray *vao = state.getVertexArray();
+ Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
+
+ if (elementArrayBuffer)
+ {
+ if (elementArrayBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
+ {
+ return kElementArrayBufferBoundForTransformFeedback;
+ }
+ if (elementArrayBuffer->isMapped() &&
+ (!elementArrayBuffer->isImmutable() ||
+ (elementArrayBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) == 0))
+ {
+ return kBufferMapped;
+ }
+ }
+ else
+ {
+ // [WebGL 1.0] Section 6.2 No Client Side Arrays
+ // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
+ // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
+ if (!context->getState().areClientArraysEnabled() || context->isWebGL())
+ {
+ return kMustHaveElementArrayBinding;
+ }
+ }
+
+ return nullptr;
+}
+
+bool ValidateDrawElementsInstancedANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei primcount)
+{
+ if (!context->getExtensions().instancedArraysANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
+ primcount))
+ {
+ return false;
+ }
+
+ return ValidateDrawInstancedANGLE(context, entryPoint);
+}
+
+bool ValidateDrawElementsInstancedEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei primcount)
+{
+ if (!context->getExtensions().instancedArraysEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
+ primcount))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetUniformBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location)
+{
+ if (program.value == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kProgramDoesNotExist);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (!programObject || !programObject->isLinked())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
+ return false;
+ }
+
+ if (!programObject->isValidUniformLocation(location))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidUniformLocation);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSizedGetUniform(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (!ValidateGetUniformBase(context, entryPoint, program, location))
+ {
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kNegativeBufferSize);
+ return false;
+ }
+
+ Program *programObject = context->getProgramResolveLink(program);
+ ASSERT(programObject);
+
+ // sized queries -- ensure the provided buffer is large enough
+ const LinkedUniform &uniform = programObject->getUniformByLocation(location);
+ size_t requiredBytes = VariableExternalSize(uniform.type);
+ if (static_cast<size_t>(bufSize) < requiredBytes)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize);
+ return false;
+ }
+
+ if (length)
+ {
+ *length = VariableComponentCount(uniform.type);
+ }
+ return true;
+}
+
+bool ValidateGetnUniformfvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLfloat *params)
+{
+ return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr);
+}
+
+bool ValidateGetnUniformfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGetnUniformivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLint *params)
+{
+ return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr);
+}
+
+bool ValidateGetnUniformivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGetnUniformuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint *params)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGetUniformfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei writeLength = 0;
+
+ // bufSize is validated in ValidateSizedGetUniform
+ if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, writeLength);
+
+ return true;
+}
+
+bool ValidateGetUniformivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei writeLength = 0;
+
+ // bufSize is validated in ValidateSizedGetUniform
+ if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, writeLength);
+
+ return true;
+}
+
+bool ValidateGetUniformuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ GLsizei writeLength = 0;
+
+ // bufSize is validated in ValidateSizedGetUniform
+ if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, writeLength);
+
+ return true;
+}
+
+bool ValidateDiscardFramebufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ bool defaultFramebuffer)
+{
+ if (numAttachments < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeAttachments);
+ return false;
+ }
+
+ for (GLsizei i = 0; i < numAttachments; ++i)
+ {
+ if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
+ {
+ if (defaultFramebuffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kDefaultFramebufferInvalidAttachment);
+ return false;
+ }
+
+ if (attachments[i] >=
+ GL_COLOR_ATTACHMENT0 + static_cast<GLuint>(context->getCaps().maxColorAttachments))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kExceedsMaxColorAttachments);
+ return false;
+ }
+ }
+ else
+ {
+ switch (attachments[i])
+ {
+ case GL_DEPTH_ATTACHMENT:
+ case GL_STENCIL_ATTACHMENT:
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (defaultFramebuffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kDefaultFramebufferInvalidAttachment);
+ return false;
+ }
+ break;
+ case GL_COLOR:
+ case GL_DEPTH:
+ case GL_STENCIL:
+ if (!defaultFramebuffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kDefaultFramebufferAttachmentOnUserFBO);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool ValidateInsertEventMarkerEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei length,
+ const char *marker)
+{
+ if (!context->getExtensions().debugMarkerEXT)
+ {
+ // The debug marker calls should not set error state
+ // However, it seems reasonable to set an error state if the extension is not enabled
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ // Note that debug marker calls must not set error state
+ if (length < 0)
+ {
+ return false;
+ }
+
+ if (marker == nullptr)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePushGroupMarkerEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei length,
+ const char *marker)
+{
+ if (!context->getExtensions().debugMarkerEXT)
+ {
+ // The debug marker calls should not set error state
+ // However, it seems reasonable to set an error state if the extension is not enabled
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ // Note that debug marker calls must not set error state
+ if (length < 0)
+ {
+ return false;
+ }
+
+ if (length > 0 && marker == nullptr)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateEGLImageObject(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType type,
+ GLeglImageOES image)
+{
+ egl::Image *imageObject = static_cast<egl::Image *>(image);
+
+ ASSERT(context->getDisplay());
+ if (!context->getDisplay()->isValidImage(imageObject))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidEGLImage);
+ return false;
+ }
+
+ if (imageObject->getSamples() > 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kEGLImageCannotCreate2DMultisampled);
+ return false;
+ }
+
+ if (!imageObject->isTexturable(context))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kEGLImageTextureFormatNotSupported);
+ return false;
+ }
+
+ // Validate source egl image and target texture are compatible
+ size_t depth = static_cast<size_t>(imageObject->getExtents().depth);
+ if (imageObject->isYUV() && type != TextureType::External)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ "Image is YUV, target must be TEXTURE_EXTERNAL_OES");
+ return false;
+ }
+
+ if (depth > 1 && type != TextureType::_2DArray && type != TextureType::CubeMap &&
+ type != TextureType::CubeMapArray && type != TextureType::_3D)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
+ return false;
+ }
+
+ if (imageObject->isCubeMap() && type != TextureType::CubeMapArray &&
+ (type != TextureType::CubeMap || depth > gl::kCubeFaceCount))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
+ return false;
+ }
+
+ if (imageObject->getLevelCount() > 1 && type == TextureType::External)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
+ return false;
+ }
+
+ // 3d EGLImages are currently not supported
+ if (type == TextureType::_3D)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
+ return false;
+ }
+
+ if (imageObject->hasProtectedContent() && !context->getState().hasProtectedContent())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ "Mismatch between Image and Context Protected Content state");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateEGLImageTargetTexture2DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType type,
+ GLeglImageOES image)
+{
+ if (!context->getExtensions().EGLImageOES && !context->getExtensions().EGLImageExternalOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ switch (type)
+ {
+ case TextureType::_2D:
+ if (!context->getExtensions().EGLImageOES)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ ToGLenum(type));
+ }
+ break;
+
+ case TextureType::_2DArray:
+ if (!context->getExtensions().EGLImageArrayEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ ToGLenum(type));
+ }
+ break;
+
+ case TextureType::External:
+ if (!context->getExtensions().EGLImageExternalOES)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ ToGLenum(type));
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ return ValidateEGLImageObject(context, entryPoint, type, image);
+}
+
+bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLeglImageOES image)
+{
+ if (!context->getExtensions().EGLImageOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_RENDERBUFFER:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget);
+ return false;
+ }
+
+ egl::Image *imageObject = static_cast<egl::Image *>(image);
+
+ ASSERT(context->getDisplay());
+ if (!context->getDisplay()->isValidImage(imageObject))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidEGLImage);
+ return false;
+ }
+
+ if (!imageObject->isRenderable(context))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kEGLImageRenderbufferFormatNotSupported);
+ return false;
+ }
+
+ if (imageObject->hasProtectedContent() != context->getState().hasProtectedContent())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ "Mismatch between Image and Context Protected Content state");
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateProgramBinaryBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length)
+{
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (programObject == nullptr)
+ {
+ return false;
+ }
+
+ const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
+ if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
+ programBinaryFormats.end())
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProgramBinaryFormat);
+ return false;
+ }
+
+ if (context->hasActiveTransformFeedback(program))
+ {
+ // ES 3.0.4 section 2.15 page 91
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackProgramBinary);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetProgramBinaryBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLenum *binaryFormat,
+ const void *binary)
+{
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (programObject == nullptr)
+ {
+ return false;
+ }
+
+ if (!programObject->isLinked())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
+ return false;
+ }
+
+ if (context->getCaps().programBinaryFormats.empty())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kNoProgramBinaryFormats);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawBuffersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLenum *bufs)
+{
+ // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
+ if (n < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
+ return false;
+ }
+ if (n > context->getCaps().maxDrawBuffers)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
+ return false;
+ }
+
+ ASSERT(context->getState().getDrawFramebuffer());
+ FramebufferID frameBufferId = context->getState().getDrawFramebuffer()->id();
+ GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
+
+ // This should come first before the check for the default frame buffer
+ // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
+ // rather than INVALID_OPERATION
+ for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
+ {
+ const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
+
+ if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
+ (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
+ bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
+ {
+ // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
+ // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
+ // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
+ // 3.1 is still a bit ambiguous about the error, but future specs are
+ // expected to clarify that GL_INVALID_ENUM is the correct error.
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDrawBuffer);
+ return false;
+ }
+ else if (bufs[colorAttachment] >= maxColorAttachment)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
+ return false;
+ }
+ else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
+ frameBufferId.value != 0)
+ {
+ // INVALID_OPERATION-GL is bound to buffer and ith argument
+ // is not COLOR_ATTACHMENTi or NONE
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDrawBufferValue);
+ return false;
+ }
+ }
+
+ // INVALID_OPERATION is generated if GL is bound to the default framebuffer
+ // and n is not 1 or bufs is bound to value other than BACK and NONE
+ if (frameBufferId.value == 0)
+ {
+ if (n != 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidDrawBufferCountForDefault);
+ return false;
+ }
+
+ if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kDefaultFramebufferInvalidDrawBuffer);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetBufferPointervBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLenum pname,
+ GLsizei *length,
+ void *const *params)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (!context->isValidBufferBinding(target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_BUFFER_MAP_POINTER:
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
+ // target bound to zero generate an INVALID_OPERATION error."
+ // GLES 3.1 section 6.6 explicitly specifies this error.
+ if (context->getState().getTargetBuffer(target) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferPointerNotAvailable);
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+
+ return true;
+}
+
+bool ValidateUnmapBufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target)
+{
+ if (!context->isValidBufferBinding(target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
+ return false;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (buffer == nullptr || !buffer->isMapped())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotMapped);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateMapBufferRangeBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ if (!context->isValidBufferBinding(target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
+ return false;
+ }
+
+ if (offset < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
+ return false;
+ }
+
+ if (length < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLength);
+ return false;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (!buffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotMappable);
+ return false;
+ }
+
+ // Check for buffer overflow
+ CheckedNumeric<size_t> checkedOffset(offset);
+ auto checkedSize = checkedOffset + length;
+
+ if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kMapOutOfRange);
+ return false;
+ }
+
+ // Check for invalid bits in the mask
+ constexpr GLbitfield kAllAccessBits =
+ GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
+ GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
+
+ if (buffer->isImmutable())
+ {
+ // GL_EXT_buffer_storage's additions to glMapBufferRange
+ constexpr GLbitfield kBufferStorageAccessBits =
+ kAllAccessBits | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT;
+
+ if ((access & ~kBufferStorageAccessBits) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidAccessBits);
+ return false;
+ }
+
+ // It is invalid if any of bufferStorageMatchedAccessBits bits are included in access,
+ // but the same bits are not included in the buffer's storage flags
+ constexpr GLbitfield kBufferStorageMatchedAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT |
+ GL_MAP_PERSISTENT_BIT_EXT |
+ GL_MAP_COHERENT_BIT_EXT;
+ GLbitfield accessFlags = access & kBufferStorageMatchedAccessBits;
+ if ((accessFlags & buffer->getStorageExtUsageFlags()) != accessFlags)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAccessBits);
+ return false;
+ }
+ }
+ else if ((access & ~kAllAccessBits) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidAccessBits);
+ return false;
+ }
+
+ if (length == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kLengthZero);
+ return false;
+ }
+
+ if (buffer->isMapped())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferAlreadyMapped);
+ return false;
+ }
+
+ // Check for invalid bit combinations
+ if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAccessBitsReadWrite);
+ return false;
+ }
+
+ GLbitfield writeOnlyBits =
+ GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
+
+ if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAccessBitsRead);
+ return false;
+ }
+
+ if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAccessBitsFlush);
+ return false;
+ }
+
+ return ValidateMapBufferBase(context, entryPoint, target);
+}
+
+bool ValidateFlushMappedBufferRangeBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length)
+{
+ if (offset < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
+ return false;
+ }
+
+ if (length < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLength);
+ return false;
+ }
+
+ if (!context->isValidBufferBinding(target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
+ return false;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (buffer == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFlushZero);
+ return false;
+ }
+
+ if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFlushTarget);
+ return false;
+ }
+
+ // Check for buffer overflow
+ CheckedNumeric<size_t> checkedOffset(offset);
+ auto checkedSize = checkedOffset + length;
+
+ if (!checkedSize.IsValid() ||
+ checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFlushOutOfRange);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGenOrDelete(const Context *context, angle::EntryPoint entryPoint, GLint n)
+{
+ if (n < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateRobustEntryPoint(const Context *context, angle::EntryPoint entryPoint, GLsizei bufSize)
+{
+ if (!context->getExtensions().robustClientMemoryANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateRobustBufferSize(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei bufSize,
+ GLsizei numParams)
+{
+ if (bufSize < numParams)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientParams);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei *numParams)
+{
+ if (!ValidFramebufferTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
+ return false;
+ }
+
+ int clientVersion = context->getClientMajorVersion();
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR:
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR:
+ if (clientVersion < 3 ||
+ !(context->getExtensions().multiviewOVR || context->getExtensions().multiview2OVR))
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT:
+ if (!context->getExtensions().multisampledRenderToTextureEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
+ if (clientVersion < 3 && !context->getExtensions().sRGBEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
+ if (clientVersion < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kES3Required);
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
+ if (!context->getExtensions().geometryShaderAny() &&
+ context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kGeometryShaderExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+
+ // Determine if the attachment is a valid enum
+ switch (attachment)
+ {
+ case GL_BACK:
+ case GL_DEPTH:
+ case GL_STENCIL:
+ if (clientVersion < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
+ return false;
+ }
+ break;
+
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (clientVersion < 3 && !context->isWebGL1())
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
+ return false;
+ }
+ break;
+
+ case GL_COLOR_ATTACHMENT0:
+ case GL_DEPTH_ATTACHMENT:
+ case GL_STENCIL_ATTACHMENT:
+ break;
+
+ default:
+ if ((clientVersion < 3 && !context->getExtensions().drawBuffersEXT) ||
+ attachment < GL_COLOR_ATTACHMENT0_EXT ||
+ (attachment - GL_COLOR_ATTACHMENT0_EXT) >=
+ static_cast<GLuint>(context->getCaps().maxColorAttachments))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
+ return false;
+ }
+ break;
+ }
+
+ const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (framebuffer->isDefault())
+ {
+ if (clientVersion < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultFramebufferTarget);
+ return false;
+ }
+
+ switch (attachment)
+ {
+ case GL_BACK:
+ case GL_DEPTH:
+ case GL_STENCIL:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAttachment);
+ return false;
+ }
+ }
+ else
+ {
+ if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+ {
+ // Valid attachment query
+ }
+ else
+ {
+ switch (attachment)
+ {
+ case GL_DEPTH_ATTACHMENT:
+ case GL_STENCIL_ATTACHMENT:
+ break;
+
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidAttachment);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAttachment);
+ return false;
+ }
+ }
+ }
+
+ const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
+ if (attachmentObject)
+ {
+ ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
+ attachmentObject->type() == GL_TEXTURE ||
+ attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ if (attachmentObject->type() != GL_RENDERBUFFER &&
+ attachmentObject->type() != GL_TEXTURE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kFramebufferIncompleteAttachment);
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+ if (attachmentObject->type() != GL_TEXTURE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kFramebufferIncompleteAttachment);
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+ if (attachmentObject->type() != GL_TEXTURE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kFramebufferIncompleteAttachment);
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAttachment);
+ return false;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
+ if (attachmentObject->type() != GL_TEXTURE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kFramebufferIncompleteAttachment);
+ return false;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
+ // is NONE, then querying any other pname will generate INVALID_ENUM.
+
+ // ES 3.0.2 spec pg 235 states that if the attachment type is none,
+ // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
+ // INVALID_OPERATION for all other pnames
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ if (clientVersion < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kInvalidFramebufferAttachmentParameter);
+ return false;
+ }
+ break;
+
+ default:
+ if (clientVersion < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kInvalidFramebufferAttachmentParameter);
+ return false;
+ }
+ else
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidFramebufferAttachmentParameter);
+ return false;
+ }
+ }
+ }
+
+ if (numParams)
+ {
+ *numParams = 1;
+ }
+
+ return true;
+}
+
+bool ValidateGetFramebufferParameterivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ const GLint *params)
+{
+ if (!ValidFramebufferTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_DEFAULT_WIDTH:
+ case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
+ case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
+ case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
+ break;
+ case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
+ if (!context->getExtensions().geometryShaderAny() &&
+ context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kGeometryShaderExtensionNotEnabled);
+ return false;
+ }
+ break;
+ case GL_FRAMEBUFFER_FLIP_Y_MESA:
+ if (!context->getExtensions().framebufferFlipYMESA)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+
+ const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (framebuffer->isDefault())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultFramebuffer);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+ if (!ValidateGetFramebufferAttachmentParameterivBase(context, entryPoint, target, attachment,
+ pname, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateGetBufferParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+ return true;
+}
+
+bool ValidateGetBufferParameteri64vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint64 *params)
+{
+ GLsizei numParams = 0;
+
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ if (!ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateGetProgramivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum pname,
+ GLsizei *numParams)
+{
+ // Currently, all GetProgramiv queries return 1 parameter
+ if (numParams)
+ {
+ *numParams = 1;
+ }
+
+ if (context->isContextLost())
+ {
+ context->validationError(entryPoint, GL_CONTEXT_LOST, kContextLost);
+
+ if (context->getExtensions().parallelShaderCompileKHR && pname == GL_COMPLETION_STATUS_KHR)
+ {
+ // Generate an error but still return true, the context still needs to return a
+ // value in this case.
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
+ Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
+ ? GetValidProgramNoResolve(context, entryPoint, program)
+ : GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_DELETE_STATUS:
+ case GL_LINK_STATUS:
+ case GL_VALIDATE_STATUS:
+ case GL_INFO_LOG_LENGTH:
+ case GL_ATTACHED_SHADERS:
+ case GL_ACTIVE_ATTRIBUTES:
+ case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+ case GL_ACTIVE_UNIFORMS:
+ case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+ break;
+
+ case GL_PROGRAM_BINARY_LENGTH:
+ if (context->getClientMajorVersion() < 3 &&
+ !context->getExtensions().getProgramBinaryOES)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+
+ case GL_ACTIVE_UNIFORM_BLOCKS:
+ case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
+ case GL_TRANSFORM_FEEDBACK_VARYINGS:
+ case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
+ case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES30);
+ return false;
+ }
+ break;
+
+ case GL_PROGRAM_SEPARABLE:
+ case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
+ if (context->getClientVersion() < Version(3, 1))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
+ return false;
+ }
+ break;
+
+ case GL_COMPUTE_WORK_GROUP_SIZE:
+ if (context->getClientVersion() < Version(3, 1))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
+ return false;
+ }
+
+ // [OpenGL ES 3.1] Chapter 7.12 Page 122
+ // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
+ // program which has not been linked successfully, or which does not contain objects to
+ // form a compute shader.
+ if (!programObject->isLinked())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
+ return false;
+ }
+ if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Compute))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kNoActiveComputeShaderStage);
+ return false;
+ }
+ break;
+
+ case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
+ case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
+ case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
+ case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
+ if (!context->getExtensions().geometryShaderAny() &&
+ context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kGeometryShaderExtensionNotEnabled);
+ return false;
+ }
+
+ // [EXT_geometry_shader] Chapter 7.12
+ // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
+ // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
+ // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
+ // successfully, or which does not contain objects to form a geometry shader.
+ if (!programObject->isLinked())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
+ return false;
+ }
+ if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Geometry))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kNoActiveGeometryShaderStage);
+ return false;
+ }
+ break;
+
+ case GL_COMPLETION_STATUS_KHR:
+ if (!context->getExtensions().parallelShaderCompileKHR)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ break;
+ case GL_TESS_CONTROL_OUTPUT_VERTICES_EXT:
+ case GL_TESS_GEN_MODE_EXT:
+ case GL_TESS_GEN_SPACING_EXT:
+ case GL_TESS_GEN_VERTEX_ORDER_EXT:
+ case GL_TESS_GEN_POINT_MODE_EXT:
+ if (!context->getExtensions().tessellationShaderEXT &&
+ context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kTessellationShaderExtensionNotEnabled);
+ return false;
+ }
+ if (!programObject->isLinked())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
+ return false;
+ }
+ break;
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetProgramivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateGetProgramivBase(context, entryPoint, program, pname, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateGetRenderbufferParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateGetRenderbufferParameterivBase(context, entryPoint, target, pname, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateGetShaderivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shader,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateGetShaderivBase(context, entryPoint, shader, pname, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateGetTexParameterfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateGetTexParameterBase(context, entryPoint, target, pname, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateGetTexParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+ GLsizei numParams = 0;
+ if (!ValidateGetTexParameterBase(context, entryPoint, target, pname, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+ return true;
+}
+
+bool ValidateGetTexParameterIivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGetTexParameterIuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint *params)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateTexParameterfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateTexParameterBase(context, entryPoint, target, pname, bufSize, true, params);
+}
+
+bool ValidateTexParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateTexParameterBase(context, entryPoint, target, pname, bufSize, true, params);
+}
+
+bool ValidateTexParameterIivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateTexParameterIuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLuint *params)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGetSamplerParameterfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+ return true;
+}
+
+bool ValidateGetSamplerParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+ return true;
+}
+
+bool ValidateGetSamplerParameterIivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGetSamplerParameterIuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint *params)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateSamplerParameterfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, bufSize, true, params);
+}
+
+bool ValidateSamplerParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, bufSize, true, params);
+}
+
+bool ValidateSamplerParameterIivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *param)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateSamplerParameterIuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLuint *param)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGetVertexAttribfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei writeLength = 0;
+
+ if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, false))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, writeLength);
+ return true;
+}
+
+bool ValidateGetVertexAttribivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei writeLength = 0;
+
+ if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, false))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, writeLength);
+
+ return true;
+}
+
+bool ValidateGetVertexAttribPointervRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ void *const *pointer)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei writeLength = 0;
+
+ if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, true, false))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, writeLength);
+
+ return true;
+}
+
+bool ValidateGetVertexAttribIivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei writeLength = 0;
+
+ if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, true))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, writeLength);
+
+ return true;
+}
+
+bool ValidateGetVertexAttribIuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei writeLength = 0;
+
+ if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, true))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, writeLength);
+
+ return true;
+}
+
+bool ValidateGetActiveUniformBlockivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformBlockIndex uniformBlockIndex,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei writeLength = 0;
+
+ if (!ValidateGetActiveUniformBlockivBase(context, entryPoint, program, uniformBlockIndex, pname,
+ &writeLength))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, writeLength);
+
+ return true;
+}
+
+bool ValidateGetInternalformativRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateGetInternalFormativBase(context, entryPoint, target, internalformat, pname,
+ bufSize, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+// Perform validation from WebGL 2 section 5.10 "Invalid Clears":
+// In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
+// specified clear value and the type of a buffer that is being cleared generates an
+// INVALID_OPERATION error instead of producing undefined results
+bool ValidateWebGLFramebufferAttachmentClearType(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint drawbuffer,
+ const GLenum *validComponentTypes,
+ size_t validComponentTypeCount)
+{
+ const FramebufferAttachment *attachment =
+ context->getState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
+ if (attachment)
+ {
+ GLenum componentType = attachment->getFormat().info->componentType;
+ const GLenum *end = validComponentTypes + validComponentTypeCount;
+ if (std::find(validComponentTypes, end, componentType) == end)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kNoDefinedClearConversion);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateRobustCompressedTexImageBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei imageSize,
+ GLsizei dataSize)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, dataSize))
+ {
+ return false;
+ }
+
+ Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
+ if (pixelUnpackBuffer == nullptr)
+ {
+ if (dataSize < imageSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kCompressedDataSizeTooSmall);
+ }
+ }
+ return true;
+}
+
+bool ValidateGetBufferParameterBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLenum pname,
+ bool pointerVersion,
+ GLsizei *numParams)
+{
+ if (numParams)
+ {
+ *numParams = 0;
+ }
+
+ if (!context->isValidBufferBinding(target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
+ return false;
+ }
+
+ const Buffer *buffer = context->getState().getTargetBuffer(target);
+ if (!buffer)
+ {
+ // A null buffer means that "0" is bound to the requested buffer target
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound);
+ return false;
+ }
+
+ const Extensions &extensions = context->getExtensions();
+
+ switch (pname)
+ {
+ case GL_BUFFER_USAGE:
+ case GL_BUFFER_SIZE:
+ break;
+
+ case GL_BUFFER_ACCESS_OES:
+ if (!extensions.mapbufferOES)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+
+ case GL_BUFFER_MAPPED:
+ static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
+ if (context->getClientMajorVersion() < 3 && !extensions.mapbufferOES &&
+ !extensions.mapBufferRangeEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+
+ case GL_BUFFER_MAP_POINTER:
+ if (!pointerVersion)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMapPointerQuery);
+ return false;
+ }
+ break;
+
+ case GL_BUFFER_ACCESS_FLAGS:
+ case GL_BUFFER_MAP_OFFSET:
+ case GL_BUFFER_MAP_LENGTH:
+ if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRangeEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+
+ case GL_MEMORY_SIZE_ANGLE:
+ if (!context->getExtensions().memorySizeANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ case GL_RESOURCE_INITIALIZED_ANGLE:
+ if (!context->getExtensions().robustResourceInitializationANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kRobustResourceInitializationExtensionRequired);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ // All buffer parameter queries return one value.
+ if (numParams)
+ {
+ *numParams = 1;
+ }
+
+ return true;
+}
+
+bool ValidateGetRenderbufferParameterivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (target != GL_RENDERBUFFER)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget);
+ return false;
+ }
+
+ Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
+ if (renderbuffer == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kRenderbufferNotBound);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_RENDERBUFFER_WIDTH:
+ case GL_RENDERBUFFER_HEIGHT:
+ case GL_RENDERBUFFER_INTERNAL_FORMAT:
+ case GL_RENDERBUFFER_RED_SIZE:
+ case GL_RENDERBUFFER_GREEN_SIZE:
+ case GL_RENDERBUFFER_BLUE_SIZE:
+ case GL_RENDERBUFFER_ALPHA_SIZE:
+ case GL_RENDERBUFFER_DEPTH_SIZE:
+ case GL_RENDERBUFFER_STENCIL_SIZE:
+ break;
+
+ case GL_RENDERBUFFER_SAMPLES_ANGLE:
+ if (context->getClientMajorVersion() < 3 &&
+ !context->getExtensions().framebufferMultisampleANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ case GL_MEMORY_SIZE_ANGLE:
+ if (!context->getExtensions().memorySizeANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+ if (!context->getExtensions().getImageANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kGetImageExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ case GL_RESOURCE_INITIALIZED_ANGLE:
+ if (!context->getExtensions().robustResourceInitializationANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kRobustResourceInitializationExtensionRequired);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+ return true;
+}
+
+bool ValidateGetShaderivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shader,
+ GLenum pname,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (context->isContextLost())
+ {
+ context->validationError(entryPoint, GL_CONTEXT_LOST, kContextLost);
+
+ if (context->getExtensions().parallelShaderCompileKHR && pname == GL_COMPLETION_STATUS_KHR)
+ {
+ // Generate an error but still return true, the context still needs to return a
+ // value in this case.
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (GetValidShader(context, entryPoint, shader) == nullptr)
+ {
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_SHADER_TYPE:
+ case GL_DELETE_STATUS:
+ case GL_COMPILE_STATUS:
+ case GL_INFO_LOG_LENGTH:
+ case GL_SHADER_SOURCE_LENGTH:
+ break;
+
+ case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
+ if (!context->getExtensions().translatedShaderSourceANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ case GL_COMPLETION_STATUS_KHR:
+ if (!context->getExtensions().parallelShaderCompileKHR)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+ return true;
+}
+
+bool ValidateGetTexParameterBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if ((!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) ||
+ target == TextureType::Buffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ if (context->getTextureByType(target) == nullptr)
+ {
+ // Should only be possible for external textures
+ context->validationError(entryPoint, GL_INVALID_ENUM, kTextureNotBound);
+ return false;
+ }
+
+ if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ break;
+
+ case GL_TEXTURE_USAGE_ANGLE:
+ if (!context->getExtensions().textureUsageANGLE)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_IMMUTABLE_FORMAT:
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorageEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_IMMUTABLE_LEVELS:
+ case GL_TEXTURE_SWIZZLE_R:
+ case GL_TEXTURE_SWIZZLE_G:
+ case GL_TEXTURE_SWIZZLE_B:
+ case GL_TEXTURE_SWIZZLE_A:
+ case GL_TEXTURE_BASE_LEVEL:
+ case GL_TEXTURE_MAX_LEVEL:
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES30);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_COMPARE_MODE:
+ case GL_TEXTURE_COMPARE_FUNC:
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().shadowSamplersEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ if (!context->getExtensions().textureSRGBDecodeEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+
+ case GL_DEPTH_STENCIL_TEXTURE_MODE:
+ case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
+ return false;
+ }
+ break;
+
+ case GL_GENERATE_MIPMAP:
+ case GL_TEXTURE_CROP_RECT_OES:
+ // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
+ // after GL_OES_draw_texture functionality implemented
+ if (context->getClientMajorVersion() > 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kGLES1Only);
+ return false;
+ }
+ break;
+
+ case GL_MEMORY_SIZE_ANGLE:
+ if (!context->getExtensions().memorySizeANGLE)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ if (!context->getExtensions().textureBorderClampOES &&
+ context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_NATIVE_ID_ANGLE:
+ if (!context->getExtensions().textureExternalUpdateANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE:
+ if (!context->getExtensions().getImageANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kGetImageExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ case GL_RESOURCE_INITIALIZED_ANGLE:
+ if (!context->getExtensions().robustResourceInitializationANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kRobustResourceInitializationExtensionRequired);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_PROTECTED_EXT:
+ if (!context->getExtensions().protectedTexturesEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kProtectedTexturesExtensionRequired);
+ return false;
+ }
+ break;
+
+ case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ if (length)
+ {
+ *length = GetTexParameterCount(pname);
+ }
+ return true;
+}
+
+bool ValidateGetVertexAttribBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ GLsizei *length,
+ bool pointer,
+ bool pureIntegerEntryPoint)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ if (pointer)
+ {
+ if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ }
+ else
+ {
+ switch (pname)
+ {
+ case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
+ case GL_VERTEX_ATTRIB_ARRAY_SIZE:
+ case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
+ case GL_VERTEX_ATTRIB_ARRAY_TYPE:
+ case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
+ case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
+ case GL_CURRENT_VERTEX_ATTRIB:
+ break;
+
+ case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
+ static_assert(
+ GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
+ "ANGLE extension enums not equal to GL enums.");
+ if (context->getClientMajorVersion() < 3 &&
+ !context->getExtensions().instancedArraysAny())
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ pname);
+ return false;
+ }
+ break;
+
+ case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ pname);
+ return false;
+ }
+ break;
+
+ case GL_VERTEX_ATTRIB_BINDING:
+ case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ }
+
+ if (length)
+ {
+ if (pname == GL_CURRENT_VERTEX_ATTRIB)
+ {
+ *length = 4;
+ }
+ else
+ {
+ *length = 1;
+ }
+ }
+
+ return true;
+}
+
+bool ValidatePixelPack(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum format,
+ GLenum type,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLsizei bufSize,
+ GLsizei *length,
+ const void *pixels)
+{
+ // Check for pixel pack buffer related API errors
+ Buffer *pixelPackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelPack);
+ if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
+ {
+ // ...the buffer object's data store is currently mapped.
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferMapped);
+ return false;
+ }
+ if (pixelPackBuffer != nullptr &&
+ pixelPackBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kPixelPackBufferBoundForTransformFeedback);
+ return false;
+ }
+
+ // .. the data would be packed to the buffer object such that the memory writes required
+ // would exceed the data store size.
+ const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
+ const Extents size(width, height, 1);
+ const auto &pack = context->getState().getPackState();
+
+ GLuint endByte = 0;
+ if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
+ return false;
+ }
+
+ if (bufSize >= 0)
+ {
+ if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize);
+ return false;
+ }
+ }
+
+ if (pixelPackBuffer != nullptr)
+ {
+ CheckedNumeric<size_t> checkedEndByte(endByte);
+ CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
+ checkedEndByte += checkedOffset;
+
+ if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
+ {
+ // Overflow past the end of the buffer
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kParamOverflow);
+ return false;
+ }
+ }
+
+ if (pixelPackBuffer == nullptr && length != nullptr)
+ {
+ if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
+ return false;
+ }
+
+ *length = static_cast<GLsizei>(endByte);
+ }
+
+ if (context->isWebGL())
+ {
+ // WebGL 2.0 disallows the scenario:
+ // GL_PACK_SKIP_PIXELS + width > DataStoreWidth
+ // where:
+ // DataStoreWidth = (GL_PACK_ROW_LENGTH ? GL_PACK_ROW_LENGTH : width)
+ // Since these two pack parameters can only be set to non-zero values
+ // on WebGL 2.0 contexts, verify them for all WebGL contexts.
+ GLint dataStoreWidth = pack.rowLength ? pack.rowLength : width;
+ if (pack.skipPixels + width > dataStoreWidth)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidPackParametersForWebGL);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateReadPixelsBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ const void *pixels)
+{
+ if (length != nullptr)
+ {
+ *length = 0;
+ }
+ if (rows != nullptr)
+ {
+ *rows = 0;
+ }
+ if (columns != nullptr)
+ {
+ *columns = 0;
+ }
+
+ if (width < 0 || height < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
+ return false;
+ }
+
+ Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
+ ASSERT(readFramebuffer);
+
+ if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer))
+ {
+ return false;
+ }
+
+ // needIntrinsic = true. Treat renderToTexture textures as single sample since they will be
+ // resolved before reading.
+ if (!readFramebuffer->isDefault() &&
+ !ValidateFramebufferNotMultisampled(context, entryPoint, readFramebuffer, true))
+ {
+ return false;
+ }
+
+ if (readFramebuffer->getReadBufferState() == GL_NONE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kReadBufferNone);
+ return false;
+ }
+
+ const FramebufferAttachment *readBuffer = nullptr;
+ switch (format)
+ {
+ case GL_DEPTH_COMPONENT:
+ readBuffer = readFramebuffer->getDepthAttachment();
+ break;
+ case GL_STENCIL_INDEX_OES:
+ case GL_DEPTH_STENCIL_OES:
+ readBuffer = readFramebuffer->getStencilOrDepthStencilAttachment();
+ break;
+ default:
+ readBuffer = readFramebuffer->getReadColorAttachment();
+ break;
+ }
+
+ // OVR_multiview2, Revision 1:
+ // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if
+ // the number of views in the current read framebuffer is more than one.
+ if (readFramebuffer->readDisallowedByMultiview())
+ {
+ context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION,
+ kMultiviewReadFramebuffer);
+ return false;
+ }
+
+ if (context->isWebGL())
+ {
+ // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
+ // excluding formats LUMINANCE and LUMINANCE_ALPHA.". This requires validating the format
+ // and type before validating the combination of format and type. However, the
+ // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
+ // verifies that GL_INVALID_OPERATION is generated.
+ // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
+ // dEQP/WebGL.
+ if (!ValidReadPixelsFormatEnum(context, format))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+
+ if (!ValidReadPixelsTypeEnum(context, type))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
+ return false;
+ }
+ }
+
+ // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
+ // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
+ // attachment and WebGL defines it to be an error. We do the check unconditionally as the
+ // situation is an application error that would lead to a crash in ANGLE.
+ if (readBuffer == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingReadAttachment);
+ return false;
+ }
+
+ GLenum currentFormat = GL_NONE;
+ GLenum currentType = GL_NONE;
+
+ switch (format)
+ {
+ case GL_DEPTH_COMPONENT:
+ case GL_STENCIL_INDEX_OES:
+ case GL_DEPTH_STENCIL_OES:
+ // Only rely on ValidReadPixelsFormatType for depth/stencil formats
+ break;
+ default:
+ currentFormat = readFramebuffer->getImplementationColorReadFormat(context);
+ currentType = readFramebuffer->getImplementationColorReadType(context);
+ break;
+ }
+
+ bool validFormatTypeCombination =
+ ValidReadPixelsFormatType(context, readBuffer->getFormat().info, format, type);
+
+ if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
+ return false;
+ }
+
+ if (!ValidatePixelPack(context, entryPoint, format, type, x, y, width, height, bufSize, length,
+ pixels))
+ {
+ return false;
+ }
+
+ auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
+ angle::CheckedNumeric<int> clippedExtent(length);
+ if (start < 0)
+ {
+ // "subtract" the area that is less than 0
+ clippedExtent += start;
+ }
+
+ angle::CheckedNumeric<int> readExtent = start;
+ readExtent += length;
+ if (!readExtent.IsValid())
+ {
+ return false;
+ }
+
+ if (readExtent.ValueOrDie() > bufferSize)
+ {
+ // Subtract the region to the right of the read buffer
+ clippedExtent -= (readExtent - bufferSize);
+ }
+
+ if (!clippedExtent.IsValid())
+ {
+ return false;
+ }
+
+ *outExtent = std::max<int>(clippedExtent.ValueOrDie(), 0);
+ return true;
+ };
+
+ GLsizei writtenColumns = 0;
+ if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
+ return false;
+ }
+
+ GLsizei writtenRows = 0;
+ if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
+ return false;
+ }
+
+ if (columns != nullptr)
+ {
+ *columns = writtenColumns;
+ }
+
+ if (rows != nullptr)
+ {
+ *rows = writtenRows;
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateTexParameterBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ bool vectorParams,
+ const ParamType *params)
+{
+ if ((!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) ||
+ target == TextureType::Buffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ if (context->getTextureByType(target) == nullptr)
+ {
+ // Should only be possible for external textures
+ context->validationError(entryPoint, GL_INVALID_ENUM, kTextureNotBound);
+ return false;
+ }
+
+ const GLsizei minBufSize = GetTexParameterCount(pname);
+ if (bufSize >= 0 && bufSize < minBufSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize);
+ return false;
+ }
+
+ if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_SWIZZLE_R:
+ case GL_TEXTURE_SWIZZLE_G:
+ case GL_TEXTURE_SWIZZLE_B:
+ case GL_TEXTURE_SWIZZLE_A:
+ case GL_TEXTURE_BASE_LEVEL:
+ case GL_TEXTURE_MAX_LEVEL:
+ case GL_TEXTURE_COMPARE_MODE:
+ case GL_TEXTURE_COMPARE_FUNC:
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ if (context->getClientMajorVersion() < 3 &&
+ !(pname == GL_TEXTURE_WRAP_R && context->getExtensions().texture3DOES))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kES3Required);
+ return false;
+ }
+ if (target == TextureType::External &&
+ !context->getExtensions().EGLImageExternalEssl3OES)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ if (target == TextureType::VideoImage && !context->getExtensions().videoTextureWEBGL)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ }
+ break;
+
+ case GL_GENERATE_MIPMAP:
+ case GL_TEXTURE_CROP_RECT_OES:
+ if (context->getClientMajorVersion() > 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kGLES1Only);
+ return false;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
+ {
+ switch (pname)
+ {
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ case GL_TEXTURE_COMPARE_MODE:
+ case GL_TEXTURE_COMPARE_FUNC:
+ case GL_TEXTURE_BORDER_COLOR:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ {
+ bool restrictedWrapModes = ((target == TextureType::External &&
+ !context->getExtensions().EGLImageExternalWrapModesEXT) ||
+ target == TextureType::Rectangle);
+ if (!ValidateTextureWrapModeValue(context, entryPoint, params, restrictedWrapModes))
+ {
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_MIN_FILTER:
+ {
+ bool restrictedMinFilter =
+ target == TextureType::External || target == TextureType::Rectangle;
+ if (!ValidateTextureMinFilterValue(context, entryPoint, params, restrictedMinFilter))
+ {
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_MAG_FILTER:
+ if (!ValidateTextureMagFilterValue(context, entryPoint, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_USAGE_ANGLE:
+ if (!context->getExtensions().textureUsageANGLE)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_NONE:
+ case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ pname);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ {
+ GLfloat paramValue = static_cast<GLfloat>(params[0]);
+ if (!ValidateTextureMaxAnisotropyValue(context, entryPoint, paramValue))
+ {
+ return false;
+ }
+ ASSERT(static_cast<ParamType>(paramValue) == params[0]);
+ }
+ break;
+
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ // any value is permissible
+ break;
+
+ case GL_TEXTURE_COMPARE_MODE:
+ if (!ValidateTextureCompareModeValue(context, entryPoint, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_COMPARE_FUNC:
+ if (!ValidateTextureCompareFuncValue(context, entryPoint, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_SWIZZLE_R:
+ case GL_TEXTURE_SWIZZLE_G:
+ case GL_TEXTURE_SWIZZLE_B:
+ case GL_TEXTURE_SWIZZLE_A:
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_ZERO:
+ case GL_ONE:
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ pname);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_BASE_LEVEL:
+ if (ConvertToGLint(params[0]) < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kBaseLevelNegative);
+ return false;
+ }
+ if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBaseLevelNonZero);
+ return false;
+ }
+ if ((target == TextureType::_2DMultisample ||
+ target == TextureType::_2DMultisampleArray) &&
+ static_cast<GLuint>(params[0]) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBaseLevelNonZero);
+ return false;
+ }
+ if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBaseLevelNonZero);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAX_LEVEL:
+ if (ConvertToGLint(params[0]) < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+ break;
+
+ case GL_DEPTH_STENCIL_TEXTURE_MODE:
+ if (context->getClientVersion() < Version(3, 1))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
+ return false;
+ }
+ switch (ConvertToGLenum(params[0]))
+ {
+ case GL_DEPTH_COMPONENT:
+ case GL_STENCIL_INDEX:
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ pname);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ if (!ValidateTextureSRGBDecodeValue(context, entryPoint, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT:
+ if (!ValidateTextureSRGBOverrideValue(context, entryPoint, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_GENERATE_MIPMAP:
+ if (context->getClientMajorVersion() > 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kGLES1Only);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_CROP_RECT_OES:
+ if (context->getClientMajorVersion() > 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kGLES1Only);
+ return false;
+ }
+ if (!vectorParams)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ if (!context->getExtensions().textureBorderClampOES &&
+ context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ return false;
+ }
+ if (!vectorParams)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInsufficientBufferSize);
+ return false;
+ }
+ break;
+
+ case GL_RESOURCE_INITIALIZED_ANGLE:
+ if (!context->getExtensions().robustResourceInitializationANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kRobustResourceInitializationExtensionRequired);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_PROTECTED_EXT:
+ if (!context->getExtensions().protectedTexturesEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kProtectedTexturesExtensionRequired);
+ return false;
+ }
+ if (ConvertToBool(params[0]) != context->getState().hasProtectedContent())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ "Protected Texture must match Protected Context");
+ return false;
+ }
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ return true;
+}
+
+template bool ValidateTexParameterBase(const Context *,
+ angle::EntryPoint,
+ TextureType,
+ GLenum,
+ GLsizei,
+ bool,
+ const GLfloat *);
+template bool ValidateTexParameterBase(const Context *,
+ angle::EntryPoint,
+ TextureType,
+ GLenum,
+ GLsizei,
+ bool,
+ const GLint *);
+template bool ValidateTexParameterBase(const Context *,
+ angle::EntryPoint,
+ TextureType,
+ GLenum,
+ GLsizei,
+ bool,
+ const GLuint *);
+
+bool ValidateGetActiveUniformBlockivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformBlockIndex uniformBlockIndex,
+ GLenum pname,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (uniformBlockIndex.value >= programObject->getActiveUniformBlockCount())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kIndexExceedsActiveUniformBlockCount);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_UNIFORM_BLOCK_BINDING:
+ case GL_UNIFORM_BLOCK_DATA_SIZE:
+ case GL_UNIFORM_BLOCK_NAME_LENGTH:
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ if (length)
+ {
+ if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
+ {
+ const InterfaceBlock &uniformBlock =
+ programObject->getUniformBlockByIndex(uniformBlockIndex.value);
+ *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
+ }
+ else
+ {
+ *length = 1;
+ }
+ }
+
+ return true;
+}
+
+template <typename ParamType>
+bool ValidateSamplerParameterBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ bool vectorParams,
+ const ParamType *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!context->isSampler(sampler))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidSampler);
+ return false;
+ }
+
+ const GLsizei minBufSize = GetSamplerParameterCount(pname);
+ if (bufSize >= 0 && bufSize < minBufSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ if (!ValidateTextureWrapModeValue(context, entryPoint, params, false))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MIN_FILTER:
+ if (!ValidateTextureMinFilterValue(context, entryPoint, params, false))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAG_FILTER:
+ if (!ValidateTextureMagFilterValue(context, entryPoint, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ // any value is permissible
+ break;
+
+ case GL_TEXTURE_COMPARE_MODE:
+ if (!ValidateTextureCompareModeValue(context, entryPoint, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_COMPARE_FUNC:
+ if (!ValidateTextureCompareFuncValue(context, entryPoint, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ if (!ValidateTextureSRGBDecodeValue(context, entryPoint, params))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ {
+ GLfloat paramValue = static_cast<GLfloat>(params[0]);
+ if (!ValidateTextureMaxAnisotropyValue(context, entryPoint, paramValue))
+ {
+ return false;
+ }
+ }
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ if (!context->getExtensions().textureBorderClampOES &&
+ context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ return false;
+ }
+ if (!vectorParams)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInsufficientBufferSize);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ return true;
+}
+
+template bool ValidateSamplerParameterBase(const Context *,
+ angle::EntryPoint,
+ SamplerID,
+ GLenum,
+ GLsizei,
+ bool,
+ const GLfloat *);
+template bool ValidateSamplerParameterBase(const Context *,
+ angle::EntryPoint,
+ SamplerID,
+ GLenum,
+ GLsizei,
+ bool,
+ const GLint *);
+template bool ValidateSamplerParameterBase(const Context *,
+ angle::EntryPoint,
+ SamplerID,
+ GLenum,
+ GLsizei,
+ bool,
+ const GLuint *);
+
+bool ValidateGetSamplerParameterBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!context->isSampler(sampler))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidSampler);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ case GL_TEXTURE_WRAP_R:
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ case GL_TEXTURE_COMPARE_MODE:
+ case GL_TEXTURE_COMPARE_FUNC:
+ break;
+
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint))
+ {
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_SRGB_DECODE_EXT:
+ if (!context->getExtensions().textureSRGBDecodeEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ if (!context->getExtensions().textureBorderClampOES &&
+ context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ if (length)
+ {
+ *length = GetSamplerParameterCount(pname);
+ }
+ return true;
+}
+
+bool ValidateGetInternalFormativBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *numParams)
+{
+ if (numParams)
+ {
+ *numParams = 0;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ if (!formatCaps.renderbuffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kFormatNotRenderable);
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_RENDERBUFFER:
+ break;
+
+ case GL_TEXTURE_2D_MULTISAMPLE:
+ if (context->getClientVersion() < ES_3_1 &&
+ !context->getExtensions().textureMultisampleANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kMultisampleTextureExtensionOrES31Required);
+ return false;
+ }
+ break;
+ case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
+ if (!context->getExtensions().textureStorageMultisample2dArrayOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kMultisampleArrayExtensionRequired);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTarget);
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInsufficientBufferSize);
+ return false;
+ }
+
+ GLsizei maxWriteParams = 0;
+ switch (pname)
+ {
+ case GL_NUM_SAMPLE_COUNTS:
+ maxWriteParams = 1;
+ break;
+
+ case GL_SAMPLES:
+ maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ if (numParams)
+ {
+ // glGetInternalFormativ will not overflow bufSize
+ *numParams = std::min(bufSize, maxWriteParams);
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferNotMultisampled(const Context *context,
+ angle::EntryPoint entryPoint,
+ const Framebuffer *framebuffer,
+ bool checkReadBufferResourceSamples)
+{
+ int samples = checkReadBufferResourceSamples
+ ? framebuffer->getReadBufferResourceSamples(context)
+ : framebuffer->getSamples(context);
+ if (samples != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidMultisampledFramebufferOperation);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateMultitextureUnit(const Context *context, angle::EntryPoint entryPoint, GLenum texture)
+{
+ if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMultitextureUnit);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateTexStorageMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei samples,
+ GLint internalFormat,
+ GLsizei width,
+ GLsizei height)
+{
+ const Caps &caps = context->getCaps();
+ if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kTextureWidthOrHeightOutOfRange);
+ return false;
+ }
+
+ if (samples == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kSamplesZero);
+ return false;
+ }
+
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
+ if (!formatCaps.textureAttachment)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kRenderableInternalFormat);
+ return false;
+ }
+
+ // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
+ // is one of the unsized base internalformats listed in table 8.11.
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
+ if (formatInfo.internalFormat == GL_NONE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kUnsizedInternalFormatUnsupported);
+ return false;
+ }
+
+ if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kSamplesOutOfRange);
+ return false;
+ }
+
+ Texture *texture = context->getTextureByType(target);
+ if (!texture || texture->id().value == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kZeroBoundToTarget);
+ return false;
+ }
+
+ if (texture->getImmutableFormat())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kImmutableTextureBound);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateTexStorage2DMultisampleBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei samples,
+ GLint internalFormat,
+ GLsizei width,
+ GLsizei height)
+{
+ if (target != TextureType::_2DMultisample)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTarget);
+ return false;
+ }
+
+ if (width < 1 || height < 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kTextureSizeTooSmall);
+ return false;
+ }
+
+ return ValidateTexStorageMultisample(context, entryPoint, target, samples, internalFormat,
+ width, height);
+}
+
+bool ValidateGetTexLevelParameterBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum pname,
+ GLsizei *length)
+{
+
+ if (length)
+ {
+ *length = 0;
+ }
+
+ TextureType type = TextureTargetToType(target);
+
+ if (!ValidTexLevelDestinationTarget(context, type))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ if (context->getTextureByType(type) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kTextureNotBound);
+ return false;
+ }
+
+ if (!ValidMipLevel(context, type, level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_RED_TYPE:
+ case GL_TEXTURE_GREEN_TYPE:
+ case GL_TEXTURE_BLUE_TYPE:
+ case GL_TEXTURE_ALPHA_TYPE:
+ case GL_TEXTURE_DEPTH_TYPE:
+ case GL_TEXTURE_RED_SIZE:
+ case GL_TEXTURE_GREEN_SIZE:
+ case GL_TEXTURE_BLUE_SIZE:
+ case GL_TEXTURE_ALPHA_SIZE:
+ case GL_TEXTURE_DEPTH_SIZE:
+ case GL_TEXTURE_STENCIL_SIZE:
+ case GL_TEXTURE_SHARED_SIZE:
+ case GL_TEXTURE_INTERNAL_FORMAT:
+ case GL_TEXTURE_WIDTH:
+ case GL_TEXTURE_HEIGHT:
+ case GL_TEXTURE_DEPTH:
+ case GL_TEXTURE_SAMPLES:
+ case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
+ case GL_TEXTURE_COMPRESSED:
+ break;
+
+ case GL_RESOURCE_INITIALIZED_ANGLE:
+ if (!context->getExtensions().robustResourceInitializationANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kRobustResourceInitializationExtensionRequired);
+ return false;
+ }
+ break;
+
+ case GL_TEXTURE_BUFFER_DATA_STORE_BINDING:
+ case GL_TEXTURE_BUFFER_OFFSET:
+ case GL_TEXTURE_BUFFER_SIZE:
+ if (context->getClientVersion() < Version(3, 2) &&
+ !context->getExtensions().textureBufferAny())
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kTextureBufferExtensionNotAvailable);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+
+ if (length)
+ {
+ *length = 1;
+ }
+ return true;
+}
+
+bool ValidateGetMultisamplefvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLuint index,
+ const GLfloat *val)
+{
+ if (pname != GL_SAMPLE_POSITION)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+
+ Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
+ GLint samples = framebuffer->getSamples(context);
+
+ if (index >= static_cast<GLuint>(samples))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsSamples);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSampleMaskiBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint maskNumber,
+ GLbitfield mask)
+{
+ if (maskNumber >= static_cast<GLuint>(context->getCaps().maxSampleMaskWords))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSampleMaskNumber);
+ return false;
+ }
+
+ return true;
+}
+
+void RecordDrawAttribsError(const Context *context, angle::EntryPoint entryPoint)
+{
+ // An overflow can happen when adding the offset. Check against a special constant.
+ if (context->getStateCache().getNonInstancedVertexElementLimit() ==
+ VertexAttribute::kIntegerOverflow ||
+ context->getStateCache().getInstancedVertexElementLimit() ==
+ VertexAttribute::kIntegerOverflow)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
+ }
+ else
+ {
+ // [OpenGL ES 3.0.2] section 2.9.4 page 40:
+ // We can return INVALID_OPERATION if our buffer does not have enough backing data.
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientVertexBufferSize);
+ }
+}
+
+bool ValidateLoseContextCHROMIUM(const Context *context,
+ angle::EntryPoint entryPoint,
+ GraphicsResetStatus current,
+ GraphicsResetStatus other)
+{
+ if (!context->getExtensions().loseContextCHROMIUM)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ switch (current)
+ {
+ case GraphicsResetStatus::GuiltyContextReset:
+ case GraphicsResetStatus::InnocentContextReset:
+ case GraphicsResetStatus::UnknownContextReset:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidResetStatus);
+ }
+
+ switch (other)
+ {
+ case GraphicsResetStatus::GuiltyContextReset:
+ case GraphicsResetStatus::InnocentContextReset:
+ case GraphicsResetStatus::UnknownContextReset:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidResetStatus);
+ }
+
+ return true;
+}
+
+// GL_ANGLE_texture_storage_external
+bool ValidateTexImage2DExternalANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type)
+{
+ if (!context->getExtensions().textureExternalUpdateANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidTexture2DDestinationTarget(context, target) &&
+ !ValidTextureExternalTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ if (context->getClientMajorVersion() <= 2)
+ {
+ if (!ValidateES2TexImageParametersBase(context, entryPoint, target, level, internalformat,
+ false, false, 0, 0, width, height, border, format,
+ type, -1, nullptr))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (!ValidateES3TexImageParametersBase(context, entryPoint, target, level, internalformat,
+ false, false, 0, 0, 0, width, height, 1, border,
+ format, type, -1, nullptr))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateInvalidateTextureANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target)
+{
+ if (!context->getExtensions().textureExternalUpdateANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateProgramExecutableXFBBuffersPresent(const Context *context,
+ const ProgramExecutable *programExecutable)
+{
+ size_t programXfbCount = programExecutable->getTransformFeedbackBufferCount();
+ const TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
+ for (size_t programXfbIndex = 0; programXfbIndex < programXfbCount; ++programXfbIndex)
+ {
+ const OffsetBindingPointer<Buffer> &buffer =
+ transformFeedback->getIndexedBuffer(programXfbIndex);
+ if (!buffer.get())
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateLogicOpCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ LogicalOperation opcodePacked)
+{
+ switch (opcodePacked)
+ {
+ case LogicalOperation::And:
+ case LogicalOperation::AndInverted:
+ case LogicalOperation::AndReverse:
+ case LogicalOperation::Clear:
+ case LogicalOperation::Copy:
+ case LogicalOperation::CopyInverted:
+ case LogicalOperation::Equiv:
+ case LogicalOperation::Invert:
+ case LogicalOperation::Nand:
+ case LogicalOperation::Noop:
+ case LogicalOperation::Nor:
+ case LogicalOperation::Or:
+ case LogicalOperation::OrInverted:
+ case LogicalOperation::OrReverse:
+ case LogicalOperation::Set:
+ case LogicalOperation::Xor:
+ return true;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidLogicOp);
+ return false;
+ }
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/validationES.h b/gfx/angle/checkout/src/libANGLE/validationES.h
new file mode 100644
index 0000000000..685e1e505b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES.h
@@ -0,0 +1,1272 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationES.h: Validation functions for generic OpenGL ES entry point parameters
+
+#ifndef LIBANGLE_VALIDATION_ES_H_
+#define LIBANGLE_VALIDATION_ES_H_
+
+#include "common/PackedEnums.h"
+#include "common/mathutil.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/VertexArray.h"
+
+#include <GLES2/gl2.h>
+#include <GLES3/gl3.h>
+#include <GLES3/gl31.h>
+
+namespace egl
+{
+class Display;
+class Image;
+} // namespace egl
+
+namespace gl
+{
+class Context;
+struct Format;
+class Framebuffer;
+struct LinkedUniform;
+class Program;
+class Shader;
+
+void SetRobustLengthParam(const GLsizei *length, GLsizei value);
+bool ValidTextureTarget(const Context *context, TextureType type);
+bool ValidTexture2DTarget(const Context *context, TextureType type);
+bool ValidTexture3DTarget(const Context *context, TextureType target);
+bool ValidTextureExternalTarget(const Context *context, TextureType target);
+bool ValidTextureExternalTarget(const Context *context, TextureTarget target);
+bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target);
+bool ValidTexture3DDestinationTarget(const Context *context, TextureTarget target);
+bool ValidTexLevelDestinationTarget(const Context *context, TextureType type);
+bool ValidFramebufferTarget(const Context *context, GLenum target);
+bool ValidMipLevel(const Context *context, TextureType type, GLint level);
+bool ValidImageSizeParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLint level,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ bool isSubImage);
+bool ValidCompressedImageSize(const Context *context,
+ GLenum internalFormat,
+ GLint level,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+bool ValidCompressedSubImageSize(const Context *context,
+ GLenum internalFormat,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ size_t textureWidth,
+ size_t textureHeight,
+ size_t textureDepth);
+bool ValidImageDataSize(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType texType,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels,
+ GLsizei imageSize);
+
+bool ValidQueryType(const Context *context, QueryType queryType);
+
+bool ValidateWebGLVertexAttribPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexAttribType type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *ptr,
+ bool pureInteger);
+
+// Returns valid program if id is a valid program name
+// Errors INVALID_OPERATION if valid shader is given and returns NULL
+// Errors INVALID_VALUE otherwise and returns NULL
+Program *GetValidProgram(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id);
+
+// Returns valid shader if id is a valid shader name
+// Errors INVALID_OPERATION if valid program is given and returns NULL
+// Errors INVALID_VALUE otherwise and returns NULL
+Shader *GetValidShader(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id);
+
+bool ValidateAttachmentTarget(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum attachment);
+
+bool ValidateBlitFramebufferParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+
+bool ValidateBindFramebufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ FramebufferID framebuffer);
+bool ValidateBindRenderbufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ RenderbufferID renderbuffer);
+bool ValidateFramebufferParameteriBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ GLint param);
+bool ValidateFramebufferRenderbufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ RenderbufferID renderbuffer);
+bool ValidateFramebufferTextureBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureID texture,
+ GLint level);
+bool ValidateGenerateMipmapBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target);
+
+bool ValidateRenderbufferStorageParametersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+
+bool ValidatePixelPack(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum format,
+ GLenum type,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLsizei bufSize,
+ GLsizei *length,
+ const void *pixels);
+
+bool ValidateReadPixelsBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLsizei *columns,
+ GLsizei *rows,
+ const void *pixels);
+bool ValidateReadPixelsRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLsizei *columns,
+ const GLsizei *rows,
+ const void *pixels);
+bool ValidateReadnPixelsEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+bool ValidateReadnPixelsRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLsizei *columns,
+ const GLsizei *rows,
+ const void *data);
+
+bool ValidateGenQueriesEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const QueryID *ids);
+bool ValidateDeleteQueriesEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const QueryID *ids);
+bool ValidateIsQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryID id);
+bool ValidateBeginQueryBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType target,
+ QueryID id);
+bool ValidateBeginQueryEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType target,
+ QueryID id);
+bool ValidateEndQueryBase(const Context *context, angle::EntryPoint entryPoint, QueryType target);
+bool ValidateEndQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryType target);
+bool ValidateQueryCounterEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ QueryType target);
+bool ValidateGetQueryivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType target,
+ GLenum pname,
+ GLsizei *numParams);
+bool ValidateGetQueryivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType target,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetQueryivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetQueryObjectValueBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ GLsizei *numParams);
+bool ValidateGetQueryObjectivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetQueryObjectivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetQueryObjectuivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ const GLuint *params);
+bool ValidateGetQueryObjectuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint *params);
+bool ValidateGetQueryObjecti64vEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ GLint64 *params);
+bool ValidateGetQueryObjecti64vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ GLint64 *params);
+bool ValidateGetQueryObjectui64vEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ GLuint64 *params);
+bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ GLuint64 *params);
+
+bool ValidateUniformCommonBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ const Program *program,
+ UniformLocation location,
+ GLsizei count,
+ const LinkedUniform **uniformOut);
+bool ValidateUniform1ivValue(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum uniformType,
+ GLsizei count,
+ const GLint *value);
+
+ANGLE_INLINE bool ValidateUniformValue(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum valueType,
+ GLenum uniformType)
+{
+ // Check that the value type is compatible with uniform type.
+ // Do the cheaper test first, for a little extra speed.
+ if (valueType != uniformType && VariableBoolVectorType(valueType) != uniformType)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, err::kUniformSizeMismatch);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateUniformMatrixValue(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum valueType,
+ GLenum uniformType);
+bool ValidateUniform(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum uniformType,
+ UniformLocation location,
+ GLsizei count);
+bool ValidateUniformMatrix(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum matrixType,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose);
+bool ValidateGetBooleanvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLboolean *params);
+bool ValidateGetFloatvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params);
+bool ValidateStateQuery(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLenum *nativeType,
+ unsigned int *numParams);
+bool ValidateGetIntegervRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *data);
+bool ValidateGetInteger64vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ GLint64 *data);
+bool ValidateRobustStateQuery(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ GLenum *nativeType,
+ unsigned int *numParams);
+
+bool ValidateCopyImageSubDataBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint srcName,
+ GLenum srcTarget,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLuint dstName,
+ GLenum dstTarget,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth);
+
+bool ValidateCopyTexImageParametersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ Format *textureFormatOut);
+
+void RecordDrawModeError(const Context *context, angle::EntryPoint entryPoint, PrimitiveMode mode);
+const char *ValidateDrawElementsStates(const Context *context);
+
+ANGLE_INLINE bool ValidateDrawBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode)
+{
+ intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
+ if (drawStatesError)
+ {
+ const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
+
+ // All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
+ // Incomplete.
+ bool isFramebufferIncomplete = strcmp(errorMessage, err::kDrawFramebufferIncomplete) == 0;
+ GLenum errorCode =
+ isFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION : GL_INVALID_OPERATION;
+ context->validationError(entryPoint, errorCode, errorMessage);
+ return false;
+ }
+
+ if (!context->getStateCache().isValidDrawMode(mode))
+ {
+ RecordDrawModeError(context, entryPoint, mode);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawArraysInstancedBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount);
+bool ValidateDrawArraysInstancedANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount);
+bool ValidateDrawArraysInstancedEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount);
+
+bool ValidateDrawElementsInstancedBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei primcount);
+bool ValidateDrawElementsInstancedANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei primcount);
+bool ValidateDrawElementsInstancedEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei primcount);
+
+bool ValidateDrawInstancedANGLE(const Context *context, angle::EntryPoint entryPoint);
+
+bool ValidateGetUniformBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location);
+bool ValidateSizedGetUniform(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ GLsizei *length);
+bool ValidateGetnUniformfvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLfloat *params);
+bool ValidateGetnUniformfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params);
+bool ValidateGetnUniformivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLint *params);
+bool ValidateGetnUniformivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetnUniformuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint *params);
+bool ValidateGetUniformfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params);
+bool ValidateGetUniformivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetUniformuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint *params);
+
+bool ValidateDiscardFramebufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ bool defaultFramebuffer);
+
+bool ValidateInsertEventMarkerEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei length,
+ const char *marker);
+bool ValidatePushGroupMarkerEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei length,
+ const char *marker);
+bool ValidateEGLImageObject(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType type,
+ GLeglImageOES image);
+bool ValidateEGLImageTargetTexture2DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType type,
+ GLeglImageOES image);
+bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLeglImageOES image);
+
+bool ValidateProgramBinaryBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length);
+bool ValidateGetProgramBinaryBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLenum *binaryFormat,
+ const void *binary);
+
+bool ValidateDrawBuffersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLenum *bufs);
+
+bool ValidateGetBufferPointervBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLenum pname,
+ GLsizei *length,
+ void *const *params);
+bool ValidateUnmapBufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target);
+bool ValidateMapBufferRangeBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access);
+bool ValidateFlushMappedBufferRangeBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length);
+
+bool ValidateGenOrDelete(const Context *context, angle::EntryPoint entryPoint, GLint n);
+
+bool ValidateRobustEntryPoint(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei bufSize);
+bool ValidateRobustBufferSize(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei bufSize,
+ GLsizei numParams);
+
+bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei *numParams);
+
+bool ValidateGetFramebufferParameterivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ const GLint *params);
+
+bool ValidateGetBufferParameterBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLenum pname,
+ bool pointerVersion,
+ GLsizei *numParams);
+
+bool ValidateGetProgramivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum pname,
+ GLsizei *numParams);
+
+bool ValidateGetRenderbufferParameterivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ GLsizei *length);
+
+bool ValidateGetShaderivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shader,
+ GLenum pname,
+ GLsizei *length);
+
+bool ValidateGetTexParameterBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLsizei *length);
+
+template <typename ParamType>
+bool ValidateTexParameterBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ bool vectorParams,
+ const ParamType *params);
+
+bool ValidateGetVertexAttribBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ GLsizei *length,
+ bool pointer,
+ bool pureIntegerEntryPoint);
+
+ANGLE_INLINE bool ValidateVertexFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint size,
+ VertexAttribTypeCase validation)
+{
+ const Caps &caps = context->getCaps();
+ if (index >= static_cast<GLuint>(caps.maxVertexAttributes))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ err::kIndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ switch (validation)
+ {
+ case VertexAttribTypeCase::Invalid:
+ context->validationError(entryPoint, GL_INVALID_ENUM, err::kInvalidType);
+ return false;
+ case VertexAttribTypeCase::Valid:
+ if (size < 1 || size > 4)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, err::kInvalidVertexAttrSize);
+ return false;
+ }
+ break;
+ case VertexAttribTypeCase::ValidSize4Only:
+ if (size != 4)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ err::kInvalidVertexAttribSize2101010);
+ return false;
+ }
+ break;
+ case VertexAttribTypeCase::ValidSize3or4:
+ if (size != 3 && size != 4)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ err::kInvalidVertexAttribSize1010102);
+ return false;
+ }
+ break;
+ }
+
+ return true;
+}
+
+// Note: These byte, short, and int types are all converted to float for the shader.
+ANGLE_INLINE bool ValidateFloatVertexFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint size,
+ VertexAttribType type)
+{
+ return ValidateVertexFormat(context, entryPoint, index, size,
+ context->getStateCache().getVertexAttribTypeValidation(type));
+}
+
+ANGLE_INLINE bool ValidateIntegerVertexFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint size,
+ VertexAttribType type)
+{
+ return ValidateVertexFormat(
+ context, entryPoint, index, size,
+ context->getStateCache().getIntegerVertexAttribTypeValidation(type));
+}
+
+bool ValidateWebGLFramebufferAttachmentClearType(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint drawbuffer,
+ const GLenum *validComponentTypes,
+ size_t validComponentTypeCount);
+
+bool ValidateRobustCompressedTexImageBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei imageSize,
+ GLsizei dataSize);
+
+bool ValidateVertexAttribIndex(const Context *context, angle::EntryPoint entryPoint, GLuint index);
+
+bool ValidateGetActiveUniformBlockivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformBlockIndex uniformBlockIndex,
+ GLenum pname,
+ GLsizei *length);
+
+bool ValidateGetSamplerParameterBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ GLsizei *length);
+
+template <typename ParamType>
+bool ValidateSamplerParameterBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ GLsizei bufSize,
+ bool vectorParams,
+ const ParamType *params);
+
+bool ValidateGetInternalFormativBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei *numParams);
+
+bool ValidateFramebufferNotMultisampled(const Context *context,
+ angle::EntryPoint entryPoint,
+ const Framebuffer *framebuffer,
+ bool checkReadBufferResourceSamples);
+
+bool ValidateMultitextureUnit(const Context *context, angle::EntryPoint entryPoint, GLenum texture);
+
+bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode transformFeedbackPrimitiveMode,
+ PrimitiveMode renderPrimitiveMode);
+
+// Common validation for 2D and 3D variants of TexStorage*Multisample.
+bool ValidateTexStorageMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei samples,
+ GLint internalFormat,
+ GLsizei width,
+ GLsizei height);
+
+bool ValidateTexStorage2DMultisampleBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei samples,
+ GLint internalFormat,
+ GLsizei width,
+ GLsizei height);
+
+bool ValidateGetTexLevelParameterBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum pname,
+ GLsizei *length);
+
+bool ValidateMapBufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target);
+bool ValidateIndexedStateQuery(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLuint index,
+ GLsizei *length);
+bool ValidateES3TexImage2DParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isCompressed,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei imageSize,
+ const void *pixels);
+bool ValidateES3CopyTexImage2DParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border);
+bool ValidateES3TexStorageParametersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+bool ValidateES3TexStorage2DParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+bool ValidateES3TexStorage3DParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+
+bool ValidateGetMultisamplefvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLuint index,
+ const GLfloat *val);
+bool ValidateSampleMaskiBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint maskNumber,
+ GLbitfield mask);
+
+bool ValidateProgramExecutableXFBBuffersPresent(const Context *context,
+ const ProgramExecutable *programExecutable);
+
+// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
+// implementation format info for incomplete framebuffers. It seems like these queries are
+// incongruent with the other errors.
+// Inlined for speed.
+template <GLenum ErrorCode = GL_INVALID_FRAMEBUFFER_OPERATION>
+ANGLE_INLINE bool ValidateFramebufferComplete(const Context *context,
+ angle::EntryPoint entryPoint,
+ const Framebuffer *framebuffer)
+{
+ const FramebufferStatus &framebufferStatus = framebuffer->checkStatus(context);
+ if (!framebufferStatus.isComplete())
+ {
+ ASSERT(framebufferStatus.reason != nullptr);
+ context->validationError(entryPoint, ErrorCode, framebufferStatus.reason);
+ return false;
+ }
+
+ return true;
+}
+
+const char *ValidateProgramPipelineDrawStates(const State &state,
+ const Extensions &extensions,
+ ProgramPipeline *programPipeline);
+const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline);
+const char *ValidateDrawStates(const Context *context);
+const char *ValidateProgramPipeline(const Context *context);
+
+void RecordDrawAttribsError(const Context *context, angle::EntryPoint entryPoint);
+
+ANGLE_INLINE bool ValidateDrawAttribs(const Context *context,
+ angle::EntryPoint entryPoint,
+ int64_t maxVertex)
+{
+ if (maxVertex > context->getStateCache().getNonInstancedVertexElementLimit())
+ {
+ RecordDrawAttribsError(context, entryPoint);
+ return false;
+ }
+
+ return true;
+}
+
+ANGLE_INLINE bool ValidateDrawArraysAttribs(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint first,
+ GLsizei count)
+{
+ if (!context->isBufferAccessValidationEnabled())
+ {
+ return true;
+ }
+
+ // Check the computation of maxVertex doesn't overflow.
+ // - first < 0 has been checked as an error condition.
+ // - if count <= 0, skip validating no-op draw calls.
+ // From this we know maxVertex will be positive, and only need to check if it overflows GLint.
+ ASSERT(first >= 0);
+ ASSERT(count > 0);
+ int64_t maxVertex = static_cast<int64_t>(first) + static_cast<int64_t>(count) - 1;
+ if (maxVertex > static_cast<int64_t>(std::numeric_limits<GLint>::max()))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, err::kIntegerOverflow);
+ return false;
+ }
+
+ return ValidateDrawAttribs(context, entryPoint, maxVertex);
+}
+
+ANGLE_INLINE bool ValidateDrawInstancedAttribs(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint primcount)
+{
+ if (!context->isBufferAccessValidationEnabled())
+ {
+ return true;
+ }
+
+ if ((primcount - 1) > context->getStateCache().getInstancedVertexElementLimit())
+ {
+ RecordDrawAttribsError(context, entryPoint);
+ return false;
+ }
+
+ return true;
+}
+
+ANGLE_INLINE bool ValidateDrawArraysCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount)
+{
+ if (first < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, err::kNegativeStart);
+ return false;
+ }
+
+ if (count <= 0)
+ {
+ if (count < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, err::kNegativeCount);
+ return false;
+ }
+
+ // Early exit.
+ return ValidateDrawBase(context, entryPoint, mode);
+ }
+
+ if (primcount <= 0)
+ {
+ if (primcount < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, err::kNegativeCount);
+ return false;
+ }
+ // Early exit.
+ return ValidateDrawBase(context, entryPoint, mode);
+ }
+
+ if (!ValidateDrawBase(context, entryPoint, mode))
+ {
+ return false;
+ }
+
+ if (context->getStateCache().isTransformFeedbackActiveUnpaused() &&
+ !context->supportsGeometryOrTesselation())
+ {
+ const State &state = context->getState();
+ TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
+ if (!curTransformFeedback->checkBufferSpaceForDraw(count, primcount))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ err::kTransformFeedbackBufferTooSmall);
+ return false;
+ }
+ }
+
+ return ValidateDrawArraysAttribs(context, entryPoint, first, count);
+}
+
+ANGLE_INLINE bool ValidateDrawElementsBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ DrawElementsType type)
+{
+ if (!context->getStateCache().isValidDrawElementsType(type))
+ {
+ if (type == DrawElementsType::UnsignedInt)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, err::kTypeNotUnsignedShortByte);
+ return false;
+ }
+
+ ASSERT(type == DrawElementsType::InvalidEnum);
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, err::kEnumInvalid);
+ return false;
+ }
+
+ intptr_t drawElementsError = context->getStateCache().getBasicDrawElementsError(context);
+ if (drawElementsError)
+ {
+ // All errors from ValidateDrawElementsStates return INVALID_OPERATION.
+ const char *errorMessage = reinterpret_cast<const char *>(drawElementsError);
+ context->validationError(entryPoint, GL_INVALID_OPERATION, errorMessage);
+ return false;
+ }
+
+ // Note that we are missing overflow checks for active transform feedback buffers.
+ return true;
+}
+
+ANGLE_INLINE bool ValidateDrawElementsCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei primcount)
+{
+ if (!ValidateDrawElementsBase(context, entryPoint, mode, type))
+ {
+ return false;
+ }
+
+ ASSERT(isPow2(GetDrawElementsTypeSize(type)) && GetDrawElementsTypeSize(type) > 0);
+
+ if (context->isWebGL())
+ {
+ GLuint typeBytes = GetDrawElementsTypeSize(type);
+
+ if ((reinterpret_cast<uintptr_t>(indices) & static_cast<uintptr_t>(typeBytes - 1)) != 0)
+ {
+ // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
+ // The offset arguments to drawElements and [...], must be a multiple of the size of the
+ // data type passed to the call, or an INVALID_OPERATION error is generated.
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ err::kOffsetMustBeMultipleOfType);
+ return false;
+ }
+
+ // [WebGL 1.0] Section 6.4 Buffer Offset and Stride Requirements
+ // In addition the offset argument to drawElements must be non-negative or an INVALID_VALUE
+ // error is generated.
+ if (reinterpret_cast<intptr_t>(indices) < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, err::kNegativeOffset);
+ return false;
+ }
+ }
+
+ if (count <= 0)
+ {
+ if (count < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, err::kNegativeCount);
+ return false;
+ }
+
+ // Early exit.
+ return ValidateDrawBase(context, entryPoint, mode);
+ }
+
+ if (!ValidateDrawBase(context, entryPoint, mode))
+ {
+ return false;
+ }
+
+ const State &state = context->getState();
+ const VertexArray *vao = state.getVertexArray();
+ Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
+
+ if (!elementArrayBuffer)
+ {
+ if (!indices)
+ {
+ // This is an application error that would normally result in a crash, but we catch
+ // it and return an error
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ err::kElementArrayNoBufferOrPointer);
+ return false;
+ }
+ }
+ else
+ {
+ // The max possible type size is 8 and count is on 32 bits so doing the multiplication
+ // in a 64 bit integer is safe. Also we are guaranteed that here count > 0.
+ static_assert(std::is_same<int, GLsizei>::value, "GLsizei isn't the expected type");
+ constexpr uint64_t kMaxTypeSize = 8;
+ constexpr uint64_t kIntMax = std::numeric_limits<int>::max();
+ constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
+ static_assert(kIntMax < kUint64Max / kMaxTypeSize, "");
+
+ uint64_t elementCount = static_cast<uint64_t>(count);
+ ASSERT(elementCount > 0 && GetDrawElementsTypeSize(type) <= kMaxTypeSize);
+
+ // Doing the multiplication here is overflow-safe
+ uint64_t elementDataSizeNoOffset = elementCount << GetDrawElementsTypeShift(type);
+
+ // The offset can be any value, check for overflows
+ uint64_t offset = static_cast<uint64_t>(reinterpret_cast<uintptr_t>(indices));
+ uint64_t elementDataSizeWithOffset = elementDataSizeNoOffset + offset;
+ if (elementDataSizeWithOffset < elementDataSizeNoOffset)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, err::kIntegerOverflow);
+ return false;
+ }
+
+ // Related to possible test bug: https://github.com/KhronosGroup/WebGL/issues/3064
+ if ((elementDataSizeWithOffset > static_cast<uint64_t>(elementArrayBuffer->getSize())) &&
+ (primcount > 0))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ err::kInsufficientBufferSize);
+ return false;
+ }
+ }
+
+ if (context->isBufferAccessValidationEnabled() && primcount > 0)
+ {
+ // Use the parameter buffer to retrieve and cache the index range.
+ IndexRange indexRange{IndexRange::Undefined()};
+ ANGLE_VALIDATION_TRY(vao->getIndexRange(context, type, count, indices, &indexRange));
+
+ // If we use an index greater than our maximum supported index range, return an error.
+ // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should
+ // always return an error if possible here.
+ if (static_cast<GLint64>(indexRange.end) >= context->getCaps().maxElementIndex)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, err::kExceedsMaxElement);
+ return false;
+ }
+
+ if (!ValidateDrawAttribs(context, entryPoint, static_cast<GLint>(indexRange.end)))
+ {
+ return false;
+ }
+
+ // No op if there are no real indices in the index data (all are primitive restart).
+ return (indexRange.vertexIndexCount > 0);
+ }
+
+ return true;
+}
+
+ANGLE_INLINE bool ValidateBindVertexArrayBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID array)
+{
+ if (!context->isVertexArrayGenerated(array))
+ {
+ // The default VAO should always exist
+ ASSERT(array.value != 0);
+ context->validationError(entryPoint, GL_INVALID_OPERATION, err::kInvalidVertexArray);
+ return false;
+ }
+
+ return true;
+}
+
+ANGLE_INLINE bool ValidateVertexAttribIndex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index)
+{
+ if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ err::kIndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateLogicOpCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ LogicalOperation opcodePacked);
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationES1.cpp b/gfx/angle/checkout/src/libANGLE/validationES1.cpp
new file mode 100644
index 0000000000..f872689492
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES1.cpp
@@ -0,0 +1,2129 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationES1.cpp: Validation functions for OpenGL ES 1.0 entry point parameters
+
+#include "libANGLE/validationES1_autogen.h"
+
+#include "common/debug.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/GLES1State.h"
+#include "libANGLE/queryconversions.h"
+#include "libANGLE/queryutils.h"
+#include "libANGLE/validationES.h"
+
+#define ANGLE_VALIDATE_IS_GLES1(context, entryPoint) \
+ do \
+ { \
+ if (context->getClientType() != EGL_OPENGL_API && context->getClientMajorVersion() > 1) \
+ { \
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kGLES1Only); \
+ return false; \
+ } \
+ } while (0)
+
+namespace gl
+{
+using namespace err;
+
+bool ValidateAlphaFuncCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ AlphaTestFunc func)
+{
+ switch (func)
+ {
+ case AlphaTestFunc::AlwaysPass:
+ case AlphaTestFunc::Equal:
+ case AlphaTestFunc::Gequal:
+ case AlphaTestFunc::Greater:
+ case AlphaTestFunc::Lequal:
+ case AlphaTestFunc::Less:
+ case AlphaTestFunc::Never:
+ case AlphaTestFunc::NotEqual:
+ return true;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumInvalid);
+ return false;
+ }
+}
+
+bool ValidateClientStateCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ ClientVertexArrayType arrayType)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ switch (arrayType)
+ {
+ case ClientVertexArrayType::Vertex:
+ case ClientVertexArrayType::Normal:
+ case ClientVertexArrayType::Color:
+ case ClientVertexArrayType::TextureCoord:
+ return true;
+ case ClientVertexArrayType::PointSize:
+ if (!context->getExtensions().pointSizeArrayOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kPointSizeArrayExtensionNotEnabled);
+ return false;
+ }
+ return true;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidClientState);
+ return false;
+ }
+}
+
+bool ValidateBuiltinVertexAttributeCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ ClientVertexArrayType arrayType,
+ GLint size,
+ VertexAttribType type,
+ GLsizei stride,
+ const void *pointer)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+
+ if (stride < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidVertexPointerStride);
+ return false;
+ }
+
+ int minSize = 1;
+ int maxSize = 4;
+
+ switch (arrayType)
+ {
+ case ClientVertexArrayType::Vertex:
+ case ClientVertexArrayType::TextureCoord:
+ minSize = 2;
+ maxSize = 4;
+ break;
+ case ClientVertexArrayType::Normal:
+ minSize = 3;
+ maxSize = 3;
+ break;
+ case ClientVertexArrayType::Color:
+ minSize = 4;
+ maxSize = 4;
+ break;
+ case ClientVertexArrayType::PointSize:
+ if (!context->getExtensions().pointSizeArrayOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kPointSizeArrayExtensionNotEnabled);
+ return false;
+ }
+
+ minSize = 1;
+ maxSize = 1;
+ break;
+ default:
+ UNREACHABLE();
+ return false;
+ }
+
+ if (size < minSize || size > maxSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidVertexPointerSize);
+ return false;
+ }
+
+ switch (type)
+ {
+ case VertexAttribType::Byte:
+ if (arrayType == ClientVertexArrayType::PointSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidVertexPointerType);
+ return false;
+ }
+ break;
+ case VertexAttribType::Short:
+ if (arrayType == ClientVertexArrayType::PointSize ||
+ arrayType == ClientVertexArrayType::Color)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidVertexPointerType);
+ return false;
+ }
+ break;
+ case VertexAttribType::Fixed:
+ case VertexAttribType::Float:
+ break;
+ case VertexAttribType::UnsignedByte:
+ if (arrayType != ClientVertexArrayType::Color)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidVertexPointerType);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidVertexPointerType);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateLightCaps(const Context *context, angle::EntryPoint entryPoint, GLenum light)
+{
+ if (light < GL_LIGHT0 || light >= GL_LIGHT0 + context->getCaps().maxLights)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidLight);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateLightCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ LightParameter pname,
+ const GLfloat *params)
+{
+
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+
+ if (!ValidateLightCaps(context, entryPoint, light))
+ {
+ return false;
+ }
+
+ switch (pname)
+ {
+ case LightParameter::Ambient:
+ case LightParameter::Diffuse:
+ case LightParameter::Specular:
+ case LightParameter::Position:
+ case LightParameter::SpotDirection:
+ return true;
+ case LightParameter::SpotExponent:
+ if (params[0] < 0.0f || params[0] > 128.0f)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kLightParameterOutOfRange);
+ return false;
+ }
+ return true;
+ case LightParameter::SpotCutoff:
+ if (params[0] == 180.0f)
+ {
+ return true;
+ }
+ if (params[0] < 0.0f || params[0] > 90.0f)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kLightParameterOutOfRange);
+ return false;
+ }
+ return true;
+ case LightParameter::ConstantAttenuation:
+ case LightParameter::LinearAttenuation:
+ case LightParameter::QuadraticAttenuation:
+ if (params[0] < 0.0f)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kLightParameterOutOfRange);
+ return false;
+ }
+ return true;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidLightParameter);
+ return false;
+ }
+}
+
+bool ValidateLightSingleComponent(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ LightParameter pname,
+ GLfloat param)
+{
+ if (!ValidateLightCommon(context, entryPoint, light, pname, &param))
+ {
+ return false;
+ }
+
+ if (GetLightParameterCount(pname) > 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidLightParameter);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateMaterialCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pname,
+ const GLfloat *params)
+{
+ switch (pname)
+ {
+ case MaterialParameter::Ambient:
+ case MaterialParameter::AmbientAndDiffuse:
+ case MaterialParameter::Diffuse:
+ case MaterialParameter::Specular:
+ case MaterialParameter::Emission:
+ return true;
+ case MaterialParameter::Shininess:
+ if (params[0] < 0.0f || params[0] > 128.0f)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kMaterialParameterOutOfRange);
+ return false;
+ }
+ return true;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMaterialParameter);
+ return false;
+ }
+}
+
+bool ValidateMaterialSetting(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pname,
+ const GLfloat *params)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+
+ if (face != GL_FRONT_AND_BACK)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMaterialFace);
+ return false;
+ }
+
+ return ValidateMaterialCommon(context, entryPoint, face, pname, params);
+}
+
+bool ValidateMaterialQuery(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pname)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+
+ if (face != GL_FRONT && face != GL_BACK)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMaterialFace);
+ return false;
+ }
+
+ GLfloat validateParams[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+ return ValidateMaterialCommon(context, entryPoint, face, pname, validateParams);
+}
+
+bool ValidateMaterialSingleComponent(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pname,
+ GLfloat param)
+{
+ if (!ValidateMaterialSetting(context, entryPoint, face, pname, &param))
+ {
+ return false;
+ }
+
+ if (GetMaterialParameterCount(pname) > 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMaterialParameter);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateLightModelCommon(const Context *context, angle::EntryPoint entryPoint, GLenum pname)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ switch (pname)
+ {
+ case GL_LIGHT_MODEL_AMBIENT:
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ return true;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidLightModelParameter);
+ return false;
+ }
+}
+
+bool ValidateLightModelSingleComponent(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname)
+{
+ if (!ValidateLightModelCommon(context, entryPoint, pname))
+ {
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ return true;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidLightModelParameter);
+ return false;
+ }
+}
+
+bool ValidateClipPlaneCommon(const Context *context, angle::EntryPoint entryPoint, GLenum plane)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+
+ if (plane < GL_CLIP_PLANE0 || plane >= GL_CLIP_PLANE0 + context->getCaps().maxClipPlanes)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidClipPlane);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFogCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLfloat *params)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+
+ switch (pname)
+ {
+ case GL_FOG_MODE:
+ {
+ GLenum modeParam = static_cast<GLenum>(params[0]);
+ switch (modeParam)
+ {
+ case GL_EXP:
+ case GL_EXP2:
+ case GL_LINEAR:
+ return true;
+ default:
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFogMode);
+ return false;
+ }
+ }
+ case GL_FOG_START:
+ case GL_FOG_END:
+ case GL_FOG_COLOR:
+ break;
+ case GL_FOG_DENSITY:
+ if (params[0] < 0.0f)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFogDensity);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFogParameter);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateTexEnvCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget target,
+ TextureEnvParameter pname,
+ const GLfloat *params)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+
+ switch (target)
+ {
+ case TextureEnvTarget::Env:
+ switch (pname)
+ {
+ case TextureEnvParameter::Mode:
+ {
+ TextureEnvMode mode = FromGLenum<TextureEnvMode>(ConvertToGLenum(params[0]));
+ switch (mode)
+ {
+ case TextureEnvMode::Add:
+ case TextureEnvMode::Blend:
+ case TextureEnvMode::Combine:
+ case TextureEnvMode::Decal:
+ case TextureEnvMode::Modulate:
+ case TextureEnvMode::Replace:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kInvalidTextureEnvMode);
+ return false;
+ }
+ break;
+ }
+ case TextureEnvParameter::CombineRgb:
+ case TextureEnvParameter::CombineAlpha:
+ {
+ TextureCombine combine = FromGLenum<TextureCombine>(ConvertToGLenum(params[0]));
+ switch (combine)
+ {
+ case TextureCombine::Add:
+ case TextureCombine::AddSigned:
+ case TextureCombine::Interpolate:
+ case TextureCombine::Modulate:
+ case TextureCombine::Replace:
+ case TextureCombine::Subtract:
+ break;
+ case TextureCombine::Dot3Rgb:
+ case TextureCombine::Dot3Rgba:
+ if (pname == TextureEnvParameter::CombineAlpha)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kInvalidTextureCombine);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kInvalidTextureCombine);
+ return false;
+ }
+ break;
+ }
+ case TextureEnvParameter::Src0Rgb:
+ case TextureEnvParameter::Src1Rgb:
+ case TextureEnvParameter::Src2Rgb:
+ case TextureEnvParameter::Src0Alpha:
+ case TextureEnvParameter::Src1Alpha:
+ case TextureEnvParameter::Src2Alpha:
+ {
+ TextureSrc combine = FromGLenum<TextureSrc>(ConvertToGLenum(params[0]));
+ switch (combine)
+ {
+ case TextureSrc::Constant:
+ case TextureSrc::Previous:
+ case TextureSrc::PrimaryColor:
+ case TextureSrc::Texture:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kInvalidTextureCombineSrc);
+ return false;
+ }
+ break;
+ }
+ case TextureEnvParameter::Op0Rgb:
+ case TextureEnvParameter::Op1Rgb:
+ case TextureEnvParameter::Op2Rgb:
+ case TextureEnvParameter::Op0Alpha:
+ case TextureEnvParameter::Op1Alpha:
+ case TextureEnvParameter::Op2Alpha:
+ {
+ TextureOp operand = FromGLenum<TextureOp>(ConvertToGLenum(params[0]));
+ switch (operand)
+ {
+ case TextureOp::SrcAlpha:
+ case TextureOp::OneMinusSrcAlpha:
+ break;
+ case TextureOp::SrcColor:
+ case TextureOp::OneMinusSrcColor:
+ if (pname == TextureEnvParameter::Op0Alpha ||
+ pname == TextureEnvParameter::Op1Alpha ||
+ pname == TextureEnvParameter::Op2Alpha)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kInvalidTextureCombine);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kInvalidTextureCombineOp);
+ return false;
+ }
+ break;
+ }
+ case TextureEnvParameter::RgbScale:
+ case TextureEnvParameter::AlphaScale:
+ if (params[0] != 1.0f && params[0] != 2.0f && params[0] != 4.0f)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kInvalidTextureEnvScale);
+ return false;
+ }
+ break;
+ case TextureEnvParameter::Color:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kInvalidTextureEnvParameter);
+ return false;
+ }
+ break;
+ case TextureEnvTarget::PointSprite:
+ if (!context->getExtensions().pointSpriteOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureEnvTarget);
+ return false;
+ }
+ switch (pname)
+ {
+ case TextureEnvParameter::PointCoordReplace:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kInvalidTextureEnvParameter);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureEnvTarget);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateGetTexEnvCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget target,
+ TextureEnvParameter pname)
+{
+ GLfloat validateParams[4] = {};
+ switch (pname)
+ {
+ case TextureEnvParameter::Mode:
+ ConvertPackedEnum(TextureEnvMode::Add, validateParams);
+ break;
+ case TextureEnvParameter::CombineRgb:
+ case TextureEnvParameter::CombineAlpha:
+ ConvertPackedEnum(TextureCombine::Add, validateParams);
+ break;
+ case TextureEnvParameter::Src0Rgb:
+ case TextureEnvParameter::Src1Rgb:
+ case TextureEnvParameter::Src2Rgb:
+ case TextureEnvParameter::Src0Alpha:
+ case TextureEnvParameter::Src1Alpha:
+ case TextureEnvParameter::Src2Alpha:
+ ConvertPackedEnum(TextureSrc::Constant, validateParams);
+ break;
+ case TextureEnvParameter::Op0Rgb:
+ case TextureEnvParameter::Op1Rgb:
+ case TextureEnvParameter::Op2Rgb:
+ case TextureEnvParameter::Op0Alpha:
+ case TextureEnvParameter::Op1Alpha:
+ case TextureEnvParameter::Op2Alpha:
+ ConvertPackedEnum(TextureOp::SrcAlpha, validateParams);
+ break;
+ case TextureEnvParameter::RgbScale:
+ case TextureEnvParameter::AlphaScale:
+ case TextureEnvParameter::PointCoordReplace:
+ validateParams[0] = 1.0f;
+ break;
+ default:
+ break;
+ }
+
+ return ValidateTexEnvCommon(context, entryPoint, target, pname, validateParams);
+}
+
+bool ValidatePointParameterCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ PointParameter pname,
+ const GLfloat *params)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+
+ switch (pname)
+ {
+ case PointParameter::PointSizeMin:
+ case PointParameter::PointSizeMax:
+ case PointParameter::PointFadeThresholdSize:
+ case PointParameter::PointDistanceAttenuation:
+ for (unsigned int i = 0; i < GetPointParameterCount(pname); i++)
+ {
+ if (params[i] < 0.0f)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kInvalidPointParameterValue);
+ return false;
+ }
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPointParameter);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePointSizeCommon(const Context *context, angle::EntryPoint entryPoint, GLfloat size)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+
+ if (size <= 0.0f)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidPointSizeValue);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawTexCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ float width,
+ float height)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+
+ if (width <= 0.0f || height <= 0.0f)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNonPositiveDrawTextureDimension);
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace gl
+
+namespace gl
+{
+
+bool ValidateAlphaFunc(const Context *context,
+ angle::EntryPoint entryPoint,
+ AlphaTestFunc func,
+ GLfloat ref)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return ValidateAlphaFuncCommon(context, entryPoint, func);
+}
+
+bool ValidateAlphaFuncx(const Context *context,
+ angle::EntryPoint entryPoint,
+ AlphaTestFunc func,
+ GLfixed ref)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return ValidateAlphaFuncCommon(context, entryPoint, func);
+}
+
+bool ValidateClearColorx(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed red,
+ GLfixed green,
+ GLfixed blue,
+ GLfixed alpha)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateClearDepthx(const Context *context, angle::EntryPoint entryPoint, GLfixed depth)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateClientActiveTexture(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return ValidateMultitextureUnit(context, entryPoint, texture);
+}
+
+bool ValidateClipPlanef(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum plane,
+ const GLfloat *eqn)
+{
+ return ValidateClipPlaneCommon(context, entryPoint, plane);
+}
+
+bool ValidateClipPlanex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum plane,
+ const GLfixed *equation)
+{
+ return ValidateClipPlaneCommon(context, entryPoint, plane);
+}
+
+bool ValidateColor4f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue,
+ GLfloat alpha)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateColor4ub(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLubyte red,
+ GLubyte green,
+ GLubyte blue,
+ GLubyte alpha)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateColor4x(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed red,
+ GLfixed green,
+ GLfixed blue,
+ GLfixed alpha)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateColorPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint size,
+ VertexAttribType type,
+ GLsizei stride,
+ const void *pointer)
+{
+ return ValidateBuiltinVertexAttributeCommon(context, entryPoint, ClientVertexArrayType::Color,
+ size, type, stride, pointer);
+}
+
+bool ValidateCullFace(const Context *context, angle::EntryPoint entryPoint, GLenum mode)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+bool ValidateDepthRangex(const Context *context, angle::EntryPoint entryPoint, GLfixed n, GLfixed f)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ if (context->isWebGL() && n > f)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDepthRange);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDisableClientState(const Context *context,
+ angle::EntryPoint entryPoint,
+ ClientVertexArrayType arrayType)
+{
+ return ValidateClientStateCommon(context, entryPoint, arrayType);
+}
+
+bool ValidateEnableClientState(const Context *context,
+ angle::EntryPoint entryPoint,
+ ClientVertexArrayType arrayType)
+{
+ return ValidateClientStateCommon(context, entryPoint, arrayType);
+}
+
+bool ValidateFogf(const Context *context, angle::EntryPoint entryPoint, GLenum pname, GLfloat param)
+{
+ return ValidateFogCommon(context, entryPoint, pname, &param);
+}
+
+bool ValidateFogfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLfloat *params)
+{
+ return ValidateFogCommon(context, entryPoint, pname, params);
+}
+
+bool ValidateFogx(const Context *context, angle::EntryPoint entryPoint, GLenum pname, GLfixed param)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ GLfloat asFloat =
+ pname == GL_FOG_MODE ? static_cast<GLfloat>(param) : ConvertFixedToFloat(param);
+ return ValidateFogCommon(context, entryPoint, pname, &asFloat);
+}
+
+bool ValidateFogxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLfixed *params)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ unsigned int paramCount = GetFogParameterCount(pname);
+ GLfloat paramsf[4] = {};
+
+ if (pname == GL_FOG_MODE)
+ {
+ paramsf[0] = static_cast<GLfloat>(params[0]);
+ }
+ else
+ {
+ for (unsigned int i = 0; i < paramCount; i++)
+ {
+ paramsf[i] = ConvertFixedToFloat(params[i]);
+ }
+ }
+
+ return ValidateFogCommon(context, entryPoint, pname, paramsf);
+}
+
+bool ValidateFrustumf(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat l,
+ GLfloat r,
+ GLfloat b,
+ GLfloat t,
+ GLfloat n,
+ GLfloat f)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ if (l == r || b == t || n == f || n <= 0.0f || f <= 0.0f)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProjectionMatrix);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateFrustumx(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed l,
+ GLfixed r,
+ GLfixed b,
+ GLfixed t,
+ GLfixed n,
+ GLfixed f)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ if (l == r || b == t || n == f || n <= 0 || f <= 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProjectionMatrix);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateGetBufferParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ const GLint *params)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+bool ValidateGetClipPlanef(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum plane,
+ const GLfloat *equation)
+{
+ return ValidateClipPlaneCommon(context, entryPoint, plane);
+}
+
+bool ValidateGetClipPlanex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum plane,
+ const GLfixed *equation)
+{
+ return ValidateClipPlaneCommon(context, entryPoint, plane);
+}
+
+bool ValidateGetFixedv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLfixed *params)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ return ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams);
+}
+
+bool ValidateGetLightfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ LightParameter pname,
+ const GLfloat *params)
+{
+ GLfloat validateParams[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ return ValidateLightCommon(context, entryPoint, light, pname, validateParams);
+}
+
+bool ValidateGetLightxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ LightParameter pname,
+ const GLfixed *params)
+{
+ GLfloat validateParams[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ return ValidateLightCommon(context, entryPoint, light, pname, validateParams);
+}
+
+bool ValidateGetMaterialfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pname,
+ const GLfloat *params)
+{
+ return ValidateMaterialQuery(context, entryPoint, face, pname);
+}
+
+bool ValidateGetMaterialxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pname,
+ const GLfixed *params)
+{
+ return ValidateMaterialQuery(context, entryPoint, face, pname);
+}
+
+bool ValidateGetTexEnvfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget target,
+ TextureEnvParameter pname,
+ const GLfloat *params)
+{
+ return ValidateGetTexEnvCommon(context, entryPoint, target, pname);
+}
+
+bool ValidateGetTexEnviv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget target,
+ TextureEnvParameter pname,
+ const GLint *params)
+{
+ return ValidateGetTexEnvCommon(context, entryPoint, target, pname);
+}
+
+bool ValidateGetTexEnvxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget target,
+ TextureEnvParameter pname,
+ const GLfixed *params)
+{
+ return ValidateGetTexEnvCommon(context, entryPoint, target, pname);
+}
+
+bool ValidateGetTexParameterxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ const GLfixed *params)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+
+ if (!ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateLightModelf(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLfloat param)
+{
+ return ValidateLightModelSingleComponent(context, entryPoint, pname);
+}
+
+bool ValidateLightModelfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLfloat *params)
+{
+ return ValidateLightModelCommon(context, entryPoint, pname);
+}
+
+bool ValidateLightModelx(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLfixed param)
+{
+ return ValidateLightModelSingleComponent(context, entryPoint, pname);
+}
+
+bool ValidateLightModelxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLfixed *param)
+{
+ return ValidateLightModelCommon(context, entryPoint, pname);
+}
+
+bool ValidateLightf(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ LightParameter pname,
+ GLfloat param)
+{
+ return ValidateLightSingleComponent(context, entryPoint, light, pname, param);
+}
+
+bool ValidateLightfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ LightParameter pname,
+ const GLfloat *params)
+{
+ return ValidateLightCommon(context, entryPoint, light, pname, params);
+}
+
+bool ValidateLightx(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ LightParameter pname,
+ GLfixed param)
+{
+ return ValidateLightSingleComponent(context, entryPoint, light, pname,
+ ConvertFixedToFloat(param));
+}
+
+bool ValidateLightxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ LightParameter pname,
+ const GLfixed *params)
+{
+ GLfloat paramsf[4];
+ for (unsigned int i = 0; i < GetLightParameterCount(pname); i++)
+ {
+ paramsf[i] = ConvertFixedToFloat(params[i]);
+ }
+
+ return ValidateLightCommon(context, entryPoint, light, pname, paramsf);
+}
+
+bool ValidateLineWidthx(const Context *context, angle::EntryPoint entryPoint, GLfixed width)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ if (width <= 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidWidth);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateLoadIdentity(const Context *context, angle::EntryPoint entryPoint)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateLoadMatrixf(const Context *context, angle::EntryPoint entryPoint, const GLfloat *m)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateLoadMatrixx(const Context *context, angle::EntryPoint entryPoint, const GLfixed *m)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateLogicOp(const Context *context, angle::EntryPoint entryPoint, LogicalOperation opcode)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return ValidateLogicOpCommon(context, entryPoint, opcode);
+}
+
+bool ValidateMaterialf(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pname,
+ GLfloat param)
+{
+ return ValidateMaterialSingleComponent(context, entryPoint, face, pname, param);
+}
+
+bool ValidateMaterialfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pname,
+ const GLfloat *params)
+{
+ return ValidateMaterialSetting(context, entryPoint, face, pname, params);
+}
+
+bool ValidateMaterialx(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pname,
+ GLfixed param)
+{
+ return ValidateMaterialSingleComponent(context, entryPoint, face, pname,
+ ConvertFixedToFloat(param));
+}
+
+bool ValidateMaterialxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pname,
+ const GLfixed *params)
+{
+ GLfloat paramsf[4];
+
+ for (unsigned int i = 0; i < GetMaterialParameterCount(pname); i++)
+ {
+ paramsf[i] = ConvertFixedToFloat(params[i]);
+ }
+
+ return ValidateMaterialSetting(context, entryPoint, face, pname, paramsf);
+}
+
+bool ValidateMatrixMode(const Context *context, angle::EntryPoint entryPoint, MatrixType mode)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ switch (mode)
+ {
+ case MatrixType::Projection:
+ case MatrixType::Modelview:
+ case MatrixType::Texture:
+ return true;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMatrixMode);
+ return false;
+ }
+}
+
+bool ValidateMultMatrixf(const Context *context, angle::EntryPoint entryPoint, const GLfloat *m)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateMultMatrixx(const Context *context, angle::EntryPoint entryPoint, const GLfixed *m)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateMultiTexCoord4f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLfloat s,
+ GLfloat t,
+ GLfloat r,
+ GLfloat q)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return ValidateMultitextureUnit(context, entryPoint, target);
+}
+
+bool ValidateMultiTexCoord4x(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLfixed s,
+ GLfixed t,
+ GLfixed r,
+ GLfixed q)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return ValidateMultitextureUnit(context, entryPoint, target);
+}
+
+bool ValidateNormal3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat nx,
+ GLfloat ny,
+ GLfloat nz)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateNormal3x(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed nx,
+ GLfixed ny,
+ GLfixed nz)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateNormalPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexAttribType type,
+ GLsizei stride,
+ const void *pointer)
+{
+ return ValidateBuiltinVertexAttributeCommon(context, entryPoint, ClientVertexArrayType::Normal,
+ 3, type, stride, pointer);
+}
+
+bool ValidateOrthof(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat l,
+ GLfloat r,
+ GLfloat b,
+ GLfloat t,
+ GLfloat n,
+ GLfloat f)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ // [OpenGL ES 1.1.12] section 2.10.2 page 31:
+ // If l is equal to r, b is equal to t, or n is equal to f, the
+ // error INVALID VALUE results.
+ if (l == r || b == t || n == f)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProjectionMatrix);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateOrthox(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed l,
+ GLfixed r,
+ GLfixed b,
+ GLfixed t,
+ GLfixed n,
+ GLfixed f)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ if (l == r || b == t || n == f)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProjectionMatrix);
+ return false;
+ }
+ return true;
+}
+
+bool ValidatePointParameterf(const Context *context,
+ angle::EntryPoint entryPoint,
+ PointParameter pname,
+ GLfloat param)
+{
+ unsigned int paramCount = GetPointParameterCount(pname);
+ if (paramCount != 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPointParameter);
+ return false;
+ }
+
+ return ValidatePointParameterCommon(context, entryPoint, pname, &param);
+}
+
+bool ValidatePointParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ PointParameter pname,
+ const GLfloat *params)
+{
+ return ValidatePointParameterCommon(context, entryPoint, pname, params);
+}
+
+bool ValidatePointParameterx(const Context *context,
+ angle::EntryPoint entryPoint,
+ PointParameter pname,
+ GLfixed param)
+{
+ unsigned int paramCount = GetPointParameterCount(pname);
+ if (paramCount != 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPointParameter);
+ return false;
+ }
+
+ GLfloat paramf = ConvertFixedToFloat(param);
+ return ValidatePointParameterCommon(context, entryPoint, pname, &paramf);
+}
+
+bool ValidatePointParameterxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ PointParameter pname,
+ const GLfixed *params)
+{
+ GLfloat paramsf[4] = {};
+ for (unsigned int i = 0; i < GetPointParameterCount(pname); i++)
+ {
+ paramsf[i] = ConvertFixedToFloat(params[i]);
+ }
+ return ValidatePointParameterCommon(context, entryPoint, pname, paramsf);
+}
+
+bool ValidatePointSize(const Context *context, angle::EntryPoint entryPoint, GLfloat size)
+{
+ return ValidatePointSizeCommon(context, entryPoint, size);
+}
+
+bool ValidatePointSizex(const Context *context, angle::EntryPoint entryPoint, GLfixed size)
+{
+ return ValidatePointSizeCommon(context, entryPoint, ConvertFixedToFloat(size));
+}
+
+bool ValidatePolygonOffsetx(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed factor,
+ GLfixed units)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidatePopMatrix(const Context *context, angle::EntryPoint entryPoint)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ const auto &stack = context->getState().gles1().currentMatrixStack();
+ if (stack.size() == 1)
+ {
+ context->validationError(entryPoint, GL_STACK_UNDERFLOW, kMatrixStackUnderflow);
+ return false;
+ }
+ return true;
+}
+
+bool ValidatePushMatrix(const Context *context, angle::EntryPoint entryPoint)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ const auto &stack = context->getState().gles1().currentMatrixStack();
+ if (stack.size() == stack.max_size())
+ {
+ context->validationError(entryPoint, GL_STACK_OVERFLOW, kMatrixStackOverflow);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateRotatef(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat angle,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateRotatex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed angle,
+ GLfixed x,
+ GLfixed y,
+ GLfixed z)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateSampleCoveragex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLclampx value,
+ GLboolean invert)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateScalef(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateScalex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed x,
+ GLfixed y,
+ GLfixed z)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateShadeModel(const Context *context, angle::EntryPoint entryPoint, ShadingModel mode)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ switch (mode)
+ {
+ case ShadingModel::Flat:
+ case ShadingModel::Smooth:
+ return true;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShadingModel);
+ return false;
+ }
+}
+
+bool ValidateTexCoordPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint size,
+ VertexAttribType type,
+ GLsizei stride,
+ const void *pointer)
+{
+ return ValidateBuiltinVertexAttributeCommon(
+ context, entryPoint, ClientVertexArrayType::TextureCoord, size, type, stride, pointer);
+}
+
+bool ValidateTexEnvf(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget target,
+ TextureEnvParameter pname,
+ GLfloat param)
+{
+ return ValidateTexEnvCommon(context, entryPoint, target, pname, &param);
+}
+
+bool ValidateTexEnvfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget target,
+ TextureEnvParameter pname,
+ const GLfloat *params)
+{
+ return ValidateTexEnvCommon(context, entryPoint, target, pname, params);
+}
+
+bool ValidateTexEnvi(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget target,
+ TextureEnvParameter pname,
+ GLint param)
+{
+ GLfloat paramf = static_cast<GLfloat>(param);
+ return ValidateTexEnvCommon(context, entryPoint, target, pname, &paramf);
+}
+
+bool ValidateTexEnviv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget target,
+ TextureEnvParameter pname,
+ const GLint *params)
+{
+ GLfloat paramsf[4];
+ for (unsigned int i = 0; i < GetTextureEnvParameterCount(pname); i++)
+ {
+ paramsf[i] = static_cast<GLfloat>(params[i]);
+ }
+ return ValidateTexEnvCommon(context, entryPoint, target, pname, paramsf);
+}
+
+bool ValidateTexEnvx(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget target,
+ TextureEnvParameter pname,
+ GLfixed param)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ GLfloat paramsf[4] = {};
+ ConvertTextureEnvFromFixed(pname, &param, paramsf);
+ return ValidateTexEnvCommon(context, entryPoint, target, pname, paramsf);
+}
+
+bool ValidateTexEnvxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget target,
+ TextureEnvParameter pname,
+ const GLfixed *params)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ GLfloat paramsf[4] = {};
+ ConvertTextureEnvFromFixed(pname, params, paramsf);
+ return ValidateTexEnvCommon(context, entryPoint, target, pname, paramsf);
+}
+
+bool ValidateTexParameterBaseForGLfixed(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLsizei bufSize,
+ bool vectorParams,
+ const GLfixed *params)
+{
+ // Convert GLfixed parameter for GL_TEXTURE_MAX_ANISOTROPY_EXT independently
+ // since it compares against 1 and maxTextureAnisotropy instead of just 0
+ // (other values are fine to leave unconverted since they only check positive or negative or
+ // are used as enums)
+ GLfloat paramValue;
+ if (pname == GL_TEXTURE_MAX_ANISOTROPY_EXT)
+ {
+ paramValue = ConvertFixedToFloat(static_cast<GLfixed>(params[0]));
+ }
+ else
+ {
+ paramValue = static_cast<GLfloat>(params[0]);
+ }
+ return ValidateTexParameterBase(context, entryPoint, target, pname, bufSize, vectorParams,
+ &paramValue);
+}
+
+bool ValidateTexParameterx(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLfixed param)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return ValidateTexParameterBaseForGLfixed(context, entryPoint, target, pname, -1, false,
+ &param);
+}
+
+bool ValidateTexParameterxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ const GLfixed *params)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return ValidateTexParameterBaseForGLfixed(context, entryPoint, target, pname, -1, true, params);
+}
+
+bool ValidateTranslatef(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateTranslatex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed x,
+ GLfixed y,
+ GLfixed z)
+{
+ ANGLE_VALIDATE_IS_GLES1(context, entryPoint);
+ return true;
+}
+
+bool ValidateVertexPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint size,
+ VertexAttribType type,
+ GLsizei stride,
+ const void *pointer)
+{
+ return ValidateBuiltinVertexAttributeCommon(context, entryPoint, ClientVertexArrayType::Vertex,
+ size, type, stride, pointer);
+}
+
+bool ValidateDrawTexfOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat width,
+ GLfloat height)
+{
+ return ValidateDrawTexCommon(context, entryPoint, width, height);
+}
+
+bool ValidateDrawTexfvOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLfloat *coords)
+{
+ return ValidateDrawTexCommon(context, entryPoint, coords[3], coords[4]);
+}
+
+bool ValidateDrawTexiOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint width,
+ GLint height)
+{
+ return ValidateDrawTexCommon(context, entryPoint, static_cast<GLfloat>(width),
+ static_cast<GLfloat>(height));
+}
+
+bool ValidateDrawTexivOES(const Context *context, angle::EntryPoint entryPoint, const GLint *coords)
+{
+ return ValidateDrawTexCommon(context, entryPoint, static_cast<GLfloat>(coords[3]),
+ static_cast<GLfloat>(coords[4]));
+}
+
+bool ValidateDrawTexsOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort x,
+ GLshort y,
+ GLshort z,
+ GLshort width,
+ GLshort height)
+{
+ return ValidateDrawTexCommon(context, entryPoint, static_cast<GLfloat>(width),
+ static_cast<GLfloat>(height));
+}
+
+bool ValidateDrawTexsvOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLshort *coords)
+{
+ return ValidateDrawTexCommon(context, entryPoint, static_cast<GLfloat>(coords[3]),
+ static_cast<GLfloat>(coords[4]));
+}
+
+bool ValidateDrawTexxOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed x,
+ GLfixed y,
+ GLfixed z,
+ GLfixed width,
+ GLfixed height)
+{
+ return ValidateDrawTexCommon(context, entryPoint, ConvertFixedToFloat(width),
+ ConvertFixedToFloat(height));
+}
+
+bool ValidateDrawTexxvOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLfixed *coords)
+{
+ return ValidateDrawTexCommon(context, entryPoint, ConvertFixedToFloat(coords[3]),
+ ConvertFixedToFloat(coords[4]));
+}
+
+bool ValidateCurrentPaletteMatrixOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint matrixpaletteindex)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+bool ValidateLoadPaletteFromModelViewMatrixOES(const Context *context, angle::EntryPoint entryPoint)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+bool ValidateMatrixIndexPointerOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+bool ValidateWeightPointerOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+bool ValidatePointSizePointerOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexAttribType type,
+ GLsizei stride,
+ const void *pointer)
+{
+ return ValidateBuiltinVertexAttributeCommon(
+ context, entryPoint, ClientVertexArrayType::PointSize, 1, type, stride, pointer);
+}
+
+bool ValidateQueryMatrixxOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLfixed *mantissa,
+ const GLint *exponent)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+bool ValidateGenFramebuffersOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const FramebufferID *framebuffers)
+{
+ if (!context->getExtensions().framebufferObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateDeleteFramebuffersOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const FramebufferID *framebuffers)
+{
+ if (!context->getExtensions().framebufferObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateGenRenderbuffersOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const RenderbufferID *renderbuffers)
+{
+ if (!context->getExtensions().framebufferObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateDeleteRenderbuffersOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const RenderbufferID *renderbuffers)
+{
+ if (!context->getExtensions().framebufferObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateBindFramebufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ FramebufferID framebuffer)
+{
+ if (!context->getExtensions().framebufferObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateBindFramebufferBase(context, entryPoint, target, framebuffer);
+}
+
+bool ValidateBindRenderbufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ RenderbufferID renderbuffer)
+{
+ if (!context->getExtensions().framebufferObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateBindRenderbufferBase(context, entryPoint, target, renderbuffer);
+}
+
+bool ValidateCheckFramebufferStatusOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target)
+{
+ if (!context->getExtensions().framebufferObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidFramebufferTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferRenderbufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ GLenum rbtarget,
+ RenderbufferID renderbuffer)
+{
+ if (!context->getExtensions().framebufferObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateFramebufferRenderbufferBase(context, entryPoint, target, attachment, rbtarget,
+ renderbuffer);
+}
+
+bool ValidateFramebufferTexture2DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textarget,
+ TextureID texture,
+ GLint level)
+{
+ if (!context->getExtensions().framebufferObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (level != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFramebufferTextureLevel);
+ return false;
+ }
+
+ if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
+ {
+ return false;
+ }
+
+ if (texture.value != 0)
+ {
+ Texture *tex = context->getTexture(texture);
+ ASSERT(tex);
+
+ const Caps &caps = context->getCaps();
+
+ switch (textarget)
+ {
+ case TextureTarget::_2D:
+ {
+ if (level > log2(caps.max2DTextureSize))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+ if (tex->getType() != TextureType::_2D)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidTextureTarget);
+ return false;
+ }
+ }
+ break;
+
+ case TextureTarget::CubeMapNegativeX:
+ case TextureTarget::CubeMapNegativeY:
+ case TextureTarget::CubeMapNegativeZ:
+ case TextureTarget::CubeMapPositiveX:
+ case TextureTarget::CubeMapPositiveY:
+ case TextureTarget::CubeMapPositiveZ:
+ {
+ if (!context->getExtensions().textureCubeMapOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ if (level > log2(caps.maxCubeMapTextureSize))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+ if (tex->getType() != TextureType::CubeMap)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTextureTargetMismatch);
+ return false;
+ }
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGenerateMipmapOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target)
+{
+ if (!context->getExtensions().framebufferObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGenerateMipmapBase(context, entryPoint, target);
+}
+
+bool ValidateGetFramebufferAttachmentParameterivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ const GLint *params)
+{
+ if (!context->getExtensions().framebufferObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGetFramebufferAttachmentParameterivBase(context, entryPoint, target, attachment,
+ pname, nullptr);
+}
+
+bool ValidateGetRenderbufferParameterivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ const GLint *params)
+{
+ if (!context->getExtensions().framebufferObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGetRenderbufferParameterivBase(context, entryPoint, target, pname, nullptr);
+}
+
+bool ValidateIsFramebufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer)
+{
+ if (!context->getExtensions().framebufferObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateIsRenderbufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ RenderbufferID renderbuffer)
+{
+ if (!context->getExtensions().framebufferObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateRenderbufferStorageOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ if (!context->getExtensions().framebufferObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateRenderbufferStorageParametersBase(context, entryPoint, target, 0, internalformat,
+ width, height);
+}
+
+// GL_OES_texture_cube_map
+
+bool ValidateGetTexGenfvOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLfloat *params)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+bool ValidateGetTexGenivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const int *params)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+bool ValidateGetTexGenxvOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLfixed *params)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+bool ValidateTexGenfvOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLfloat *params)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+bool ValidateTexGenivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLint *param)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+bool ValidateTexGenxvOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLint *param)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+bool ValidateTexGenfOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ GLfloat param)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+bool ValidateTexGeniOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ GLint param)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+bool ValidateTexGenxOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ GLfixed param)
+{
+ UNIMPLEMENTED();
+ return true;
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/validationES1.h b/gfx/angle/checkout/src/libANGLE/validationES1.h
new file mode 100644
index 0000000000..e2e6248400
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES1.h
@@ -0,0 +1,20 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationES1.h:
+// Inlined validation functions for OpenGL ES 1.0 entry points.
+
+#ifndef LIBANGLE_VALIDATION_ES1_H_
+#define LIBANGLE_VALIDATION_ES1_H_
+
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/validationES1_autogen.h"
+
+namespace gl
+{
+// Nothing here yet.
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES1_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationES1_autogen.h b/gfx/angle/checkout/src/libANGLE/validationES1_autogen.h
new file mode 100644
index 0000000000..81f168e573
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES1_autogen.h
@@ -0,0 +1,395 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationES1_autogen.h:
+// Validation functions for the OpenGL ES 1.0 entry points.
+
+#ifndef LIBANGLE_VALIDATION_ES1_AUTOGEN_H_
+#define LIBANGLE_VALIDATION_ES1_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "common/entry_points_enum_autogen.h"
+
+namespace gl
+{
+class Context;
+
+bool ValidateAlphaFunc(const Context *context,
+ angle::EntryPoint entryPoint,
+ AlphaTestFunc funcPacked,
+ GLfloat ref);
+bool ValidateAlphaFuncx(const Context *context,
+ angle::EntryPoint entryPoint,
+ AlphaTestFunc funcPacked,
+ GLfixed ref);
+bool ValidateClearColorx(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed red,
+ GLfixed green,
+ GLfixed blue,
+ GLfixed alpha);
+bool ValidateClearDepthx(const Context *context, angle::EntryPoint entryPoint, GLfixed depth);
+bool ValidateClientActiveTexture(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture);
+bool ValidateClipPlanef(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum p,
+ const GLfloat *eqn);
+bool ValidateClipPlanex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum plane,
+ const GLfixed *equation);
+bool ValidateColor4f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue,
+ GLfloat alpha);
+bool ValidateColor4ub(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLubyte red,
+ GLubyte green,
+ GLubyte blue,
+ GLubyte alpha);
+bool ValidateColor4x(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed red,
+ GLfixed green,
+ GLfixed blue,
+ GLfixed alpha);
+bool ValidateColorPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint size,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer);
+bool ValidateDepthRangex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed n,
+ GLfixed f);
+bool ValidateDisableClientState(const Context *context,
+ angle::EntryPoint entryPoint,
+ ClientVertexArrayType arrayPacked);
+bool ValidateEnableClientState(const Context *context,
+ angle::EntryPoint entryPoint,
+ ClientVertexArrayType arrayPacked);
+bool ValidateFogf(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLfloat param);
+bool ValidateFogfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLfloat *params);
+bool ValidateFogx(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLfixed param);
+bool ValidateFogxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLfixed *param);
+bool ValidateFrustumf(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat l,
+ GLfloat r,
+ GLfloat b,
+ GLfloat t,
+ GLfloat n,
+ GLfloat f);
+bool ValidateFrustumx(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed l,
+ GLfixed r,
+ GLfixed b,
+ GLfixed t,
+ GLfixed n,
+ GLfixed f);
+bool ValidateGetClipPlanef(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum plane,
+ const GLfloat *equation);
+bool ValidateGetClipPlanex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum plane,
+ const GLfixed *equation);
+bool ValidateGetFixedv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLfixed *params);
+bool ValidateGetLightfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ LightParameter pnamePacked,
+ const GLfloat *params);
+bool ValidateGetLightxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ LightParameter pnamePacked,
+ const GLfixed *params);
+bool ValidateGetMaterialfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ const GLfloat *params);
+bool ValidateGetMaterialxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ const GLfixed *params);
+bool ValidateGetTexEnvfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ const GLfloat *params);
+bool ValidateGetTexEnviv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ const GLint *params);
+bool ValidateGetTexEnvxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ const GLfixed *params);
+bool ValidateGetTexParameterxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLfixed *params);
+bool ValidateLightModelf(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLfloat param);
+bool ValidateLightModelfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLfloat *params);
+bool ValidateLightModelx(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLfixed param);
+bool ValidateLightModelxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLfixed *param);
+bool ValidateLightf(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ LightParameter pnamePacked,
+ GLfloat param);
+bool ValidateLightfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ LightParameter pnamePacked,
+ const GLfloat *params);
+bool ValidateLightx(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ LightParameter pnamePacked,
+ GLfixed param);
+bool ValidateLightxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ LightParameter pnamePacked,
+ const GLfixed *params);
+bool ValidateLineWidthx(const Context *context, angle::EntryPoint entryPoint, GLfixed width);
+bool ValidateLoadIdentity(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateLoadMatrixf(const Context *context, angle::EntryPoint entryPoint, const GLfloat *m);
+bool ValidateLoadMatrixx(const Context *context, angle::EntryPoint entryPoint, const GLfixed *m);
+bool ValidateLogicOp(const Context *context,
+ angle::EntryPoint entryPoint,
+ LogicalOperation opcodePacked);
+bool ValidateMaterialf(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ GLfloat param);
+bool ValidateMaterialfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ const GLfloat *params);
+bool ValidateMaterialx(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ GLfixed param);
+bool ValidateMaterialxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ MaterialParameter pnamePacked,
+ const GLfixed *param);
+bool ValidateMatrixMode(const Context *context,
+ angle::EntryPoint entryPoint,
+ MatrixType modePacked);
+bool ValidateMultMatrixf(const Context *context, angle::EntryPoint entryPoint, const GLfloat *m);
+bool ValidateMultMatrixx(const Context *context, angle::EntryPoint entryPoint, const GLfixed *m);
+bool ValidateMultiTexCoord4f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLfloat s,
+ GLfloat t,
+ GLfloat r,
+ GLfloat q);
+bool ValidateMultiTexCoord4x(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLfixed s,
+ GLfixed t,
+ GLfixed r,
+ GLfixed q);
+bool ValidateNormal3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat nx,
+ GLfloat ny,
+ GLfloat nz);
+bool ValidateNormal3x(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed nx,
+ GLfixed ny,
+ GLfixed nz);
+bool ValidateNormalPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer);
+bool ValidateOrthof(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat l,
+ GLfloat r,
+ GLfloat b,
+ GLfloat t,
+ GLfloat n,
+ GLfloat f);
+bool ValidateOrthox(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed l,
+ GLfixed r,
+ GLfixed b,
+ GLfixed t,
+ GLfixed n,
+ GLfixed f);
+bool ValidatePointParameterf(const Context *context,
+ angle::EntryPoint entryPoint,
+ PointParameter pnamePacked,
+ GLfloat param);
+bool ValidatePointParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ PointParameter pnamePacked,
+ const GLfloat *params);
+bool ValidatePointParameterx(const Context *context,
+ angle::EntryPoint entryPoint,
+ PointParameter pnamePacked,
+ GLfixed param);
+bool ValidatePointParameterxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ PointParameter pnamePacked,
+ const GLfixed *params);
+bool ValidatePointSize(const Context *context, angle::EntryPoint entryPoint, GLfloat size);
+bool ValidatePointSizex(const Context *context, angle::EntryPoint entryPoint, GLfixed size);
+bool ValidatePolygonOffsetx(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed factor,
+ GLfixed units);
+bool ValidatePopMatrix(const Context *context, angle::EntryPoint entryPoint);
+bool ValidatePushMatrix(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateRotatef(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat angle,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z);
+bool ValidateRotatex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed angle,
+ GLfixed x,
+ GLfixed y,
+ GLfixed z);
+bool ValidateSampleCoveragex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLclampx value,
+ GLboolean invert);
+bool ValidateScalef(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z);
+bool ValidateScalex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed x,
+ GLfixed y,
+ GLfixed z);
+bool ValidateShadeModel(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShadingModel modePacked);
+bool ValidateTexCoordPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint size,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer);
+bool ValidateTexEnvf(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ GLfloat param);
+bool ValidateTexEnvfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ const GLfloat *params);
+bool ValidateTexEnvi(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ GLint param);
+bool ValidateTexEnviv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ const GLint *params);
+bool ValidateTexEnvx(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ GLfixed param);
+bool ValidateTexEnvxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureEnvTarget targetPacked,
+ TextureEnvParameter pnamePacked,
+ const GLfixed *params);
+bool ValidateTexParameterx(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ GLfixed param);
+bool ValidateTexParameterxv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLfixed *params);
+bool ValidateTranslatef(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z);
+bool ValidateTranslatex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed x,
+ GLfixed y,
+ GLfixed z);
+bool ValidateVertexPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint size,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer);
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES1_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationES2.cpp b/gfx/angle/checkout/src/libANGLE/validationES2.cpp
new file mode 100644
index 0000000000..00f5fc5502
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES2.cpp
@@ -0,0 +1,6544 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
+
+#include "libANGLE/validationES2_autogen.h"
+
+#include <cstdint>
+
+#include "common/mathutil.h"
+#include "common/string_utils.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/MemoryObject.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES2.h"
+#include "libANGLE/validationES3_autogen.h"
+
+namespace gl
+{
+using namespace err;
+
+namespace
+{
+
+bool IsPartialBlit(const Context *context,
+ const FramebufferAttachment *readBuffer,
+ const FramebufferAttachment *writeBuffer,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1)
+{
+ const Extents &writeSize = writeBuffer->getSize();
+ const Extents &readSize = readBuffer->getSize();
+
+ if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
+ dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
+ {
+ return true;
+ }
+
+ if (context->getState().isScissorTestEnabled())
+ {
+ const Rectangle &scissor = context->getState().getScissor();
+ return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
+ scissor.height < writeSize.height;
+ }
+
+ return false;
+}
+
+bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
+{
+ // Table 1.1 from the CHROMIUM_copy_texture spec
+ switch (GetUnsizedFormat(internalFormat))
+ {
+ case GL_RED:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGB:
+ case GL_RGBA:
+ case GL_RGB8:
+ case GL_RGBA8:
+ case GL_BGRA_EXT:
+ case GL_BGRA8_EXT:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)
+{
+ return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
+}
+
+bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)
+{
+ // Table 1.0 from the CHROMIUM_copy_texture spec
+ switch (internalFormat)
+ {
+ case GL_ALPHA:
+ case GL_BGRA8_EXT:
+ case GL_BGRA_EXT:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_R11F_G11F_B10F:
+ case GL_R16F:
+ case GL_R32F:
+ case GL_R8:
+ case GL_R8UI:
+ case GL_RG16F:
+ case GL_RG32F:
+ case GL_RG8:
+ case GL_RG8UI:
+ case GL_RGB:
+ case GL_RGB10_A2:
+ case GL_RGB16F:
+ case GL_RGB32F:
+ case GL_RGB565:
+ case GL_RGB5_A1:
+ case GL_RGB8:
+ case GL_RGB8UI:
+ case GL_RGB9_E5:
+ case GL_RGBA:
+ case GL_RGBA16F:
+ case GL_RGBA32F:
+ case GL_RGBA4:
+ case GL_RGBA8:
+ case GL_RGBA8UI:
+ case GL_RGBX8_ANGLE:
+ case GL_SRGB8:
+ case GL_SRGB8_ALPHA8:
+ case GL_SRGB_ALPHA_EXT:
+ case GL_SRGB_EXT:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
+{
+ return IsValidCopyTextureDestinationInternalFormatEnum(internalFormat);
+}
+
+bool IsValidCopyTextureDestinationFormatType(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint internalFormat,
+ GLenum type)
+{
+ if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
+ internalFormat);
+ return false;
+ }
+
+ if (!ValidES3FormatCombination(GetUnsizedFormat(internalFormat), type, internalFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
+ return false;
+ }
+
+ const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
+ if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
+ internalFormat);
+ return false;
+ }
+
+ return true;
+}
+
+bool IsValidCopyTextureDestinationTargetEnum(const Context *context, TextureTarget target)
+{
+ switch (target)
+ {
+ case TextureTarget::_2D:
+ case TextureTarget::CubeMapNegativeX:
+ case TextureTarget::CubeMapNegativeY:
+ case TextureTarget::CubeMapNegativeZ:
+ case TextureTarget::CubeMapPositiveX:
+ case TextureTarget::CubeMapPositiveY:
+ case TextureTarget::CubeMapPositiveZ:
+ return true;
+
+ case TextureTarget::Rectangle:
+ return context->getExtensions().textureRectangleANGLE;
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidCopyTextureDestinationTarget(const Context *context,
+ TextureType textureType,
+ TextureTarget target)
+{
+ return TextureTargetToType(target) == textureType;
+}
+
+bool IsValidCopyTextureSourceTarget(const Context *context, TextureType type)
+{
+ switch (type)
+ {
+ case TextureType::_2D:
+ return true;
+ case TextureType::Rectangle:
+ return context->getExtensions().textureRectangleANGLE;
+ case TextureType::External:
+ return context->getExtensions().EGLImageExternalOES;
+ case TextureType::VideoImage:
+ return context->getExtensions().videoTextureWEBGL;
+ default:
+ return false;
+ }
+}
+
+bool IsValidCopyTextureSourceLevel(const Context *context, TextureType type, GLint level)
+{
+ if (!ValidMipLevel(context, type, level))
+ {
+ return false;
+ }
+
+ if (level > 0 && context->getClientVersion() < ES_3_0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool IsValidCopyTextureDestinationLevel(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType type,
+ GLint level,
+ GLsizei width,
+ GLsizei height,
+ bool isSubImage)
+{
+ if (!ValidMipLevel(context, type, level))
+ {
+ return false;
+ }
+
+ if (!ValidImageSizeParameters(context, entryPoint, type, level, width, height, 1, isSubImage))
+ {
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ switch (type)
+ {
+ case TextureType::_2D:
+ return width <= (caps.max2DTextureSize >> level) &&
+ height <= (caps.max2DTextureSize >> level);
+ case TextureType::Rectangle:
+ ASSERT(level == 0);
+ return width <= (caps.max2DTextureSize >> level) &&
+ height <= (caps.max2DTextureSize >> level);
+
+ case TextureType::CubeMap:
+ return width <= (caps.maxCubeMapTextureSize >> level) &&
+ height <= (caps.maxCubeMapTextureSize >> level);
+ default:
+ return true;
+ }
+}
+
+bool IsValidStencilFunc(GLenum func)
+{
+ switch (func)
+ {
+ case GL_NEVER:
+ case GL_ALWAYS:
+ case GL_LESS:
+ case GL_LEQUAL:
+ case GL_EQUAL:
+ case GL_GEQUAL:
+ case GL_GREATER:
+ case GL_NOTEQUAL:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidStencilFace(GLenum face)
+{
+ switch (face)
+ {
+ case GL_FRONT:
+ case GL_BACK:
+ case GL_FRONT_AND_BACK:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidStencilOp(GLenum op)
+{
+ switch (op)
+ {
+ case GL_ZERO:
+ case GL_KEEP:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+ case GL_INCR_WRAP:
+ case GL_DECR_WRAP:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static inline bool Valid1to4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
+{
+ return (context->getExtensions().textureFloatOES &&
+ (format == GL_RGBA32F || format == GL_RGB32F || format == GL_RG32F ||
+ format == GL_R32F)) ||
+ (context->getExtensions().textureHalfFloatOES &&
+ (format == GL_RGBA16F || format == GL_RGB16F || format == GL_RG16F ||
+ format == GL_R16F));
+}
+
+static inline bool Valid2to4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
+{
+ return (context->getExtensions().textureFloatOES &&
+ (format == GL_RGBA32F || format == GL_RGB32F || format == GL_RG32F)) ||
+ (context->getExtensions().textureHalfFloatOES &&
+ (format == GL_RGBA16F || format == GL_RGB16F || format == GL_RG16F));
+}
+
+static inline bool Valid3to4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
+{
+ return (context->getExtensions().textureFloatOES &&
+ (format == GL_RGBA32F || format == GL_RGB32F)) ||
+ (context->getExtensions().textureHalfFloatOES &&
+ (format == GL_RGBA16F || format == GL_RGB16F));
+}
+
+static inline bool Valid4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
+{
+ return (context->getExtensions().textureFloatOES && format == GL_RGBA32F) ||
+ (context->getExtensions().textureHalfFloatOES && format == GL_RGBA16F);
+}
+
+bool ValidateES2CopyTexImageParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ if (!ValidTexture2DDestinationTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ TextureType texType = TextureTargetToType(target);
+ if (!ValidImageSizeParameters(context, entryPoint, texType, level, width, height, 1,
+ isSubImage))
+ {
+ // Error is already handled.
+ return false;
+ }
+
+ Format textureFormat = Format::Invalid();
+ if (!ValidateCopyTexImageParametersBase(context, entryPoint, target, level, internalformat,
+ isSubImage, xoffset, yoffset, 0, x, y, width, height,
+ border, &textureFormat))
+ {
+ return false;
+ }
+
+ ASSERT(textureFormat.valid() || !isSubImage);
+
+ const Framebuffer *framebuffer = context->getState().getReadFramebuffer();
+ GLenum colorbufferFormat =
+ framebuffer->getReadColorAttachment()->getFormat().info->sizedInternalFormat;
+ const auto &formatInfo = *textureFormat.info;
+
+ // ValidateCopyTexImageParametersBase rejects compressed formats with GL_INVALID_OPERATION.
+ ASSERT(!formatInfo.compressed);
+ ASSERT(!GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE).compressed);
+
+ // ValidateCopyTexImageParametersBase rejects depth formats with GL_INVALID_OPERATION.
+ ASSERT(!formatInfo.depthBits);
+ ASSERT(!GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE).depthBits);
+
+ // [OpenGL ES 2.0.24] table 3.9
+ if (isSubImage)
+ {
+ switch (formatInfo.format)
+ {
+ case GL_ALPHA:
+ if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
+ colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
+ !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+ break;
+ case GL_LUMINANCE:
+ if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
+ colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+ colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX &&
+ colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
+ !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+ break;
+ case GL_RED_EXT:
+ if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
+ colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+ colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
+ colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
+ colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX &&
+ colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
+ !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+ break;
+ case GL_RG_EXT:
+ if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
+ colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
+ colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
+ colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX &&
+ colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
+ !Valid2to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+ break;
+ case GL_RGB:
+ if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+ colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
+ colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX &&
+ colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
+ !Valid3to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGBA:
+ if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
+ colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
+ !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+
+ if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloatOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+ }
+ else
+ {
+ switch (internalformat)
+ {
+ case GL_ALPHA:
+ if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
+ colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
+ colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
+ !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+ break;
+ case GL_LUMINANCE:
+ case GL_RED_EXT:
+ if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
+ colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+ colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX &&
+ colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
+ !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+ break;
+ case GL_RG_EXT:
+ if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
+ colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
+ colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
+ colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
+ colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
+ !Valid2to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+ break;
+ case GL_RGB:
+ if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
+ colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX &&
+ colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
+ !Valid3to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGBA:
+ if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
+ colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX && colorbufferFormat != GL_RGBA16F &&
+ !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+ break;
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ internalformat);
+ return false;
+ }
+ }
+
+ // If width or height is zero, it is a no-op. Return false without setting an error.
+ return (width > 0 && height > 0);
+}
+
+bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
+{
+ switch (cap)
+ {
+ // EXT_multisample_compatibility
+ case GL_MULTISAMPLE_EXT:
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ return context->getExtensions().multisampleCompatibilityEXT;
+
+ case GL_CULL_FACE:
+ case GL_POLYGON_OFFSET_FILL:
+ case GL_SAMPLE_ALPHA_TO_COVERAGE:
+ case GL_SAMPLE_COVERAGE:
+ case GL_SCISSOR_TEST:
+ case GL_STENCIL_TEST:
+ case GL_DEPTH_TEST:
+ case GL_BLEND:
+ case GL_DITHER:
+ return true;
+
+ case GL_PRIMITIVE_RESTART_FIXED_INDEX:
+ case GL_RASTERIZER_DISCARD:
+ return (context->getClientMajorVersion() >= 3);
+
+ case GL_DEBUG_OUTPUT_SYNCHRONOUS:
+ case GL_DEBUG_OUTPUT:
+ return context->getExtensions().debugKHR;
+
+ case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
+ return queryOnly && context->getExtensions().bindGeneratesResourceCHROMIUM;
+
+ case GL_CLIENT_ARRAYS_ANGLE:
+ return queryOnly && context->getExtensions().clientArraysANGLE;
+
+ case GL_FRAMEBUFFER_SRGB_EXT:
+ return context->getExtensions().sRGBWriteControlEXT;
+
+ case GL_SAMPLE_MASK:
+ return context->getClientVersion() >= Version(3, 1);
+
+ case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
+ return queryOnly && context->getExtensions().robustResourceInitializationANGLE;
+
+ case GL_TEXTURE_RECTANGLE_ANGLE:
+ return context->isWebGL();
+
+ // GL_APPLE_clip_distance/GL_EXT_clip_cull_distance
+ case GL_CLIP_DISTANCE0_EXT:
+ case GL_CLIP_DISTANCE1_EXT:
+ case GL_CLIP_DISTANCE2_EXT:
+ case GL_CLIP_DISTANCE3_EXT:
+ case GL_CLIP_DISTANCE4_EXT:
+ case GL_CLIP_DISTANCE5_EXT:
+ case GL_CLIP_DISTANCE6_EXT:
+ case GL_CLIP_DISTANCE7_EXT:
+ if (context->getExtensions().clipDistanceAPPLE ||
+ context->getExtensions().clipCullDistanceEXT)
+ {
+ return true;
+ }
+ break;
+ case GL_SAMPLE_SHADING:
+ return context->getExtensions().sampleShadingOES;
+ case GL_SHADING_RATE_PRESERVE_ASPECT_RATIO_QCOM:
+ return context->getExtensions().shadingRateQCOM;
+
+ // COLOR_LOGIC_OP is in GLES1, but exposed through an ANGLE extension.
+ case GL_COLOR_LOGIC_OP:
+ return context->getClientVersion() < Version(2, 0) ||
+ context->getExtensions().logicOpANGLE;
+
+ default:
+ break;
+ }
+
+ // GLES1 emulation: GLES1-specific caps after this point
+ if (context->getClientVersion().major != 1)
+ {
+ return false;
+ }
+
+ switch (cap)
+ {
+ case GL_ALPHA_TEST:
+ case GL_VERTEX_ARRAY:
+ case GL_NORMAL_ARRAY:
+ case GL_COLOR_ARRAY:
+ case GL_TEXTURE_COORD_ARRAY:
+ case GL_TEXTURE_2D:
+ case GL_LIGHTING:
+ case GL_LIGHT0:
+ case GL_LIGHT1:
+ case GL_LIGHT2:
+ case GL_LIGHT3:
+ case GL_LIGHT4:
+ case GL_LIGHT5:
+ case GL_LIGHT6:
+ case GL_LIGHT7:
+ case GL_NORMALIZE:
+ case GL_RESCALE_NORMAL:
+ case GL_COLOR_MATERIAL:
+ case GL_CLIP_PLANE0:
+ case GL_CLIP_PLANE1:
+ case GL_CLIP_PLANE2:
+ case GL_CLIP_PLANE3:
+ case GL_CLIP_PLANE4:
+ case GL_CLIP_PLANE5:
+ case GL_FOG:
+ case GL_POINT_SMOOTH:
+ case GL_LINE_SMOOTH:
+ return context->getClientVersion() < Version(2, 0);
+ case GL_POINT_SIZE_ARRAY_OES:
+ return context->getClientVersion() < Version(2, 0) &&
+ context->getExtensions().pointSizeArrayOES;
+ case GL_TEXTURE_CUBE_MAP:
+ return context->getClientVersion() < Version(2, 0) &&
+ context->getExtensions().textureCubeMapOES;
+ case GL_POINT_SPRITE_OES:
+ return context->getClientVersion() < Version(2, 0) &&
+ context->getExtensions().pointSpriteOES;
+ default:
+ return false;
+ }
+}
+
+// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
+// 3.1.
+bool IsValidESSLCharacter(unsigned char c)
+{
+ // Printing characters are valid except " $ ` @ \ ' DEL.
+ if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
+ c != '\'')
+ {
+ return true;
+ }
+
+ // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
+ if (c >= 9 && c <= 13)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+bool IsValidESSLString(const char *str, size_t len)
+{
+ for (size_t i = 0; i < len; i++)
+ {
+ if (!IsValidESSLCharacter(str[i]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateWebGLNamePrefix(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLchar *name)
+{
+ ASSERT(context->isWebGL());
+
+ // WebGL 1.0 [Section 6.16] GLSL Constructs
+ // Identifiers starting with "webgl_" and "_webgl_" are reserved for use by WebGL.
+ if (strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kWebglBindAttribLocationReservedPrefix);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateWebGLNameLength(const Context *context, angle::EntryPoint entryPoint, size_t length)
+{
+ ASSERT(context->isWebGL());
+
+ if (context->isWebGL1() && length > 256)
+ {
+ // WebGL 1.0 [Section 6.21] Maxmimum Uniform and Attribute Location Lengths
+ // WebGL imposes a limit of 256 characters on the lengths of uniform and attribute
+ // locations.
+ context->validationError(entryPoint, GL_INVALID_VALUE, kWebglNameLengthLimitExceeded);
+
+ return false;
+ }
+ else if (length > 1024)
+ {
+ // WebGL 2.0 [Section 4.3.2] WebGL 2.0 imposes a limit of 1024 characters on the lengths of
+ // uniform and attribute locations.
+ context->validationError(entryPoint, GL_INVALID_VALUE, kWebgl2NameLengthLimitExceeded);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidBlendFunc(const Context *context, GLenum val)
+{
+ const Extensions &ext = context->getExtensions();
+
+ // these are always valid for src and dst.
+ switch (val)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ return true;
+
+ // EXT_blend_func_extended.
+ case GL_SRC1_COLOR_EXT:
+ case GL_SRC1_ALPHA_EXT:
+ case GL_ONE_MINUS_SRC1_COLOR_EXT:
+ case GL_ONE_MINUS_SRC1_ALPHA_EXT:
+ case GL_SRC_ALPHA_SATURATE_EXT:
+ return ext.blendFuncExtendedEXT;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidSrcBlendFunc(const Context *context, GLenum val)
+{
+ if (ValidBlendFunc(context, val))
+ return true;
+
+ if (val == GL_SRC_ALPHA_SATURATE)
+ return true;
+
+ return false;
+}
+
+bool ValidDstBlendFunc(const Context *context, GLenum val)
+{
+ if (ValidBlendFunc(context, val))
+ return true;
+
+ if (val == GL_SRC_ALPHA_SATURATE)
+ {
+ if (context->getClientMajorVersion() >= 3)
+ return true;
+ }
+
+ return false;
+}
+
+bool ValidateES2TexImageParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isCompressed,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei imageSize,
+ const void *pixels)
+{
+ if (!ValidTexture2DDestinationTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ return ValidateES2TexImageParametersBase(context, entryPoint, target, level, internalformat,
+ isCompressed, isSubImage, xoffset, yoffset, width,
+ height, border, format, type, imageSize, pixels);
+}
+
+} // anonymous namespace
+
+bool ValidateES2TexImageParametersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isCompressed,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei imageSize,
+ const void *pixels)
+{
+
+ TextureType texType = TextureTargetToType(target);
+ if (!ValidImageSizeParameters(context, entryPoint, texType, level, width, height, 1,
+ isSubImage))
+ {
+ // Error already handled.
+ return false;
+ }
+
+ if (!ValidMipLevel(context, texType, level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+
+ if ((xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width) ||
+ (yoffset < 0 || std::numeric_limits<GLsizei>::max() - yoffset < height))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+
+ switch (texType)
+ {
+ case TextureType::_2D:
+ case TextureType::External:
+ case TextureType::VideoImage:
+ if (width > (caps.max2DTextureSize >> level) ||
+ height > (caps.max2DTextureSize >> level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ break;
+
+ case TextureType::Rectangle:
+ ASSERT(level == 0);
+ if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ if (isCompressed)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kRectangleTextureCompressed);
+ return false;
+ }
+ break;
+
+ case TextureType::CubeMap:
+ if (!isSubImage && width != height)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kCubemapFacesEqualDimensions);
+ return false;
+ }
+
+ if (width > (caps.maxCubeMapTextureSize >> level) ||
+ height > (caps.maxCubeMapTextureSize >> level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ Texture *texture = context->getTextureByType(texType);
+ if (!texture)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound);
+ return false;
+ }
+
+ // Verify zero border
+ if (border != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBorder);
+ return false;
+ }
+
+ bool nonEqualFormatsAllowed = false;
+
+ if (isCompressed)
+ {
+ GLenum actualInternalFormat =
+ isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
+ : internalformat;
+
+ const InternalFormat &internalFormatInfo = GetSizedInternalFormatInfo(actualInternalFormat);
+
+ if (!internalFormatInfo.compressed && !internalFormatInfo.paletted)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kInvalidInternalFormat,
+ internalformat);
+ return false;
+ }
+
+ if (!internalFormatInfo.textureSupport(context->getClientVersion(),
+ context->getExtensions()))
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kInvalidInternalFormat,
+ internalformat);
+ return false;
+ }
+
+ if (isSubImage)
+ {
+ // From OpenGL ES Version 1.1.12, section 3.7.4 Compressed Paletted
+ // Textures:
+ //
+ // Subimages may not be specified for compressed paletted textures.
+ // Calling CompressedTexSubImage2D with any of the PALETTE*
+ // arguments in table 3.11 will generate an INVALID OPERATION error.
+ if (internalFormatInfo.paletted)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
+ internalformat);
+ return false;
+ }
+
+ // From the OES_compressed_ETC1_RGB8_texture spec:
+ //
+ // INVALID_OPERATION is generated by CompressedTexSubImage2D, TexSubImage2D, or
+ // CopyTexSubImage2D if the texture image <level> bound to <target> has internal format
+ // ETC1_RGB8_OES.
+ //
+ // This is relaxed if GL_EXT_compressed_ETC1_RGB8_sub_texture is supported.
+ if (IsETC1Format(actualInternalFormat) &&
+ !context->getExtensions().compressedETC1RGB8SubTextureEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
+ internalformat);
+ return false;
+ }
+
+ if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, 0,
+ width, height, 1, texture->getWidth(target, level),
+ texture->getHeight(target, level),
+ texture->getDepth(target, level)))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidCompressedImageSize);
+ return false;
+ }
+
+ if (format != actualInternalFormat)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+ }
+ else
+ {
+ if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height, 1))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidCompressedImageSize);
+ return false;
+ }
+ }
+ }
+ else
+ {
+ // validate <type> by itself (used as secondary key below)
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT:
+ case GL_UNSIGNED_INT:
+ case GL_UNSIGNED_INT_24_8_OES:
+ case GL_HALF_FLOAT_OES:
+ case GL_FLOAT:
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
+ if (!context->getExtensions().textureType2101010REVEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, type);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
+ return false;
+ }
+
+ // validate <format> + <type> combinations
+ // - invalid <format> -> sets INVALID_ENUM
+ // - invalid <format>+<type> combination -> sets INVALID_OPERATION
+ switch (format)
+ {
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+ case GL_RED:
+ case GL_RG:
+ if (!context->getExtensions().textureRgEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ format);
+ return false;
+ }
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ case GL_FLOAT:
+ if (!context->getExtensions().textureFloatOES)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM,
+ kEnumNotSupported, type);
+ return false;
+ }
+ break;
+ case GL_HALF_FLOAT_OES:
+ if (!context->getExtensions().textureFloatOES &&
+ !context->getExtensions().textureHalfFloatOES)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM,
+ kEnumNotSupported, type);
+ return false;
+ }
+ break;
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ if (!context->getExtensions().textureNorm16EXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM,
+ kEnumNotSupported, type);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+ case GL_RGB:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
+ case GL_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ break;
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ if (!context->getExtensions().textureNorm16EXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+ case GL_RGBA:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
+ break;
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ if (!context->getExtensions().textureNorm16EXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+ case GL_BGRA_EXT:
+ if (!context->getExtensions().textureFormatBGRA8888EXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ format);
+ return false;
+ }
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+ case GL_SRGB_EXT:
+ case GL_SRGB_ALPHA_EXT:
+ if (!context->getExtensions().sRGBEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ format);
+ return false;
+ }
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+ case GL_DEPTH_COMPONENT:
+ switch (type)
+ {
+ case GL_UNSIGNED_SHORT:
+ case GL_UNSIGNED_INT:
+ break;
+ case GL_FLOAT:
+ if (!context->getExtensions().depthBufferFloat2NV)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+ case GL_DEPTH_STENCIL_OES:
+ switch (type)
+ {
+ case GL_UNSIGNED_INT_24_8_OES:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+ case GL_STENCIL_INDEX:
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, format);
+ return false;
+ }
+
+ switch (format)
+ {
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL_OES:
+ if (!context->getExtensions().depthTextureANGLE &&
+ !((context->getExtensions().packedDepthStencilOES ||
+ context->getExtensions().depthTextureCubeMapOES) &&
+ context->getExtensions().depthTextureOES))
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ format);
+ return false;
+ }
+
+ switch (target)
+ {
+ case TextureTarget::_2D:
+ break;
+ case TextureTarget::CubeMapNegativeX:
+ case TextureTarget::CubeMapNegativeY:
+ case TextureTarget::CubeMapNegativeZ:
+ case TextureTarget::CubeMapPositiveX:
+ case TextureTarget::CubeMapPositiveY:
+ case TextureTarget::CubeMapPositiveZ:
+ if (!context->getExtensions().depthTextureCubeMapOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTargetAndFormat);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTargetAndFormat);
+ return false;
+ }
+
+ // OES_depth_texture supports loading depth data and multiple levels,
+ // but ANGLE_depth_texture does not
+ if (!context->getExtensions().depthTextureOES)
+ {
+ if (pixels != nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kPixelDataNotNull);
+ return false;
+ }
+ if (level != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kLevelNotZero);
+ return false;
+ }
+ }
+ break;
+ case GL_STENCIL_INDEX:
+ if (!context->getExtensions().textureStencil8OES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+
+ switch (target)
+ {
+ case TextureTarget::_2D:
+ case TextureTarget::_2DArray:
+ case TextureTarget::CubeMapNegativeX:
+ case TextureTarget::CubeMapNegativeY:
+ case TextureTarget::CubeMapNegativeZ:
+ case TextureTarget::CubeMapPositiveX:
+ case TextureTarget::CubeMapPositiveY:
+ case TextureTarget::CubeMapPositiveZ:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTargetAndFormat);
+ return false;
+ }
+
+ if (internalformat != GL_STENCIL_INDEX8)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTargetAndFormat);
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!isSubImage)
+ {
+ switch (internalformat)
+ {
+ // Core ES 2.0 formats
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGB:
+ case GL_RGBA:
+ break;
+
+ case GL_RGBA32F:
+ if (!context->getExtensions().colorBufferFloatRgbaCHROMIUM)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+
+ nonEqualFormatsAllowed = true;
+
+ if (type != GL_FLOAT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ if (format != GL_RGBA)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+
+ case GL_RGB32F:
+ if (!context->getExtensions().colorBufferFloatRgbCHROMIUM)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+
+ nonEqualFormatsAllowed = true;
+
+ if (type != GL_FLOAT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ if (format != GL_RGB)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+ break;
+
+ case GL_BGRA_EXT:
+ if (!context->getExtensions().textureFormatBGRA8888EXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+ break;
+
+ case GL_DEPTH_COMPONENT:
+ if (!(context->getExtensions().depthTextureAny()))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+ break;
+
+ case GL_DEPTH_STENCIL:
+ if (!(context->getExtensions().depthTextureANGLE ||
+ context->getExtensions().packedDepthStencilOES ||
+ context->getExtensions().depthTextureCubeMapOES))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+ break;
+
+ case GL_STENCIL_INDEX8:
+ if (!context->getExtensions().textureStencil8OES)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+ break;
+
+ case GL_RED:
+ case GL_RG:
+ if (!context->getExtensions().textureRgEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+ break;
+
+ case GL_SRGB_EXT:
+ case GL_SRGB_ALPHA_EXT:
+ if (!context->getExtensions().sRGBEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ internalformat);
+ return false;
+ }
+ break;
+
+ case GL_RGB10_A2_EXT:
+ if (!context->getExtensions().textureType2101010REVEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ internalformat);
+ return false;
+ }
+
+ if (type != GL_UNSIGNED_INT_2_10_10_10_REV_EXT || format != GL_RGBA)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMismatchedTypeAndFormat);
+ return false;
+ }
+
+ nonEqualFormatsAllowed = true;
+
+ break;
+
+ case GL_RGB5_A1:
+ if (context->getExtensions().textureType2101010REVEXT &&
+ type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT && format == GL_RGBA)
+ {
+ nonEqualFormatsAllowed = true;
+ }
+
+ break;
+
+ case GL_RGBX8_ANGLE:
+ if (context->getExtensions().rgbxInternalFormatANGLE &&
+ type == GL_UNSIGNED_BYTE && format == GL_RGB)
+ {
+ nonEqualFormatsAllowed = true;
+ }
+
+ break;
+
+ case GL_R16_EXT:
+ case GL_RG16_EXT:
+ case GL_RGB16_EXT:
+ case GL_RGBA16_EXT:
+ case GL_R16_SNORM_EXT:
+ case GL_RG16_SNORM_EXT:
+ case GL_RGB16_SNORM_EXT:
+ case GL_RGBA16_SNORM_EXT:
+ if (!context->getExtensions().textureNorm16EXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ internalformat);
+ return false;
+ }
+ break;
+ default:
+ // Compressed formats are not valid internal formats for glTexImage*D
+ context->validationErrorF(entryPoint, GL_INVALID_VALUE, kInvalidInternalFormat,
+ internalformat);
+ return false;
+ }
+ }
+
+ if (type == GL_FLOAT)
+ {
+ if (!context->getExtensions().textureFloatOES)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, type);
+ return false;
+ }
+ }
+ else if (type == GL_HALF_FLOAT_OES)
+ {
+ if (!context->getExtensions().textureHalfFloatOES)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, type);
+ return false;
+ }
+ }
+ }
+
+ if (isSubImage)
+ {
+ const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
+ if (textureInternalFormat.internalFormat == GL_NONE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureLevel);
+ return false;
+ }
+
+ if (format != textureInternalFormat.format)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, err::kTextureFormatMismatch);
+ return false;
+ }
+
+ if (context->isWebGL())
+ {
+ if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
+ textureInternalFormat.sizedInternalFormat)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureTypeMismatch);
+ return false;
+ }
+ }
+
+ if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
+ static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow);
+ return false;
+ }
+
+ if (width > 0 && height > 0 && pixels == nullptr &&
+ context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kPixelDataNull);
+ return false;
+ }
+ }
+ else
+ {
+ if (texture->getImmutableFormat())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsImmutable);
+ return false;
+ }
+ }
+
+ // From GL_CHROMIUM_color_buffer_float_rgb[a]:
+ // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
+ // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
+ // internalformat parameter and format parameter of TexImage2D must match is lifted for this
+ // case.
+ if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormatCombination);
+ return false;
+ }
+
+ GLenum sizeCheckFormat = isSubImage ? format : internalformat;
+ return ValidImageDataSize(context, entryPoint, texType, width, height, 1, sizeCheckFormat, type,
+ pixels, imageSize);
+}
+
+bool ValidateES2TexStorageParametersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ if (target != TextureType::_2D && target != TextureType::CubeMap &&
+ target != TextureType::Rectangle)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ if (width < 1 || height < 1 || levels < 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kTextureSizeTooSmall);
+ return false;
+ }
+
+ if (target == TextureType::CubeMap && width != height)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
+ return false;
+ }
+
+ if (levels != 1 && levels != log2(std::max(width, height)) + 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidMipLevels);
+ return false;
+ }
+
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
+ if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+
+ switch (target)
+ {
+ case TextureType::_2D:
+ if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ break;
+ case TextureType::Rectangle:
+ if (levels != 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+
+ if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ if (formatInfo.compressed)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kRectangleTextureCompressed);
+ return false;
+ }
+ break;
+ case TextureType::CubeMap:
+ if (width > caps.maxCubeMapTextureSize || height > caps.maxCubeMapTextureSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ break;
+ case TextureType::InvalidEnum:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumInvalid);
+ return false;
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ ToGLenum(target));
+ return false;
+ }
+
+ if (levels != 1 && !context->getExtensions().textureNpotOES)
+ {
+ if (!isPow2(width) || !isPow2(height))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDimensionsMustBePow2);
+ return false;
+ }
+ }
+
+ if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+
+ // Even with OES_texture_npot, some compressed formats may impose extra restrictions.
+ if (formatInfo.compressed)
+ {
+ if (!ValidCompressedImageSize(context, formatInfo.internalFormat, 0, width, height, 1))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidCompressedImageSize);
+ return false;
+ }
+ }
+
+ switch (internalformat)
+ {
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT32_OES:
+ switch (target)
+ {
+ case TextureType::_2D:
+ break;
+ case TextureType::CubeMap:
+ if (!context->getExtensions().depthTextureCubeMapOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidTextureTarget);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidTextureTarget);
+ return false;
+ }
+
+ // ANGLE_depth_texture only supports 1-level textures
+ if (!context->getExtensions().depthTextureOES)
+ {
+ if (levels != 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidMipLevels);
+ return false;
+ }
+ }
+ break;
+ case GL_DEPTH24_STENCIL8_OES:
+ switch (target)
+ {
+ case TextureType::_2D:
+ break;
+ case TextureType::CubeMap:
+ if (!context->getExtensions().depthTextureCubeMapOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidTextureTarget);
+ return false;
+ }
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidTextureTarget);
+ return false;
+ }
+
+ if (!context->getExtensions().packedDepthStencilOES &&
+ !context->getExtensions().depthTextureCubeMapOES)
+ {
+ // ANGLE_depth_texture only supports 1-level textures
+ if (levels != 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidMipLevels);
+ return false;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ Texture *texture = context->getTextureByType(target);
+ if (!texture || texture->id().value == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingTexture);
+ return false;
+ }
+
+ if (texture->getImmutableFormat())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsImmutable);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDiscardFramebufferEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments)
+{
+ if (!context->getExtensions().discardFramebufferEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ bool defaultFramebuffer = false;
+
+ switch (target)
+ {
+ case GL_FRAMEBUFFER:
+ defaultFramebuffer =
+ (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->isDefault());
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
+ return false;
+ }
+
+ return ValidateDiscardFramebufferBase(context, entryPoint, target, numAttachments, attachments,
+ defaultFramebuffer);
+}
+
+bool ValidateBindVertexArrayOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID array)
+{
+ if (!context->getExtensions().vertexArrayObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateBindVertexArrayBase(context, entryPoint, array);
+}
+
+bool ValidateDeleteVertexArraysOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const VertexArrayID *arrays)
+{
+ if (!context->getExtensions().vertexArrayObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateGenVertexArraysOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const VertexArrayID *arrays)
+{
+ if (!context->getExtensions().vertexArrayObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateIsVertexArrayOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID array)
+{
+ if (!context->getExtensions().vertexArrayObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateProgramBinaryOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length)
+{
+ if (!context->getExtensions().getProgramBinaryOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramBinaryBase(context, entryPoint, program, binaryFormat, binary, length);
+}
+
+bool ValidateGetProgramBinaryOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLenum *binaryFormat,
+ const void *binary)
+{
+ if (!context->getExtensions().getProgramBinaryOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGetProgramBinaryBase(context, entryPoint, program, bufSize, length, binaryFormat,
+ binary);
+}
+
+static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
+{
+ switch (source)
+ {
+ case GL_DEBUG_SOURCE_API:
+ case GL_DEBUG_SOURCE_SHADER_COMPILER:
+ case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
+ case GL_DEBUG_SOURCE_OTHER:
+ // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
+ return !mustBeThirdPartyOrApplication;
+
+ case GL_DEBUG_SOURCE_THIRD_PARTY:
+ case GL_DEBUG_SOURCE_APPLICATION:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static bool ValidDebugType(GLenum type)
+{
+ switch (type)
+ {
+ case GL_DEBUG_TYPE_ERROR:
+ case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
+ case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
+ case GL_DEBUG_TYPE_PERFORMANCE:
+ case GL_DEBUG_TYPE_PORTABILITY:
+ case GL_DEBUG_TYPE_OTHER:
+ case GL_DEBUG_TYPE_MARKER:
+ case GL_DEBUG_TYPE_PUSH_GROUP:
+ case GL_DEBUG_TYPE_POP_GROUP:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+static bool ValidDebugSeverity(GLenum severity)
+{
+ switch (severity)
+ {
+ case GL_DEBUG_SEVERITY_HIGH:
+ case GL_DEBUG_SEVERITY_MEDIUM:
+ case GL_DEBUG_SEVERITY_LOW:
+ case GL_DEBUG_SEVERITY_NOTIFICATION:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidateDebugMessageControlKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled)
+{
+ if (!context->getExtensions().debugKHR)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugSource);
+ return false;
+ }
+
+ if (!ValidDebugType(type) && type != GL_DONT_CARE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugType);
+ return false;
+ }
+
+ if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugSeverity);
+ return false;
+ }
+
+ if (count > 0)
+ {
+ if (source == GL_DONT_CARE || type == GL_DONT_CARE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDebugSourceType);
+ return false;
+ }
+
+ if (severity != GL_DONT_CARE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDebugSeverity);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateDebugMessageInsertKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *buf)
+{
+ if (!context->getExtensions().debugKHR)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!context->getState().getDebug().isOutputEnabled())
+ {
+ // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
+ // not generate an error.
+ return false;
+ }
+
+ if (!ValidDebugSeverity(severity))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugSource);
+ return false;
+ }
+
+ if (!ValidDebugType(type))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugType);
+ return false;
+ }
+
+ if (!ValidDebugSource(source, true))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugSource);
+ return false;
+ }
+
+ size_t messageLength = (length < 0) ? strlen(buf) : length;
+ if (messageLength > context->getCaps().maxDebugMessageLength)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxDebugMessageLength);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDebugMessageCallbackKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLDEBUGPROCKHR callback,
+ const void *userParam)
+{
+ if (!context->getExtensions().debugKHR)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetDebugMessageLogKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint count,
+ GLsizei bufSize,
+ const GLenum *sources,
+ const GLenum *types,
+ const GLuint *ids,
+ const GLenum *severities,
+ const GLsizei *lengths,
+ const GLchar *messageLog)
+{
+ if (!context->getExtensions().debugKHR)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (bufSize < 0 && messageLog != nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePushDebugGroupKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum source,
+ GLuint id,
+ GLsizei length,
+ const GLchar *message)
+{
+ if (!context->getExtensions().debugKHR)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidDebugSource(source, true))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugSource);
+ return false;
+ }
+
+ size_t messageLength = (length < 0) ? strlen(message) : length;
+ if (messageLength > context->getCaps().maxDebugMessageLength)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxDebugMessageLength);
+ return false;
+ }
+
+ size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
+ if (currentStackSize >= context->getCaps().maxDebugGroupStackDepth)
+ {
+ context->validationError(entryPoint, GL_STACK_OVERFLOW, kExceedsMaxDebugGroupStackDepth);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePopDebugGroupKHR(const Context *context, angle::EntryPoint entryPoint)
+{
+ if (!context->getExtensions().debugKHR)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
+ if (currentStackSize <= 1)
+ {
+ context->validationError(entryPoint, GL_STACK_UNDERFLOW, kCannotPopDefaultDebugGroup);
+ return false;
+ }
+
+ return true;
+}
+
+static bool ValidateObjectIdentifierAndName(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum identifier,
+ GLuint name)
+{
+ switch (identifier)
+ {
+ case GL_BUFFER:
+ if (context->getBuffer({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBufferName);
+ return false;
+ }
+ return true;
+
+ case GL_SHADER:
+ if (context->getShader({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidShaderName);
+ return false;
+ }
+ return true;
+
+ case GL_PROGRAM:
+ if (context->getProgramNoResolveLink({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramName);
+ return false;
+ }
+ return true;
+
+ case GL_VERTEX_ARRAY:
+ if (context->getVertexArray({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidVertexArrayName);
+ return false;
+ }
+ return true;
+
+ case GL_QUERY:
+ if (context->getQuery({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidQueryName);
+ return false;
+ }
+ return true;
+
+ case GL_TRANSFORM_FEEDBACK:
+ if (context->getTransformFeedback({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kInvalidTransformFeedbackName);
+ return false;
+ }
+ return true;
+
+ case GL_SAMPLER:
+ if (context->getSampler({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSamplerName);
+ return false;
+ }
+ return true;
+
+ case GL_TEXTURE:
+ if (context->getTexture({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidTextureName);
+ return false;
+ }
+ return true;
+
+ case GL_RENDERBUFFER:
+ if (!context->isRenderbuffer({name}))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidRenderbufferName);
+ return false;
+ }
+ return true;
+
+ case GL_FRAMEBUFFER:
+ if (context->getFramebuffer({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFramebufferName);
+ return false;
+ }
+ return true;
+
+ case GL_PROGRAM_PIPELINE:
+ if (context->getProgramPipeline({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramPipelineName);
+ return false;
+ }
+ return true;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidIndentifier);
+ return false;
+ }
+}
+
+static bool ValidateLabelLength(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei length,
+ const GLchar *label)
+{
+ size_t labelLength = 0;
+
+ if (length < 0)
+ {
+ if (label != nullptr)
+ {
+ labelLength = strlen(label);
+ }
+ }
+ else
+ {
+ labelLength = static_cast<size_t>(length);
+ }
+
+ if (labelLength > context->getCaps().maxLabelLength)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxLabelLength);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateObjectLabelKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum identifier,
+ GLuint name,
+ GLsizei length,
+ const GLchar *label)
+{
+ if (!context->getExtensions().debugKHR)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidateObjectIdentifierAndName(context, entryPoint, identifier, name))
+ {
+ return false;
+ }
+
+ if (!ValidateLabelLength(context, entryPoint, length, label))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetObjectLabelKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *label)
+{
+ if (!context->getExtensions().debugKHR)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ if (!ValidateObjectIdentifierAndName(context, entryPoint, identifier, name))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+static bool ValidateObjectPtrName(const Context *context,
+ angle::EntryPoint entryPoint,
+ const void *ptr)
+{
+ if (context->getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSyncPointer);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateObjectPtrLabelKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ const void *ptr,
+ GLsizei length,
+ const GLchar *label)
+{
+ if (!context->getExtensions().debugKHR)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidateObjectPtrName(context, entryPoint, ptr))
+ {
+ return false;
+ }
+
+ if (!ValidateLabelLength(context, entryPoint, length, label))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetObjectPtrLabelKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ const void *ptr,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *label)
+{
+ if (!context->getExtensions().debugKHR)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ if (!ValidateObjectPtrName(context, entryPoint, ptr))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetPointervKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ void *const *params)
+{
+ if (!context->getExtensions().debugKHR)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ // TODO: represent this in Context::getQueryParameterInfo.
+ switch (pname)
+ {
+ case GL_DEBUG_CALLBACK_FUNCTION:
+ case GL_DEBUG_CALLBACK_USER_PARAM:
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetPointervRobustANGLERobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ void *const *params)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateBlitFramebufferANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter)
+{
+ if (!context->getExtensions().framebufferBlitANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitExtensionNotAvailable);
+ return false;
+ }
+
+ if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
+ {
+ // TODO(jmadill): Determine if this should be available on other implementations.
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitExtensionScaleOrFlip);
+ return false;
+ }
+
+ if (filter == GL_LINEAR)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kBlitExtensionLinear);
+ return false;
+ }
+
+ Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
+ Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
+
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ const FramebufferAttachment *readColorAttachment =
+ readFramebuffer->getReadColorAttachment();
+ const FramebufferAttachment *drawColorAttachment =
+ drawFramebuffer->getFirstColorAttachment();
+
+ if (readColorAttachment && drawColorAttachment)
+ {
+ if (!(readColorAttachment->type() == GL_TEXTURE &&
+ (readColorAttachment->getTextureImageIndex().getType() == TextureType::_2D ||
+ readColorAttachment->getTextureImageIndex().getType() ==
+ TextureType::Rectangle)) &&
+ readColorAttachment->type() != GL_RENDERBUFFER &&
+ readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitExtensionFromInvalidAttachmentType);
+ return false;
+ }
+
+ for (size_t drawbufferIdx = 0;
+ drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
+ {
+ const FramebufferAttachment *attachment =
+ drawFramebuffer->getDrawBuffer(drawbufferIdx);
+ if (attachment)
+ {
+ if (!(attachment->type() == GL_TEXTURE &&
+ (attachment->getTextureImageIndex().getType() == TextureType::_2D ||
+ attachment->getTextureImageIndex().getType() ==
+ TextureType::Rectangle)) &&
+ attachment->type() != GL_RENDERBUFFER &&
+ attachment->type() != GL_FRAMEBUFFER_DEFAULT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitExtensionToInvalidAttachmentType);
+ return false;
+ }
+
+ // Return an error if the destination formats do not match
+ if (!Format::EquivalentForBlit(attachment->getFormat(),
+ readColorAttachment->getFormat()))
+ {
+ context->validationErrorF(
+ entryPoint, GL_INVALID_OPERATION, kBlitExtensionFormatMismatch,
+ readColorAttachment->getFormat().info->sizedInternalFormat,
+ attachment->getFormat().info->sizedInternalFormat);
+ return false;
+ }
+ }
+ }
+
+ GLint samples = readFramebuffer->getSamples(context);
+ if (samples != 0 &&
+ IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
+ srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitExtensionMultisampledWholeBufferBlit);
+ return false;
+ }
+ }
+ }
+
+ GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
+ GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
+ for (size_t i = 0; i < 2; i++)
+ {
+ if (mask & masks[i])
+ {
+ const FramebufferAttachment *readBuffer =
+ readFramebuffer->getAttachment(context, attachments[i]);
+ const FramebufferAttachment *drawBuffer =
+ drawFramebuffer->getAttachment(context, attachments[i]);
+
+ if (readBuffer && drawBuffer)
+ {
+ if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1))
+ {
+ // only whole-buffer copies are permitted
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitExtensionDepthStencilWholeBufferBlit);
+ return false;
+ }
+
+ if (readBuffer->getResourceSamples() != 0 || drawBuffer->getResourceSamples() != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBlitExtensionMultisampledDepthOrStencil);
+ return false;
+ }
+ }
+ }
+ }
+
+ return ValidateBlitFramebufferParameters(context, entryPoint, srcX0, srcY0, srcX1, srcY1, dstX0,
+ dstY0, dstX1, dstY1, mask, filter);
+}
+
+bool ValidateBlitFramebufferNV(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter)
+{
+ if (!context->getExtensions().framebufferBlitANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitExtensionNotAvailable);
+ return false;
+ }
+
+ return ValidateBlitFramebufferParameters(context, entryPoint, srcX0, srcY0, srcX1, srcY1, dstX0,
+ dstY0, dstX1, dstY1, mask, filter);
+}
+
+bool ValidateClear(const Context *context, angle::EntryPoint entryPoint, GLbitfield mask)
+{
+ Framebuffer *fbo = context->getState().getDrawFramebuffer();
+ const Extensions &extensions = context->getExtensions();
+
+ if (!ValidateFramebufferComplete(context, entryPoint, fbo))
+ {
+ return false;
+ }
+
+ if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidClearMask);
+ return false;
+ }
+
+ if (extensions.webglCompatibilityANGLE && (mask & GL_COLOR_BUFFER_BIT) != 0)
+ {
+ constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
+ GL_SIGNED_NORMALIZED};
+
+ for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
+ drawBufferIdx++)
+ {
+ if (!ValidateWebGLFramebufferAttachmentClearType(context, entryPoint, drawBufferIdx,
+ validComponentTypes,
+ ArraySize(validComponentTypes)))
+ {
+ return false;
+ }
+ }
+ }
+
+ if ((extensions.multiviewOVR || extensions.multiview2OVR) && extensions.disjointTimerQueryEXT)
+ {
+ const State &state = context->getState();
+ Framebuffer *framebuffer = state.getDrawFramebuffer();
+ if (framebuffer->getNumViews() > 1 && state.isQueryActive(QueryType::TimeElapsed))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kMultiviewTimerQuery);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateDrawBuffersEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLenum *bufs)
+{
+ if (!context->getExtensions().drawBuffersEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateDrawBuffersBase(context, entryPoint, n, bufs);
+}
+
+bool ValidateTexImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2TexImageParameters(context, entryPoint, target, level, internalformat,
+ false, false, 0, 0, width, height, border, format,
+ type, -1, pixels);
+ }
+
+ ASSERT(context->getClientMajorVersion() >= 3);
+ return ValidateES3TexImage2DParameters(context, entryPoint, target, level, internalformat,
+ false, false, 0, 0, 0, width, height, 1, border, format,
+ type, -1, pixels);
+}
+
+bool ValidateTexImage2DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2TexImageParameters(context, entryPoint, target, level, internalformat,
+ false, false, 0, 0, width, height, border, format,
+ type, bufSize, pixels);
+ }
+
+ ASSERT(context->getClientMajorVersion() >= 3);
+ return ValidateES3TexImage2DParameters(context, entryPoint, target, level, internalformat,
+ false, false, 0, 0, 0, width, height, 1, border, format,
+ type, bufSize, pixels);
+}
+
+bool ValidateTexSubImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2TexImageParameters(context, entryPoint, target, level, GL_NONE, false,
+ true, xoffset, yoffset, width, height, 0, format, type,
+ -1, pixels);
+ }
+
+ ASSERT(context->getClientMajorVersion() >= 3);
+ return ValidateES3TexImage2DParameters(context, entryPoint, target, level, GL_NONE, false, true,
+ xoffset, yoffset, 0, width, height, 1, 0, format, type,
+ -1, pixels);
+}
+
+bool ValidateTexSubImage2DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2TexImageParameters(context, entryPoint, target, level, GL_NONE, false,
+ true, xoffset, yoffset, width, height, 0, format, type,
+ bufSize, pixels);
+ }
+
+ ASSERT(context->getClientMajorVersion() >= 3);
+ return ValidateES3TexImage2DParameters(context, entryPoint, target, level, GL_NONE, false, true,
+ xoffset, yoffset, 0, width, height, 1, 0, format, type,
+ bufSize, pixels);
+}
+
+bool ValidateTexSubImage3DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ return ValidateTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset, zoffset,
+ width, height, depth, format, type, pixels);
+}
+
+bool ValidateCompressedTexImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const void *data)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ if (!ValidateES2TexImageParameters(context, entryPoint, target, level, internalformat, true,
+ false, 0, 0, width, height, border, GL_NONE, GL_NONE, -1,
+ data))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ ASSERT(context->getClientMajorVersion() >= 3);
+ if (!ValidateES3TexImage2DParameters(context, entryPoint, target, level, internalformat,
+ true, false, 0, 0, 0, width, height, 1, border,
+ GL_NONE, GL_NONE, -1, data))
+ {
+ return false;
+ }
+ }
+
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
+
+ GLuint expectedImageSize = 0;
+ if (!formatInfo.computeCompressedImageSize(Extents(width, height, 1), &expectedImageSize))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
+ return false;
+ }
+
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != expectedImageSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kCompressedTextureDimensionsMustMatchData);
+ return false;
+ }
+
+ if (target == TextureTarget::Rectangle)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kRectangleTextureCompressed);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCompressedTexImage2DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const void *data)
+{
+ if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize))
+ {
+ return false;
+ }
+
+ return ValidateCompressedTexImage2D(context, entryPoint, target, level, internalformat, width,
+ height, border, imageSize, data);
+}
+
+bool ValidateCompressedTexImage3DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const void *data)
+{
+ return ValidateCompressedTexImage3D(context, entryPoint, target, level, internalformat, width,
+ height, depth, border, imageSize, data);
+}
+
+bool ValidateCompressedTexSubImage2DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const void *data)
+{
+ if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize))
+ {
+ return false;
+ }
+
+ return ValidateCompressedTexSubImage2D(context, entryPoint, target, level, xoffset, yoffset,
+ width, height, format, imageSize, data);
+}
+
+bool ValidateCompressedTexSubImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ if (!ValidateES2TexImageParameters(context, entryPoint, target, level, GL_NONE, true, true,
+ xoffset, yoffset, width, height, 0, format, GL_NONE, -1,
+ data))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ ASSERT(context->getClientMajorVersion() >= 3);
+ if (!ValidateES3TexImage2DParameters(context, entryPoint, target, level, GL_NONE, true,
+ true, xoffset, yoffset, 0, width, height, 1, 0, format,
+ GL_NONE, -1, data))
+ {
+ return false;
+ }
+ }
+
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
+ GLuint blockSize = 0;
+ if (!formatInfo.computeCompressedImageSize(Extents(width, height, 1), &blockSize))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
+ return false;
+ }
+
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidCompressedImageSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCompressedTexSubImage3DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ return ValidateCompressedTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset,
+ zoffset, width, height, depth, format, imageSize, data);
+}
+
+bool ValidateGetBufferPointervOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLenum pname,
+ void *const *params)
+{
+ if (!context->getExtensions().mapbufferOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGetBufferPointervBase(context, entryPoint, target, pname, nullptr, params);
+}
+
+bool ValidateMapBufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLenum access)
+{
+ if (!context->getExtensions().mapbufferOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!context->isValidBufferBinding(target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
+ return false;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (buffer == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotMappable);
+ return false;
+ }
+
+ if (access != GL_WRITE_ONLY_OES)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAccessBits);
+ return false;
+ }
+
+ // Though there is no explicit mention of an interaction between GL_EXT_buffer_storage
+ // and GL_OES_mapbuffer extension, allow it as long as the access type of glmapbufferOES
+ // is compatible with the buffer's usage flags specified during glBufferStorageEXT
+ if (buffer->isImmutable() && (buffer->getStorageExtUsageFlags() & GL_MAP_WRITE_BIT) == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotMappable);
+ return false;
+ }
+
+ if (buffer->isMapped())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferAlreadyMapped);
+ return false;
+ }
+
+ return ValidateMapBufferBase(context, entryPoint, target);
+}
+
+bool ValidateUnmapBufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target)
+{
+ if (!context->getExtensions().mapbufferOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateUnmapBufferBase(context, entryPoint, target);
+}
+
+bool ValidateMapBufferRangeEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ if (!context->getExtensions().mapBufferRangeEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateMapBufferRangeBase(context, entryPoint, target, offset, length, access);
+}
+
+bool ValidateMapBufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target)
+{
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+ ASSERT(buffer != nullptr);
+
+ // Check if this buffer is currently being used as a transform feedback output buffer
+ if (context->getState().isTransformFeedbackActive())
+ {
+ TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
+ for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
+ {
+ const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
+ if (transformFeedbackBuffer.get() == buffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBufferBoundForTransformFeedback);
+ return false;
+ }
+ }
+ }
+
+ if (buffer->hasWebGLXFBBindingConflict(context->isWebGL()))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBufferBoundForTransformFeedback);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFlushMappedBufferRangeEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length)
+{
+ if (!context->getExtensions().mapBufferRangeEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateFlushMappedBufferRangeBase(context, entryPoint, target, offset, length);
+}
+
+bool ValidateBindUniformLocationCHROMIUM(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ const GLchar *name)
+{
+ if (!context->getExtensions().bindUniformLocationCHROMIUM)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (location.value < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLocation);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (static_cast<long>(location.value) >=
+ (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBindUniformLocation);
+ return false;
+ }
+
+ // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
+ // shader-related entry points
+ if (context->isWebGL() && !IsValidESSLString(name, strlen(name)))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidNameCharacters);
+ return false;
+ }
+
+ if (strncmp(name, "gl_", 3) == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNameBeginsWithGL);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCoverageModulationCHROMIUM(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum components)
+{
+ if (!context->getExtensions().framebufferMixedSamplesCHROMIUM)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ switch (components)
+ {
+ case GL_RGB:
+ case GL_RGBA:
+ case GL_ALPHA:
+ case GL_NONE:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCoverageComponents);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopyTextureCHROMIUM(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID sourceId,
+ GLint sourceLevel,
+ TextureTarget destTarget,
+ TextureID destId,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ if (!context->getExtensions().copyTextureCHROMIUM)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ const Texture *source = context->getTexture(sourceId);
+ if (source == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTexture);
+ return false;
+ }
+
+ if (!IsValidCopyTextureSourceTarget(context, source->getType()))
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
+ internalFormat);
+ return false;
+ }
+
+ TextureType sourceType = source->getType();
+ ASSERT(sourceType != TextureType::CubeMap);
+ TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
+
+ if (!IsValidCopyTextureSourceLevel(context, sourceType, sourceLevel))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTextureLevel);
+ return false;
+ }
+
+ GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
+ GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
+ if (sourceWidth == 0 || sourceHeight == 0)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
+ internalFormat);
+ return false;
+ }
+
+ const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
+ if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidSourceTextureInternalFormat);
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ const Texture *dest = context->getTexture(destId);
+ if (dest == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTexture);
+ return false;
+ }
+
+ const InternalFormat &destInternalFormatInfo = GetInternalFormatInfo(internalFormat, destType);
+ if (sourceType == TextureType::External && destInternalFormatInfo.isInt() &&
+ !context->getExtensions().EGLImageExternalEssl3OES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kANGLECopyTextureMissingRequiredExtension);
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationTarget(context, dest->getType(), destTarget))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTextureType);
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationLevel(context, entryPoint, dest->getType(), destLevel,
+ sourceWidth, sourceHeight, false))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationFormatType(context, entryPoint, internalFormat, destType))
+ {
+ return false;
+ }
+
+ if (dest->getType() == TextureType::CubeMap && sourceWidth != sourceHeight)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
+ return false;
+ }
+
+ if (dest->getImmutableFormat())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDestinationImmutable);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopySubTextureCHROMIUM(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID sourceId,
+ GLint sourceLevel,
+ TextureTarget destTarget,
+ TextureID destId,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ if (!context->getExtensions().copyTextureCHROMIUM)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ const Texture *source = context->getTexture(sourceId);
+ if (source == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTexture);
+ return false;
+ }
+
+ if (!IsValidCopyTextureSourceTarget(context, source->getType()))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTextureType);
+ return false;
+ }
+
+ TextureType sourceType = source->getType();
+ ASSERT(sourceType != TextureType::CubeMap);
+ TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
+
+ if (!IsValidCopyTextureSourceLevel(context, sourceType, sourceLevel))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+
+ if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
+ source->getHeight(sourceTarget, sourceLevel) == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTextureLevel);
+ return false;
+ }
+
+ if (x < 0 || y < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
+ return false;
+ }
+
+ if (width < 0 || height < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
+ return false;
+ }
+
+ if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
+ static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kSourceTextureTooSmall);
+ return false;
+ }
+
+ const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
+ if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
+ sourceFormat.info->internalFormat);
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ const Texture *dest = context->getTexture(destId);
+ if (dest == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTexture);
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationTarget(context, dest->getType(), destTarget))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTextureType);
+ return false;
+ }
+
+ if (!IsValidCopyTextureDestinationLevel(context, entryPoint, dest->getType(), destLevel, width,
+ height, true))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+
+ if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDestinationLevelNotDefined);
+ return false;
+ }
+
+ const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
+ if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormatCombination);
+ return false;
+ }
+
+ if (sourceType == TextureType::External && destFormat.isInt() &&
+ !context->getExtensions().EGLImageExternalEssl3OES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kANGLECopyTextureMissingRequiredExtension);
+ return false;
+ }
+
+ if (xoffset < 0 || yoffset < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
+ return false;
+ }
+
+ if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
+ static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCompressedCopyTextureCHROMIUM(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID sourceId,
+ TextureID destId)
+{
+ if (!context->getExtensions().copyCompressedTextureCHROMIUM)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ const Texture *source = context->getTexture(sourceId);
+ if (source == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTexture);
+ return false;
+ }
+
+ if (source->getType() != TextureType::_2D)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTextureType);
+ return false;
+ }
+
+ if (source->getWidth(TextureTarget::_2D, 0) == 0 ||
+ source->getHeight(TextureTarget::_2D, 0) == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kSourceTextureLevelZeroDefined);
+ return false;
+ }
+
+ const Format &sourceFormat = source->getFormat(TextureTarget::_2D, 0);
+ if (!sourceFormat.info->compressed)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kSourceTextureMustBeCompressed);
+ return false;
+ }
+
+ const Texture *dest = context->getTexture(destId);
+ if (dest == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTexture);
+ return false;
+ }
+
+ if (dest->getType() != TextureType::_2D)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTextureType);
+ return false;
+ }
+
+ if (dest->getImmutableFormat())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDestinationImmutable);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCreateShader(const Context *context, angle::EntryPoint entryPoint, ShaderType type)
+{
+ switch (type)
+ {
+ case ShaderType::Vertex:
+ case ShaderType::Fragment:
+ break;
+
+ case ShaderType::Compute:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kES31Required);
+ return false;
+ }
+ break;
+
+ case ShaderType::Geometry:
+ if (!context->getExtensions().geometryShaderAny() &&
+ context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
+ return false;
+ }
+ break;
+
+ case ShaderType::TessControl:
+ if (!context->getExtensions().tessellationShaderEXT &&
+ context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
+ return false;
+ }
+ break;
+
+ case ShaderType::TessEvaluation:
+ if (!context->getExtensions().tessellationShaderEXT &&
+ context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBufferData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLsizeiptr size,
+ const void *data,
+ BufferUsage usage)
+{
+ if (size < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
+ return false;
+ }
+
+ switch (usage)
+ {
+ case BufferUsage::StreamDraw:
+ case BufferUsage::StaticDraw:
+ case BufferUsage::DynamicDraw:
+ break;
+
+ case BufferUsage::StreamRead:
+ case BufferUsage::StaticRead:
+ case BufferUsage::DynamicRead:
+ case BufferUsage::StreamCopy:
+ case BufferUsage::StaticCopy:
+ case BufferUsage::DynamicCopy:
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferUsage);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferUsage);
+ return false;
+ }
+
+ if (!context->isValidBufferBinding(target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
+ return false;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (!buffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound);
+ return false;
+ }
+
+ if (buffer->hasWebGLXFBBindingConflict(context->isWebGL()))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBufferBoundForTransformFeedback);
+ return false;
+ }
+
+ if (buffer->isImmutable())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferImmutable);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data)
+{
+ if (size < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
+ return false;
+ }
+
+ if (offset < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
+ return false;
+ }
+
+ if (!context->isValidBufferBinding(target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
+ return false;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (!buffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound);
+ return false;
+ }
+
+ // EXT_buffer_storage allows persistently mapped buffers to be updated via glBufferSubData
+ bool isPersistent = (buffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
+
+ // Verify that buffer is not currently mapped unless persistent
+ if (buffer->isMapped() && !isPersistent)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferMapped);
+ return false;
+ }
+
+ if (buffer->hasWebGLXFBBindingConflict(context->isWebGL()))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBufferBoundForTransformFeedback);
+ return false;
+ }
+
+ if (buffer->isImmutable() &&
+ (buffer->getStorageExtUsageFlags() & GL_DYNAMIC_STORAGE_BIT_EXT) == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotUpdatable);
+ return false;
+ }
+
+ // Check for possible overflow of size + offset
+ angle::CheckedNumeric<decltype(size + offset)> checkedSize(size);
+ checkedSize += offset;
+ if (!checkedSize.IsValid())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kParamOverflow);
+ return false;
+ }
+
+ if (size + offset > buffer->getSize())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInsufficientBufferSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateRequestExtensionANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLchar *name)
+{
+ if (!context->getExtensions().requestExtensionANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!context->isExtensionRequestable(name))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotRequestable);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDisableExtensionANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLchar *name)
+{
+ if (!context->getExtensions().requestExtensionANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!context->isExtensionDisablable(name))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotDisablable);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateActiveTexture(const Context *context, angle::EntryPoint entryPoint, GLenum texture)
+{
+ if (context->getClientMajorVersion() < 2)
+ {
+ return ValidateMultitextureUnit(context, entryPoint, texture);
+ }
+
+ if (texture < GL_TEXTURE0 ||
+ texture >
+ GL_TEXTURE0 + static_cast<GLuint>(context->getCaps().maxCombinedTextureImageUnits) - 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCombinedImageUnit);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateAttachShader(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ ShaderProgramID shader)
+{
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ Shader *shaderObject = GetValidShader(context, entryPoint, shader);
+ if (!shaderObject)
+ {
+ return false;
+ }
+
+ if (programObject->getAttachedShader(shaderObject->getType()))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kShaderAttachmentHasShader);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindAttribLocation(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLuint index,
+ const GLchar *name)
+{
+ if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ if (strncmp(name, "gl_", 3) == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kNameBeginsWithGL);
+ return false;
+ }
+
+ if (context->isWebGL())
+ {
+ const size_t length = strlen(name);
+
+ if (!IsValidESSLString(name, length))
+ {
+ // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
+ // for shader-related entry points
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidNameCharacters);
+ return false;
+ }
+
+ if (!ValidateWebGLNameLength(context, entryPoint, length) ||
+ !ValidateWebGLNamePrefix(context, entryPoint, name))
+ {
+ return false;
+ }
+ }
+
+ return GetValidProgram(context, entryPoint, program) != nullptr;
+}
+
+bool ValidateBindFramebuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ FramebufferID framebuffer)
+{
+ return ValidateBindFramebufferBase(context, entryPoint, target, framebuffer);
+}
+
+bool ValidateBindRenderbuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ RenderbufferID renderbuffer)
+{
+ return ValidateBindRenderbufferBase(context, entryPoint, target, renderbuffer);
+}
+
+static bool ValidBlendEquationMode(const Context *context, GLenum mode)
+{
+ switch (mode)
+ {
+ case GL_FUNC_ADD:
+ case GL_FUNC_SUBTRACT:
+ case GL_FUNC_REVERSE_SUBTRACT:
+ return true;
+
+ case GL_MIN:
+ case GL_MAX:
+ return context->getClientVersion() >= ES_3_0 || context->getExtensions().blendMinmaxEXT;
+
+ default:
+ return false;
+ }
+}
+
+static bool ValidAdvancedBlendEquationMode(const Context *context, GLenum mode)
+{
+ switch (mode)
+ {
+ case GL_MULTIPLY_KHR:
+ case GL_SCREEN_KHR:
+ case GL_OVERLAY_KHR:
+ case GL_DARKEN_KHR:
+ case GL_LIGHTEN_KHR:
+ case GL_COLORDODGE_KHR:
+ case GL_COLORBURN_KHR:
+ case GL_HARDLIGHT_KHR:
+ case GL_SOFTLIGHT_KHR:
+ case GL_DIFFERENCE_KHR:
+ case GL_EXCLUSION_KHR:
+ case GL_HSL_HUE_KHR:
+ case GL_HSL_SATURATION_KHR:
+ case GL_HSL_COLOR_KHR:
+ case GL_HSL_LUMINOSITY_KHR:
+ return context->getClientVersion() >= ES_3_2 ||
+ context->getExtensions().blendEquationAdvancedKHR;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidateBlendColor(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue,
+ GLfloat alpha)
+{
+ return true;
+}
+
+bool ValidateBlendEquation(const Context *context, angle::EntryPoint entryPoint, GLenum mode)
+{
+ if (!ValidBlendEquationMode(context, mode) && !ValidAdvancedBlendEquationMode(context, mode))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendEquation);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBlendEquationSeparate(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum modeRGB,
+ GLenum modeAlpha)
+{
+ if (!ValidBlendEquationMode(context, modeRGB))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendEquation);
+ return false;
+ }
+
+ if (!ValidBlendEquationMode(context, modeAlpha))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendEquation);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBlendFunc(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum sfactor,
+ GLenum dfactor)
+{
+ return ValidateBlendFuncSeparate(context, entryPoint, sfactor, dfactor, sfactor, dfactor);
+}
+
+bool ValidateBlendFuncSeparate(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha)
+{
+ if (!ValidSrcBlendFunc(context, srcRGB))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendFunction);
+ return false;
+ }
+
+ if (!ValidDstBlendFunc(context, dstRGB))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendFunction);
+ return false;
+ }
+
+ if (!ValidSrcBlendFunc(context, srcAlpha))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendFunction);
+ return false;
+ }
+
+ if (!ValidDstBlendFunc(context, dstAlpha))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendFunction);
+ return false;
+ }
+
+ if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
+ context->isWebGL())
+ {
+ bool constantColorUsed =
+ (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
+ dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
+
+ bool constantAlphaUsed =
+ (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
+ dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
+
+ if (constantColorUsed && constantAlphaUsed)
+ {
+ if (context->isWebGL())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidConstantColor);
+ return false;
+ }
+
+ WARN() << kConstantColorAlphaLimitation;
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kConstantColorAlphaLimitation);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetString(const Context *context, angle::EntryPoint entryPoint, GLenum name)
+{
+ switch (name)
+ {
+ case GL_VENDOR:
+ case GL_RENDERER:
+ case GL_VERSION:
+ case GL_SHADING_LANGUAGE_VERSION:
+ case GL_EXTENSIONS:
+ break;
+
+ case GL_REQUESTABLE_EXTENSIONS_ANGLE:
+ if (!context->getExtensions().requestExtensionANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidName);
+ return false;
+ }
+ break;
+
+ case GL_SERIALIZED_CONTEXT_STRING_ANGLE:
+ if (!context->getExtensions().getSerializedContextStringANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidName);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidName);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateLineWidth(const Context *context, angle::EntryPoint entryPoint, GLfloat width)
+{
+ if (width <= 0.0f || isNaN(width))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidWidth);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDepthRangef(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat zNear,
+ GLfloat zFar)
+{
+ if (context->isWebGL() && zNear > zFar)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDepthRange);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateRenderbufferStorage(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ return ValidateRenderbufferStorageParametersBase(context, entryPoint, target, 0, internalformat,
+ width, height);
+}
+
+bool ValidateRenderbufferStorageMultisampleANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ if (!context->getExtensions().framebufferMultisampleANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
+ // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
+ // generated.
+ if (samples > context->getCaps().maxSamples)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kSamplesOutOfRange);
+ return false;
+ }
+
+ // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
+ // the specified storage. This is different than ES 3.0 in which a sample number higher
+ // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
+ // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
+ if (context->getClientMajorVersion() >= 3)
+ {
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
+ {
+ context->validationError(entryPoint, GL_OUT_OF_MEMORY, kSamplesOutOfRange);
+ return false;
+ }
+ }
+
+ return ValidateRenderbufferStorageParametersBase(context, entryPoint, target, samples,
+ internalformat, width, height);
+}
+
+bool ValidateCheckFramebufferStatus(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target)
+{
+ if (!ValidFramebufferTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateClearColor(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue,
+ GLfloat alpha)
+{
+ return true;
+}
+
+bool ValidateClearDepthf(const Context *context, angle::EntryPoint entryPoint, GLfloat depth)
+{
+ return true;
+}
+
+bool ValidateClearStencil(const Context *context, angle::EntryPoint entryPoint, GLint s)
+{
+ return true;
+}
+
+bool ValidateColorMask(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLboolean red,
+ GLboolean green,
+ GLboolean blue,
+ GLboolean alpha)
+{
+ return true;
+}
+
+bool ValidateCompileShader(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shader)
+{
+ return true;
+}
+
+bool ValidateCreateProgram(const Context *context, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidateCullFace(const Context *context, angle::EntryPoint entryPoint, CullFaceMode mode)
+{
+ switch (mode)
+ {
+ case CullFaceMode::Front:
+ case CullFaceMode::Back:
+ case CullFaceMode::FrontAndBack:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCullMode);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDeleteProgram(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program)
+{
+ if (program.value == 0)
+ {
+ return false;
+ }
+
+ if (!context->getProgramResolveLink(program))
+ {
+ if (context->getShader(program))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExpectedProgramName);
+ return false;
+ }
+ else
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramName);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateDeleteShader(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shader)
+{
+ if (shader.value == 0)
+ {
+ return false;
+ }
+
+ if (!context->getShader(shader))
+ {
+ if (context->getProgramResolveLink(shader))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidShaderName);
+ return false;
+ }
+ else
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExpectedShaderName);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateDepthFunc(const Context *context, angle::EntryPoint entryPoint, GLenum func)
+{
+ switch (func)
+ {
+ case GL_NEVER:
+ case GL_ALWAYS:
+ case GL_LESS:
+ case GL_LEQUAL:
+ case GL_EQUAL:
+ case GL_GREATER:
+ case GL_GEQUAL:
+ case GL_NOTEQUAL:
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, func);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDepthMask(const Context *context, angle::EntryPoint entryPoint, GLboolean flag)
+{
+ return true;
+}
+
+bool ValidateDetachShader(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ ShaderProgramID shader)
+{
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ Shader *shaderObject = GetValidShader(context, entryPoint, shader);
+ if (!shaderObject)
+ {
+ return false;
+ }
+
+ const Shader *attachedShader = programObject->getAttachedShader(shaderObject->getType());
+ if (attachedShader != shaderObject)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kShaderToDetachMustBeAttached);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDisableVertexAttribArray(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index)
+{
+ if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateEnableVertexAttribArray(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index)
+{
+ if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFinish(const Context *context, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidateFlush(const Context *context, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidateFrontFace(const Context *context, angle::EntryPoint entryPoint, GLenum mode)
+{
+ switch (mode)
+ {
+ case GL_CW:
+ case GL_CCW:
+ break;
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, mode);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetActiveAttrib(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLuint index,
+ GLsizei bufsize,
+ const GLsizei *length,
+ const GLint *size,
+ const GLenum *type,
+ const GLchar *name)
+{
+ if (bufsize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetActiveUniform(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLuint index,
+ GLsizei bufsize,
+ const GLsizei *length,
+ const GLint *size,
+ const GLenum *type,
+ const GLchar *name)
+{
+ if (bufsize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetAttachedShaders(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLsizei maxcount,
+ const GLsizei *count,
+ const ShaderProgramID *shaders)
+{
+ if (maxcount < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeMaxCount);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetAttribLocation(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ const GLchar *name)
+{
+ if (strncmp(name, "gl_", 3) == 0)
+ {
+ return false;
+ }
+
+ if (context->isWebGL())
+ {
+ const size_t length = strlen(name);
+
+ if (!IsValidESSLString(name, length))
+ {
+ // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
+ // for shader-related entry points
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidNameCharacters);
+ return false;
+ }
+
+ if (!ValidateWebGLNameLength(context, entryPoint, length) ||
+ strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0)
+ {
+ return false;
+ }
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+
+ if (!programObject)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotBound);
+ return false;
+ }
+
+ if (!programObject->isLinked())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBooleanv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLboolean *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ return ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams);
+}
+
+bool ValidateGetError(const Context *context, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidateGetFloatv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLfloat *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ return ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams);
+}
+
+bool ValidateGetIntegerv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLint *params)
+{
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ return ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams);
+}
+
+bool ValidateGetProgramInfoLog(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLsizei bufsize,
+ const GLsizei *length,
+ const GLchar *infolog)
+{
+ if (bufsize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetShaderInfoLog(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shader,
+ GLsizei bufsize,
+ const GLsizei *length,
+ const GLchar *infolog)
+{
+ if (bufsize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ Shader *shaderObject = GetValidShader(context, entryPoint, shader);
+ if (!shaderObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetShaderPrecisionFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum shadertype,
+ GLenum precisiontype,
+ const GLint *range,
+ const GLint *precision)
+{
+ switch (shadertype)
+ {
+ case GL_VERTEX_SHADER:
+ case GL_FRAGMENT_SHADER:
+ break;
+ case GL_COMPUTE_SHADER:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kUnimplementedComputeShaderPrecision);
+ return false;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
+ return false;
+ }
+
+ switch (precisiontype)
+ {
+ case GL_LOW_FLOAT:
+ case GL_MEDIUM_FLOAT:
+ case GL_HIGH_FLOAT:
+ case GL_LOW_INT:
+ case GL_MEDIUM_INT:
+ case GL_HIGH_INT:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPrecision);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetShaderSource(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shader,
+ GLsizei bufsize,
+ const GLsizei *length,
+ const GLchar *source)
+{
+ if (bufsize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ Shader *shaderObject = GetValidShader(context, entryPoint, shader);
+ if (!shaderObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetUniformLocation(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ const GLchar *name)
+{
+ if (strstr(name, "gl_") == name)
+ {
+ return false;
+ }
+
+ // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
+ // shader-related entry points
+ if (context->isWebGL() && !IsValidESSLString(name, strlen(name)))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidNameCharacters);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (!programObject->isLinked())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateHint(const Context *context, angle::EntryPoint entryPoint, GLenum target, GLenum mode)
+{
+ switch (mode)
+ {
+ case GL_FASTEST:
+ case GL_NICEST:
+ case GL_DONT_CARE:
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, mode);
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_GENERATE_MIPMAP_HINT:
+ break;
+
+ case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
+ if (!context->getExtensions().textureFilteringHintCHROMIUM)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
+ return false;
+ }
+ break;
+
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
+ if (context->getClientVersion() < ES_3_0 &&
+ !context->getExtensions().standardDerivativesOES)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
+ return false;
+ }
+ break;
+
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ case GL_POINT_SMOOTH_HINT:
+ case GL_LINE_SMOOTH_HINT:
+ case GL_FOG_HINT:
+ if (context->getClientMajorVersion() >= 2)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateIsBuffer(const Context *context, angle::EntryPoint entryPoint, BufferID buffer)
+{
+ return true;
+}
+
+bool ValidateIsFramebuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer)
+{
+ return true;
+}
+
+bool ValidateIsProgram(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program)
+{
+ return true;
+}
+
+bool ValidateIsRenderbuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ RenderbufferID renderbuffer)
+{
+ return true;
+}
+
+bool ValidateIsShader(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID shader)
+{
+ return true;
+}
+
+bool ValidateIsTexture(const Context *context, angle::EntryPoint entryPoint, TextureID texture)
+{
+ return true;
+}
+
+bool ValidatePixelStorei(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLint param)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ switch (pname)
+ {
+ case GL_UNPACK_IMAGE_HEIGHT:
+ case GL_UNPACK_SKIP_IMAGES:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+
+ case GL_UNPACK_ROW_LENGTH:
+ case GL_UNPACK_SKIP_ROWS:
+ case GL_UNPACK_SKIP_PIXELS:
+ if (!context->getExtensions().unpackSubimageEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+ break;
+
+ case GL_PACK_ROW_LENGTH:
+ case GL_PACK_SKIP_ROWS:
+ case GL_PACK_SKIP_PIXELS:
+ if (!context->getExtensions().packSubimageNV)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+ break;
+ }
+ }
+
+ if (param < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeParam);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_UNPACK_ALIGNMENT:
+ if (param != 1 && param != 2 && param != 4 && param != 8)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidUnpackAlignment);
+ return false;
+ }
+ break;
+
+ case GL_PACK_ALIGNMENT:
+ if (param != 1 && param != 2 && param != 4 && param != 8)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidUnpackAlignment);
+ return false;
+ }
+ break;
+
+ case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+ if (!context->getExtensions().packReverseRowOrderANGLE)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ }
+ break;
+
+ case GL_UNPACK_ROW_LENGTH:
+ case GL_UNPACK_IMAGE_HEIGHT:
+ case GL_UNPACK_SKIP_IMAGES:
+ case GL_UNPACK_SKIP_ROWS:
+ case GL_UNPACK_SKIP_PIXELS:
+ case GL_PACK_ROW_LENGTH:
+ case GL_PACK_SKIP_ROWS:
+ case GL_PACK_SKIP_PIXELS:
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePolygonOffset(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat factor,
+ GLfloat units)
+{
+ return true;
+}
+
+bool ValidateReleaseShaderCompiler(const Context *context, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidateSampleCoverage(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat value,
+ GLboolean invert)
+{
+ return true;
+}
+
+bool ValidateScissor(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ if (width < 0 || height < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateShaderBinary(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const ShaderProgramID *shaders,
+ GLenum binaryformat,
+ const void *binary,
+ GLsizei length)
+{
+ const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
+ if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
+ shaderBinaryFormats.end())
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderBinaryFormat);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateShaderSource(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shader,
+ GLsizei count,
+ const GLchar *const *string,
+ const GLint *length)
+{
+ if (count < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
+ return false;
+ }
+
+ Shader *shaderObject = GetValidShader(context, entryPoint, shader);
+ if (!shaderObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilFunc(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum func,
+ GLint ref,
+ GLuint mask)
+{
+ if (!IsValidStencilFunc(func))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilFuncSeparate(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ GLenum func,
+ GLint ref,
+ GLuint mask)
+{
+ if (!IsValidStencilFace(face))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
+ return false;
+ }
+
+ if (!IsValidStencilFunc(func))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilMask(const Context *context, angle::EntryPoint entryPoint, GLuint mask)
+{
+ return true;
+}
+
+bool ValidateStencilMaskSeparate(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ GLuint mask)
+{
+ if (!IsValidStencilFace(face))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilOp(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum fail,
+ GLenum zfail,
+ GLenum zpass)
+{
+ if (!IsValidStencilOp(fail))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
+ return false;
+ }
+
+ if (!IsValidStencilOp(zfail))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
+ return false;
+ }
+
+ if (!IsValidStencilOp(zpass))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateStencilOpSeparate(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ GLenum fail,
+ GLenum zfail,
+ GLenum zpass)
+{
+ if (!IsValidStencilFace(face))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
+ return false;
+ }
+
+ return ValidateStencilOp(context, entryPoint, fail, zfail, zpass);
+}
+
+bool ValidateUniform1f(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLfloat x)
+{
+ return ValidateUniform(context, entryPoint, GL_FLOAT, location, 1);
+}
+
+bool ValidateUniform1fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLfloat *v)
+{
+ return ValidateUniform(context, entryPoint, GL_FLOAT, location, count);
+}
+
+bool ValidateUniform1i(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLint x)
+{
+ return ValidateUniform1iv(context, entryPoint, location, 1, &x);
+}
+
+bool ValidateUniform2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLfloat *v)
+{
+ return ValidateUniform(context, entryPoint, GL_FLOAT_VEC2, location, count);
+}
+
+bool ValidateUniform2i(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLint x,
+ GLint y)
+{
+ return ValidateUniform(context, entryPoint, GL_INT_VEC2, location, 1);
+}
+
+bool ValidateUniform2iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLint *v)
+{
+ return ValidateUniform(context, entryPoint, GL_INT_VEC2, location, count);
+}
+
+bool ValidateUniform3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z)
+{
+ return ValidateUniform(context, entryPoint, GL_FLOAT_VEC3, location, 1);
+}
+
+bool ValidateUniform3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLfloat *v)
+{
+ return ValidateUniform(context, entryPoint, GL_FLOAT_VEC3, location, count);
+}
+
+bool ValidateUniform3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLint x,
+ GLint y,
+ GLint z)
+{
+ return ValidateUniform(context, entryPoint, GL_INT_VEC3, location, 1);
+}
+
+bool ValidateUniform3iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLint *v)
+{
+ return ValidateUniform(context, entryPoint, GL_INT_VEC3, location, count);
+}
+
+bool ValidateUniform4f(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w)
+{
+ return ValidateUniform(context, entryPoint, GL_FLOAT_VEC4, location, 1);
+}
+
+bool ValidateUniform4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLfloat *v)
+{
+ return ValidateUniform(context, entryPoint, GL_FLOAT_VEC4, location, count);
+}
+
+bool ValidateUniform4i(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint w)
+{
+ return ValidateUniform(context, entryPoint, GL_INT_VEC4, location, 1);
+}
+
+bool ValidateUniform4iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLint *v)
+{
+ return ValidateUniform(context, entryPoint, GL_INT_VEC4, location, count);
+}
+
+bool ValidateUniformMatrix2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT2, location, count, transpose);
+}
+
+bool ValidateUniformMatrix3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT3, location, count, transpose);
+}
+
+bool ValidateUniformMatrix4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT4, location, count, transpose);
+}
+
+bool ValidateValidateProgram(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program)
+{
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexAttrib1f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLfloat x)
+{
+ return ValidateVertexAttribIndex(context, entryPoint, index);
+}
+
+bool ValidateVertexAttrib1fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLfloat *values)
+{
+ return ValidateVertexAttribIndex(context, entryPoint, index);
+}
+
+bool ValidateVertexAttrib2f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLfloat x,
+ GLfloat y)
+{
+ return ValidateVertexAttribIndex(context, entryPoint, index);
+}
+
+bool ValidateVertexAttrib2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLfloat *values)
+{
+ return ValidateVertexAttribIndex(context, entryPoint, index);
+}
+
+bool ValidateVertexAttrib3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z)
+{
+ return ValidateVertexAttribIndex(context, entryPoint, index);
+}
+
+bool ValidateVertexAttrib3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLfloat *values)
+{
+ return ValidateVertexAttribIndex(context, entryPoint, index);
+}
+
+bool ValidateVertexAttrib4f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w)
+{
+ return ValidateVertexAttribIndex(context, entryPoint, index);
+}
+
+bool ValidateVertexAttrib4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLfloat *values)
+{
+ return ValidateVertexAttribIndex(context, entryPoint, index);
+}
+
+bool ValidateViewport(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ if (width < 0 || height < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kViewportNegativeSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetFramebufferAttachmentParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ const GLint *params)
+{
+ return ValidateGetFramebufferAttachmentParameterivBase(context, entryPoint, target, attachment,
+ pname, nullptr);
+}
+
+bool ValidateGetProgramiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum pname,
+ const GLint *params)
+{
+ return ValidateGetProgramivBase(context, entryPoint, program, pname, nullptr);
+}
+
+bool ValidateCopyTexImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2CopyTexImageParameters(context, entryPoint, target, level, internalformat,
+ false, 0, 0, x, y, width, height, border);
+ }
+
+ ASSERT(context->getClientMajorVersion() == 3);
+ return ValidateES3CopyTexImage2DParameters(context, entryPoint, target, level, internalformat,
+ false, 0, 0, 0, x, y, width, height, border);
+}
+
+bool ValidateCopyTexSubImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2CopyTexImageParameters(context, entryPoint, target, level, GL_NONE, true,
+ xoffset, yoffset, x, y, width, height, 0);
+ }
+
+ return ValidateES3CopyTexImage2DParameters(context, entryPoint, target, level, GL_NONE, true,
+ xoffset, yoffset, 0, x, y, width, height, 0);
+}
+
+bool ValidateCopyTexSubImage3DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ return ValidateCopyTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset, zoffset,
+ x, y, width, height);
+}
+
+bool ValidateDeleteBuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint n,
+ const BufferID *buffers)
+{
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateDeleteFramebuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint n,
+ const FramebufferID *framebuffers)
+{
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateDeleteRenderbuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint n,
+ const RenderbufferID *renderbuffers)
+{
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateDeleteTextures(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint n,
+ const TextureID *textures)
+{
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateDisable(const Context *context, angle::EntryPoint entryPoint, GLenum cap)
+{
+ if (!ValidCap(context, cap, false))
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, cap);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateEnable(const Context *context, angle::EntryPoint entryPoint, GLenum cap)
+{
+ if (!ValidCap(context, cap, false))
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, cap);
+ return false;
+ }
+
+ if (context->getLimitations().noSampleAlphaToCoverageSupport &&
+ cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kNoSampleAlphaToCoveragesLimitation);
+
+ // We also output an error message to the debugger window if tracing is active, so that
+ // developers can see the error message.
+ ERR() << kNoSampleAlphaToCoveragesLimitation;
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferRenderbuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ RenderbufferID renderbuffer)
+{
+ return ValidateFramebufferRenderbufferBase(context, entryPoint, target, attachment,
+ renderbuffertarget, renderbuffer);
+}
+
+bool ValidateFramebufferTexture2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textarget,
+ TextureID texture,
+ GLint level)
+{
+ // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
+ // extension
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmapOES &&
+ level != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFramebufferTextureLevel);
+ return false;
+ }
+
+ if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
+ {
+ return false;
+ }
+
+ if (texture.value != 0)
+ {
+ Texture *tex = context->getTexture(texture);
+ ASSERT(tex);
+
+ const Caps &caps = context->getCaps();
+
+ switch (textarget)
+ {
+ case TextureTarget::_2D:
+ {
+ if (level > log2(caps.max2DTextureSize))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+ if (tex->getType() != TextureType::_2D)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidTextureTarget);
+ return false;
+ }
+ }
+ break;
+
+ case TextureTarget::Rectangle:
+ {
+ if (level != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+ if (tex->getType() != TextureType::Rectangle)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTextureTargetMismatch);
+ return false;
+ }
+ }
+ break;
+
+ case TextureTarget::CubeMapNegativeX:
+ case TextureTarget::CubeMapNegativeY:
+ case TextureTarget::CubeMapNegativeZ:
+ case TextureTarget::CubeMapPositiveX:
+ case TextureTarget::CubeMapPositiveY:
+ case TextureTarget::CubeMapPositiveZ:
+ {
+ if (level > log2(caps.maxCubeMapTextureSize))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+ if (tex->getType() != TextureType::CubeMap)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTextureTargetMismatch);
+ return false;
+ }
+ }
+ break;
+
+ case TextureTarget::_2DMultisample:
+ {
+ if (context->getClientVersion() < ES_3_1 &&
+ !context->getExtensions().textureMultisampleANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMultisampleTextureExtensionOrES31Required);
+ return false;
+ }
+
+ if (level != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kLevelNotZero);
+ return false;
+ }
+ if (tex->getType() != TextureType::_2DMultisample)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTextureTargetMismatch);
+ return false;
+ }
+ }
+ break;
+
+ case TextureTarget::External:
+ {
+ if (!context->getExtensions().YUVTargetEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kYUVTargetExtensionRequired);
+ return false;
+ }
+
+ if (attachment != GL_COLOR_ATTACHMENT0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAttachment);
+ return false;
+ }
+
+ if (tex->getType() != TextureType::External)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTextureTargetMismatch);
+ return false;
+ }
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferTexture3DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texture,
+ GLint level,
+ GLint zoffset)
+{
+ // We don't call into a base ValidateFramebufferTexture3D here because
+ // it doesn't exist for OpenGL ES. This function is replaced by
+ // FramebufferTextureLayer in ES 3.x, which has broader support.
+ if (!context->getExtensions().texture3DOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ // Attachments are required to be bound to level 0 without ES3 or the
+ // GL_OES_fbo_render_mipmap extension
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmapOES &&
+ level != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFramebufferTextureLevel);
+ return false;
+ }
+
+ if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
+ {
+ return false;
+ }
+
+ if (texture.value != 0)
+ {
+ Texture *tex = context->getTexture(texture);
+ ASSERT(tex);
+
+ const Caps &caps = context->getCaps();
+
+ switch (textargetPacked)
+ {
+ case TextureTarget::_3D:
+ {
+ if (level > log2(caps.max3DTextureSize))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+ if (zoffset >= caps.max3DTextureSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidZOffset);
+ return false;
+ }
+ if (tex->getType() != TextureType::_3D)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureType);
+ return false;
+ }
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureTarget);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGenBuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint n,
+ const BufferID *buffers)
+{
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateGenFramebuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint n,
+ const FramebufferID *framebuffers)
+{
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateGenRenderbuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint n,
+ const RenderbufferID *renderbuffers)
+{
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateGenTextures(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint n,
+ const TextureID *textures)
+{
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateGenerateMipmap(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target)
+{
+ return ValidateGenerateMipmapBase(context, entryPoint, target);
+}
+
+bool ValidateGetBufferParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLenum pname,
+ const GLint *params)
+{
+ return ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, nullptr);
+}
+
+bool ValidateGetRenderbufferParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ const GLint *params)
+{
+ return ValidateGetRenderbufferParameterivBase(context, entryPoint, target, pname, nullptr);
+}
+
+bool ValidateGetShaderiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shader,
+ GLenum pname,
+ const GLint *params)
+{
+ return ValidateGetShaderivBase(context, entryPoint, shader, pname, nullptr);
+}
+
+bool ValidateGetTexParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ const GLfloat *params)
+{
+ return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr);
+}
+
+bool ValidateGetTexParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ const GLint *params)
+{
+ return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr);
+}
+
+bool ValidateGetTexParameterIivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ const GLint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr);
+}
+
+bool ValidateGetTexParameterIuivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ const GLuint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr);
+}
+
+bool ValidateGetUniformfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ const GLfloat *params)
+{
+ return ValidateGetUniformBase(context, entryPoint, program, location);
+}
+
+bool ValidateGetUniformiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ const GLint *params)
+{
+ return ValidateGetUniformBase(context, entryPoint, program, location);
+}
+
+bool ValidateGetVertexAttribfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ const GLfloat *params)
+{
+ return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, false);
+}
+
+bool ValidateGetVertexAttribiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ const GLint *params)
+{
+ return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, false);
+}
+
+bool ValidateGetVertexAttribPointerv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ void *const *pointer)
+{
+ return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, true, false);
+}
+
+bool ValidateIsEnabled(const Context *context, angle::EntryPoint entryPoint, GLenum cap)
+{
+ if (!ValidCap(context, cap, true))
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, cap);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateLinkProgram(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program)
+{
+ if (context->hasActiveTransformFeedback(program))
+ {
+ // ES 3.0.4 section 2.15 page 91
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTransformFeedbackActiveDuringLink);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateReadPixels(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ return ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, -1,
+ nullptr, nullptr, nullptr, pixels);
+}
+
+bool ValidateTexParameterf(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLfloat param)
+{
+ return ValidateTexParameterBase(context, entryPoint, target, pname, -1, false, &param);
+}
+
+bool ValidateTexParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ const GLfloat *params)
+{
+ return ValidateTexParameterBase(context, entryPoint, target, pname, -1, true, params);
+}
+
+bool ValidateTexParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ GLint param)
+{
+ return ValidateTexParameterBase(context, entryPoint, target, pname, -1, false, &param);
+}
+
+bool ValidateTexParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ const GLint *params)
+{
+ return ValidateTexParameterBase(context, entryPoint, target, pname, -1, true, params);
+}
+
+bool ValidateTexParameterIivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ const GLint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateTexParameterBase(context, entryPoint, target, pname, -1, true, params);
+}
+
+bool ValidateTexParameterIuivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum pname,
+ const GLuint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateTexParameterBase(context, entryPoint, target, pname, -1, true, params);
+}
+
+bool ValidateUseProgram(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program)
+{
+ if (program.value != 0)
+ {
+ Program *programObject = context->getProgramResolveLink(program);
+ if (!programObject)
+ {
+ // ES 3.1.0 section 7.3 page 72
+ if (context->getShader(program))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExpectedProgramName);
+ return false;
+ }
+ else
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramName);
+ return false;
+ }
+ }
+ if (!programObject->isLinked())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
+ return false;
+ }
+ }
+ if (context->getState().isTransformFeedbackActiveUnpaused())
+ {
+ // ES 3.0.4 section 2.15 page 91
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackUseProgram);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDeleteFencesNV(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const FenceNVID *fences)
+{
+ if (!context->getExtensions().fenceNV)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported);
+ return false;
+ }
+
+ if (n < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFinishFenceNV(const Context *context, angle::EntryPoint entryPoint, FenceNVID fence)
+{
+ if (!context->getExtensions().fenceNV)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported);
+ return false;
+ }
+
+ FenceNV *fenceObject = context->getFenceNV(fence);
+
+ if (fenceObject == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFence);
+ return false;
+ }
+
+ if (!fenceObject->isSet())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFenceState);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGenFencesNV(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const FenceNVID *fences)
+{
+ if (!context->getExtensions().fenceNV)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported);
+ return false;
+ }
+
+ if (n < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetFenceivNV(const Context *context,
+ angle::EntryPoint entryPoint,
+ FenceNVID fence,
+ GLenum pname,
+ const GLint *params)
+{
+ if (!context->getExtensions().fenceNV)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported);
+ return false;
+ }
+
+ FenceNV *fenceObject = context->getFenceNV(fence);
+
+ if (fenceObject == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFence);
+ return false;
+ }
+
+ if (!fenceObject->isSet())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFenceState);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_FENCE_STATUS_NV:
+ case GL_FENCE_CONDITION_NV:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetGraphicsResetStatusEXT(const Context *context, angle::EntryPoint entryPoint)
+{
+ if (!context->getExtensions().robustnessEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetTranslatedShaderSourceANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shader,
+ GLsizei bufsize,
+ const GLsizei *length,
+ const GLchar *source)
+{
+ if (!context->getExtensions().translatedShaderSourceANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (bufsize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ Shader *shaderObject = context->getShader(shader);
+
+ if (!shaderObject)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidShaderName);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateIsFenceNV(const Context *context, angle::EntryPoint entryPoint, FenceNVID fence)
+{
+ if (!context->getExtensions().fenceNV)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSetFenceNV(const Context *context,
+ angle::EntryPoint entryPoint,
+ FenceNVID fence,
+ GLenum condition)
+{
+ if (!context->getExtensions().fenceNV)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported);
+ return false;
+ }
+
+ if (condition != GL_ALL_COMPLETED_NV)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFenceCondition);
+ return false;
+ }
+
+ FenceNV *fenceObject = context->getFenceNV(fence);
+
+ if (fenceObject == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFence);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTestFenceNV(const Context *context, angle::EntryPoint entryPoint, FenceNVID fence)
+{
+ if (!context->getExtensions().fenceNV)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported);
+ return false;
+ }
+
+ FenceNV *fenceObject = context->getFenceNV(fence);
+
+ if (fenceObject == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFence);
+ return false;
+ }
+
+ if (fenceObject->isSet() != GL_TRUE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFenceState);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTexStorage2DEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType type,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ if (!context->getExtensions().textureStorageEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2TexStorageParametersBase(context, entryPoint, type, levels,
+ internalformat, width, height);
+ }
+
+ ASSERT(context->getClientMajorVersion() >= 3);
+ return ValidateES3TexStorage2DParameters(context, entryPoint, type, levels, internalformat,
+ width, height, 1);
+}
+
+bool ValidateVertexAttribDivisorANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLuint divisor)
+{
+ if (!context->getExtensions().instancedArraysANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ if (context->getLimitations().attributeZeroRequiresZeroDivisorInEXT)
+ {
+ if (index == 0 && divisor != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kAttributeZeroRequiresDivisorLimitation);
+
+ // We also output an error message to the debugger window if tracing is active, so
+ // that developers can see the error message.
+ ERR() << kAttributeZeroRequiresDivisorLimitation;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateVertexAttribDivisorEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLuint divisor)
+{
+ if (!context->getExtensions().instancedArraysEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTexImage3DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ return ValidateTexImage3D(context, entryPoint, target, level, internalformat, width, height,
+ depth, border, format, type, pixels);
+}
+
+bool ValidatePopGroupMarkerEXT(const Context *context, angle::EntryPoint entryPoint)
+{
+ if (!context->getExtensions().debugMarkerEXT)
+ {
+ // The debug marker calls should not set error state
+ // However, it seems reasonable to set an error state if the extension is not enabled
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTexStorage1DEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width)
+{
+ UNIMPLEMENTED();
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+}
+
+bool ValidateTexStorage3DEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ if (!context->getExtensions().textureStorageEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateES3TexStorage3DParameters(context, entryPoint, target, levels, internalformat,
+ width, height, depth);
+}
+
+bool ValidateMaxShaderCompilerThreadsKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint count)
+{
+ if (!context->getExtensions().parallelShaderCompileKHR)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateMultiDrawArraysANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ GLsizei drawcount)
+{
+ if (!context->getExtensions().multiDrawANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
+ {
+ if (!ValidateDrawArrays(context, entryPoint, mode, firsts[drawID], counts[drawID]))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateMultiDrawElementsANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ const GLsizei *counts,
+ DrawElementsType type,
+ const GLvoid *const *indices,
+ GLsizei drawcount)
+{
+ if (!context->getExtensions().multiDrawANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
+ {
+ if (!ValidateDrawElements(context, entryPoint, mode, counts[drawID], type, indices[drawID]))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateProvokingVertexANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProvokingVertexConvention modePacked)
+{
+ if (!context->getExtensions().provokingVertexANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ switch (modePacked)
+ {
+ case ProvokingVertexConvention::FirstVertexConvention:
+ case ProvokingVertexConvention::LastVertexConvention:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProvokingVertex);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferTexture2DMultisampleEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textarget,
+ TextureID texture,
+ GLint level,
+ GLsizei samples)
+{
+ if (!context->getExtensions().multisampledRenderToTextureEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (samples < 0)
+ {
+ return false;
+ }
+
+ // EXT_multisampled_render_to_texture states that the value of samples
+ // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples)
+ // otherwise GL_INVALID_VALUE is generated.
+ if (samples > context->getCaps().maxSamples)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kSamplesOutOfRange);
+ return false;
+ }
+
+ if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
+ {
+ return false;
+ }
+
+ // EXT_multisampled_render_to_texture returns INVALID_OPERATION when a sample number higher than
+ // the maximum sample number supported by this format is passed.
+ // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
+ if (texture.value != 0 && context->getClientMajorVersion() >= 3)
+ {
+ Texture *tex = context->getTexture(texture);
+ GLenum sizedInternalFormat = tex->getFormat(textarget, level).info->sizedInternalFormat;
+ const TextureCaps &formatCaps = context->getTextureCaps().get(sizedInternalFormat);
+ if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kSamplesOutOfRange);
+ return false;
+ }
+ }
+
+ // Unless EXT_multisampled_render_to_texture2 is enabled, only color attachment 0 can be used.
+ if (!context->getExtensions().multisampledRenderToTexture2EXT &&
+ attachment != GL_COLOR_ATTACHMENT0)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
+ return false;
+ }
+
+ if (!ValidTexture2DDestinationTarget(context, textarget))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateRenderbufferStorageMultisampleEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ if (!context->getExtensions().multisampledRenderToTextureEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ if (!ValidateRenderbufferStorageParametersBase(context, entryPoint, target, samples,
+ internalformat, width, height))
+ {
+ return false;
+ }
+
+ // EXT_multisampled_render_to_texture states that the value of samples
+ // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples)
+ // otherwise GL_INVALID_VALUE is generated.
+ if (samples > context->getCaps().maxSamples)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kSamplesOutOfRange);
+ return false;
+ }
+
+ // EXT_multisampled_render_to_texture returns GL_OUT_OF_MEMORY on failure to create
+ // the specified storage. This is different than ES 3.0 in which a sample number higher
+ // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
+ // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
+ if (context->getClientMajorVersion() >= 3)
+ {
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
+ {
+ context->validationError(entryPoint, GL_OUT_OF_MEMORY, kSamplesOutOfRange);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void RecordBindTextureTypeError(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target)
+{
+ ASSERT(!context->getStateCache().isValidBindTextureType(target));
+
+ switch (target)
+ {
+ case TextureType::Rectangle:
+ ASSERT(!context->getExtensions().textureRectangleANGLE);
+ context->validationError(entryPoint, GL_INVALID_ENUM, kTextureRectangleNotSupported);
+ break;
+
+ case TextureType::_3D:
+ case TextureType::_2DArray:
+ ASSERT(context->getClientMajorVersion() < 3);
+ context->validationError(entryPoint, GL_INVALID_ENUM, kES3Required);
+ break;
+
+ case TextureType::_2DMultisample:
+ ASSERT(context->getClientVersion() < Version(3, 1) &&
+ !context->getExtensions().textureMultisampleANGLE);
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kMultisampleTextureExtensionOrES31Required);
+ break;
+
+ case TextureType::_2DMultisampleArray:
+ ASSERT(!context->getExtensions().textureStorageMultisample2dArrayOES);
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kMultisampleArrayExtensionRequired);
+ break;
+
+ case TextureType::External:
+ ASSERT(!context->getExtensions().EGLImageExternalOES &&
+ !context->getExtensions().EGLStreamConsumerExternalNV);
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExternalTextureNotSupported);
+ break;
+
+ case TextureType::VideoImage:
+ ASSERT(!context->getExtensions().videoTextureWEBGL);
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ break;
+
+ case TextureType::Buffer:
+ ASSERT(!context->getExtensions().textureBufferOES &&
+ !context->getExtensions().textureBufferEXT);
+ context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ }
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/validationES2.h b/gfx/angle/checkout/src/libANGLE/validationES2.h
new file mode 100644
index 0000000000..399779aa7c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES2.h
@@ -0,0 +1,207 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationES2.h:
+// Inlined validation functions for OpenGL ES 2.0 entry points.
+
+#ifndef LIBANGLE_VALIDATION_ES2_H_
+#define LIBANGLE_VALIDATION_ES2_H_
+
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES2_autogen.h"
+
+namespace gl
+{
+ANGLE_INLINE bool ValidateDrawArrays(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count)
+{
+ return ValidateDrawArraysCommon(context, entryPoint, mode, first, count, 1);
+}
+
+ANGLE_INLINE bool ValidateUniform2f(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLfloat x,
+ GLfloat y)
+{
+ return ValidateUniform(context, entryPoint, GL_FLOAT_VEC2, location, 1);
+}
+
+ANGLE_INLINE bool ValidateBindBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ BufferID buffer)
+{
+ if (!context->isValidBufferBinding(target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, err::kInvalidBufferTypes);
+ return false;
+ }
+
+ if (!context->getState().isBindGeneratesResourceEnabled() &&
+ !context->isBufferGenerated(buffer))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, err::kObjectNotGenerated);
+ return false;
+ }
+
+ return true;
+}
+
+ANGLE_INLINE bool ValidateDrawElements(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices)
+{
+ return ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, 1);
+}
+
+ANGLE_INLINE bool ValidateVertexAttribPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint size,
+ VertexAttribType type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *ptr)
+{
+ if (!ValidateFloatVertexFormat(context, entryPoint, index, size, type))
+ {
+ return false;
+ }
+
+ if (stride < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, err::kNegativeStride);
+ return false;
+ }
+
+ if (context->getClientVersion() >= ES_3_1)
+ {
+ const Caps &caps = context->getCaps();
+ if (stride > caps.maxVertexAttribStride)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ err::kExceedsMaxVertexAttribStride);
+ return false;
+ }
+
+ if (index >= static_cast<GLuint>(caps.maxVertexAttribBindings))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ err::kExceedsMaxVertexAttribBindings);
+ return false;
+ }
+ }
+
+ // [OpenGL ES 3.0.2] Section 2.8 page 24:
+ // An INVALID_OPERATION error is generated when a non-zero vertex array object
+ // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
+ // and the pointer argument is not NULL.
+ bool nullBufferAllowed = context->getState().areClientArraysEnabled() &&
+ context->getState().getVertexArray()->id().value == 0;
+ if (!nullBufferAllowed && context->getState().getTargetBuffer(BufferBinding::Array) == 0 &&
+ ptr != nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, err::kClientDataInVertexArray);
+ return false;
+ }
+
+ if (context->isWebGL())
+ {
+ // WebGL 1.0 [Section 6.14] Fixed point support
+ // The WebGL API does not support the GL_FIXED data type.
+ if (type == VertexAttribType::Fixed)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, err::kFixedNotInWebGL);
+ return false;
+ }
+
+ if (!ValidateWebGLVertexAttribPointer(context, entryPoint, type, normalized, stride, ptr,
+ false))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void RecordBindTextureTypeError(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target);
+
+ANGLE_INLINE bool ValidateBindTexture(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ TextureID texture)
+{
+ if (!context->getStateCache().isValidBindTextureType(target))
+ {
+ RecordBindTextureTypeError(context, entryPoint, target);
+ return false;
+ }
+
+ if (texture.value == 0)
+ {
+ return true;
+ }
+
+ Texture *textureObject = context->getTexture(texture);
+ if (textureObject && textureObject->getType() != target)
+ {
+ context->validationErrorF(
+ entryPoint, GL_INVALID_OPERATION, err::kTextureTargetMismatchWithLabel,
+ static_cast<uint8_t>(target), static_cast<uint8_t>(textureObject->getType()),
+ textureObject->getLabel().c_str());
+ return false;
+ }
+
+ if (!context->getState().isBindGeneratesResourceEnabled() &&
+ !context->isTextureGenerated(texture))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, err::kObjectNotGenerated);
+ return false;
+ }
+
+ return true;
+}
+
+// Validation of all Tex[Sub]Image2D parameters except TextureTarget.
+bool ValidateES2TexImageParametersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isCompressed,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei imageSize,
+ const void *pixels);
+
+// Validation of TexStorage*2DEXT
+bool ValidateES2TexStorageParametersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES2_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationES2_autogen.h b/gfx/angle/checkout/src/libANGLE/validationES2_autogen.h
new file mode 100644
index 0000000000..335139fe70
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES2_autogen.h
@@ -0,0 +1,666 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationES2_autogen.h:
+// Validation functions for the OpenGL ES 2.0 entry points.
+
+#ifndef LIBANGLE_VALIDATION_ES2_AUTOGEN_H_
+#define LIBANGLE_VALIDATION_ES2_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "common/entry_points_enum_autogen.h"
+
+namespace gl
+{
+class Context;
+
+bool ValidateActiveTexture(const Context *context, angle::EntryPoint entryPoint, GLenum texture);
+bool ValidateAttachShader(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ ShaderProgramID shaderPacked);
+bool ValidateBindAttribLocation(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLuint index,
+ const GLchar *name);
+bool ValidateBindBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ BufferID bufferPacked);
+bool ValidateBindFramebuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ FramebufferID framebufferPacked);
+bool ValidateBindRenderbuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ RenderbufferID renderbufferPacked);
+bool ValidateBindTexture(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ TextureID texturePacked);
+bool ValidateBlendColor(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue,
+ GLfloat alpha);
+bool ValidateBlendEquation(const Context *context, angle::EntryPoint entryPoint, GLenum mode);
+bool ValidateBlendEquationSeparate(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum modeRGB,
+ GLenum modeAlpha);
+bool ValidateBlendFunc(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum sfactor,
+ GLenum dfactor);
+bool ValidateBlendFuncSeparate(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum sfactorRGB,
+ GLenum dfactorRGB,
+ GLenum sfactorAlpha,
+ GLenum dfactorAlpha);
+bool ValidateBufferData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLsizeiptr size,
+ const void *data,
+ BufferUsage usagePacked);
+bool ValidateBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data);
+bool ValidateCheckFramebufferStatus(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target);
+bool ValidateClear(const Context *context, angle::EntryPoint entryPoint, GLbitfield mask);
+bool ValidateClearColor(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue,
+ GLfloat alpha);
+bool ValidateClearDepthf(const Context *context, angle::EntryPoint entryPoint, GLfloat d);
+bool ValidateClearStencil(const Context *context, angle::EntryPoint entryPoint, GLint s);
+bool ValidateColorMask(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLboolean red,
+ GLboolean green,
+ GLboolean blue,
+ GLboolean alpha);
+bool ValidateCompileShader(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shaderPacked);
+bool ValidateCompressedTexImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const void *data);
+bool ValidateCompressedTexSubImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+bool ValidateCopyTexImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border);
+bool ValidateCopyTexSubImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+bool ValidateCreateProgram(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateCreateShader(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderType typePacked);
+bool ValidateCullFace(const Context *context,
+ angle::EntryPoint entryPoint,
+ CullFaceMode modePacked);
+bool ValidateDeleteBuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const BufferID *buffersPacked);
+bool ValidateDeleteFramebuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const FramebufferID *framebuffersPacked);
+bool ValidateDeleteProgram(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked);
+bool ValidateDeleteRenderbuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const RenderbufferID *renderbuffersPacked);
+bool ValidateDeleteShader(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shaderPacked);
+bool ValidateDeleteTextures(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const TextureID *texturesPacked);
+bool ValidateDepthFunc(const Context *context, angle::EntryPoint entryPoint, GLenum func);
+bool ValidateDepthMask(const Context *context, angle::EntryPoint entryPoint, GLboolean flag);
+bool ValidateDepthRangef(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat n,
+ GLfloat f);
+bool ValidateDetachShader(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ ShaderProgramID shaderPacked);
+bool ValidateDisable(const Context *context, angle::EntryPoint entryPoint, GLenum cap);
+bool ValidateDisableVertexAttribArray(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index);
+bool ValidateDrawArrays(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLint first,
+ GLsizei count);
+bool ValidateDrawElements(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices);
+bool ValidateEnable(const Context *context, angle::EntryPoint entryPoint, GLenum cap);
+bool ValidateEnableVertexAttribArray(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index);
+bool ValidateFinish(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateFlush(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateFramebufferRenderbuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ RenderbufferID renderbufferPacked);
+bool ValidateFramebufferTexture2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texturePacked,
+ GLint level);
+bool ValidateFrontFace(const Context *context, angle::EntryPoint entryPoint, GLenum mode);
+bool ValidateGenBuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const BufferID *buffersPacked);
+bool ValidateGenFramebuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const FramebufferID *framebuffersPacked);
+bool ValidateGenRenderbuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const RenderbufferID *renderbuffersPacked);
+bool ValidateGenTextures(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const TextureID *texturesPacked);
+bool ValidateGenerateMipmap(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked);
+bool ValidateGetActiveAttrib(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *size,
+ const GLenum *type,
+ const GLchar *name);
+bool ValidateGetActiveUniform(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *size,
+ const GLenum *type,
+ const GLchar *name);
+bool ValidateGetAttachedShaders(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLsizei maxCount,
+ const GLsizei *count,
+ const ShaderProgramID *shadersPacked);
+bool ValidateGetAttribLocation(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ const GLchar *name);
+bool ValidateGetBooleanv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLboolean *data);
+bool ValidateGetBufferParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetError(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateGetFloatv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLfloat *data);
+bool ValidateGetFramebufferAttachmentParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetIntegerv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLint *data);
+bool ValidateGetProgramInfoLog(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *infoLog);
+bool ValidateGetProgramiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetRenderbufferParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetShaderInfoLog(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shaderPacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *infoLog);
+bool ValidateGetShaderPrecisionFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum shadertype,
+ GLenum precisiontype,
+ const GLint *range,
+ const GLint *precision);
+bool ValidateGetShaderSource(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shaderPacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *source);
+bool ValidateGetShaderiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shaderPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetString(const Context *context, angle::EntryPoint entryPoint, GLenum name);
+bool ValidateGetTexParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLfloat *params);
+bool ValidateGetTexParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetUniformLocation(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ const GLchar *name);
+bool ValidateGetUniformfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ const GLfloat *params);
+bool ValidateGetUniformiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ const GLint *params);
+bool ValidateGetVertexAttribPointerv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ void *const *pointer);
+bool ValidateGetVertexAttribfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ const GLfloat *params);
+bool ValidateGetVertexAttribiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ const GLint *params);
+bool ValidateHint(const Context *context, angle::EntryPoint entryPoint, GLenum target, GLenum mode);
+bool ValidateIsBuffer(const Context *context, angle::EntryPoint entryPoint, BufferID bufferPacked);
+bool ValidateIsEnabled(const Context *context, angle::EntryPoint entryPoint, GLenum cap);
+bool ValidateIsFramebuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked);
+bool ValidateIsProgram(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked);
+bool ValidateIsRenderbuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ RenderbufferID renderbufferPacked);
+bool ValidateIsShader(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shaderPacked);
+bool ValidateIsTexture(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked);
+bool ValidateLineWidth(const Context *context, angle::EntryPoint entryPoint, GLfloat width);
+bool ValidateLinkProgram(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked);
+bool ValidatePixelStorei(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLint param);
+bool ValidatePolygonOffset(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat factor,
+ GLfloat units);
+bool ValidateReadPixels(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateReleaseShaderCompiler(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateRenderbufferStorage(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+bool ValidateSampleCoverage(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat value,
+ GLboolean invert);
+bool ValidateScissor(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+bool ValidateShaderBinary(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei count,
+ const ShaderProgramID *shadersPacked,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length);
+bool ValidateShaderSource(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shaderPacked,
+ GLsizei count,
+ const GLchar *const *string,
+ const GLint *length);
+bool ValidateStencilFunc(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum func,
+ GLint ref,
+ GLuint mask);
+bool ValidateStencilFuncSeparate(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ GLenum func,
+ GLint ref,
+ GLuint mask);
+bool ValidateStencilMask(const Context *context, angle::EntryPoint entryPoint, GLuint mask);
+bool ValidateStencilMaskSeparate(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ GLuint mask);
+bool ValidateStencilOp(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum fail,
+ GLenum zfail,
+ GLenum zpass);
+bool ValidateStencilOpSeparate(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ GLenum sfail,
+ GLenum dpfail,
+ GLenum dppass);
+bool ValidateTexImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateTexParameterf(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ GLfloat param);
+bool ValidateTexParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLfloat *params);
+bool ValidateTexParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ GLint param);
+bool ValidateTexParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateTexSubImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateUniform1f(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLfloat v0);
+bool ValidateUniform1fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateUniform1i(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLint v0);
+bool ValidateUniform1iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateUniform2f(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1);
+bool ValidateUniform2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateUniform2i(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1);
+bool ValidateUniform2iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateUniform3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2);
+bool ValidateUniform3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateUniform3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2);
+bool ValidateUniform3iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateUniform4f(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2,
+ GLfloat v3);
+bool ValidateUniform4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateUniform4i(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2,
+ GLint v3);
+bool ValidateUniform4iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateUniformMatrix2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUniformMatrix3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUniformMatrix4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUseProgram(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked);
+bool ValidateValidateProgram(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked);
+bool ValidateVertexAttrib1f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLfloat x);
+bool ValidateVertexAttrib1fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLfloat *v);
+bool ValidateVertexAttrib2f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLfloat x,
+ GLfloat y);
+bool ValidateVertexAttrib2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLfloat *v);
+bool ValidateVertexAttrib3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z);
+bool ValidateVertexAttrib3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLfloat *v);
+bool ValidateVertexAttrib4f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w);
+bool ValidateVertexAttrib4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLfloat *v);
+bool ValidateVertexAttribPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint size,
+ VertexAttribType typePacked,
+ GLboolean normalized,
+ GLsizei stride,
+ const void *pointer);
+bool ValidateViewport(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES2_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationES3.cpp b/gfx/angle/checkout/src/libANGLE/validationES3.cpp
new file mode 100644
index 0000000000..633cc02da9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES3.cpp
@@ -0,0 +1,5311 @@
+//
+// Copyright 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
+
+#include "libANGLE/validationES3_autogen.h"
+
+#include "anglebase/numerics/safe_conversions.h"
+#include "common/mathutil.h"
+#include "common/utilities.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/PixelLocalStorage.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/validationES.h"
+
+using namespace angle;
+
+namespace gl
+{
+using namespace err;
+
+namespace
+{
+bool ValidateFramebufferTextureMultiviewBaseANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureID texture,
+ GLint level,
+ GLsizei numViews)
+{
+ if (!(context->getExtensions().multiviewOVR || context->getExtensions().multiview2OVR))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kMultiviewNotAvailable);
+ return false;
+ }
+
+ if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
+ {
+ return false;
+ }
+
+ if (texture.value != 0 && numViews < 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kMultiviewViewsTooSmall);
+ return false;
+ }
+
+ if (static_cast<GLuint>(numViews) > context->getCaps().maxViews)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kMultiviewViewsTooLarge);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferTextureMultiviewLevelAndFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ const Texture *texture,
+ GLint level)
+{
+ TextureType type = texture->getType();
+ if (!ValidMipLevel(context, type, level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+
+ const auto &format = texture->getFormat(NonCubeTextureTypeToTarget(type), level);
+ if (format.info->compressed)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kCompressedTexturesNotAttachable);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateUniformES3(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum uniformType,
+ UniformLocation location,
+ GLint count)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateUniform(context, entryPoint, uniformType, location, count);
+}
+
+bool ValidateUniformMatrixES3(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum valueType,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose)
+{
+ // Check for ES3 uniform entry points
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateUniformMatrix(context, entryPoint, valueType, location, count, transpose);
+}
+
+bool ValidateGenOrDeleteES3(const Context *context, angle::EntryPoint entryPoint, GLint n)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateGenOrDeleteCountES3(const Context *context, angle::EntryPoint entryPoint, GLint count)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ if (count < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateCopyTexture3DCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ const Texture *source,
+ GLint sourceLevel,
+ GLint srcInternalFormat,
+ const Texture *dest,
+ GLint destLevel,
+ GLint internalFormat,
+ TextureTarget destTarget)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!context->getExtensions().copyTexture3dANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kANGLECopyTexture3DUnavailable);
+ return false;
+ }
+
+ if (!ValidTexture3DTarget(context, source->getType()))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ // Table 1.1 from the ANGLE_copy_texture_3d spec
+ switch (GetUnsizedFormat(srcInternalFormat))
+ {
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RED:
+ case GL_RED_INTEGER:
+ case GL_RG:
+ case GL_RG_INTEGER:
+ case GL_RGB:
+ case GL_RGB_INTEGER:
+ case GL_RGBA:
+ case GL_RGBA_INTEGER:
+ case GL_DEPTH_COMPONENT:
+ case GL_DEPTH_STENCIL:
+ break;
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
+ srcInternalFormat);
+ return false;
+ }
+
+ if (!ValidTexture3DTarget(context, TextureTargetToType(destTarget)))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ // Table 1.0 from the ANGLE_copy_texture_3d spec
+ switch (internalFormat)
+ {
+ case GL_RGB:
+ case GL_RGBA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_ALPHA:
+ case GL_R8:
+ case GL_R8_SNORM:
+ case GL_R16F:
+ case GL_R32F:
+ case GL_R8UI:
+ case GL_R8I:
+ case GL_R16UI:
+ case GL_R16I:
+ case GL_R32UI:
+ case GL_R32I:
+ case GL_RG:
+ case GL_RG8:
+ case GL_RG8_SNORM:
+ case GL_RG16F:
+ case GL_RG32F:
+ case GL_RG8UI:
+ case GL_RG8I:
+ case GL_RG16UI:
+ case GL_RG16I:
+ case GL_RG32UI:
+ case GL_RG32I:
+ case GL_RGB8:
+ case GL_RGBX8_ANGLE:
+ case GL_SRGB8:
+ case GL_RGB565:
+ case GL_RGB8_SNORM:
+ case GL_R11F_G11F_B10F:
+ case GL_RGB9_E5:
+ case GL_RGB16F:
+ case GL_RGB32F:
+ case GL_RGB8UI:
+ case GL_RGB8I:
+ case GL_RGB16UI:
+ case GL_RGB16I:
+ case GL_RGB32UI:
+ case GL_RGB32I:
+ case GL_RGBA8:
+ case GL_SRGB8_ALPHA8:
+ case GL_RGBA8_SNORM:
+ case GL_RGB5_A1:
+ case GL_RGBA4:
+ case GL_RGB10_A2:
+ case GL_RGBA16F:
+ case GL_RGBA32F:
+ case GL_RGBA8UI:
+ case GL_RGBA8I:
+ case GL_RGB10_A2UI:
+ case GL_RGBA16UI:
+ case GL_RGBA16I:
+ case GL_RGBA32I:
+ case GL_RGBA32UI:
+ break;
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
+ internalFormat);
+ return false;
+ }
+
+ return true;
+}
+} // anonymous namespace
+
+static bool ValidateTexImageFormatCombination(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum internalFormat,
+ GLenum format,
+ GLenum type)
+{
+ // Different validation if on desktop api
+ if (context->getClientType() == EGL_OPENGL_API)
+ {
+ // The type and format are valid if any supported internal format has that type and format
+ if (!ValidDesktopFormat(format))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+
+ if (!ValidDesktopType(type))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
+ return false;
+ }
+ }
+ else
+ {
+ // The type and format are valid if any supported internal format has that type and format.
+ // ANGLE_texture_external_yuv_sampling extension adds support for YUV formats
+ if (gl::IsYuvFormat(format))
+ {
+ if (!context->getExtensions().yuvInternalFormatANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+ }
+ else
+ {
+ if (!ValidES3Format(format))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+ }
+
+ if (!ValidES3Type(type) || (type == GL_HALF_FLOAT_OES && context->isWebGL()))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
+ return false;
+ }
+ }
+
+ // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
+ // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
+ // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
+ // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
+ if (!ValidES3InternalFormat(internalFormat))
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_VALUE, kInvalidInternalFormat,
+ internalFormat);
+ return false;
+ }
+
+ // From the ES 3.0 spec section 3.8.3:
+ // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
+ // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
+ // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
+ // INVALID_OPERATION error.
+ if (target == TextureType::_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, k3DDepthStencil);
+ return false;
+ }
+
+ if (context->getClientType() == EGL_OPENGL_API)
+ {
+ // Check if this is a valid format combination to load texture data
+ if (!ValidDesktopFormatCombination(format, type, internalFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormatCombination);
+ return false;
+ }
+ }
+ else
+ {
+ // Check if this is a valid format combination to load texture data
+ // ANGLE_texture_external_yuv_sampling extension adds support for YUV formats
+ if (gl::IsYuvFormat(format))
+ {
+ if (type != GL_UNSIGNED_BYTE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidFormatCombination);
+ return false;
+ }
+ }
+ else
+ {
+ if (!ValidES3FormatCombination(format, type, internalFormat))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidFormatCombination);
+ return false;
+ }
+ }
+ }
+
+ const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat, type);
+ if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
+ internalFormat);
+ return false;
+ }
+
+ return true;
+}
+
+static bool ValidateES3CompressedFormatForTexture2DArray(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum format)
+{
+ if (IsETC1Format(format) || IsPVRTC1Format(format))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInternalFormatRequiresTexture2D);
+ return false;
+ }
+
+ return true;
+}
+
+static bool ValidateES3CompressedFormatForTexture3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum format)
+{
+ if (IsETC1Format(format) || IsPVRTC1Format(format))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInternalFormatRequiresTexture2D);
+ return false;
+ }
+
+ if (IsETC2EACFormat(format))
+ {
+ // ES 3.1, Section 8.7, page 169.
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInternalFormatRequiresTexture2DArray);
+ return false;
+ }
+
+ if (IsASTC2DFormat(format) && !(context->getExtensions().textureCompressionAstcHdrKHR ||
+ context->getExtensions().textureCompressionAstcSliced3dKHR))
+ {
+ // GL_KHR_texture_compression_astc_hdr, TEXTURE_3D is not supported without HDR profile
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInternalFormatRequiresTexture2DArrayASTC);
+ return false;
+ }
+
+ if (IsS3TCFormat(format))
+ {
+ // GL_EXT_texture_compression_s3tc
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInternalFormatRequiresTexture2DArrayS3TC);
+ return false;
+ }
+
+ if (IsRGTCFormat(format))
+ {
+ // GL_EXT_texture_compression_rgtc
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInternalFormatRequiresTexture2DArrayRGTC);
+ return false;
+ }
+
+ if (IsBPTCFormat(format) && (context->getLimitations().noCompressedTexture3D))
+ {
+ // GL_EXT_texture_compression_bptc
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInternalFormatRequiresTexture2DArrayBPTC);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateES3TexImageParametersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isCompressed,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei imageSize,
+ const void *pixels)
+{
+ TextureType texType = TextureTargetToType(target);
+
+ if (gl::IsYuvFormat(format))
+ {
+ // According to ANGLE_yuv_internal_format, the texture needs to be an immutable
+ // texture, texture target can only be TEXTURE_2D and there is no mipmap support
+ if (!context->getExtensions().yuvInternalFormatANGLE || !isSubImage)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+
+ if (target != TextureTarget::_2D)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ if (level != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+ }
+
+ // Validate image size
+ if (!ValidImageSizeParameters(context, entryPoint, texType, level, width, height, depth,
+ isSubImage))
+ {
+ // Error already processed.
+ return false;
+ }
+
+ // Verify zero border
+ if (border != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBorder);
+ return false;
+ }
+
+ if (xoffset < 0 || yoffset < 0 || zoffset < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
+ return false;
+ }
+
+ if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
+ std::numeric_limits<GLsizei>::max() - yoffset < height ||
+ std::numeric_limits<GLsizei>::max() - zoffset < depth)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+
+ switch (texType)
+ {
+ case TextureType::_2D:
+ case TextureType::External:
+ case TextureType::VideoImage:
+ if (width > (caps.max2DTextureSize >> level) ||
+ height > (caps.max2DTextureSize >> level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ break;
+
+ case TextureType::Rectangle:
+ ASSERT(level == 0);
+ if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ if (isCompressed)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kRectangleTextureCompressed);
+ return false;
+ }
+ break;
+
+ case TextureType::CubeMap:
+ if (!isSubImage && width != height)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kCubemapFacesEqualDimensions);
+ return false;
+ }
+
+ if (width > (caps.maxCubeMapTextureSize >> level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ break;
+
+ case TextureType::_3D:
+ if (width > (caps.max3DTextureSize >> level) ||
+ height > (caps.max3DTextureSize >> level) ||
+ depth > (caps.max3DTextureSize >> level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ break;
+
+ case TextureType::_2DArray:
+ if (width > (caps.max2DTextureSize >> level) ||
+ height > (caps.max2DTextureSize >> level) || depth > caps.maxArrayTextureLayers)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ break;
+
+ case TextureType::CubeMapArray:
+ if (!isSubImage && width != height)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kCubemapFacesEqualDimensions);
+ return false;
+ }
+
+ if (width > (caps.maxCubeMapTextureSize >> level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+
+ if (width > (caps.max3DTextureSize >> level) ||
+ height > (caps.max3DTextureSize >> level) ||
+ depth > (caps.max3DTextureSize >> level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+
+ if (!isSubImage && depth % 6 != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kCubemapInvalidDepth);
+ return false;
+ }
+ break;
+
+ case TextureType::InvalidEnum:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumInvalid);
+ return false;
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ ToGLenum(texType));
+ return false;
+ }
+
+ Texture *texture = context->getTextureByType(texType);
+ if (!texture)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingTexture);
+ return false;
+ }
+
+ if (texture->getImmutableFormat() && !isSubImage)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsImmutable);
+ return false;
+ }
+
+ // Validate texture formats
+ GLenum actualInternalFormat =
+ isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
+ if (isSubImage && actualInternalFormat == GL_NONE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidMipLevel);
+ return false;
+ }
+
+ const InternalFormat &actualFormatInfo = isSubImage
+ ? *texture->getFormat(target, level).info
+ : GetInternalFormatInfo(internalformat, type);
+ if (isCompressed)
+ {
+ // compressedTexSubImage does not generate GL_INVALID_ENUM when format is unknown or invalid
+ if (!isSubImage)
+ {
+ if (!actualFormatInfo.compressed && !actualFormatInfo.paletted)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kCompressedMismatch);
+ return false;
+ }
+
+ if (!actualFormatInfo.textureSupport(context->getClientVersion(),
+ context->getExtensions()))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+ }
+
+ if (texType == TextureType::_2DArray)
+ {
+ GLenum compressedDataFormat = isSubImage ? format : internalformat;
+ if (!ValidateES3CompressedFormatForTexture2DArray(context, entryPoint,
+ compressedDataFormat))
+ {
+ // Error already generated.
+ return false;
+ }
+ }
+
+ if (texType == TextureType::_3D)
+ {
+ GLenum compressedDataFormat = isSubImage ? format : internalformat;
+ if (!ValidateES3CompressedFormatForTexture3D(context, entryPoint, compressedDataFormat))
+ {
+ // Error already generated.
+ return false;
+ }
+ }
+
+ if (isSubImage)
+ {
+ if (!ValidCompressedSubImageSize(
+ context, actualFormatInfo.internalFormat, xoffset, yoffset, zoffset, width,
+ height, depth, texture->getWidth(target, level),
+ texture->getHeight(target, level), texture->getDepth(target, level)))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidCompressedImageSize);
+ return false;
+ }
+
+ if (format != actualInternalFormat)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kMismatchedFormat);
+ return false;
+ }
+
+ // GL_EXT_compressed_ETC1_RGB8_sub_texture allows this format
+ if (IsETC1Format(actualInternalFormat) &&
+ !context->getExtensions().compressedETC1RGB8SubTextureEXT)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
+ internalformat);
+ return false;
+ }
+ }
+ else
+ {
+ if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height,
+ depth))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidCompressedImageSize);
+ return false;
+ }
+ }
+
+ // Disallow 3D-only compressed formats from being set on 2D textures
+ if (actualFormatInfo.compressedBlockDepth > 1 && texType != TextureType::_2DArray)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureTarget);
+ return false;
+ }
+ }
+ else
+ {
+ // Compressed formats are not valid internal formats for glTexImage*D
+ if (!isSubImage)
+ {
+ const InternalFormat &internalFormatInfo = GetSizedInternalFormatInfo(internalformat);
+ if (internalFormatInfo.compressed)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_VALUE, kInvalidInternalFormat,
+ internalformat);
+ return false;
+ }
+ }
+
+ if (!ValidateTexImageFormatCombination(context, entryPoint, texType, actualInternalFormat,
+ format, type))
+ {
+ return false;
+ }
+ }
+
+ // Validate sub image parameters
+ if (isSubImage)
+ {
+ if (isCompressed != actualFormatInfo.compressed)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kCompressedMismatch);
+ return false;
+ }
+
+ if (xoffset < 0 || yoffset < 0 || zoffset < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
+ return false;
+ }
+
+ if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
+ std::numeric_limits<GLsizei>::max() - yoffset < height ||
+ std::numeric_limits<GLsizei>::max() - zoffset < depth)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow);
+ return false;
+ }
+
+ if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
+ static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
+ static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow);
+ return false;
+ }
+
+ if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
+ context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kPixelDataNull);
+ return false;
+ }
+ }
+
+ GLenum sizeCheckFormat = isSubImage ? format : internalformat;
+ if (!ValidImageDataSize(context, entryPoint, texType, width, height, depth, sizeCheckFormat,
+ type, pixels, imageSize))
+ {
+ return false;
+ }
+
+ // Check for pixel unpack buffer related API errors
+ Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
+ if (pixelUnpackBuffer != nullptr)
+ {
+ // ...data is not evenly divisible into the number of bytes needed to store in memory a
+ // datum
+ // indicated by type.
+ if (!isCompressed)
+ {
+ size_t offset = reinterpret_cast<size_t>(pixels);
+ size_t dataBytesPerPixel = static_cast<size_t>(GetTypeInfo(type).bytes);
+
+ if ((offset % dataBytesPerPixel) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDataTypeNotAligned);
+ return false;
+ }
+ }
+
+ // ...the buffer object's data store is currently mapped but not persistently.
+ if (pixelUnpackBuffer->isMapped() && !pixelUnpackBuffer->isPersistentlyMapped())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferMapped);
+ return false;
+ }
+ }
+
+ if (context->getExtensions().webglCompatibilityANGLE)
+ {
+ // Define:
+ // DataStoreWidth = (GL_UNPACK_ROW_LENGTH ? GL_UNPACK_ROW_LENGTH : width)
+ // DataStoreHeight = (GL_UNPACK_IMAGE_HEIGHT ? GL_UNPACK_IMAGE_HEIGHT : height)
+ //
+ // WebGL 2.0 imposes the following additional constraints:
+ //
+ // 1) texImage2D and texSubImage2D generate INVALID_OPERATION if:
+ // GL_UNPACK_SKIP_PIXELS + width > DataStoreWidth
+ // except for texImage2D if no GL_PIXEL_UNPACK_BUFFER is
+ // bound and _pixels_ is null.
+ //
+ // 2) texImage3D and texSubImage3D generate INVALID_OPERATION if:
+ // GL_UNPACK_SKIP_PIXELS + width > DataStoreWidth
+ // GL_UNPACK_SKIP_ROWS + height > DataStoreHeight
+ // except for texImage3D if no GL_PIXEL_UNPACK_BUFFER is
+ // bound and _pixels_ is null.
+ if (!pixelUnpackBuffer && !pixels && !isSubImage)
+ {
+ // Exception case for texImage2D or texImage3D, above.
+ }
+ else
+ {
+ const auto &unpack = context->getState().getUnpackState();
+ GLint dataStoreWidth = unpack.rowLength ? unpack.rowLength : width;
+ if (unpack.skipPixels + width > dataStoreWidth)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidUnpackParametersForWebGL);
+ return false;
+ }
+ if (target == TextureTarget::_3D || target == TextureTarget::_2DArray)
+ {
+ GLint dataStoreHeight = unpack.imageHeight ? unpack.imageHeight : height;
+ if (unpack.skipRows + height > dataStoreHeight)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidUnpackParametersForWebGL);
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+bool ValidateES3TexImage2DParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isCompressed,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei imageSize,
+ const void *pixels)
+{
+ if (!ValidTexture2DDestinationTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ return ValidateES3TexImageParametersBase(
+ context, entryPoint, target, level, internalformat, isCompressed, isSubImage, xoffset,
+ yoffset, zoffset, width, height, depth, border, format, type, imageSize, pixels);
+}
+
+bool ValidateES3TexImage3DParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isCompressed,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ if (!ValidTexture3DDestinationTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ return ValidateES3TexImageParametersBase(
+ context, entryPoint, target, level, internalformat, isCompressed, isSubImage, xoffset,
+ yoffset, zoffset, width, height, depth, border, format, type, bufSize, pixels);
+}
+
+struct EffectiveInternalFormatInfo
+{
+ GLenum effectiveFormat;
+ GLenum destFormat;
+ GLuint minRedBits;
+ GLuint maxRedBits;
+ GLuint minGreenBits;
+ GLuint maxGreenBits;
+ GLuint minBlueBits;
+ GLuint maxBlueBits;
+ GLuint minAlphaBits;
+ GLuint maxAlphaBits;
+};
+
+static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
+ GLenum targetFormat,
+ const EffectiveInternalFormatInfo *list,
+ size_t size,
+ GLenum *outEffectiveFormat)
+{
+ for (size_t curFormat = 0; curFormat < size; ++curFormat)
+ {
+ const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
+ if ((formatInfo.destFormat == targetFormat) &&
+ (formatInfo.minRedBits <= srcFormat.redBits &&
+ formatInfo.maxRedBits >= srcFormat.redBits) &&
+ (formatInfo.minGreenBits <= srcFormat.greenBits &&
+ formatInfo.maxGreenBits >= srcFormat.greenBits) &&
+ (formatInfo.minBlueBits <= srcFormat.blueBits &&
+ formatInfo.maxBlueBits >= srcFormat.blueBits) &&
+ (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
+ formatInfo.maxAlphaBits >= srcFormat.alphaBits))
+ {
+ *outEffectiveFormat = formatInfo.effectiveFormat;
+ return true;
+ }
+ }
+
+ *outEffectiveFormat = GL_NONE;
+ return false;
+}
+
+bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
+ GLenum *outEffectiveFormat)
+{
+ // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
+ // Effective internal format coresponding to destination internal format and linear source
+ // buffer component sizes.
+ // | Source channel min/max sizes |
+ // Effective Internal Format | N/A | R | G | B | A |
+ // clang-format off
+ constexpr EffectiveInternalFormatInfo list[] = {
+ { GL_ALPHA8_EXT, GL_NONE, 0, 0, 0, 0, 0, 0, 1, 8 },
+ { GL_R8, GL_NONE, 1, 8, 0, 0, 0, 0, 0, 0 },
+ { GL_RG8, GL_NONE, 1, 8, 1, 8, 0, 0, 0, 0 },
+ { GL_RGB565, GL_NONE, 1, 5, 1, 6, 1, 5, 0, 0 },
+ { GL_RGB8, GL_NONE, 6, 8, 7, 8, 6, 8, 0, 0 },
+ { GL_RGBA4, GL_NONE, 1, 4, 1, 4, 1, 4, 1, 4 },
+ { GL_RGB5_A1, GL_NONE, 5, 5, 5, 5, 5, 5, 1, 1 },
+ { GL_RGBA8, GL_NONE, 5, 8, 5, 8, 5, 8, 2, 8 },
+ { GL_RGB10_A2, GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
+ };
+ // clang-format on
+
+ return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
+}
+
+bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
+ const InternalFormat &destFormat,
+ GLenum *outEffectiveFormat)
+{
+ constexpr GLuint umax = UINT_MAX;
+
+ // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
+ // Effective internal format coresponding to destination internal format andlinear source buffer
+ // component sizes.
+ // | Source channel min/max sizes |
+ // Effective Internal Format | Dest Format | R | G | B | A |
+ // clang-format off
+ constexpr EffectiveInternalFormatInfo list[] = {
+ { GL_ALPHA8_EXT, GL_ALPHA, 0, umax, 0, umax, 0, umax, 1, 8 },
+ { GL_LUMINANCE8_EXT, GL_LUMINANCE, 1, 8, 0, umax, 0, umax, 0, umax },
+ { GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, 1, 8, 0, umax, 0, umax, 1, 8 },
+ { GL_RGB565, GL_RGB, 1, 5, 1, 6, 1, 5, 0, umax },
+ { GL_RGB8, GL_RGB, 6, 8, 7, 8, 6, 8, 0, umax },
+ { GL_RGBA4, GL_RGBA, 1, 4, 1, 4, 1, 4, 1, 4 },
+ { GL_RGB5_A1, GL_RGBA, 5, 5, 5, 5, 5, 5, 1, 1 },
+ { GL_RGBA8, GL_RGBA, 5, 8, 5, 8, 5, 8, 5, 8 },
+ };
+ // clang-format on
+
+ return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
+ outEffectiveFormat);
+}
+
+static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
+ const InternalFormat &destFormat,
+ GLenum *outEffectiveFormat)
+{
+ if (destFormat.sized)
+ {
+ return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
+ }
+ else
+ {
+ return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
+ }
+}
+
+static bool EqualOrFirstZero(GLuint first, GLuint second)
+{
+ return first == 0 || first == second;
+}
+
+static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
+ const InternalFormat &framebufferFormatInfo,
+ FramebufferID readBufferHandle)
+{
+ if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
+ {
+ return false;
+ }
+
+ // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
+ // must both be signed, unsigned, or fixed point and both source and destinations
+ // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
+ // conversion between fixed and floating point.
+
+ if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
+ (framebufferFormatInfo.colorEncoding == GL_SRGB))
+ {
+ return false;
+ }
+
+ if (((textureFormatInfo.componentType == GL_INT) !=
+ (framebufferFormatInfo.componentType == GL_INT)) ||
+ ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
+ (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
+ {
+ return false;
+ }
+
+ if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
+ textureFormatInfo.componentType == GL_SIGNED_NORMALIZED) &&
+ !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
+ framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED))
+ {
+ return false;
+ }
+
+ // SNORM is not supported (e.g. is not in the tables of "effective internal format" that
+ // correspond to internal formats.
+ if (textureFormatInfo.componentType == GL_SIGNED_NORMALIZED)
+ {
+ return false;
+ }
+
+ // Section 3.8.5 of the GLES 3.0.3 (and section 8.6 of the GLES 3.2) spec has a caveat, that
+ // the KHR dEQP tests enforce:
+ //
+ // Note that the above rules disallow matches where some components sizes are smaller and
+ // others are larger (such as RGB10_A2).
+ if (!textureFormatInfo.sized && (framebufferFormatInfo.internalFormat == GL_RGB10_A2))
+ {
+ return false;
+ }
+
+ // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
+ // The effective internal format of the source buffer is determined with the following rules
+ // applied in order:
+ // * If the source buffer is a texture or renderbuffer that was created with a sized internal
+ // format then the effective internal format is the source buffer's sized internal format.
+ // * If the source buffer is a texture that was created with an unsized base internal format,
+ // then the effective internal format is the source image array's effective internal
+ // format, as specified by table 3.12, which is determined from the <format> and <type>
+ // that were used when the source image array was specified by TexImage*.
+ // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
+ // where Destination Internal Format matches internalformat and where the [source channel
+ // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
+ // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
+ // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
+ const InternalFormat *sourceEffectiveFormat = nullptr;
+ if (readBufferHandle.value != 0)
+ {
+ // Not the default framebuffer, therefore the read buffer must be a user-created texture or
+ // renderbuffer
+ if (framebufferFormatInfo.sized)
+ {
+ sourceEffectiveFormat = &framebufferFormatInfo;
+ }
+ else
+ {
+ // Renderbuffers cannot be created with an unsized internal format, so this must be an
+ // unsized-format texture. We can use the same table we use when creating textures to
+ // get its effective sized format.
+ sourceEffectiveFormat =
+ &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
+ }
+ }
+ else
+ {
+ // The effective internal format must be derived from the source framebuffer's channel
+ // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
+ if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
+ {
+ GLenum effectiveFormat;
+ if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
+ &effectiveFormat))
+ {
+ sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
+ {
+ // SRGB buffers can only be copied to sized format destinations according to table 3.18
+ if (textureFormatInfo.sized &&
+ (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
+ (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
+ (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
+ (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
+ {
+ sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ UNREACHABLE();
+ return false;
+ }
+ }
+
+ if (textureFormatInfo.sized)
+ {
+ // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
+ // sized, component sizes of the source and destination formats must exactly match if the
+ // destination format exists.
+ if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
+ !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
+ !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
+ !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
+ {
+ return false;
+ }
+ }
+
+ return true; // A conversion function exists, and no rule in the specification has precluded
+ // conversion between these formats.
+}
+
+bool ValidateES3CopyTexImageParametersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ Format textureFormat = Format::Invalid();
+ if (!ValidateCopyTexImageParametersBase(context, entryPoint, target, level, internalformat,
+ isSubImage, xoffset, yoffset, zoffset, x, y, width,
+ height, border, &textureFormat))
+ {
+ return false;
+ }
+ ASSERT(textureFormat.valid() || !isSubImage);
+
+ const auto &state = context->getState();
+ Framebuffer *framebuffer = state.getReadFramebuffer();
+ FramebufferID readFramebufferID = framebuffer->id();
+
+ if (!ValidateFramebufferComplete(context, entryPoint, framebuffer))
+ {
+ return false;
+ }
+
+ // needIntrinsic = true. Treat renderToTexture textures as single sample since they will be
+ // resolved before copying
+ if (!framebuffer->isDefault() &&
+ !ValidateFramebufferNotMultisampled(context, entryPoint, framebuffer, true))
+ {
+ return false;
+ }
+
+ const FramebufferAttachment *source = framebuffer->getReadColorAttachment();
+
+ // According to ES 3.x spec, if the internalformat of the texture
+ // is RGB9_E5 and copy to such a texture, generate INVALID_OPERATION.
+ if (textureFormat.info->internalFormat == GL_RGB9_E5)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
+ return false;
+ }
+
+ if (isSubImage)
+ {
+ if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
+ readFramebufferID))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidCopyCombination);
+ return false;
+ }
+ }
+ else
+ {
+ // Use format/type from the source FBO. (Might not be perfect for all cases?)
+ const InternalFormat &framebufferFormat = *source->getFormat().info;
+ const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
+ if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidCopyCombination);
+ return false;
+ }
+ }
+
+ // If width or height is zero, it is a no-op. Return false without setting an error.
+ return (width > 0 && height > 0);
+}
+
+bool ValidateES3CopyTexImage2DParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ if (!ValidTexture2DDestinationTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ return ValidateES3CopyTexImageParametersBase(context, entryPoint, target, level, internalformat,
+ isSubImage, xoffset, yoffset, zoffset, x, y, width,
+ height, border);
+}
+
+bool ValidateES3CopyTexImage3DParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLint border)
+{
+ if (!ValidTexture3DDestinationTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ return ValidateES3CopyTexImageParametersBase(context, entryPoint, target, level, internalformat,
+ isSubImage, xoffset, yoffset, zoffset, x, y, width,
+ height, border);
+}
+
+bool ValidateES3TexStorageParametersLevel(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ GLsizei maxDim = std::max(width, height);
+ if (target != TextureType::_2DArray)
+ {
+ maxDim = std::max(maxDim, depth);
+ }
+
+ if (levels > log2(maxDim) + 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidMipLevels);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateES3TexStorageParametersExtent(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ const Caps &caps = context->getCaps();
+
+ switch (target)
+ {
+ case TextureType::_2D:
+ {
+ if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ }
+ break;
+
+ case TextureType::Rectangle:
+ {
+ if (levels != 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevels);
+ return false;
+ }
+
+ if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ }
+ break;
+
+ case TextureType::CubeMap:
+ {
+ if (width != height)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kCubemapFacesEqualDimensions);
+ return false;
+ }
+
+ if (width > caps.maxCubeMapTextureSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ }
+ break;
+
+ case TextureType::_3D:
+ {
+ if (width > caps.max3DTextureSize || height > caps.max3DTextureSize ||
+ depth > caps.max3DTextureSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ }
+ break;
+
+ case TextureType::_2DArray:
+ {
+ if (width > caps.max2DTextureSize || height > caps.max2DTextureSize ||
+ depth > caps.maxArrayTextureLayers)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ }
+ break;
+
+ case TextureType::CubeMapArray:
+ {
+ if (width != height)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kCubemapFacesEqualDimensions);
+ return false;
+ }
+
+ if (width > caps.maxCubeMapTextureSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+
+ if (width > caps.max3DTextureSize || height > caps.max3DTextureSize ||
+ depth > caps.max3DTextureSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+
+ if (depth % 6 != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kCubemapInvalidDepth);
+ return false;
+ }
+ }
+ break;
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateES3TexStorageParametersTexObject(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target)
+{
+ Texture *texture = context->getTextureByType(target);
+ if (!texture || texture->id().value == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingTexture);
+ return false;
+ }
+
+ if (texture->getImmutableFormat())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsImmutable);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateES3TexStorageParametersFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ // From ANGLE_texture_external_yuv_sampling:
+ // Texture target can only be TEXTURE_2D, there is no mipmap support
+ if (gl::IsYuvFormat(internalformat))
+ {
+ if (!context->getExtensions().yuvInternalFormatANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+
+ if (target != TextureType::_2D)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ if (levels != 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+ }
+
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
+ if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+
+ if (!formatInfo.sized)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+
+ if (formatInfo.compressed)
+ {
+ if (target == TextureType::Rectangle)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kRectangleTextureCompressed);
+ return false;
+ }
+
+ if (target == TextureType::_2DArray)
+ {
+ if (!ValidateES3CompressedFormatForTexture2DArray(context, entryPoint,
+ formatInfo.internalFormat))
+ {
+ // Error already generated.
+ return false;
+ }
+ }
+
+ if (target == TextureType::_3D)
+ {
+ if (!ValidateES3CompressedFormatForTexture3D(context, entryPoint,
+ formatInfo.internalFormat))
+ {
+ // Error already generated.
+ return false;
+ }
+ }
+
+ if (!ValidCompressedImageSize(context, formatInfo.internalFormat, 0, width, height, depth))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidCompressedImageSize);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateES3TexStorageParametersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ if (width < 1 || height < 1 || depth < 1 || levels < 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kTextureSizeTooSmall);
+ return false;
+ }
+
+ if (!ValidateES3TexStorageParametersLevel(context, entryPoint, target, levels, width, height,
+ depth))
+ {
+ // Error already generated.
+ return false;
+ }
+
+ if (!ValidateES3TexStorageParametersExtent(context, entryPoint, target, levels, width, height,
+ depth))
+ {
+ // Error already generated.
+ return false;
+ }
+
+ if (!ValidateES3TexStorageParametersTexObject(context, entryPoint, target))
+ {
+ // Error already generated.
+ return false;
+ }
+
+ if (!ValidateES3TexStorageParametersFormat(context, entryPoint, target, levels, internalformat,
+ width, height, depth))
+ {
+ // Error already generated.
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateES3TexStorage2DParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ if (!ValidTexture2DTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ return ValidateES3TexStorageParametersBase(context, entryPoint, target, levels, internalformat,
+ width, height, depth);
+}
+
+bool ValidateES3TexStorage3DParameters(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ if (!ValidTexture3DTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ return ValidateES3TexStorageParametersBase(context, entryPoint, target, levels, internalformat,
+ width, height, depth);
+}
+
+bool ValidateBeginQuery(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType target,
+ QueryID id)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateBeginQueryBase(context, entryPoint, target, id);
+}
+
+bool ValidateEndQuery(const Context *context, angle::EntryPoint entryPoint, QueryType target)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateEndQueryBase(context, entryPoint, target);
+}
+
+bool ValidateGetQueryiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType target,
+ GLenum pname,
+ const GLint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateGetQueryivBase(context, entryPoint, target, pname, nullptr);
+}
+
+bool ValidateGetQueryObjectuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ const GLuint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
+}
+
+bool ValidateFramebufferTextureLayer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureID texture,
+ GLint level,
+ GLint layer)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
+ {
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (texture.value != 0)
+ {
+ if (layer < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLayer);
+ return false;
+ }
+
+ Texture *tex = context->getTexture(texture);
+ ASSERT(tex);
+
+ switch (tex->getType())
+ {
+ case TextureType::_2DArray:
+ {
+ if (level > log2(caps.max2DTextureSize))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kFramebufferTextureInvalidMipLevel);
+ return false;
+ }
+
+ if (layer >= caps.maxArrayTextureLayers)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kFramebufferTextureInvalidLayer);
+ return false;
+ }
+ }
+ break;
+
+ case TextureType::_3D:
+ {
+ if (level > log2(caps.max3DTextureSize))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kFramebufferTextureInvalidMipLevel);
+ return false;
+ }
+
+ if (layer >= caps.max3DTextureSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kFramebufferTextureInvalidLayer);
+ return false;
+ }
+ }
+ break;
+
+ case TextureType::_2DMultisampleArray:
+ {
+ if (level != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kFramebufferTextureInvalidMipLevel);
+ return false;
+ }
+
+ if (layer >= caps.maxArrayTextureLayers)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kFramebufferTextureInvalidLayer);
+ return false;
+ }
+ }
+ break;
+
+ case TextureType::CubeMap:
+ {
+ if (level > log2(caps.maxCubeMapTextureSize))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kFramebufferTextureInvalidMipLevel);
+ return false;
+ }
+
+ if (layer >= static_cast<GLint>(kCubeFaceCount))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kFramebufferTextureInvalidLayer);
+ return false;
+ }
+ }
+ break;
+
+ case TextureType::CubeMapArray:
+ {
+ if (level > log2(caps.maxCubeMapTextureSize))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kFramebufferTextureInvalidMipLevel);
+ return false;
+ }
+
+ if (layer >= caps.maxArrayTextureLayers)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kFramebufferTextureInvalidLayer);
+ return false;
+ }
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kFramebufferTextureLayerIncorrectTextureType);
+ return false;
+ }
+
+ const auto &format = tex->getFormat(TextureTypeToTarget(tex->getType(), layer), level);
+ if (format.info->compressed)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kCompressedTexturesNotAttachable);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateInvalidateFramebuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ bool defaultFramebuffer = false;
+
+ switch (target)
+ {
+ case GL_DRAW_FRAMEBUFFER:
+ case GL_FRAMEBUFFER:
+ defaultFramebuffer = context->getState().getDrawFramebuffer()->isDefault();
+ break;
+ case GL_READ_FRAMEBUFFER:
+ defaultFramebuffer = context->getState().getReadFramebuffer()->isDefault();
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
+ return false;
+ }
+
+ return ValidateDiscardFramebufferBase(context, entryPoint, target, numAttachments, attachments,
+ defaultFramebuffer);
+}
+
+bool ValidateInvalidateSubFramebuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ if (width < 0 || height < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
+ return false;
+ }
+
+ return ValidateInvalidateFramebuffer(context, entryPoint, target, numAttachments, attachments);
+}
+
+bool ValidateClearBuffer(const Context *context, angle::EntryPoint entryPoint)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!ValidateFramebufferComplete(context, entryPoint, context->getState().getDrawFramebuffer()))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawRangeElements(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (end < start)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidElementRange);
+ return false;
+ }
+
+ if (!ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, 0))
+ {
+ return false;
+ }
+
+ // Skip range checks for no-op calls.
+ if (count <= 0)
+ {
+ return true;
+ }
+
+ return true;
+}
+
+bool ValidateGetUniformuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ const GLuint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateGetUniformBase(context, entryPoint, program, location);
+}
+
+bool ValidateReadBuffer(const Context *context, angle::EntryPoint entryPoint, GLenum src)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ const Framebuffer *readFBO = context->getState().getReadFramebuffer();
+
+ if (readFBO == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kNoReadFramebuffer);
+ return false;
+ }
+
+ if (src == GL_NONE)
+ {
+ return true;
+ }
+
+ if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidReadBuffer);
+ return false;
+ }
+
+ if (readFBO->isDefault())
+ {
+ if (src != GL_BACK)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDefaultReadBuffer);
+ return false;
+ }
+ }
+ else
+ {
+ GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
+
+ if (drawBuffer >= static_cast<GLuint>(context->getCaps().maxColorAttachments))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateCompressedTexImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const void *data)
+{
+ if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!ValidTextureTarget(context, TextureTargetToType(target)))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ // Validate image size
+ if (!ValidImageSizeParameters(context, entryPoint, TextureTargetToType(target), level, width,
+ height, depth, false))
+ {
+ // Error already generated.
+ return false;
+ }
+
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
+ if (!formatInfo.compressed)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCompressedFormat);
+ return false;
+ }
+
+ GLuint blockSize = 0;
+ if (!formatInfo.computeCompressedImageSize(Extents(width, height, depth), &blockSize))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIntegerOverflow);
+ return false;
+ }
+
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidCompressedImageSize);
+ return false;
+ }
+
+ // 3D texture target validation
+ if (target != TextureTarget::_3D && target != TextureTarget::_2DArray)
+ {
+ if (context->getClientVersion() < ES_3_2 || target != TextureTarget::CubeMapArray)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+ }
+
+ // validateES3TexImageFormat sets the error code if there is an error
+ if (!ValidateES3TexImage3DParameters(context, entryPoint, target, level, internalformat, true,
+ false, 0, 0, 0, width, height, depth, border, GL_NONE,
+ GL_NONE, -1, data))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCompressedTexImage3DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const void *data)
+{
+ if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize))
+ {
+ return false;
+ }
+
+ return ValidateCompressedTexImage3D(context, entryPoint, target, level, internalformat, width,
+ height, depth, border, imageSize, data);
+}
+
+bool ValidateBindVertexArray(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID array)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateBindVertexArrayBase(context, entryPoint, array);
+}
+
+bool ValidateIsVertexArray(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID array)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return true;
+}
+
+static bool ValidateBindBufferCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLuint index,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (buffer.value != 0 && offset < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
+ return false;
+ }
+
+ if (!context->getState().isBindGeneratesResourceEnabled() &&
+ !context->isBufferGenerated(buffer))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ switch (target)
+ {
+ case BufferBinding::TransformFeedback:
+ {
+ if (index >= static_cast<GLuint>(caps.maxTransformFeedbackSeparateAttributes))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kIndexExceedsTransformFeedbackBufferBindings);
+ return false;
+ }
+ if (buffer.value != 0 && ((offset % 4) != 0 || (size % 4) != 0))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetAndSizeAlignment);
+ return false;
+ }
+
+ if (context->getState().isTransformFeedbackActive())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTransformFeedbackTargetActive);
+ return false;
+ }
+ break;
+ }
+ case BufferBinding::Uniform:
+ {
+ if (index >= static_cast<GLuint>(caps.maxUniformBufferBindings))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kIndexExceedsMaxUniformBufferBindings);
+ return false;
+ }
+
+ ASSERT(caps.uniformBufferOffsetAlignment);
+ if (buffer.value != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kUniformBufferOffsetAlignment);
+ return false;
+ }
+ break;
+ }
+ case BufferBinding::AtomicCounter:
+ {
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
+ return false;
+ }
+ if (index >= static_cast<GLuint>(caps.maxAtomicCounterBufferBindings))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kIndexExceedsMaxAtomicCounterBufferBindings);
+ return false;
+ }
+ if (buffer.value != 0 && (offset % 4) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetAlignment);
+ return false;
+ }
+ break;
+ }
+ case BufferBinding::ShaderStorage:
+ {
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
+ return false;
+ }
+ if (index >= static_cast<GLuint>(caps.maxShaderStorageBufferBindings))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kExceedsMaxShaderStorageBufferBindings);
+ return false;
+ }
+ ASSERT(caps.shaderStorageBufferOffsetAlignment);
+ if (buffer.value != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kShaderStorageBufferOffsetAlignment);
+ return false;
+ }
+ break;
+ }
+ case BufferBinding::Texture:
+ {
+ if (!context->getExtensions().textureBufferAny())
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kTextureBufferExtensionNotAvailable);
+ return false;
+ }
+ if (index != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kIndexExceedsMaxUniformBufferBindings);
+ return false;
+ }
+ if (buffer.value != 0 && (offset % caps.textureBufferOffsetAlignment) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kTextureBufferOffsetAlignment);
+ return false;
+ }
+ break;
+ }
+ case BufferBinding::InvalidEnum:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumInvalid);
+ return false;
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ ToGLenum(target));
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindBufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLuint index,
+ BufferID buffer)
+{
+ return ValidateBindBufferCommon(context, entryPoint, target, index, buffer, 0, 0);
+}
+
+bool ValidateBindBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLuint index,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ if (buffer.value != 0 && size <= 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBindBufferSize);
+ return false;
+ }
+ return ValidateBindBufferCommon(context, entryPoint, target, index, buffer, offset, size);
+}
+
+bool ValidateProgramBinary(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateProgramBinaryBase(context, entryPoint, program, binaryFormat, binary, length);
+}
+
+bool ValidateGetProgramBinary(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLenum *binaryFormat,
+ const void *binary)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateGetProgramBinaryBase(context, entryPoint, program, bufSize, length, binaryFormat,
+ binary);
+}
+
+bool ValidateProgramParameteriBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum pname,
+ GLint value)
+{
+ if (GetValidProgram(context, entryPoint, program) == nullptr)
+ {
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
+ if (value != GL_FALSE && value != GL_TRUE)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBooleanValue);
+ return false;
+ }
+ break;
+
+ case GL_PROGRAM_SEPARABLE:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kES31Required);
+ return false;
+ }
+
+ if (value != GL_FALSE && value != GL_TRUE)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBooleanValue);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateProgramParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum pname,
+ GLint value)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateProgramParameteriBase(context, entryPoint, program, pname, value);
+}
+
+bool ValidateBlitFramebuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter)
+{
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().framebufferBlitNV)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateBlitFramebufferParameters(context, entryPoint, srcX0, srcY0, srcX1, srcY1, dstX0,
+ dstY0, dstX1, dstY1, mask, filter);
+}
+
+bool ValidateClearBufferiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *value)
+{
+ switch (buffer)
+ {
+ case GL_COLOR:
+ if (drawbuffer < 0 || drawbuffer >= context->getCaps().maxDrawBuffers)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
+ return false;
+ }
+ if (context->getExtensions().webglCompatibilityANGLE)
+ {
+ constexpr GLenum validComponentTypes[] = {GL_INT};
+ if (!ValidateWebGLFramebufferAttachmentClearType(context, entryPoint, drawbuffer,
+ validComponentTypes,
+ ArraySize(validComponentTypes)))
+ {
+ return false;
+ }
+ }
+ break;
+
+ case GL_STENCIL:
+ if (drawbuffer != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kInvalidDepthStencilDrawBuffer);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, buffer);
+ return false;
+ }
+
+ return ValidateClearBuffer(context, entryPoint);
+}
+
+bool ValidateClearBufferuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *value)
+{
+ switch (buffer)
+ {
+ case GL_COLOR:
+ if (drawbuffer < 0 || drawbuffer >= context->getCaps().maxDrawBuffers)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
+ return false;
+ }
+ if (context->getExtensions().webglCompatibilityANGLE)
+ {
+ constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
+ if (!ValidateWebGLFramebufferAttachmentClearType(context, entryPoint, drawbuffer,
+ validComponentTypes,
+ ArraySize(validComponentTypes)))
+ {
+ return false;
+ }
+ }
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, buffer);
+ return false;
+ }
+
+ return ValidateClearBuffer(context, entryPoint);
+}
+
+bool ValidateClearBufferfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *value)
+{
+ switch (buffer)
+ {
+ case GL_COLOR:
+ if (drawbuffer < 0 || drawbuffer >= context->getCaps().maxDrawBuffers)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
+ return false;
+ }
+ if (context->getExtensions().webglCompatibilityANGLE)
+ {
+ constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
+ GL_SIGNED_NORMALIZED};
+ if (!ValidateWebGLFramebufferAttachmentClearType(context, entryPoint, drawbuffer,
+ validComponentTypes,
+ ArraySize(validComponentTypes)))
+ {
+ return false;
+ }
+ }
+ break;
+
+ case GL_DEPTH:
+ if (drawbuffer != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kInvalidDepthStencilDrawBuffer);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, buffer);
+ return false;
+ }
+
+ return ValidateClearBuffer(context, entryPoint);
+}
+
+bool ValidateClearBufferfi(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil)
+{
+ switch (buffer)
+ {
+ case GL_DEPTH_STENCIL:
+ if (drawbuffer != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kInvalidDepthStencilDrawBuffer);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, buffer);
+ return false;
+ }
+
+ return ValidateClearBuffer(context, entryPoint);
+}
+
+bool ValidateDrawBuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLenum *bufs)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateDrawBuffersBase(context, entryPoint, n, bufs);
+}
+
+bool ValidateCopyTexSubImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateES3CopyTexImage3DParameters(context, entryPoint, target, level, GL_NONE, true,
+ xoffset, yoffset, zoffset, x, y, width, height, 0);
+}
+
+bool ValidateCopyTexture3DANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID sourceId,
+ GLint sourceLevel,
+ TextureTarget destTarget,
+ TextureID destId,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ const Texture *source = context->getTexture(sourceId);
+ if (source == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTexture);
+ return false;
+ }
+
+ TextureType sourceType = source->getType();
+ ASSERT(sourceType != TextureType::CubeMap);
+ TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
+ const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
+
+ const Texture *dest = context->getTexture(destId);
+ if (dest == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTexture);
+ return false;
+ }
+
+ if (!ValidateCopyTexture3DCommon(context, entryPoint, source, sourceLevel,
+ sourceFormat.info->internalFormat, dest, destLevel,
+ internalFormat, destTarget))
+ {
+ return false;
+ }
+
+ if (!ValidMipLevel(context, source->getType(), sourceLevel))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTextureLevel);
+ return false;
+ }
+
+ GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
+ GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
+ if (sourceWidth == 0 || sourceHeight == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidSourceTextureSize);
+ return false;
+ }
+
+ if (dest->getImmutableFormat())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDestinationImmutable);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopySubTexture3DANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID sourceId,
+ GLint sourceLevel,
+ TextureTarget destTarget,
+ TextureID destId,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha)
+{
+ const Texture *source = context->getTexture(sourceId);
+ if (source == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTexture);
+ return false;
+ }
+
+ TextureType sourceType = source->getType();
+ ASSERT(sourceType != TextureType::CubeMap);
+ TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
+ const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
+
+ const Texture *dest = context->getTexture(destId);
+ if (dest == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTexture);
+ return false;
+ }
+
+ const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
+
+ if (!ValidateCopyTexture3DCommon(context, entryPoint, source, sourceLevel,
+ sourceFormat.info->internalFormat, dest, destLevel,
+ destFormat.internalFormat, destTarget))
+ {
+ return false;
+ }
+
+ if (x < 0 || y < 0 || z < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeXYZ);
+ return false;
+ }
+
+ if (width < 0 || height < 0 || depth < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeHeightWidthDepth);
+ return false;
+ }
+
+ if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
+ static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel) ||
+ static_cast<size_t>(z + depth) > source->getDepth(sourceTarget, sourceLevel))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kSourceTextureTooSmall);
+ return false;
+ }
+
+ if (TextureTargetToType(destTarget) != dest->getType())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTextureType);
+ return false;
+ }
+
+ if (xoffset < 0 || yoffset < 0 || zoffset < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
+ return false;
+ }
+
+ if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
+ static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel) ||
+ static_cast<size_t>(zoffset + depth) > dest->getDepth(destTarget, destLevel))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kDestinationTextureTooSmall);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTexImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateES3TexImage3DParameters(context, entryPoint, target, level, internalformat,
+ false, false, 0, 0, 0, width, height, depth, border,
+ format, type, -1, pixels);
+}
+
+bool ValidateTexImage3DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateES3TexImage3DParameters(context, entryPoint, target, level, internalformat,
+ false, false, 0, 0, 0, width, height, depth, border,
+ format, type, bufSize, pixels);
+}
+
+bool ValidateTexSubImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateES3TexImage3DParameters(context, entryPoint, target, level, GL_NONE, false, true,
+ xoffset, yoffset, zoffset, width, height, depth, 0,
+ format, type, -1, pixels);
+}
+
+bool ValidateTexSubImage3DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ return ValidateES3TexImage3DParameters(context, entryPoint, target, level, GL_NONE, false, true,
+ xoffset, yoffset, zoffset, width, height, depth, 0,
+ format, type, bufSize, pixels);
+}
+
+bool ValidateCompressedTexSubImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!ValidateES3TexImage3DParameters(context, entryPoint, target, level, GL_NONE, true, true,
+ xoffset, yoffset, zoffset, width, height, depth, 0, format,
+ GL_NONE, -1, data))
+ {
+ return false;
+ }
+
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
+
+ if (!formatInfo.compressed)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCompressedFormat);
+ return false;
+ }
+
+ GLuint blockSize = 0;
+ if (!formatInfo.computeCompressedImageSize(Extents(width, height, depth), &blockSize))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
+ return false;
+ }
+
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidCompressedImageSize);
+ return false;
+ }
+
+ if (data == nullptr)
+ {
+ if (context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr)
+ {
+ // If data is null, we need an unpack buffer to read from
+ context->validationError(entryPoint, GL_INVALID_VALUE, kPixelDataNull);
+ return false;
+ }
+
+ if (context->getTextureByTarget(target)->isCompressedFormatEmulated(context, target, level))
+ {
+ // TODO (anglebug.com/7464): Can't populate from a buffer using emulated format
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidEmulatedFormat);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateCompressedTexSubImage3DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const void *data)
+{
+ if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize))
+ {
+ return false;
+ }
+
+ return ValidateCompressedTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset,
+ zoffset, width, height, depth, format, imageSize, data);
+}
+
+bool ValidateGenQueries(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const QueryID *queries)
+{
+ return ValidateGenOrDeleteES3(context, entryPoint, n);
+}
+
+bool ValidateDeleteQueries(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const QueryID *queries)
+{
+ return ValidateGenOrDeleteES3(context, entryPoint, n);
+}
+
+bool ValidateGenSamplers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei count,
+ const SamplerID *samplers)
+{
+ return ValidateGenOrDeleteCountES3(context, entryPoint, count);
+}
+
+bool ValidateDeleteSamplers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei count,
+ const SamplerID *samplers)
+{
+ return ValidateGenOrDeleteCountES3(context, entryPoint, count);
+}
+
+bool ValidateGenTransformFeedbacks(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const TransformFeedbackID *ids)
+{
+ return ValidateGenOrDeleteES3(context, entryPoint, n);
+}
+
+bool ValidateDeleteTransformFeedbacks(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const TransformFeedbackID *ids)
+{
+ if (!ValidateGenOrDeleteES3(context, entryPoint, n))
+ {
+ return false;
+ }
+ for (GLint i = 0; i < n; ++i)
+ {
+ auto *transformFeedback = context->getTransformFeedback(ids[i]);
+ if (transformFeedback != nullptr && transformFeedback->isActive())
+ {
+ // ES 3.0.4 section 2.15.1 page 86
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTransformFeedbackActiveDelete);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateGenVertexArrays(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const VertexArrayID *arrays)
+{
+ return ValidateGenOrDeleteES3(context, entryPoint, n);
+}
+
+bool ValidateDeleteVertexArrays(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const VertexArrayID *arrays)
+{
+ return ValidateGenOrDeleteES3(context, entryPoint, n);
+}
+
+bool ValidateBeginTransformFeedback(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode primitiveMode)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ switch (primitiveMode)
+ {
+ case PrimitiveMode::Triangles:
+ case PrimitiveMode::Lines:
+ case PrimitiveMode::Points:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPrimitiveMode);
+ return false;
+ }
+
+ TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != nullptr);
+
+ if (transformFeedback->isActive())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTransfomFeedbackAlreadyActive);
+ return false;
+ }
+
+ for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
+ {
+ const OffsetBindingPointer<Buffer> &buffer = transformFeedback->getIndexedBuffer(i);
+ if (buffer.get())
+ {
+ if (buffer->isMapped())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferMapped);
+ return false;
+ }
+ if ((context->getLimitations().noDoubleBoundTransformFeedbackBuffers ||
+ context->getExtensions().webglCompatibilityANGLE) &&
+ buffer->isDoubleBoundForTransformFeedback())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTransformFeedbackBufferMultipleOutputs);
+ return false;
+ }
+ }
+ }
+
+ const ProgramExecutable *programExecutable =
+ context->getState().getLinkedProgramExecutable(context);
+ if (!programExecutable)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotBound);
+ return false;
+ }
+
+ if (programExecutable->getLinkedTransformFeedbackVaryings().empty())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kNoTransformFeedbackOutputVariables);
+ return false;
+ }
+
+ if (!ValidateProgramExecutableXFBBuffersPresent(context, programExecutable))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackBufferMissing);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBufferPointerv(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLenum pname,
+ void *const *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateGetBufferPointervBase(context, entryPoint, target, pname, nullptr, params);
+}
+
+bool ValidateGetBufferPointervRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ void *const *params)
+{
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapbufferOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidateGetBufferPointervBase(context, entryPoint, target, pname, &numParams, params))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateUnmapBuffer(const Context *context, angle::EntryPoint entryPoint, BufferBinding target)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateUnmapBufferBase(context, entryPoint, target);
+}
+
+bool ValidateMapBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateMapBufferRangeBase(context, entryPoint, target, offset, length, access);
+}
+
+bool ValidateFlushMappedBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLintptr offset,
+ GLsizeiptr length)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateFlushMappedBufferRangeBase(context, entryPoint, target, offset, length);
+}
+
+bool ValidateIndexedStateQuery(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLuint index,
+ GLsizei *length)
+{
+ if (length)
+ {
+ *length = 0;
+ }
+
+ GLenum nativeType;
+ unsigned int numParams;
+ if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ switch (pname)
+ {
+ case GL_BLEND_SRC_RGB:
+ case GL_BLEND_SRC_ALPHA:
+ case GL_BLEND_DST_RGB:
+ case GL_BLEND_DST_ALPHA:
+ case GL_BLEND_EQUATION_RGB:
+ case GL_BLEND_EQUATION_ALPHA:
+ case GL_COLOR_WRITEMASK:
+ if (!context->getExtensions().drawBuffersIndexedAny())
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kDrawBuffersIndexedExtensionNotAvailable);
+ return false;
+ }
+ if (index >= static_cast<GLuint>(caps.maxDrawBuffers))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
+ return false;
+ }
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ if (index >= static_cast<GLuint>(caps.maxTransformFeedbackSeparateAttributes))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kIndexExceedsMaxTransformFeedbackAttribs);
+ return false;
+ }
+ break;
+
+ case GL_UNIFORM_BUFFER_START:
+ case GL_UNIFORM_BUFFER_SIZE:
+ case GL_UNIFORM_BUFFER_BINDING:
+ if (index >= static_cast<GLuint>(caps.maxUniformBufferBindings))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kIndexExceedsMaxUniformBufferBindings);
+ return false;
+ }
+ break;
+
+ case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
+ case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
+ if (index >= 3u)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kIndexExceedsMaxWorkgroupDimensions);
+ return false;
+ }
+ break;
+
+ case GL_ATOMIC_COUNTER_BUFFER_START:
+ case GL_ATOMIC_COUNTER_BUFFER_SIZE:
+ case GL_ATOMIC_COUNTER_BUFFER_BINDING:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
+ return false;
+ }
+ if (index >= static_cast<GLuint>(caps.maxAtomicCounterBufferBindings))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kIndexExceedsMaxAtomicCounterBufferBindings);
+ return false;
+ }
+ break;
+
+ case GL_SHADER_STORAGE_BUFFER_START:
+ case GL_SHADER_STORAGE_BUFFER_SIZE:
+ case GL_SHADER_STORAGE_BUFFER_BINDING:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
+ return false;
+ }
+ if (index >= static_cast<GLuint>(caps.maxShaderStorageBufferBindings))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kExceedsMaxShaderStorageBufferBindings);
+ return false;
+ }
+ break;
+
+ case GL_VERTEX_BINDING_BUFFER:
+ case GL_VERTEX_BINDING_DIVISOR:
+ case GL_VERTEX_BINDING_OFFSET:
+ case GL_VERTEX_BINDING_STRIDE:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
+ return false;
+ }
+ if (index >= static_cast<GLuint>(caps.maxVertexAttribBindings))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kExceedsMaxVertexAttribBindings);
+ return false;
+ }
+ break;
+ case GL_SAMPLE_MASK_VALUE:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
+ return false;
+ }
+ if (index >= static_cast<GLuint>(caps.maxSampleMaskWords))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSampleMaskNumber);
+ return false;
+ }
+ break;
+ case GL_IMAGE_BINDING_NAME:
+ case GL_IMAGE_BINDING_LEVEL:
+ case GL_IMAGE_BINDING_LAYERED:
+ case GL_IMAGE_BINDING_LAYER:
+ case GL_IMAGE_BINDING_ACCESS:
+ case GL_IMAGE_BINDING_FORMAT:
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
+ return false;
+ }
+ if (index >= static_cast<GLuint>(caps.maxImageUnits))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxImageUnits);
+ return false;
+ }
+ break;
+ // GL_ANGLE_shader_pixel_local_storage
+ case GL_PIXEL_LOCAL_FORMAT_ANGLE:
+ case GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE:
+ case GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE:
+ case GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE:
+ {
+ // Check that the pixel local storage extension is enabled at all.
+ if (!context->getExtensions().shaderPixelLocalStorageANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSExtensionNotEnabled);
+ return false;
+ }
+ // INVALID_FRAMEBUFFER_OPERATION is generated if the default framebuffer object name 0
+ // is bound to DRAW_FRAMEBUFFER.
+ Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
+ if (framebuffer->id().value == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION,
+ kPLSDefaultFramebufferBound);
+ return false;
+ }
+ // INVALID_VALUE is generated if <index> >= MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.
+ if (index >= context->getCaps().maxPixelLocalStoragePlanes)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSPlaneOutOfRange);
+ return false;
+ }
+ break;
+ }
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ if (length)
+ {
+ if (pname == GL_COLOR_WRITEMASK)
+ {
+ *length = 4;
+ }
+ else
+ {
+ *length = 1;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetIntegeri_v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ const GLint *data)
+{
+ if (context->getClientVersion() < ES_3_0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateIndexedStateQuery(context, entryPoint, target, index, nullptr);
+}
+
+bool ValidateGetIntegeri_vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *data)
+{
+ if (context->getClientVersion() < ES_3_0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateIndexedStateQuery(context, entryPoint, target, index, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateGetInteger64i_v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ const GLint64 *data)
+{
+ if (context->getClientVersion() < ES_3_0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateIndexedStateQuery(context, entryPoint, target, index, nullptr);
+}
+
+bool ValidateGetInteger64i_vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint64 *data)
+{
+ if (context->getClientVersion() < ES_3_0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateIndexedStateQuery(context, entryPoint, target, index, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+
+ return true;
+}
+
+bool ValidateCopyBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding readTarget,
+ BufferBinding writeTarget,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
+ return false;
+ }
+
+ Buffer *readBuffer = context->getState().getTargetBuffer(readTarget);
+ Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget);
+
+ if (!readBuffer || !writeBuffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound);
+ return false;
+ }
+
+ // EXT_buffer_storage allows persistently mapped buffers to be updated via glCopyBufferSubData
+ bool isReadPersistent = (readBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
+ bool isWritePersistent = (writeBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
+
+ // Verify that readBuffer and writeBuffer are not currently mapped unless persistent
+ if ((readBuffer->isMapped() && !isReadPersistent) ||
+ (writeBuffer->isMapped() && !isWritePersistent))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferMapped);
+ return false;
+ }
+
+ if (readBuffer->hasWebGLXFBBindingConflict(context->isWebGL()) ||
+ writeBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kBufferBoundForTransformFeedback);
+ return false;
+ }
+
+ CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
+ CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
+ CheckedNumeric<GLintptr> checkedSize(size);
+
+ auto checkedReadSum = checkedReadOffset + checkedSize;
+ auto checkedWriteSum = checkedWriteOffset + checkedSize;
+
+ if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
+ !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
+ !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIntegerOverflow);
+ return false;
+ }
+
+ if (readOffset < 0 || writeOffset < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
+ return false;
+ }
+
+ if (size < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
+ return false;
+ }
+
+ if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
+ checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kBufferOffsetOverflow);
+ return false;
+ }
+
+ if (readBuffer == writeBuffer)
+ {
+ auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
+ if (!checkedOffsetDiff.IsValid())
+ {
+ // This shold not be possible.
+ UNREACHABLE();
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIntegerOverflow);
+ return false;
+ }
+
+ if (checkedOffsetDiff.ValueOrDie() < size)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kCopyAlias);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetStringi(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum name,
+ GLuint index)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ switch (name)
+ {
+ case GL_EXTENSIONS:
+ if (index >= context->getExtensionStringCount())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsNumExtensions);
+ return false;
+ }
+ break;
+
+ case GL_REQUESTABLE_EXTENSIONS_ANGLE:
+ if (!context->getExtensions().requestExtensionANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidName);
+ return false;
+ }
+ if (index >= context->getRequestableExtensionStringCount())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kExceedsNumRequestableExtensions);
+ return false;
+ }
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidName);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateRenderbufferStorageMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!ValidateRenderbufferStorageParametersBase(context, entryPoint, target, samples,
+ internalformat, width, height))
+ {
+ return false;
+ }
+
+ // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
+ // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
+ // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
+ const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
+ if (formatInfo.isInt())
+ {
+ if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
+ samples > context->getCaps().maxIntegerSamples)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kSamplesOutOfRange);
+ return false;
+ }
+ }
+
+ // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kSamplesOutOfRange);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexAttribIPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint size,
+ VertexAttribType type,
+ GLsizei stride,
+ const void *pointer)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!ValidateIntegerVertexFormat(context, entryPoint, index, size, type))
+ {
+ return false;
+ }
+
+ if (stride < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeStride);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (context->getClientVersion() >= ES_3_1)
+ {
+ if (stride > caps.maxVertexAttribStride)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribStride);
+ return false;
+ }
+
+ // [OpenGL ES 3.1] Section 10.3.1 page 245:
+ // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
+ // validation should be inherited.
+ if (index >= static_cast<GLuint>(caps.maxVertexAttribBindings))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
+ return false;
+ }
+ }
+
+ // [OpenGL ES 3.0.2] Section 2.8 page 24:
+ // An INVALID_OPERATION error is generated when a non-zero vertex array object
+ // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
+ // and the pointer argument is not NULL.
+ if (context->getState().getVertexArrayId().value != 0 &&
+ context->getState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kClientDataInVertexArray);
+ return false;
+ }
+
+ if (context->getExtensions().webglCompatibilityANGLE)
+ {
+ if (!ValidateWebGLVertexAttribPointer(context, entryPoint, type, false, stride, pointer,
+ true))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetSynciv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsync sync,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *values)
+{
+ if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ if (context->isContextLost())
+ {
+ context->validationError(entryPoint, GL_CONTEXT_LOST, kContextLost);
+
+ if (pname == GL_SYNC_STATUS)
+ {
+ // Generate an error but still return true, the context still needs to return a
+ // value in this case.
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ Sync *syncObject = context->getSync(sync);
+ if (!syncObject)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kSyncMissing);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_OBJECT_TYPE:
+ case GL_SYNC_CONDITION:
+ case GL_SYNC_FLAGS:
+ case GL_SYNC_STATUS:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawElementsInstanced(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei instanceCount)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
+ instanceCount);
+}
+
+bool ValidateMultiDrawArraysInstancedANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount)
+{
+ if (!context->getExtensions().multiDrawANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ if (context->getClientMajorVersion() < 3)
+ {
+ if (!context->getExtensions().instancedArraysAny())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ if (!ValidateDrawInstancedANGLE(context, entryPoint))
+ {
+ return false;
+ }
+ }
+ for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
+ {
+ if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, firsts[drawID],
+ counts[drawID], instanceCounts[drawID]))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateMultiDrawElementsInstancedANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ const GLsizei *counts,
+ DrawElementsType type,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount)
+{
+ if (!context->getExtensions().multiDrawANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ if (context->getClientMajorVersion() < 3)
+ {
+ if (!context->getExtensions().instancedArraysAny())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ if (!ValidateDrawInstancedANGLE(context, entryPoint))
+ {
+ return false;
+ }
+ }
+ for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
+ {
+ if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, counts[drawID], type,
+ indices[drawID], instanceCounts[drawID]))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateDrawArraysInstancedBaseInstanceANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount,
+ GLuint baseInstance)
+{
+ if (!context->getExtensions().baseVertexBaseInstanceANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, instanceCount);
+}
+
+bool ValidateDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const GLvoid *indices,
+ GLsizei instanceCount,
+ GLint baseVertex,
+ GLuint baseInstance)
+{
+ if (!context->getExtensions().baseVertexBaseInstanceANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
+ instanceCount);
+}
+
+bool ValidateMultiDrawArraysInstancedBaseInstanceANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ const GLuint *baseInstances,
+ GLsizei drawcount)
+{
+ if (!context->getExtensions().multiDrawANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ if (drawcount < 0)
+ {
+ return false;
+ }
+ for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
+ {
+ if (!ValidateDrawArraysInstancedBase(context, entryPoint, modePacked, firsts[drawID],
+ counts[drawID], instanceCounts[drawID]))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount)
+{
+ if (!context->getExtensions().multiDrawANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ if (drawcount < 0)
+ {
+ return false;
+ }
+ for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
+ {
+ if (!ValidateDrawElementsInstancedBase(context, entryPoint, modePacked, counts[drawID],
+ typePacked, indices[drawID], instanceCounts[drawID]))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateFramebufferTextureMultiviewOVR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureID texture,
+ GLint level,
+ GLint baseViewIndex,
+ GLsizei numViews)
+{
+ if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, entryPoint, target, attachment,
+ texture, level, numViews))
+ {
+ return false;
+ }
+
+ if (texture.value != 0)
+ {
+ if (baseViewIndex < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBaseViewIndex);
+ return false;
+ }
+
+ Texture *tex = context->getTexture(texture);
+ ASSERT(tex);
+
+ switch (tex->getType())
+ {
+ case TextureType::_2DArray:
+ case TextureType::_2DMultisampleArray:
+ {
+ if (tex->getType() == TextureType::_2DMultisampleArray)
+ {
+ if (!context->getExtensions().multiviewMultisampleANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidTextureType);
+ return false;
+ }
+ }
+
+ const Caps &caps = context->getCaps();
+ if (baseViewIndex + numViews > caps.maxArrayTextureLayers)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kViewsExceedMaxArrayLayers);
+ return false;
+ }
+
+ break;
+ }
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureType);
+ return false;
+ }
+
+ if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, entryPoint, tex, level))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateUniform1ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLuint v0)
+{
+ return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT, location, 1);
+}
+
+bool ValidateUniform2ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLuint v0,
+ GLuint v1)
+{
+ return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC2, location, 1);
+}
+
+bool ValidateUniform3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC3, location, 1);
+}
+
+bool ValidateUniform4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC4, location, 1);
+}
+
+bool ValidateUniform1uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLuint *value)
+{
+ return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT, location, count);
+}
+
+bool ValidateUniform2uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLuint *value)
+{
+ return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC2, location, count);
+}
+
+bool ValidateUniform3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLuint *value)
+{
+ return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC3, location, count);
+}
+
+bool ValidateUniform4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLuint *value)
+{
+ return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC4, location, count);
+}
+
+bool ValidateIsQuery(const Context *context, angle::EntryPoint entryPoint, QueryID id)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateUniformMatrix2x3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT2x3, location, count,
+ transpose);
+}
+
+bool ValidateUniformMatrix3x2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT3x2, location, count,
+ transpose);
+}
+
+bool ValidateUniformMatrix2x4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT2x4, location, count,
+ transpose);
+}
+
+bool ValidateUniformMatrix4x2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT4x2, location, count,
+ transpose);
+}
+
+bool ValidateUniformMatrix3x4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT3x4, location, count,
+ transpose);
+}
+
+bool ValidateUniformMatrix4x3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT4x3, location, count,
+ transpose);
+}
+
+bool ValidateEndTransformFeedback(const Context *context, angle::EntryPoint entryPoint)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != nullptr);
+
+ if (!transformFeedback->isActive())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackNotActive);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTransformFeedbackVaryings(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (count < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
+ return false;
+ }
+
+ switch (bufferMode)
+ {
+ case GL_INTERLEAVED_ATTRIBS:
+ break;
+ case GL_SEPARATE_ATTRIBS:
+ {
+ const Caps &caps = context->getCaps();
+ if (count > caps.maxTransformFeedbackSeparateAttributes)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kInvalidTransformFeedbackAttribsCount);
+ return false;
+ }
+ break;
+ }
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, bufferMode);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetTransformFeedbackVarying(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLsizei *size,
+ const GLenum *type,
+ const GLchar *name)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kTransformFeedbackVaryingIndexOutOfRange);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindTransformFeedback(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ TransformFeedbackID id)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK:
+ {
+ // Cannot bind a transform feedback object if the current one is started and not
+ // paused (3.0.2 pg 85 section 2.14.1)
+ if (context->getState().isTransformFeedbackActiveUnpaused())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTransformFeedbackNotPaused);
+ return false;
+ }
+
+ // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
+ // 2.14.1)
+ if (!context->isTransformFeedbackGenerated(id))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTransformFeedbackDoesNotExist);
+ return false;
+ }
+ }
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateIsTransformFeedback(const Context *context,
+ angle::EntryPoint entryPoint,
+ TransformFeedbackID id)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePauseTransformFeedback(const Context *context, angle::EntryPoint entryPoint)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != nullptr);
+
+ // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
+ if (!transformFeedback->isActive())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackNotActive);
+ return false;
+ }
+
+ if (transformFeedback->isPaused())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackPaused);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateResumeTransformFeedback(const Context *context, angle::EntryPoint entryPoint)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != nullptr);
+
+ // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
+ if (!transformFeedback->isActive())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackNotActive);
+ return false;
+ }
+
+ if (!transformFeedback->isPaused())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackNotPaused);
+ return false;
+ }
+
+ if (!ValidateProgramExecutableXFBBuffersPresent(
+ context, context->getState().getLinkedProgramExecutable(context)))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackBufferMissing);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexAttribI4i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint w)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateVertexAttribIndex(context, entryPoint, index);
+}
+
+bool ValidateVertexAttribI4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLuint x,
+ GLuint y,
+ GLuint z,
+ GLuint w)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateVertexAttribIndex(context, entryPoint, index);
+}
+
+bool ValidateVertexAttribI4iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLint *v)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateVertexAttribIndex(context, entryPoint, index);
+}
+
+bool ValidateVertexAttribI4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLuint *v)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateVertexAttribIndex(context, entryPoint, index);
+}
+
+bool ValidateGetFragDataLocation(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ const GLchar *name)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (!programObject->isLinked())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetUniformIndices(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLsizei uniformCount,
+ const GLchar *const *uniformNames,
+ const GLuint *uniformIndices)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (uniformCount < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetActiveUniformsiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLsizei uniformCount,
+ const GLuint *uniformIndices,
+ GLenum pname,
+ const GLint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (uniformCount < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_UNIFORM_TYPE:
+ case GL_UNIFORM_SIZE:
+ break;
+ case GL_UNIFORM_NAME_LENGTH:
+ if (context->getExtensions().webglCompatibilityANGLE)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+ break;
+ case GL_UNIFORM_BLOCK_INDEX:
+ case GL_UNIFORM_OFFSET:
+ case GL_UNIFORM_ARRAY_STRIDE:
+ case GL_UNIFORM_MATRIX_STRIDE:
+ case GL_UNIFORM_IS_ROW_MAJOR:
+ break;
+
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
+ return false;
+ }
+
+ if (uniformCount > programObject->getActiveUniformCount())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
+ return false;
+ }
+
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+ {
+ const GLuint index = uniformIndices[uniformId];
+
+ if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetUniformBlockIndex(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ const GLchar *uniformBlockName)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetActiveUniformBlockiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformBlockIndex uniformBlockIndex,
+ GLenum pname,
+ const GLint *params)
+{
+ return ValidateGetActiveUniformBlockivBase(context, entryPoint, program, uniformBlockIndex,
+ pname, nullptr);
+}
+
+bool ValidateGetActiveUniformBlockName(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformBlockIndex uniformBlockIndex,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *uniformBlockName)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ if (uniformBlockIndex.value >= programObject->getActiveUniformBlockCount())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxActiveUniformBlock);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateUniformBlockBinding(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformBlockIndex uniformBlockIndex,
+ GLuint uniformBlockBinding)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (uniformBlockBinding >= static_cast<GLuint>(context->getCaps().maxUniformBufferBindings))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kIndexExceedsMaxUniformBufferBindings);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+
+ // if never linked, there won't be any uniform blocks
+ if (uniformBlockIndex.value >= programObject->getActiveUniformBlockCount())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kIndexExceedsMaxUniformBufferBindings);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawArraysInstanced(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount);
+}
+
+bool ValidateFenceSync(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum condition,
+ GLbitfield flags)
+{
+ if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFenceCondition);
+ return false;
+ }
+
+ if (flags != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFlags);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateIsSync(const Context *context, angle::EntryPoint entryPoint, GLsync sync)
+{
+ if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDeleteSync(const Context *context, angle::EntryPoint entryPoint, GLsync sync)
+{
+ if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kSyncMissing);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateClientWaitSync(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsync sync,
+ GLbitfield flags,
+ GLuint64 timeout)
+{
+ if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFlags);
+ return false;
+ }
+
+ Sync *clientWaitSync = context->getSync(sync);
+ if (!clientWaitSync)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kSyncMissing);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateWaitSync(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsync sync,
+ GLbitfield flags,
+ GLuint64 timeout)
+{
+ if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (flags != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFlags);
+ return false;
+ }
+
+ if (timeout != GL_TIMEOUT_IGNORED)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidTimeout);
+ return false;
+ }
+
+ Sync *waitSync = context->getSync(sync);
+ if (!waitSync)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kSyncMissing);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetInteger64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLint64 *params)
+{
+ if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ GLenum nativeType = GL_NONE;
+ unsigned int numParams = 0;
+ if (!ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateIsSampler(const Context *context, angle::EntryPoint entryPoint, SamplerID sampler)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindSampler(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint unit,
+ SamplerID sampler)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (GetIDValue(sampler) != 0 && !context->isSampler(sampler))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidSampler);
+ return false;
+ }
+
+ if (unit >= static_cast<GLuint>(context->getCaps().maxCombinedTextureImageUnits))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidCombinedImageUnit);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexAttribDivisor(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLuint divisor)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ return ValidateVertexAttribIndex(context, entryPoint, index);
+}
+
+bool ValidateTexStorage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!ValidateES3TexStorage2DParameters(context, entryPoint, target, levels, internalformat,
+ width, height, 1))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTexStorage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+
+ if (!ValidateES3TexStorage3DParameters(context, entryPoint, target, levels, internalformat,
+ width, height, depth))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBufferParameteri64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding target,
+ GLenum pname,
+ const GLint64 *params)
+{
+ return ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, nullptr);
+}
+
+bool ValidateGetSamplerParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ const GLfloat *params)
+{
+ return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
+}
+
+bool ValidateGetSamplerParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ const GLint *params)
+{
+ return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
+}
+
+bool ValidateGetSamplerParameterIivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ const GLint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
+}
+
+bool ValidateGetSamplerParameterIuivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ const GLuint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
+}
+
+bool ValidateSamplerParameterf(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ GLfloat param)
+{
+ return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, false, &param);
+}
+
+bool ValidateSamplerParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ const GLfloat *params)
+{
+ return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
+}
+
+bool ValidateSamplerParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ GLint param)
+{
+ return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, false, &param);
+}
+
+bool ValidateSamplerParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ const GLint *params)
+{
+ return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
+}
+
+bool ValidateSamplerParameterIivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ const GLint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
+}
+
+bool ValidateSamplerParameterIuivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ const GLuint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
+}
+
+bool ValidateGetVertexAttribIiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ const GLint *params)
+{
+ return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, true);
+}
+
+bool ValidateGetVertexAttribIuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ const GLuint *params)
+{
+ return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, true);
+}
+
+bool ValidateGetInternalformativ(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params)
+{
+ return ValidateGetInternalFormativBase(context, entryPoint, target, internalformat, pname,
+ bufSize, nullptr);
+}
+
+bool ValidateBindFragDataLocationIndexedEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLuint colorNumber,
+ GLuint index,
+ const char *name)
+{
+ if (!context->getExtensions().blendFuncExtendedEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ if (index > 1)
+ {
+ // This error is not explicitly specified but the spec does say that "<index> may be zero or
+ // one to specify that the color be used as either the first or second color input to the
+ // blend equation, respectively"
+ context->validationError(entryPoint, GL_INVALID_VALUE, kFragDataBindingIndexOutOfRange);
+ return false;
+ }
+ if (index == 1)
+ {
+ if (colorNumber >= context->getCaps().maxDualSourceDrawBuffers)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kColorNumberGreaterThanMaxDualSourceDrawBuffers);
+ return false;
+ }
+ }
+ else
+ {
+ if (colorNumber >= static_cast<GLuint>(context->getCaps().maxDrawBuffers))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE,
+ kColorNumberGreaterThanMaxDrawBuffers);
+ return false;
+ }
+ }
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool ValidateBindFragDataLocationEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLuint colorNumber,
+ const char *name)
+{
+ return ValidateBindFragDataLocationIndexedEXT(context, entryPoint, program, colorNumber, 0u,
+ name);
+}
+
+bool ValidateGetFragDataIndexEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ const char *name)
+{
+ if (!context->getExtensions().blendFuncExtendedEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+ if (!programObject->isLinked())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateTexStorage2DMultisampleANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedSampleLocations)
+{
+ if (!context->getExtensions().textureMultisampleANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMultisampleTextureExtensionOrES31Required);
+ return false;
+ }
+
+ return ValidateTexStorage2DMultisampleBase(context, entryPoint, target, samples, internalFormat,
+ width, height);
+}
+
+bool ValidateGetTexLevelParameterfvANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum pname,
+ const GLfloat *params)
+{
+ if (!context->getExtensions().textureMultisampleANGLE &&
+ !context->getExtensions().getTexLevelParameterANGLE)
+ {
+ context->validationError(
+ entryPoint, GL_INVALID_OPERATION,
+ kMultisampleTextureExtensionOrGetTexLevelParameterExtensionOrES31Required);
+ return false;
+ }
+
+ return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr);
+}
+
+bool ValidateGetTexLevelParameterivANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum pname,
+ const GLint *params)
+{
+ if (!context->getExtensions().textureMultisampleANGLE &&
+ !context->getExtensions().getTexLevelParameterANGLE)
+ {
+ context->validationError(
+ entryPoint, GL_INVALID_OPERATION,
+ kMultisampleTextureExtensionOrGetTexLevelParameterExtensionOrES31Required);
+ return false;
+ }
+
+ return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr);
+}
+
+bool ValidateGetMultisamplefvANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLuint index,
+ const GLfloat *val)
+{
+ if (!context->getExtensions().textureMultisampleANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMultisampleTextureExtensionOrES31Required);
+ return false;
+ }
+
+ return ValidateGetMultisamplefvBase(context, entryPoint, pname, index, val);
+}
+
+bool ValidateSampleMaskiANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint maskNumber,
+ GLbitfield mask)
+{
+ if (!context->getExtensions().textureMultisampleANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMultisampleTextureExtensionOrES31Required);
+ return false;
+ }
+
+ return ValidateSampleMaskiBase(context, entryPoint, maskNumber, mask);
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/validationES3.h b/gfx/angle/checkout/src/libANGLE/validationES3.h
new file mode 100644
index 0000000000..dcea322874
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES3.h
@@ -0,0 +1,72 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationES3.h:
+// Inlined validation functions for OpenGL ES 3.0 entry points.
+
+#ifndef LIBANGLE_VALIDATION_ES3_H_
+#define LIBANGLE_VALIDATION_ES3_H_
+
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/validationES3_autogen.h"
+
+namespace gl
+{
+bool ValidateES3TexImageParametersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum internalformat,
+ bool isCompressed,
+ bool isSubImage,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei imageSize,
+ const void *pixels);
+
+bool ValidateES3TexStorageParametersLevel(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+
+bool ValidateES3TexStorageParametersExtent(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+
+bool ValidateES3TexStorageParametersTexObject(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target);
+
+bool ValidateES3TexStorageParametersFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+
+bool ValidateProgramParameteriBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum pname,
+ GLint value);
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES3_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationES31.cpp b/gfx/angle/checkout/src/libANGLE/validationES31.cpp
new file mode 100644
index 0000000000..c0222f7497
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES31.cpp
@@ -0,0 +1,3157 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationES31.cpp: Validation functions for OpenGL ES 3.1 entry point parameters
+
+#include "libANGLE/validationES31_autogen.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/ProgramExecutable.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES2_autogen.h"
+#include "libANGLE/validationES31.h"
+#include "libANGLE/validationES3_autogen.h"
+
+#include "common/utilities.h"
+
+using namespace angle;
+
+namespace gl
+{
+using namespace err;
+
+namespace
+{
+
+bool ValidateNamedProgramInterface(GLenum programInterface)
+{
+ switch (programInterface)
+ {
+ case GL_UNIFORM:
+ case GL_UNIFORM_BLOCK:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ case GL_BUFFER_VARIABLE:
+ case GL_SHADER_STORAGE_BLOCK:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool ValidateLocationProgramInterface(GLenum programInterface)
+{
+ switch (programInterface)
+ {
+ case GL_UNIFORM:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool ValidateProgramInterface(GLenum programInterface)
+{
+ return (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
+ ValidateNamedProgramInterface(programInterface));
+}
+
+bool ValidateProgramResourceProperty(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum prop)
+{
+ ASSERT(context);
+ switch (prop)
+ {
+ case GL_ACTIVE_VARIABLES:
+ case GL_BUFFER_BINDING:
+ case GL_NUM_ACTIVE_VARIABLES:
+
+ case GL_ARRAY_SIZE:
+
+ case GL_ARRAY_STRIDE:
+ case GL_BLOCK_INDEX:
+ case GL_IS_ROW_MAJOR:
+ case GL_MATRIX_STRIDE:
+
+ case GL_ATOMIC_COUNTER_BUFFER_INDEX:
+
+ case GL_BUFFER_DATA_SIZE:
+
+ case GL_LOCATION:
+
+ case GL_NAME_LENGTH:
+
+ case GL_OFFSET:
+
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+
+ case GL_TOP_LEVEL_ARRAY_SIZE:
+ case GL_TOP_LEVEL_ARRAY_STRIDE:
+
+ case GL_TYPE:
+ return true;
+
+ case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
+ return context->getExtensions().geometryShaderAny() ||
+ context->getClientVersion() >= ES_3_2;
+
+ case GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT:
+ case GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT:
+ case GL_IS_PER_PATCH_EXT:
+ return context->getExtensions().tessellationShaderEXT ||
+ context->getClientVersion() >= ES_3_2;
+
+ case GL_LOCATION_INDEX_EXT:
+ return context->getExtensions().blendFuncExtendedEXT;
+
+ default:
+ return false;
+ }
+}
+
+// GLES 3.10 spec: Page 82 -- Table 7.2
+bool ValidateProgramResourcePropertyByInterface(GLenum prop, GLenum programInterface)
+{
+ switch (prop)
+ {
+ case GL_ACTIVE_VARIABLES:
+ case GL_BUFFER_BINDING:
+ case GL_NUM_ACTIVE_VARIABLES:
+ {
+ switch (programInterface)
+ {
+ case GL_ATOMIC_COUNTER_BUFFER:
+ case GL_SHADER_STORAGE_BLOCK:
+ case GL_UNIFORM_BLOCK:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ case GL_ARRAY_SIZE:
+ {
+ switch (programInterface)
+ {
+ case GL_BUFFER_VARIABLE:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ case GL_UNIFORM:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ case GL_ARRAY_STRIDE:
+ case GL_BLOCK_INDEX:
+ case GL_IS_ROW_MAJOR:
+ case GL_MATRIX_STRIDE:
+ {
+ switch (programInterface)
+ {
+ case GL_BUFFER_VARIABLE:
+ case GL_UNIFORM:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ case GL_ATOMIC_COUNTER_BUFFER_INDEX:
+ {
+ if (programInterface == GL_UNIFORM)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ case GL_BUFFER_DATA_SIZE:
+ {
+ switch (programInterface)
+ {
+ case GL_ATOMIC_COUNTER_BUFFER:
+ case GL_SHADER_STORAGE_BLOCK:
+ case GL_UNIFORM_BLOCK:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ case GL_LOCATION:
+ {
+ return ValidateLocationProgramInterface(programInterface);
+ }
+
+ case GL_LOCATION_INDEX_EXT:
+ {
+ // EXT_blend_func_extended
+ return (programInterface == GL_PROGRAM_OUTPUT);
+ }
+
+ case GL_NAME_LENGTH:
+ {
+ return ValidateNamedProgramInterface(programInterface);
+ }
+
+ case GL_OFFSET:
+ {
+ switch (programInterface)
+ {
+ case GL_BUFFER_VARIABLE:
+ case GL_UNIFORM:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ case GL_REFERENCED_BY_VERTEX_SHADER:
+ case GL_REFERENCED_BY_FRAGMENT_SHADER:
+ case GL_REFERENCED_BY_COMPUTE_SHADER:
+ case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
+ case GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT:
+ case GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT:
+ {
+ switch (programInterface)
+ {
+ case GL_ATOMIC_COUNTER_BUFFER:
+ case GL_BUFFER_VARIABLE:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_SHADER_STORAGE_BLOCK:
+ case GL_UNIFORM:
+ case GL_UNIFORM_BLOCK:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ case GL_TOP_LEVEL_ARRAY_SIZE:
+ case GL_TOP_LEVEL_ARRAY_STRIDE:
+ {
+ if (programInterface == GL_BUFFER_VARIABLE)
+ {
+ return true;
+ }
+ return false;
+ }
+
+ case GL_TYPE:
+ {
+ switch (programInterface)
+ {
+ case GL_BUFFER_VARIABLE:
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ case GL_UNIFORM:
+ return true;
+ default:
+ return false;
+ }
+ }
+ case GL_IS_PER_PATCH_EXT:
+ switch (programInterface)
+ {
+ case GL_PROGRAM_INPUT:
+ case GL_PROGRAM_OUTPUT:
+ return true;
+ }
+ return false;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidateProgramResourceIndex(const Program *programObject,
+ GLenum programInterface,
+ GLuint index)
+{
+ switch (programInterface)
+ {
+ case GL_PROGRAM_INPUT:
+ return (index <
+ static_cast<GLuint>(programObject->getState().getProgramInputs().size()));
+
+ case GL_PROGRAM_OUTPUT:
+ return (index < static_cast<GLuint>(programObject->getOutputResourceCount()));
+
+ case GL_UNIFORM:
+ return (index < static_cast<GLuint>(programObject->getActiveUniformCount()));
+
+ case GL_BUFFER_VARIABLE:
+ return (index < static_cast<GLuint>(programObject->getActiveBufferVariableCount()));
+
+ case GL_SHADER_STORAGE_BLOCK:
+ return (index < static_cast<GLuint>(programObject->getActiveShaderStorageBlockCount()));
+
+ case GL_UNIFORM_BLOCK:
+ return (index < programObject->getActiveUniformBlockCount());
+
+ case GL_ATOMIC_COUNTER_BUFFER:
+ return (index < programObject->getActiveAtomicCounterBufferCount());
+
+ case GL_TRANSFORM_FEEDBACK_VARYING:
+ return (index < static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()));
+
+ default:
+ UNREACHABLE();
+ return false;
+ }
+}
+
+bool ValidateProgramUniformBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum valueType,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count)
+{
+ const LinkedUniform *uniform = nullptr;
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
+ &uniform) &&
+ ValidateUniformValue(context, entryPoint, valueType, uniform->type);
+}
+
+bool ValidateProgramUniformMatrixBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum valueType,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose)
+{
+ const LinkedUniform *uniform = nullptr;
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
+ &uniform) &&
+ ValidateUniformMatrixValue(context, entryPoint, valueType, uniform->type);
+}
+
+bool ValidateVertexAttribFormatCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint relativeOffset)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kRelativeOffsetTooLarge);
+ return false;
+ }
+
+ // [OpenGL ES 3.1] Section 10.3.1 page 243:
+ // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+ if (context->getState().getVertexArrayId().value == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray);
+ return false;
+ }
+
+ return true;
+}
+
+} // anonymous namespace
+
+bool ValidateGetBooleani_v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ const GLboolean *data)
+{
+ if (context->getClientVersion() < ES_3_1 && !context->getExtensions().drawBuffersIndexedAny())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kES31OrDrawBuffersIndexedExtensionNotAvailable);
+ return false;
+ }
+
+ if (!ValidateIndexedStateQuery(context, entryPoint, target, index, nullptr))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetBooleani_vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLboolean *data)
+{
+ if (context->getClientVersion() < ES_3_1 && !context->getExtensions().drawBuffersIndexedAny())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kES31OrDrawBuffersIndexedExtensionNotAvailable);
+ return false;
+ }
+
+ if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
+ {
+ return false;
+ }
+
+ GLsizei numParams = 0;
+
+ if (!ValidateIndexedStateQuery(context, entryPoint, target, index, &numParams))
+ {
+ return false;
+ }
+
+ if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
+ {
+ return false;
+ }
+
+ SetRobustLengthParam(length, numParams);
+ return true;
+}
+
+bool ValidateDrawIndirectBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ const void *indirect)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ // Here the third parameter 1 is only to pass the count validation.
+ if (!ValidateDrawBase(context, entryPoint, mode))
+ {
+ return false;
+ }
+
+ const State &state = context->getState();
+
+ // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
+ // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
+ if (state.getVertexArrayId().value == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray);
+ return false;
+ }
+
+ if (context->getStateCache().hasAnyActiveClientAttrib())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kClientDataInVertexArray);
+ return false;
+ }
+
+ Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
+ if (!drawIndirectBuffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDrawIndirectBufferNotBound);
+ return false;
+ }
+
+ // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
+ // machine units, of uint.
+ GLint64 offset = reinterpret_cast<GLint64>(indirect);
+ if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidIndirectOffset);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawArraysIndirect(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ const void *indirect)
+{
+ const State &state = context->getState();
+ TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
+ if (curTransformFeedback && curTransformFeedback->isActive() &&
+ !curTransformFeedback->isPaused())
+ {
+ // EXT_geometry_shader allows transform feedback to work with all draw commands.
+ // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
+ if (context->getExtensions().geometryShaderAny() || context->getClientVersion() >= ES_3_2)
+ {
+ if (!ValidateTransformFeedbackPrimitiveMode(
+ context, entryPoint, curTransformFeedback->getPrimitiveMode(), mode))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidDrawModeTransformFeedback);
+ return false;
+ }
+ }
+ else
+ {
+ // An INVALID_OPERATION error is generated if transform feedback is active and not
+ // paused.
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kUnsupportedDrawModeForTransformFeedback);
+ return false;
+ }
+ }
+
+ if (!ValidateDrawIndirectBase(context, entryPoint, mode, indirect))
+ return false;
+
+ Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
+ CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
+ // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
+ // which's size is 4 * sizeof(uint).
+ auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
+ if (!checkedSum.IsValid() ||
+ checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kParamOverflow);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawElementsIndirect(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ DrawElementsType type,
+ const void *indirect)
+{
+ if (!ValidateDrawElementsBase(context, entryPoint, mode, type))
+ {
+ return false;
+ }
+
+ const State &state = context->getState();
+ const VertexArray *vao = state.getVertexArray();
+ Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
+ if (!elementArrayBuffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kMustHaveElementArrayBinding);
+ return false;
+ }
+
+ if (!ValidateDrawIndirectBase(context, entryPoint, mode, indirect))
+ return false;
+
+ Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
+ CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
+ // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
+ // which's size is 5 * sizeof(uint).
+ auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
+ if (!checkedSum.IsValid() ||
+ checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kParamOverflow);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateMultiDrawIndirectBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei drawcount,
+ GLsizei stride)
+{
+ if (!context->getExtensions().multiDrawIndirectEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ // An INVALID_VALUE error is generated if stride is neither 0 nor a multiple of 4.
+ if ((stride & 3) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDrawBufferValue);
+ return false;
+ }
+
+ // An INVALID_VALUE error is generated if drawcount is not positive.
+ if (drawcount <= 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidValueNonPositive);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateProgramUniform1iBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLint v0)
+{
+ return ValidateProgramUniform1ivBase(context, entryPoint, program, location, 1, &v0);
+}
+
+bool ValidateProgramUniform2iBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLint v0,
+ GLint v1)
+{
+ GLint xy[2] = {v0, v1};
+ return ValidateProgramUniform2ivBase(context, entryPoint, program, location, 1, xy);
+}
+
+bool ValidateProgramUniform3iBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLint v0,
+ GLint v1,
+ GLint v2)
+{
+ GLint xyz[3] = {v0, v1, v2};
+ return ValidateProgramUniform3ivBase(context, entryPoint, program, location, 1, xyz);
+}
+
+bool ValidateProgramUniform4iBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLint v0,
+ GLint v1,
+ GLint v2,
+ GLint v3)
+{
+ GLint xyzw[4] = {v0, v1, v2, v3};
+ return ValidateProgramUniform4ivBase(context, entryPoint, program, location, 1, xyzw);
+}
+
+bool ValidateProgramUniform1uiBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLuint v0)
+{
+ return ValidateProgramUniform1uivBase(context, entryPoint, program, location, 1, &v0);
+}
+
+bool ValidateProgramUniform2uiBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLuint v0,
+ GLuint v1)
+{
+ GLuint xy[2] = {v0, v1};
+ return ValidateProgramUniform2uivBase(context, entryPoint, program, location, 1, xy);
+}
+
+bool ValidateProgramUniform3uiBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ GLuint xyz[3] = {v0, v1, v2};
+ return ValidateProgramUniform3uivBase(context, entryPoint, program, location, 1, xyz);
+}
+
+bool ValidateProgramUniform4uiBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ GLuint xyzw[4] = {v0, v1, v2, v3};
+ return ValidateProgramUniform4uivBase(context, entryPoint, program, location, 1, xyzw);
+}
+
+bool ValidateProgramUniform1fBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLfloat v0)
+{
+ return ValidateProgramUniform1fvBase(context, entryPoint, program, location, 1, &v0);
+}
+
+bool ValidateProgramUniform2fBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLfloat v0,
+ GLfloat v1)
+{
+ GLfloat xy[2] = {v0, v1};
+ return ValidateProgramUniform2fvBase(context, entryPoint, program, location, 1, xy);
+}
+
+bool ValidateProgramUniform3fBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2)
+{
+ GLfloat xyz[3] = {v0, v1, v2};
+ return ValidateProgramUniform3fvBase(context, entryPoint, program, location, 1, xyz);
+}
+
+bool ValidateProgramUniform4fBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2,
+ GLfloat v3)
+{
+ GLfloat xyzw[4] = {v0, v1, v2, v3};
+ return ValidateProgramUniform4fvBase(context, entryPoint, program, location, 1, xyzw);
+}
+
+bool ValidateProgramUniform1ivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLint *value)
+{
+ const LinkedUniform *uniform = nullptr;
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
+ &uniform) &&
+ ValidateUniform1ivValue(context, entryPoint, uniform->type, count, value);
+}
+
+bool ValidateProgramUniform2ivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLint *value)
+{
+ return ValidateProgramUniformBase(context, entryPoint, GL_INT_VEC2, program, location, count);
+}
+
+bool ValidateProgramUniform3ivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLint *value)
+{
+ return ValidateProgramUniformBase(context, entryPoint, GL_INT_VEC3, program, location, count);
+}
+
+bool ValidateProgramUniform4ivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLint *value)
+{
+ return ValidateProgramUniformBase(context, entryPoint, GL_INT_VEC4, program, location, count);
+}
+
+bool ValidateProgramUniform1uivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLuint *value)
+{
+ return ValidateProgramUniformBase(context, entryPoint, GL_UNSIGNED_INT, program, location,
+ count);
+}
+
+bool ValidateProgramUniform2uivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLuint *value)
+{
+ return ValidateProgramUniformBase(context, entryPoint, GL_UNSIGNED_INT_VEC2, program, location,
+ count);
+}
+
+bool ValidateProgramUniform3uivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLuint *value)
+{
+ return ValidateProgramUniformBase(context, entryPoint, GL_UNSIGNED_INT_VEC3, program, location,
+ count);
+}
+
+bool ValidateProgramUniform4uivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLuint *value)
+{
+ return ValidateProgramUniformBase(context, entryPoint, GL_UNSIGNED_INT_VEC4, program, location,
+ count);
+}
+
+bool ValidateProgramUniform1fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformBase(context, entryPoint, GL_FLOAT, program, location, count);
+}
+
+bool ValidateProgramUniform2fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformBase(context, entryPoint, GL_FLOAT_VEC2, program, location, count);
+}
+
+bool ValidateProgramUniform3fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformBase(context, entryPoint, GL_FLOAT_VEC3, program, location, count);
+}
+
+bool ValidateProgramUniform4fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformBase(context, entryPoint, GL_FLOAT_VEC4, program, location, count);
+}
+
+bool ValidateProgramUniformMatrix2fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT2, program, location,
+ count, transpose);
+}
+
+bool ValidateProgramUniformMatrix3fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT3, program, location,
+ count, transpose);
+}
+
+bool ValidateProgramUniformMatrix4fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT4, program, location,
+ count, transpose);
+}
+
+bool ValidateProgramUniformMatrix2x3fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT2x3, program, location,
+ count, transpose);
+}
+
+bool ValidateProgramUniformMatrix3x2fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT3x2, program, location,
+ count, transpose);
+}
+
+bool ValidateProgramUniformMatrix2x4fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT2x4, program, location,
+ count, transpose);
+}
+
+bool ValidateProgramUniformMatrix4x2fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT4x2, program, location,
+ count, transpose);
+}
+
+bool ValidateProgramUniformMatrix3x4fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT3x4, program, location,
+ count, transpose);
+}
+
+bool ValidateProgramUniformMatrix4x3fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT4x3, program, location,
+ count, transpose);
+}
+
+bool ValidateGetTexLevelParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum pname,
+ const GLfloat *params)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr);
+}
+
+bool ValidateGetTexLevelParameterfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGetTexLevelParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum pname,
+ const GLint *params)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr);
+}
+
+bool ValidateGetTexLevelParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateTexStorage2DMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedSampleLocations)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateTexStorage2DMultisampleBase(context, entryPoint, target, samples, internalFormat,
+ width, height);
+}
+
+bool ValidateTexStorageMem2DMultisampleEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memory,
+ GLuint64 offset)
+{
+ if (!context->getExtensions().memoryObjectEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGetMultisamplefv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLuint index,
+ const GLfloat *val)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateGetMultisamplefvBase(context, entryPoint, pname, index, val);
+}
+
+bool ValidateGetMultisamplefvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *val)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateFramebufferParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ GLint param)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateFramebufferParameteriBase(context, entryPoint, target, pname, param);
+}
+
+bool ValidateGetFramebufferParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ const GLint *params)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateGetFramebufferParameterivBase(context, entryPoint, target, pname, params);
+}
+
+bool ValidateGetFramebufferParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGetProgramResourceIndex(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (programObject == nullptr)
+ {
+ return false;
+ }
+
+ if (!ValidateNamedProgramInterface(programInterface))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProgramInterface);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindVertexBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint bindingIndex,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizei stride)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ if (!context->isBufferGenerated(buffer))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (bindingIndex >= static_cast<GLuint>(caps.maxVertexAttribBindings))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
+ return false;
+ }
+
+ if (offset < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
+ return false;
+ }
+
+ if (stride < 0 || stride > caps.maxVertexAttribStride)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribStride);
+ return false;
+ }
+
+ // [OpenGL ES 3.1] Section 10.3.1 page 244:
+ // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+ if (context->getState().getVertexArrayId().value == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexBindingDivisor(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint bindingIndex,
+ GLuint divisor)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (bindingIndex >= static_cast<GLuint>(caps.maxVertexAttribBindings))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
+ return false;
+ }
+
+ // [OpenGL ES 3.1] Section 10.3.1 page 243:
+ // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+ if (context->getState().getVertexArrayId().value == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateVertexAttribFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint attribindex,
+ GLint size,
+ VertexAttribType type,
+ GLboolean normalized,
+ GLuint relativeoffset)
+{
+ if (!ValidateVertexAttribFormatCommon(context, entryPoint, relativeoffset))
+ {
+ return false;
+ }
+
+ return ValidateFloatVertexFormat(context, entryPoint, attribindex, size, type);
+}
+
+bool ValidateVertexAttribIFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint attribindex,
+ GLint size,
+ VertexAttribType type,
+ GLuint relativeoffset)
+{
+ if (!ValidateVertexAttribFormatCommon(context, entryPoint, relativeoffset))
+ {
+ return false;
+ }
+
+ return ValidateIntegerVertexFormat(context, entryPoint, attribindex, size, type);
+}
+
+bool ValidateVertexAttribBinding(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint attribIndex,
+ GLuint bindingIndex)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ // [OpenGL ES 3.1] Section 10.3.1 page 243:
+ // An INVALID_OPERATION error is generated if the default vertex array object is bound.
+ if (context->getState().getVertexArrayId().value == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (attribIndex >= static_cast<GLuint>(caps.maxVertexAttributes))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
+ return false;
+ }
+
+ if (bindingIndex >= static_cast<GLuint>(caps.maxVertexAttribBindings))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetProgramResourceName(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *name)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (programObject == nullptr)
+ {
+ return false;
+ }
+
+ if (!ValidateNamedProgramInterface(programInterface))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProgramInterface);
+ return false;
+ }
+
+ if (!ValidateProgramResourceIndex(programObject, programInterface, index))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramResourceIndex);
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDispatchCompute(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint numGroupsX,
+ GLuint numGroupsY,
+ GLuint numGroupsZ)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ const State &state = context->getState();
+ const ProgramExecutable *executable = state.getProgramExecutable();
+
+ if (executable == nullptr || !executable->hasLinkedShaderStage(ShaderType::Compute))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kNoActiveProgramWithComputeShader);
+ return false;
+ }
+
+ const Caps &caps = context->getCaps();
+ if (numGroupsX > static_cast<GLuint>(caps.maxComputeWorkGroupCount[0]))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsComputeWorkGroupCountX);
+ return false;
+ }
+ if (numGroupsY > static_cast<GLuint>(caps.maxComputeWorkGroupCount[1]))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsComputeWorkGroupCountY);
+ return false;
+ }
+ if (numGroupsZ > static_cast<GLuint>(caps.maxComputeWorkGroupCount[2]))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsComputeWorkGroupCountZ);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDispatchComputeIndirect(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLintptr indirect)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ const State &state = context->getState();
+ const ProgramExecutable *executable = state.getProgramExecutable();
+
+ if (executable == nullptr || !executable->hasLinkedShaderStage(ShaderType::Compute))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kNoActiveProgramWithComputeShader);
+ return false;
+ }
+
+ if (indirect < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
+ return false;
+ }
+
+ if ((indirect & (sizeof(GLuint) - 1)) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetMustBeMultipleOfUint);
+ return false;
+ }
+
+ Buffer *dispatchIndirectBuffer = state.getTargetBuffer(BufferBinding::DispatchIndirect);
+ if (!dispatchIndirectBuffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kDispatchIndirectBufferNotBound);
+ return false;
+ }
+
+ CheckedNumeric<GLuint64> checkedOffset(static_cast<GLuint64>(indirect));
+ auto checkedSum = checkedOffset + static_cast<GLuint64>(3 * sizeof(GLuint));
+ if (!checkedSum.IsValid() ||
+ checkedSum.ValueOrDie() > static_cast<GLuint64>(dispatchIndirectBuffer->getSize()))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBindImageTexture(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint unit,
+ TextureID texture,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ GLuint maxImageUnits = static_cast<GLuint>(context->getCaps().maxImageUnits);
+ if (unit >= maxImageUnits)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxImageUnits);
+ return false;
+ }
+
+ if (level < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLevel);
+ return false;
+ }
+
+ if (layer < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLayer);
+ return false;
+ }
+
+ if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidImageAccess);
+ return false;
+ }
+
+ switch (format)
+ {
+ case GL_RGBA32F:
+ case GL_RGBA16F:
+ case GL_R32F:
+ case GL_RGBA32UI:
+ case GL_RGBA16UI:
+ case GL_RGBA8UI:
+ case GL_R32UI:
+ case GL_RGBA32I:
+ case GL_RGBA16I:
+ case GL_RGBA8I:
+ case GL_R32I:
+ case GL_RGBA8:
+ case GL_RGBA8_SNORM:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidImageFormat);
+ return false;
+ }
+
+ if (texture.value != 0)
+ {
+ Texture *tex = context->getTexture(texture);
+
+ if (tex == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kMissingTextureName);
+ return false;
+ }
+
+ if (!tex->getImmutableFormat() && tex->getType() != gl::TextureType::Buffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTextureIsNeitherImmutableNorTextureBuffer);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetProgramResourceLocation(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (programObject == nullptr)
+ {
+ return false;
+ }
+
+ if (!programObject->isLinked())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
+ return false;
+ }
+
+ if (!ValidateLocationProgramInterface(programInterface))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProgramInterface);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateGetProgramResourceiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (programObject == nullptr)
+ {
+ return false;
+ }
+ if (!ValidateProgramInterface(programInterface))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProgramInterface);
+ return false;
+ }
+ if (propCount <= 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidPropCount);
+ return false;
+ }
+ if (bufSize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufSize);
+ return false;
+ }
+ if (!ValidateProgramResourceIndex(programObject, programInterface, index))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramResourceIndex);
+ return false;
+ }
+ for (GLsizei i = 0; i < propCount; i++)
+ {
+ if (!ValidateProgramResourceProperty(context, entryPoint, props[i]))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProgramResourceProperty);
+ return false;
+ }
+ if (!ValidateProgramResourcePropertyByInterface(props[i], programInterface))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidPropertyForProgramInterface);
+ return false;
+ }
+ }
+ return true;
+}
+
+bool ValidateGetProgramInterfaceiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum programInterface,
+ GLenum pname,
+ const GLint *params)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (programObject == nullptr)
+ {
+ return false;
+ }
+
+ if (!ValidateProgramInterface(programInterface))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProgramInterface);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_ACTIVE_RESOURCES:
+ case GL_MAX_NAME_LENGTH:
+ case GL_MAX_NUM_ACTIVE_VARIABLES:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+
+ if (pname == GL_MAX_NAME_LENGTH && programInterface == GL_ATOMIC_COUNTER_BUFFER)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kAtomicCounterResourceName);
+ return false;
+ }
+
+ if (pname == GL_MAX_NUM_ACTIVE_VARIABLES)
+ {
+ switch (programInterface)
+ {
+ case GL_ATOMIC_COUNTER_BUFFER:
+ case GL_SHADER_STORAGE_BLOCK:
+ case GL_UNIFORM_BLOCK:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kMaxActiveVariablesInterface);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateGetProgramInterfaceivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum programInterface,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGenProgramPipelinesBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const ProgramPipelineID *pipelines)
+{
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateDeleteProgramPipelinesBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const ProgramPipelineID *pipelines)
+{
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateBindProgramPipelineBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipeline)
+{
+ if (!context->isProgramPipelineGenerated({pipeline}))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateIsProgramPipelineBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipeline)
+{
+ return true;
+}
+
+bool ValidateUseProgramStagesBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipeline,
+ GLbitfield stages,
+ ShaderProgramID programId)
+{
+ // GL_INVALID_VALUE is generated if shaders contains set bits that are not recognized, and is
+ // not the reserved value GL_ALL_SHADER_BITS.
+ GLbitfield knownShaderBits =
+ GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT | GL_COMPUTE_SHADER_BIT;
+
+ if (context->getClientVersion() >= ES_3_2 || context->getExtensions().geometryShaderAny())
+ {
+ knownShaderBits |= GL_GEOMETRY_SHADER_BIT;
+ }
+
+ if (context->getClientVersion() >= ES_3_2 || context->getExtensions().tessellationShaderEXT)
+ {
+ knownShaderBits |= GL_TESS_CONTROL_SHADER_BIT;
+ knownShaderBits |= GL_TESS_EVALUATION_SHADER_BIT;
+ }
+
+ if ((stages & ~knownShaderBits) && (stages != GL_ALL_SHADER_BITS))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kUnrecognizedShaderStageBit);
+ return false;
+ }
+
+ // GL_INVALID_OPERATION is generated if pipeline is not a name previously returned from a call
+ // to glGenProgramPipelines or if such a name has been deleted by a call to
+ // glDeleteProgramPipelines.
+ if (!context->isProgramPipelineGenerated({pipeline}))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated);
+ return false;
+ }
+
+ // If program is zero, or refers to a program object with no valid shader executable for a given
+ // stage, it is as if the pipeline object has no programmable stage configured for the indicated
+ // shader stages.
+ if (programId.value == 0)
+ {
+ return true;
+ }
+
+ Program *program = context->getProgramNoResolveLink(programId);
+ if (!program)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kProgramDoesNotExist);
+ return false;
+ }
+
+ // GL_INVALID_OPERATION is generated if program refers to a program object that was not linked
+ // with its GL_PROGRAM_SEPARABLE status set.
+ // resolveLink() may not have been called if glCreateShaderProgramv() was not used and
+ // glDetachShader() was not called.
+ program->resolveLink(context);
+ if (!program->isSeparable())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotSeparable);
+ return false;
+ }
+
+ // GL_INVALID_OPERATION is generated if program refers to a program object that has not been
+ // successfully linked.
+ if (!program->isLinked())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateActiveShaderProgramBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipeline,
+ ShaderProgramID programId)
+{
+ // An INVALID_OPERATION error is generated if pipeline is not a name returned from a previous
+ // call to GenProgramPipelines or if such a name has since been deleted by
+ // DeleteProgramPipelines.
+ if (!context->isProgramPipelineGenerated({pipeline}))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated);
+ return false;
+ }
+
+ // An INVALID_VALUE error is generated if program is not zero and is not the name of either a
+ // program or shader object.
+ if ((programId.value != 0) && !context->isProgram(programId) && !context->isShader(programId))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kProgramDoesNotExist);
+ return false;
+ }
+
+ // An INVALID_OPERATION error is generated if program is the name of a shader object.
+ if (context->isShader(programId))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExpectedProgramName);
+ return false;
+ }
+
+ // An INVALID_OPERATION error is generated if program is not zero and has not been linked, or
+ // was last linked unsuccessfully. The active program is not modified.
+ Program *program = context->getProgramNoResolveLink(programId);
+ if ((programId.value != 0) && !program->isLinked())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCreateShaderProgramvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderType type,
+ GLsizei count,
+ const GLchar *const *strings)
+{
+ switch (type)
+ {
+ case ShaderType::InvalidEnum:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
+ return false;
+ case ShaderType::Vertex:
+ case ShaderType::Fragment:
+ case ShaderType::Compute:
+ break;
+ case ShaderType::Geometry:
+ if (!context->getExtensions().geometryShaderAny() &&
+ context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
+ return false;
+ }
+ break;
+ case ShaderType::TessControl:
+ case ShaderType::TessEvaluation:
+ if (!context->getExtensions().tessellationShaderEXT &&
+ context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
+ return false;
+ }
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ // GL_INVALID_VALUE is generated if count is negative.
+ if (count < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCreateShaderProgramvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderType type,
+ GLsizei count,
+ const GLchar **strings)
+{
+ const GLchar *const *tmpStrings = strings;
+ return ValidateCreateShaderProgramvBase(context, entryPoint, type, count, tmpStrings);
+}
+
+bool ValidateGetProgramPipelineivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipeline,
+ GLenum pname,
+ const GLint *params)
+{
+ // An INVALID_OPERATION error is generated if pipeline is not a name returned from a previous
+ // call to GenProgramPipelines or if such a name has since been deleted by
+ // DeleteProgramPipelines.
+ if ((pipeline.value == 0) || (!context->isProgramPipelineGenerated(pipeline)))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramPipelineDoesNotExist);
+ return false;
+ }
+
+ // An INVALID_ENUM error is generated if pname is not ACTIVE_PROGRAM,
+ // INFO_LOG_LENGTH, VALIDATE_STATUS, or one of the type arguments in
+ // table 7.1.
+ switch (pname)
+ {
+ case GL_ACTIVE_PROGRAM:
+ case GL_INFO_LOG_LENGTH:
+ case GL_VALIDATE_STATUS:
+ case GL_VERTEX_SHADER:
+ case GL_FRAGMENT_SHADER:
+ case GL_COMPUTE_SHADER:
+ break;
+ case GL_GEOMETRY_SHADER:
+ return context->getExtensions().geometryShaderAny() ||
+ context->getClientVersion() >= ES_3_2;
+ case GL_TESS_CONTROL_SHADER:
+ case GL_TESS_EVALUATION_SHADER:
+ return context->getExtensions().tessellationShaderEXT ||
+ context->getClientVersion() >= ES_3_2;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateValidateProgramPipelineBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipeline)
+{
+ if (pipeline.value == 0)
+ {
+ return false;
+ }
+
+ if (!context->isProgramPipelineGenerated(pipeline))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramPipelineDoesNotExist);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetProgramPipelineInfoLogBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipeline,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *infoLog)
+{
+ if (bufSize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ if (!context->isProgramPipelineGenerated(pipeline))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kProgramPipelineDoesNotExist);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateActiveShaderProgram(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ ShaderProgramID programPacked)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateActiveShaderProgramBase(context, entryPoint, pipelinePacked, programPacked);
+}
+
+bool ValidateBindProgramPipeline(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateBindProgramPipelineBase(context, entryPoint, pipelinePacked);
+}
+
+bool ValidateCreateShaderProgramv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderType typePacked,
+ GLsizei count,
+ const GLchar *const *strings)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateCreateShaderProgramvBase(context, entryPoint, typePacked, count, strings);
+}
+
+bool ValidateDeleteProgramPipelines(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const ProgramPipelineID *pipelinesPacked)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateDeleteProgramPipelinesBase(context, entryPoint, n, pipelinesPacked);
+}
+
+bool ValidateGenProgramPipelines(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const ProgramPipelineID *pipelinesPacked)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateGenProgramPipelinesBase(context, entryPoint, n, pipelinesPacked);
+}
+
+bool ValidateGetProgramPipelineInfoLog(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *infoLog)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateGetProgramPipelineInfoLogBase(context, entryPoint, pipelinePacked, bufSize,
+ length, infoLog);
+}
+
+bool ValidateGetProgramPipelineiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ GLenum pname,
+ const GLint *params)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateGetProgramPipelineivBase(context, entryPoint, pipelinePacked, pname, params);
+}
+
+bool ValidateIsProgramPipeline(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateIsProgramPipelineBase(context, entryPoint, pipelinePacked);
+}
+
+bool ValidateProgramUniform1f(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform1fBase(context, entryPoint, programPacked, locationPacked, v0);
+}
+
+bool ValidateProgramUniform1fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform1fvBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform1i(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform1iBase(context, entryPoint, programPacked, locationPacked, v0);
+}
+
+bool ValidateProgramUniform1iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform1ivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform1ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform1uiBase(context, entryPoint, programPacked, locationPacked, v0);
+}
+
+bool ValidateProgramUniform1uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform1uivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform2f(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform2fBase(context, entryPoint, programPacked, locationPacked, v0, v1);
+}
+
+bool ValidateProgramUniform2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform2fvBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform2i(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform2iBase(context, entryPoint, programPacked, locationPacked, v0, v1);
+}
+
+bool ValidateProgramUniform2iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform2ivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform2ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform2uiBase(context, entryPoint, programPacked, locationPacked, v0,
+ v1);
+}
+
+bool ValidateProgramUniform2uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform2uivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform3fBase(context, entryPoint, programPacked, locationPacked, v0, v1,
+ v2);
+}
+
+bool ValidateProgramUniform3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform3fvBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform3iBase(context, entryPoint, programPacked, locationPacked, v0, v1,
+ v2);
+}
+
+bool ValidateProgramUniform3iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform3ivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform3uiBase(context, entryPoint, programPacked, locationPacked, v0, v1,
+ v2);
+}
+
+bool ValidateProgramUniform3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform3uivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform4f(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2,
+ GLfloat v3)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform4fBase(context, entryPoint, programPacked, locationPacked, v0, v1,
+ v2, v3);
+}
+
+bool ValidateProgramUniform4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform4fvBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform4i(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2,
+ GLint v3)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform4iBase(context, entryPoint, programPacked, locationPacked, v0, v1,
+ v2, v3);
+}
+
+bool ValidateProgramUniform4iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform4ivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform4uiBase(context, entryPoint, programPacked, locationPacked, v0, v1,
+ v2, v3);
+}
+
+bool ValidateProgramUniform4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniform4uivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniformMatrix2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix2fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix2x3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix2x3fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix2x4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix2x4fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix3fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix3x2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix3x2fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix3x4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix3x4fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix4fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix4x2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix4x2fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix4x3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix4x3fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateUseProgramStages(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ GLbitfield stages,
+ ShaderProgramID programPacked)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateUseProgramStagesBase(context, entryPoint, pipelinePacked, stages, programPacked);
+}
+
+bool ValidateValidateProgramPipeline(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateValidateProgramPipelineBase(context, entryPoint, pipelinePacked);
+}
+
+bool ValidateMemoryBarrier(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLbitfield barriers)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ if (barriers == GL_ALL_BARRIER_BITS)
+ {
+ return true;
+ }
+
+ GLbitfield supported_barrier_bits =
+ GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
+ GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
+ GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
+ GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT |
+ GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT;
+
+ if (context->getExtensions().bufferStorageEXT)
+ {
+ supported_barrier_bits |= GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT;
+ }
+
+ if (barriers == 0 || (barriers & ~supported_barrier_bits) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMemoryBarrierBit);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateMemoryBarrierByRegion(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLbitfield barriers)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ if (barriers == GL_ALL_BARRIER_BITS)
+ {
+ return true;
+ }
+
+ GLbitfield supported_barrier_bits = GL_ATOMIC_COUNTER_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT |
+ GL_SHADER_IMAGE_ACCESS_BARRIER_BIT |
+ GL_SHADER_STORAGE_BARRIER_BIT |
+ GL_TEXTURE_FETCH_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT;
+ if (barriers == 0 || (barriers & ~supported_barrier_bits) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMemoryBarrierBit);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSampleMaski(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint maskNumber,
+ GLbitfield mask)
+{
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+
+ return ValidateSampleMaskiBase(context, entryPoint, maskNumber, mask);
+}
+
+bool ValidateMinSampleShadingOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat value)
+{
+ if (!context->getExtensions().sampleShadingOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferTextureCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureID texture,
+ GLint level)
+{
+ if (texture.value != 0)
+ {
+ Texture *tex = context->getTexture(texture);
+
+ // [EXT_geometry_shader] Section 9.2.8 "Attaching Texture Images to a Framebuffer"
+ // An INVALID_VALUE error is generated if <texture> is not the name of a texture object.
+ // We put this validation before ValidateFramebufferTextureBase because it is an
+ // INVALID_OPERATION error for both FramebufferTexture2D and FramebufferTextureLayer:
+ // [OpenGL ES 3.1] Chapter 9.2.8 (FramebufferTexture2D)
+ // An INVALID_OPERATION error is generated if texture is not zero, and does not name an
+ // existing texture object of type matching textarget.
+ // [OpenGL ES 3.1 Chapter 9.2.8 (FramebufferTextureLayer)
+ // An INVALID_OPERATION error is generated if texture is non-zero and is not the name of a
+ // three-dimensional or two-dimensional array texture.
+ if (tex == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidTextureName);
+ return false;
+ }
+
+ if (!ValidMipLevel(context, tex->getType(), level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+
+ // GLES spec 3.1, Section 9.2.8 "Attaching Texture Images to a Framebuffer"
+ // If textarget is TEXTURE_2D_MULTISAMPLE, then level must be zero.
+ if (tex->getType() == TextureType::_2DMultisample && level != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kLevelNotZero);
+ return false;
+ }
+
+ // [OES_texture_storage_multisample_2d_array] Section 9.2.2 "Attaching Images to Framebuffer
+ // Objects"
+ // If texture is a two-dimensional multisample array texture, then level must be zero.
+ if (context->getExtensions().textureStorageMultisample2dArrayOES &&
+ tex->getType() == TextureType::_2DMultisampleArray && level != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kLevelNotZero);
+ return false;
+ }
+ }
+
+ if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferTextureEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureID texture,
+ GLint level)
+{
+ if (!context->getExtensions().geometryShaderEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kGeometryShaderExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateFramebufferTextureCommon(context, entryPoint, target, attachment, texture,
+ level);
+}
+
+bool ValidateFramebufferTextureOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureID texture,
+ GLint level)
+{
+ if (!context->getExtensions().geometryShaderOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kGeometryShaderExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateFramebufferTextureCommon(context, entryPoint, target, attachment, texture,
+ level);
+}
+
+// GL_OES_texture_storage_multisample_2d_array
+bool ValidateTexStorage3DMultisampleOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei samples,
+ GLenum sizedinternalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedsamplelocations)
+{
+ if (!context->getExtensions().textureStorageMultisample2dArrayOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
+ return false;
+ }
+
+ if (target != TextureType::_2DMultisampleArray)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM,
+ kTargetMustBeTexture2DMultisampleArrayOES);
+ return false;
+ }
+
+ if (width < 1 || height < 1 || depth < 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
+ return false;
+ }
+
+ if (depth > context->getCaps().maxArrayTextureLayers)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kTextureDepthOutOfRange);
+ return false;
+ }
+
+ return ValidateTexStorageMultisample(context, entryPoint, target, samples, sizedinternalformat,
+ width, height);
+}
+
+bool ValidateTexStorageMem3DMultisampleEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memory,
+ GLuint64 offset)
+{
+ if (!context->getExtensions().memoryObjectEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGetProgramResourceLocationIndexEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum programInterface,
+ const char *name)
+{
+ if (!context->getExtensions().blendFuncExtendedEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ if (context->getClientVersion() < ES_3_1)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
+ return false;
+ }
+ if (programInterface != GL_PROGRAM_OUTPUT)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kProgramInterfaceMustBeProgramOutput);
+ return false;
+ }
+ Program *programObject = GetValidProgram(context, entryPoint, program);
+ if (!programObject)
+ {
+ return false;
+ }
+ if (!programObject->isLinked())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
+ return false;
+ }
+ return true;
+}
+
+// GL_OES_texture_buffer
+bool ValidateTexBufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum internalformat,
+ BufferID bufferPacked)
+{
+ if (!context->getExtensions().textureBufferOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTextureBufferExtensionNotAvailable);
+ return false;
+ }
+
+ return ValidateTexBufferBase(context, entryPoint, target, internalformat, bufferPacked);
+}
+
+bool ValidateTexBufferRangeOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum internalformat,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ if (!context->getExtensions().textureBufferOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTextureBufferExtensionNotAvailable);
+ return false;
+ }
+
+ return ValidateTexBufferRangeBase(context, entryPoint, target, internalformat, bufferPacked,
+ offset, size);
+}
+
+// GL_EXT_texture_buffer
+bool ValidateTexBufferEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum internalformat,
+ BufferID bufferPacked)
+{
+ if (!context->getExtensions().textureBufferEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTextureBufferExtensionNotAvailable);
+ return false;
+ }
+
+ return ValidateTexBufferBase(context, entryPoint, target, internalformat, bufferPacked);
+}
+
+bool ValidateTexBufferRangeEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum internalformat,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ if (!context->getExtensions().textureBufferEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTextureBufferExtensionNotAvailable);
+ return false;
+ }
+
+ return ValidateTexBufferRangeBase(context, entryPoint, target, internalformat, bufferPacked,
+ offset, size);
+}
+
+bool ValidateTexBufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum internalformat,
+ BufferID bufferPacked)
+{
+ if (target != TextureType::Buffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kTextureBufferTarget);
+ return false;
+ }
+
+ switch (internalformat)
+ {
+ case GL_R8:
+ case GL_R16F:
+ case GL_R32F:
+ case GL_R8I:
+ case GL_R16I:
+ case GL_R32I:
+ case GL_R8UI:
+ case GL_R16UI:
+ case GL_R32UI:
+ case GL_RG8:
+ case GL_RG16F:
+ case GL_RG32F:
+ case GL_RG8I:
+ case GL_RG16I:
+ case GL_RG32I:
+ case GL_RG8UI:
+ case GL_RG16UI:
+ case GL_RG32UI:
+ case GL_RGB32F:
+ case GL_RGB32I:
+ case GL_RGB32UI:
+ case GL_RGBA8:
+ case GL_RGBA16F:
+ case GL_RGBA32F:
+ case GL_RGBA8I:
+ case GL_RGBA16I:
+ case GL_RGBA32I:
+ case GL_RGBA8UI:
+ case GL_RGBA16UI:
+ case GL_RGBA32UI:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kTextureBufferInternalFormat);
+ return false;
+ }
+
+ if (bufferPacked.value != 0)
+ {
+ if (!context->isBufferGenerated(bufferPacked))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureBufferInvalidBuffer);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateTexBufferRangeBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum internalformat,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ const Caps &caps = context->getCaps();
+
+ if (offset < 0 || (offset % caps.textureBufferOffsetAlignment) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kTextureBufferOffsetAlignment);
+ return false;
+ }
+ if (size <= 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kTextureBufferSize);
+ return false;
+ }
+ const Buffer *buffer = context->getBuffer(bufferPacked);
+
+ if (!buffer)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound);
+ return false;
+ }
+
+ if (offset + size > buffer->getSize())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kTextureBufferSizeOffset);
+ return false;
+ }
+
+ return ValidateTexBufferBase(context, entryPoint, target, internalformat, bufferPacked);
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/validationES31.h b/gfx/angle/checkout/src/libANGLE/validationES31.h
new file mode 100644
index 0000000000..c41cedf0da
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES31.h
@@ -0,0 +1,300 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationES31.h:
+// Inlined validation functions for OpenGL ES 3.1 entry points.
+
+#ifndef LIBANGLE_VALIDATION_ES31_H_
+#define LIBANGLE_VALIDATION_ES31_H_
+
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/validationES31_autogen.h"
+
+namespace gl
+{
+
+bool ValidateTexBufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum internalformat,
+ BufferID bufferPacked);
+bool ValidateTexBufferRangeBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum internalformat,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size);
+
+// GL_EXT_multi_draw_indirect
+bool ValidateMultiDrawIndirectBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei drawcount,
+ GLsizei stride);
+
+// GL_EXT_separate_shader_objects
+bool ValidateActiveShaderProgramBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ ShaderProgramID programPacked);
+bool ValidateBindProgramPipelineBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked);
+bool ValidateCreateShaderProgramvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderType typePacked,
+ GLsizei count,
+ const GLchar **strings);
+bool ValidateDeleteProgramPipelinesBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const ProgramPipelineID *pipelinesPacked);
+bool ValidateGenProgramPipelinesBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const ProgramPipelineID *pipelinesPacked);
+bool ValidateGetProgramPipelineInfoLogBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *infoLog);
+bool ValidateGetProgramPipelineivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateIsProgramPipelineBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked);
+bool ValidateProgramParameteriBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum pname,
+ GLint value);
+bool ValidateProgramUniform1fBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0);
+bool ValidateProgramUniform1fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniform1iBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0);
+bool ValidateProgramUniform1ivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform1uiBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0);
+bool ValidateProgramUniform1uivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniform2fBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1);
+bool ValidateProgramUniform2fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniform2iBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1);
+bool ValidateProgramUniform2ivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform2uiBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1);
+bool ValidateProgramUniform2uivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniform3fBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2);
+bool ValidateProgramUniform3fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniform3iBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2);
+bool ValidateProgramUniform3ivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform3uiBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2);
+bool ValidateProgramUniform3uivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniform4fBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2,
+ GLfloat v3);
+bool ValidateProgramUniform4fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniform4iBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2,
+ GLint v3);
+bool ValidateProgramUniform4ivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform4uiBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3);
+bool ValidateProgramUniform4uivBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniformMatrix2fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix2x3fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix2x4fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix3fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix3x2fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix3x4fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix4fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix4x2fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix4x3fvBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUseProgramStagesBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ GLbitfield stages,
+ ShaderProgramID programPacked);
+bool ValidateValidateProgramPipelineBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked);
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES31_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationES31_autogen.h b/gfx/angle/checkout/src/libANGLE/validationES31_autogen.h
new file mode 100644
index 0000000000..3e2adb50d0
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES31_autogen.h
@@ -0,0 +1,415 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationES31_autogen.h:
+// Validation functions for the OpenGL ES 3.1 entry points.
+
+#ifndef LIBANGLE_VALIDATION_ES31_AUTOGEN_H_
+#define LIBANGLE_VALIDATION_ES31_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "common/entry_points_enum_autogen.h"
+
+namespace gl
+{
+class Context;
+
+bool ValidateActiveShaderProgram(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ ShaderProgramID programPacked);
+bool ValidateBindImageTexture(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint unit,
+ TextureID texturePacked,
+ GLint level,
+ GLboolean layered,
+ GLint layer,
+ GLenum access,
+ GLenum format);
+bool ValidateBindProgramPipeline(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked);
+bool ValidateBindVertexBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint bindingindex,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizei stride);
+bool ValidateCreateShaderProgramv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderType typePacked,
+ GLsizei count,
+ const GLchar *const *strings);
+bool ValidateDeleteProgramPipelines(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const ProgramPipelineID *pipelinesPacked);
+bool ValidateDispatchCompute(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint num_groups_x,
+ GLuint num_groups_y,
+ GLuint num_groups_z);
+bool ValidateDispatchComputeIndirect(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLintptr indirect);
+bool ValidateDrawArraysIndirect(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const void *indirect);
+bool ValidateDrawElementsIndirect(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ DrawElementsType typePacked,
+ const void *indirect);
+bool ValidateFramebufferParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ GLint param);
+bool ValidateGenProgramPipelines(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const ProgramPipelineID *pipelinesPacked);
+bool ValidateGetBooleani_v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ const GLboolean *data);
+bool ValidateGetFramebufferParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetMultisamplefv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLuint index,
+ const GLfloat *val);
+bool ValidateGetProgramInterfaceiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetProgramPipelineInfoLog(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *infoLog);
+bool ValidateGetProgramPipelineiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetProgramResourceIndex(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ const GLchar *name);
+bool ValidateGetProgramResourceLocation(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ const GLchar *name);
+bool ValidateGetProgramResourceName(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *name);
+bool ValidateGetProgramResourceiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLuint index,
+ GLsizei propCount,
+ const GLenum *props,
+ GLsizei count,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetTexLevelParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ const GLfloat *params);
+bool ValidateGetTexLevelParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ const GLint *params);
+bool ValidateIsProgramPipeline(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked);
+bool ValidateMemoryBarrier(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLbitfield barriers);
+bool ValidateMemoryBarrierByRegion(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLbitfield barriers);
+bool ValidateProgramUniform1f(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0);
+bool ValidateProgramUniform1fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniform1i(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0);
+bool ValidateProgramUniform1iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform1ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0);
+bool ValidateProgramUniform1uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniform2f(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1);
+bool ValidateProgramUniform2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniform2i(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1);
+bool ValidateProgramUniform2iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform2ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1);
+bool ValidateProgramUniform2uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniform3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2);
+bool ValidateProgramUniform3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniform3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2);
+bool ValidateProgramUniform3iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2);
+bool ValidateProgramUniform3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniform4f(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2,
+ GLfloat v3);
+bool ValidateProgramUniform4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniform4i(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2,
+ GLint v3);
+bool ValidateProgramUniform4iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3);
+bool ValidateProgramUniform4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniformMatrix2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix2x3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix2x4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix3x2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix3x4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix4x2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix4x3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateSampleMaski(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint maskNumber,
+ GLbitfield mask);
+bool ValidateTexStorage2DMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations);
+bool ValidateUseProgramStages(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ GLbitfield stages,
+ ShaderProgramID programPacked);
+bool ValidateValidateProgramPipeline(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked);
+bool ValidateVertexAttribBinding(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint attribindex,
+ GLuint bindingindex);
+bool ValidateVertexAttribFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint attribindex,
+ GLint size,
+ VertexAttribType typePacked,
+ GLboolean normalized,
+ GLuint relativeoffset);
+bool ValidateVertexAttribIFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint attribindex,
+ GLint size,
+ VertexAttribType typePacked,
+ GLuint relativeoffset);
+bool ValidateVertexBindingDivisor(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint bindingindex,
+ GLuint divisor);
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES31_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationES32.cpp b/gfx/angle/checkout/src/libANGLE/validationES32.cpp
new file mode 100644
index 0000000000..b7d412393b
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES32.cpp
@@ -0,0 +1,628 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationES32.cpp: Validation functions for OpenGL ES 3.2 entry point parameters
+
+#include "libANGLE/validationES32_autogen.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES2_autogen.h"
+#include "libANGLE/validationES31.h"
+#include "libANGLE/validationES31_autogen.h"
+#include "libANGLE/validationES3_autogen.h"
+
+#include "common/utilities.h"
+
+using namespace angle;
+
+namespace gl
+{
+using namespace err;
+
+bool ValidateBlendBarrier(const Context *context, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidateBlendEquationSeparatei(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum modeRGB,
+ GLenum modeAlpha)
+{
+ if (buf >= static_cast<GLuint>(context->getCaps().maxDrawBuffers))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxDrawBuffers);
+ return false;
+ }
+
+ if (!ValidateBlendEquationSeparate(context, entryPoint, modeRGB, modeAlpha))
+ {
+ // error already generated
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBlendEquationi(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum mode)
+{
+ if (buf >= static_cast<GLuint>(context->getCaps().maxDrawBuffers))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxDrawBuffers);
+ return false;
+ }
+
+ if (!ValidateBlendEquation(context, entryPoint, mode))
+ {
+ // error already generated
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBlendFuncSeparatei(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha)
+{
+ if (buf >= static_cast<GLuint>(context->getCaps().maxDrawBuffers))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxDrawBuffers);
+ return false;
+ }
+
+ if (!ValidateBlendFuncSeparate(context, entryPoint, srcRGB, dstRGB, srcAlpha, dstAlpha))
+ {
+ // error already generated
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateBlendFunci(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum src,
+ GLenum dst)
+{
+ if (buf >= static_cast<GLuint>(context->getCaps().maxDrawBuffers))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxDrawBuffers);
+ return false;
+ }
+
+ if (!ValidateBlendFunc(context, entryPoint, src, dst))
+ {
+ // error already generated
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateColorMaski(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLboolean r,
+ GLboolean g,
+ GLboolean b,
+ GLboolean a)
+{
+ if (index >= static_cast<GLuint>(context->getCaps().maxDrawBuffers))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopyImageSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint srcName,
+ GLenum srcTarget,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLuint dstName,
+ GLenum dstTarget,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth)
+{
+ if (context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES32Required);
+ return false;
+ }
+
+ return ValidateCopyImageSubDataBase(context, entryPoint, srcName, srcTarget, srcLevel, srcX,
+ srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ,
+ srcWidth, srcHeight, srcDepth);
+}
+
+bool ValidateDebugMessageCallback(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLDEBUGPROC callback,
+ const void *userParam)
+{
+ return true;
+}
+
+bool ValidateDebugMessageControl(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled)
+{
+ return true;
+}
+
+bool ValidateDebugMessageInsert(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *buf)
+{
+ return true;
+}
+
+bool ValidateDisablei(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index)
+{
+ switch (target)
+ {
+ case GL_BLEND:
+ if (index >= static_cast<GLuint>(context->getCaps().maxDrawBuffers))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
+ return false;
+ }
+ break;
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateDrawElementsBaseVertex(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLint basevertex)
+{
+ return ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, 1);
+}
+
+bool ValidateDrawElementsInstancedBaseVertex(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex)
+{
+ return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
+ instancecount);
+}
+
+bool ValidateDrawRangeElementsBaseVertex(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLint basevertex)
+{
+ if (end < start)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidElementRange);
+ return false;
+ }
+
+ if (!ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, 0))
+ {
+ return false;
+ }
+
+ // Skip range checks for no-op calls.
+ if (count <= 0)
+ {
+ return true;
+ }
+
+ return true;
+}
+
+bool ValidateEnablei(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index)
+{
+ switch (target)
+ {
+ case GL_BLEND:
+ if (index >= static_cast<GLuint>(context->getCaps().maxDrawBuffers))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
+ return false;
+ }
+ break;
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateFramebufferTexture(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureID texture,
+ GLint level)
+{
+ return true;
+}
+
+bool ValidateGetDebugMessageLog(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint count,
+ GLsizei bufSize,
+ const GLenum *sources,
+ const GLenum *types,
+ const GLuint *ids,
+ const GLenum *severities,
+ const GLsizei *lengths,
+ const GLchar *messageLog)
+{
+ return true;
+}
+
+bool ValidateGetGraphicsResetStatus(const Context *context, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidateGetObjectLabel(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *label)
+{
+ return true;
+}
+
+bool ValidateGetObjectPtrLabel(const Context *context,
+ angle::EntryPoint entryPoint,
+ const void *ptr,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *label)
+{
+ return true;
+}
+
+bool ValidateGetPointerv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ void *const *params)
+{
+ Version clientVersion = context->getClientVersion();
+
+ if ((clientVersion == ES_1_0) || (clientVersion == ES_1_1))
+ {
+ switch (pname)
+ {
+ case GL_VERTEX_ARRAY_POINTER:
+ case GL_NORMAL_ARRAY_POINTER:
+ case GL_COLOR_ARRAY_POINTER:
+ case GL_TEXTURE_COORD_ARRAY_POINTER:
+ case GL_POINT_SIZE_ARRAY_POINTER_OES:
+ return true;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPointerQuery);
+ return false;
+ }
+ }
+ else if (clientVersion == ES_3_2)
+ {
+ switch (pname)
+ {
+ case GL_DEBUG_CALLBACK_FUNCTION:
+ case GL_DEBUG_CALLBACK_USER_PARAM:
+ return true;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPointerQuery);
+ return false;
+ }
+ }
+ else
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES1or32Required);
+ return false;
+ }
+}
+
+bool ValidateGetSamplerParameterIiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateGetSamplerParameterIuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ const GLuint *params)
+{
+ return true;
+}
+
+bool ValidateGetTexParameterIiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateGetTexParameterIuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params)
+{
+ return true;
+}
+
+bool ValidateGetnUniformfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLfloat *params)
+{
+ return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr);
+}
+
+bool ValidateGetnUniformiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLint *params)
+{
+ return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr);
+}
+
+bool ValidateGetnUniformuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLuint *params)
+{
+ return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr);
+}
+
+bool ValidateIsEnabledi(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index)
+{
+ switch (target)
+ {
+ case GL_BLEND:
+ if (index >= static_cast<GLuint>(context->getCaps().maxDrawBuffers))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
+ return false;
+ }
+ break;
+ default:
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateMinSampleShading(const Context *context, angle::EntryPoint entryPoint, GLfloat value)
+{
+ return true;
+}
+
+bool ValidateObjectLabel(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum identifier,
+ GLuint name,
+ GLsizei length,
+ const GLchar *label)
+{
+ return true;
+}
+
+bool ValidateObjectPtrLabel(const Context *context,
+ angle::EntryPoint entryPoint,
+ const void *ptr,
+ GLsizei length,
+ const GLchar *label)
+{
+ return true;
+}
+
+bool ValidatePatchParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLint value)
+{
+ return true;
+}
+
+bool ValidatePopDebugGroup(const Context *context, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidatePrimitiveBoundingBox(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat minX,
+ GLfloat minY,
+ GLfloat minZ,
+ GLfloat minW,
+ GLfloat maxX,
+ GLfloat maxY,
+ GLfloat maxZ,
+ GLfloat maxW)
+{
+ return true;
+}
+
+bool ValidatePushDebugGroup(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum source,
+ GLuint id,
+ GLsizei length,
+ const GLchar *message)
+{
+ return true;
+}
+
+bool ValidateReadnPixels(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *data)
+{
+ return true;
+}
+
+bool ValidateSamplerParameterIiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ const GLint *param)
+{
+ return true;
+}
+
+bool ValidateSamplerParameterIuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID sampler,
+ GLenum pname,
+ const GLuint *param)
+{
+ return true;
+}
+
+bool ValidateTexBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum internalformat,
+ BufferID buffer)
+{
+ if (context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES32Required);
+ return false;
+ }
+
+ return ValidateTexBufferBase(context, entryPoint, target, internalformat, buffer);
+}
+
+bool ValidateTexBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLenum internalformat,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ if (context->getClientVersion() < ES_3_2)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES32Required);
+ return false;
+ }
+
+ return ValidateTexBufferRangeBase(context, entryPoint, target, internalformat, buffer, offset,
+ size);
+}
+
+bool ValidateTexParameterIiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateTexParameterIuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params)
+{
+ return true;
+}
+
+bool ValidateTexStorage3DMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedsamplelocations)
+{
+ return true;
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/validationES32.h b/gfx/angle/checkout/src/libANGLE/validationES32.h
new file mode 100644
index 0000000000..674bc81d06
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES32.h
@@ -0,0 +1,20 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationES32.h:
+// Inlined validation functions for OpenGL ES 3.2 entry points.
+
+#ifndef LIBANGLE_VALIDATION_ES32_H_
+#define LIBANGLE_VALIDATION_ES32_H_
+
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/validationES32_autogen.h"
+
+namespace gl
+{
+// Nothing here yet.
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES32_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationES32_autogen.h b/gfx/angle/checkout/src/libANGLE/validationES32_autogen.h
new file mode 100644
index 0000000000..171f94d55c
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES32_autogen.h
@@ -0,0 +1,281 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationES32_autogen.h:
+// Validation functions for the OpenGL ES 3.2 entry points.
+
+#ifndef LIBANGLE_VALIDATION_ES32_AUTOGEN_H_
+#define LIBANGLE_VALIDATION_ES32_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "common/entry_points_enum_autogen.h"
+
+namespace gl
+{
+class Context;
+
+bool ValidateBlendBarrier(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateBlendEquationSeparatei(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum modeRGB,
+ GLenum modeAlpha);
+bool ValidateBlendEquationi(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum mode);
+bool ValidateBlendFuncSeparatei(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha);
+bool ValidateBlendFunci(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum src,
+ GLenum dst);
+bool ValidateColorMaski(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLboolean r,
+ GLboolean g,
+ GLboolean b,
+ GLboolean a);
+bool ValidateCopyImageSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint srcName,
+ GLenum srcTarget,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLuint dstName,
+ GLenum dstTarget,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth);
+bool ValidateDebugMessageCallback(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLDEBUGPROC callback,
+ const void *userParam);
+bool ValidateDebugMessageControl(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled);
+bool ValidateDebugMessageInsert(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *buf);
+bool ValidateDisablei(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index);
+bool ValidateDrawElementsBaseVertex(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex);
+bool ValidateDrawElementsInstancedBaseVertex(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex);
+bool ValidateDrawRangeElementsBaseVertex(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex);
+bool ValidateEnablei(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index);
+bool ValidateFramebufferTexture(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureID texturePacked,
+ GLint level);
+bool ValidateGetDebugMessageLog(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint count,
+ GLsizei bufSize,
+ const GLenum *sources,
+ const GLenum *types,
+ const GLuint *ids,
+ const GLenum *severities,
+ const GLsizei *lengths,
+ const GLchar *messageLog);
+bool ValidateGetGraphicsResetStatus(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateGetObjectLabel(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *label);
+bool ValidateGetObjectPtrLabel(const Context *context,
+ angle::EntryPoint entryPoint,
+ const void *ptr,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *label);
+bool ValidateGetPointerv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ void *const *params);
+bool ValidateGetSamplerParameterIiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetSamplerParameterIuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLuint *params);
+bool ValidateGetTexParameterIiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetTexParameterIuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params);
+bool ValidateGetnUniformfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ const GLfloat *params);
+bool ValidateGetnUniformiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ const GLint *params);
+bool ValidateGetnUniformuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ const GLuint *params);
+bool ValidateIsEnabledi(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index);
+bool ValidateMinSampleShading(const Context *context, angle::EntryPoint entryPoint, GLfloat value);
+bool ValidateObjectLabel(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum identifier,
+ GLuint name,
+ GLsizei length,
+ const GLchar *label);
+bool ValidateObjectPtrLabel(const Context *context,
+ angle::EntryPoint entryPoint,
+ const void *ptr,
+ GLsizei length,
+ const GLchar *label);
+bool ValidatePatchParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLint value);
+bool ValidatePopDebugGroup(const Context *context, angle::EntryPoint entryPoint);
+bool ValidatePrimitiveBoundingBox(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat minX,
+ GLfloat minY,
+ GLfloat minZ,
+ GLfloat minW,
+ GLfloat maxX,
+ GLfloat maxY,
+ GLfloat maxZ,
+ GLfloat maxW);
+bool ValidatePushDebugGroup(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum source,
+ GLuint id,
+ GLsizei length,
+ const GLchar *message);
+bool ValidateReadnPixels(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *data);
+bool ValidateSamplerParameterIiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *param);
+bool ValidateSamplerParameterIuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLuint *param);
+bool ValidateTexBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum internalformat,
+ BufferID bufferPacked);
+bool ValidateTexBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum internalformat,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size);
+bool ValidateTexParameterIiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateTexParameterIuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params);
+bool ValidateTexStorage3DMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedsamplelocations);
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES32_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationES3_autogen.h b/gfx/angle/checkout/src/libANGLE/validationES3_autogen.h
new file mode 100644
index 0000000000..10465c63f5
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationES3_autogen.h
@@ -0,0 +1,578 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationES3_autogen.h:
+// Validation functions for the OpenGL ES 3.0 entry points.
+
+#ifndef LIBANGLE_VALIDATION_ES3_AUTOGEN_H_
+#define LIBANGLE_VALIDATION_ES3_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "common/entry_points_enum_autogen.h"
+
+namespace gl
+{
+class Context;
+
+bool ValidateBeginQuery(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType targetPacked,
+ QueryID idPacked);
+bool ValidateBeginTransformFeedback(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode primitiveModePacked);
+bool ValidateBindBufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLuint index,
+ BufferID bufferPacked);
+bool ValidateBindBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLuint index,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size);
+bool ValidateBindSampler(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint unit,
+ SamplerID samplerPacked);
+bool ValidateBindTransformFeedback(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ TransformFeedbackID idPacked);
+bool ValidateBindVertexArray(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID arrayPacked);
+bool ValidateBlitFramebuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+bool ValidateClearBufferfi(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil);
+bool ValidateClearBufferfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *value);
+bool ValidateClearBufferiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *value);
+bool ValidateClearBufferuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *value);
+bool ValidateClientWaitSync(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsync sync,
+ GLbitfield flags,
+ GLuint64 timeout);
+bool ValidateCompressedTexImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const void *data);
+bool ValidateCompressedTexSubImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+bool ValidateCopyBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding readTargetPacked,
+ BufferBinding writeTargetPacked,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size);
+bool ValidateCopyTexSubImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+bool ValidateDeleteQueries(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const QueryID *idsPacked);
+bool ValidateDeleteSamplers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei count,
+ const SamplerID *samplersPacked);
+bool ValidateDeleteSync(const Context *context, angle::EntryPoint entryPoint, GLsync sync);
+bool ValidateDeleteTransformFeedbacks(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const TransformFeedbackID *idsPacked);
+bool ValidateDeleteVertexArrays(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const VertexArrayID *arraysPacked);
+bool ValidateDrawArraysInstanced(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLint first,
+ GLsizei count,
+ GLsizei instancecount);
+bool ValidateDrawBuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLenum *bufs);
+bool ValidateDrawElementsInstanced(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount);
+bool ValidateDrawRangeElements(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices);
+bool ValidateEndQuery(const Context *context, angle::EntryPoint entryPoint, QueryType targetPacked);
+bool ValidateEndTransformFeedback(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateFenceSync(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum condition,
+ GLbitfield flags);
+bool ValidateFlushMappedBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLintptr offset,
+ GLsizeiptr length);
+bool ValidateFramebufferTextureLayer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureID texturePacked,
+ GLint level,
+ GLint layer);
+bool ValidateGenQueries(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const QueryID *idsPacked);
+bool ValidateGenSamplers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei count,
+ const SamplerID *samplersPacked);
+bool ValidateGenTransformFeedbacks(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const TransformFeedbackID *idsPacked);
+bool ValidateGenVertexArrays(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const VertexArrayID *arraysPacked);
+bool ValidateGetActiveUniformBlockName(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformBlockIndex uniformBlockIndexPacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *uniformBlockName);
+bool ValidateGetActiveUniformBlockiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformBlockIndex uniformBlockIndexPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetActiveUniformsiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLsizei uniformCount,
+ const GLuint *uniformIndices,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetBufferParameteri64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLenum pname,
+ const GLint64 *params);
+bool ValidateGetBufferPointerv(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLenum pname,
+ void *const *params);
+bool ValidateGetFragDataLocation(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ const GLchar *name);
+bool ValidateGetInteger64i_v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ const GLint64 *data);
+bool ValidateGetInteger64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLint64 *data);
+bool ValidateGetIntegeri_v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ const GLint *data);
+bool ValidateGetInternalformativ(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei count,
+ const GLint *params);
+bool ValidateGetProgramBinary(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLenum *binaryFormat,
+ const void *binary);
+bool ValidateGetQueryObjectuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID idPacked,
+ GLenum pname,
+ const GLuint *params);
+bool ValidateGetQueryiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType targetPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetSamplerParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLfloat *params);
+bool ValidateGetSamplerParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetStringi(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum name,
+ GLuint index);
+bool ValidateGetSynciv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsync sync,
+ GLenum pname,
+ GLsizei count,
+ const GLsizei *length,
+ const GLint *values);
+bool ValidateGetTransformFeedbackVarying(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLsizei *size,
+ const GLenum *type,
+ const GLchar *name);
+bool ValidateGetUniformBlockIndex(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ const GLchar *uniformBlockName);
+bool ValidateGetUniformIndices(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLsizei uniformCount,
+ const GLchar *const *uniformNames,
+ const GLuint *uniformIndices);
+bool ValidateGetUniformuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ const GLuint *params);
+bool ValidateGetVertexAttribIiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetVertexAttribIuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ const GLuint *params);
+bool ValidateInvalidateFramebuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments);
+bool ValidateInvalidateSubFramebuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+bool ValidateIsQuery(const Context *context, angle::EntryPoint entryPoint, QueryID idPacked);
+bool ValidateIsSampler(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked);
+bool ValidateIsSync(const Context *context, angle::EntryPoint entryPoint, GLsync sync);
+bool ValidateIsTransformFeedback(const Context *context,
+ angle::EntryPoint entryPoint,
+ TransformFeedbackID idPacked);
+bool ValidateIsVertexArray(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID arrayPacked);
+bool ValidateMapBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access);
+bool ValidatePauseTransformFeedback(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateProgramBinary(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum binaryFormat,
+ const void *binary,
+ GLsizei length);
+bool ValidateProgramParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum pname,
+ GLint value);
+bool ValidateReadBuffer(const Context *context, angle::EntryPoint entryPoint, GLenum src);
+bool ValidateRenderbufferStorageMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+bool ValidateResumeTransformFeedback(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateSamplerParameterf(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLfloat param);
+bool ValidateSamplerParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLfloat *param);
+bool ValidateSamplerParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLint param);
+bool ValidateSamplerParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *param);
+bool ValidateTexImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateTexStorage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+bool ValidateTexStorage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+bool ValidateTexSubImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateTransformFeedbackVaryings(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLsizei count,
+ const GLchar *const *varyings,
+ GLenum bufferMode);
+bool ValidateUniform1ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLuint v0);
+bool ValidateUniform1uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateUniform2ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1);
+bool ValidateUniform2uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateUniform3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2);
+bool ValidateUniform3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateUniform4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3);
+bool ValidateUniform4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateUniformBlockBinding(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformBlockIndex uniformBlockIndexPacked,
+ GLuint uniformBlockBinding);
+bool ValidateUniformMatrix2x3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUniformMatrix2x4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUniformMatrix3x2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUniformMatrix3x4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUniformMatrix4x2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUniformMatrix4x3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUnmapBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked);
+bool ValidateVertexAttribDivisor(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLuint divisor);
+bool ValidateVertexAttribI4i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint w);
+bool ValidateVertexAttribI4iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLint *v);
+bool ValidateVertexAttribI4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLuint x,
+ GLuint y,
+ GLuint z,
+ GLuint w);
+bool ValidateVertexAttribI4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLuint *v);
+bool ValidateVertexAttribIPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint size,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer);
+bool ValidateWaitSync(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsync sync,
+ GLbitfield flags,
+ GLuint64 timeout);
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ES3_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationESEXT.cpp b/gfx/angle/checkout/src/libANGLE/validationESEXT.cpp
new file mode 100644
index 0000000000..c708206412
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationESEXT.cpp
@@ -0,0 +1,3599 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationESEXT.cpp: Validation functions for OpenGL ES extension entry points.
+
+#include "libANGLE/validationESEXT_autogen.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/MemoryObject.h"
+#include "libANGLE/PixelLocalStorage.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES2.h"
+#include "libANGLE/validationES3.h"
+#include "libANGLE/validationES31.h"
+#include "libANGLE/validationES32.h"
+
+namespace gl
+{
+using namespace err;
+
+namespace
+{
+template <typename ObjectT>
+bool ValidateGetImageFormatAndType(const Context *context,
+ angle::EntryPoint entryPoint,
+ ObjectT *obj,
+ GLenum format,
+ GLenum type)
+{
+ GLenum implFormat = obj->getImplementationColorReadFormat(context);
+ if (!ValidES3Format(format) && (format != implFormat || format == GL_NONE))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
+ return false;
+ }
+
+ GLenum implType = obj->getImplementationColorReadType(context);
+ if (!ValidES3Type(type) && (type != implType || type == GL_NONE))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
+ return false;
+ }
+
+ // Format/type combinations are not yet validated.
+
+ return true;
+}
+
+bool IsValidImageLayout(ImageLayout layout)
+{
+ switch (layout)
+ {
+ case ImageLayout::Undefined:
+ case ImageLayout::General:
+ case ImageLayout::ColorAttachment:
+ case ImageLayout::DepthStencilAttachment:
+ case ImageLayout::DepthStencilReadOnlyAttachment:
+ case ImageLayout::ShaderReadOnly:
+ case ImageLayout::TransferSrc:
+ case ImageLayout::TransferDst:
+ case ImageLayout::DepthReadOnlyStencilAttachment:
+ case ImageLayout::DepthAttachmentStencilReadOnly:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool IsValidMemoryObjectParamater(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname)
+{
+ switch (pname)
+ {
+ case GL_DEDICATED_MEMORY_OBJECT_EXT:
+ return true;
+
+ case GL_PROTECTED_MEMORY_OBJECT_EXT:
+ if (!context->getExtensions().protectedTexturesEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool ValidateObjectIdentifierAndName(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum identifier,
+ GLuint name)
+{
+ bool isGLES11 = context->getClientVersion() == Version(1, 1);
+ bool isGLES3 = context->getClientMajorVersion() >= 3;
+ bool isGLES31 = context->getClientVersion() >= Version(3, 1);
+ switch (identifier)
+ {
+ case GL_BUFFER_OBJECT_EXT:
+ if (context->getBuffer({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidBufferName);
+ return false;
+ }
+ return true;
+
+ case GL_SHADER_OBJECT_EXT:
+ if (isGLES11)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
+ return false;
+ }
+ if (context->getShader({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidShaderName);
+ return false;
+ }
+ return true;
+
+ case GL_PROGRAM_OBJECT_EXT:
+ if (isGLES11)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
+ return false;
+ }
+ if (context->getProgramNoResolveLink({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidProgramName);
+ return false;
+ }
+ return true;
+
+ case GL_VERTEX_ARRAY_OBJECT_EXT:
+ if (!isGLES3 && !context->getExtensions().vertexArrayObjectOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
+ return false;
+ }
+ if (context->getVertexArray({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidVertexArrayName);
+ return false;
+ }
+ return true;
+
+ case GL_QUERY_OBJECT_EXT:
+ if (!isGLES3 && !context->getExtensions().occlusionQueryBooleanEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
+ return false;
+ }
+ if (context->getQuery({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidQueryName);
+ return false;
+ }
+ return true;
+
+ case GL_TRANSFORM_FEEDBACK:
+ if (!isGLES3)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
+ return false;
+ }
+ if (context->getTransformFeedback({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidTransformFeedbackName);
+ return false;
+ }
+ return true;
+
+ case GL_SAMPLER:
+ if (!isGLES3)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
+ return false;
+ }
+ if (context->getSampler({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidSamplerName);
+ return false;
+ }
+ return true;
+
+ case GL_TEXTURE:
+ if (context->getTexture({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureName);
+ return false;
+ }
+ return true;
+
+ case GL_RENDERBUFFER:
+ if (!context->isRenderbuffer({name}))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidRenderbufferName);
+ return false;
+ }
+ return true;
+
+ case GL_FRAMEBUFFER:
+ if (context->getFramebuffer({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFramebufferName);
+ return false;
+ }
+ return true;
+
+ case GL_PROGRAM_PIPELINE_OBJECT_EXT:
+ if (!isGLES31 && !context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
+ return false;
+ }
+ if (context->getProgramPipeline({name}) == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidProgramPipelineName);
+ return false;
+ }
+ return true;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidIndentifier);
+ return false;
+ }
+}
+} // namespace
+
+bool ValidateGetTexImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level)
+{
+ if (!context->getExtensions().getImageANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kGetImageExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidTexture2DDestinationTarget(context, target) &&
+ !ValidTexture3DDestinationTarget(context, target))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ if (level < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLevel);
+ return false;
+ }
+
+ TextureType textureType = TextureTargetToType(target);
+ if (!ValidMipLevel(context, textureType, level))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetTexImageANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ if (!ValidateGetTexImage(context, entryPoint, target, level))
+ {
+ return false;
+ }
+
+ Texture *texture = context->getTextureByTarget(target);
+
+ if (!ValidateGetImageFormatAndType(context, entryPoint, texture, format, type))
+ {
+ return false;
+ }
+
+ GLsizei width = static_cast<GLsizei>(texture->getWidth(target, level));
+ GLsizei height = static_cast<GLsizei>(texture->getHeight(target, level));
+ if (!ValidatePixelPack(context, entryPoint, format, type, 0, 0, width, height, -1, nullptr,
+ pixels))
+ {
+ return false;
+ }
+
+ if (texture->getFormat(target, level).info->compressed)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kGetImageCompressed);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetCompressedTexImageANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ const void *pixels)
+{
+ if (!ValidateGetTexImage(context, entryPoint, target, level))
+ {
+ return false;
+ }
+
+ Texture *texture = context->getTextureByTarget(target);
+ if (!texture->getFormat(target, level).info->compressed)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kGetImageNotCompressed);
+ return false;
+ }
+
+ if (texture->isCompressedFormatEmulated(context, target, level))
+ {
+ // TODO (anglebug.com/7464): We can't currently read back from an emulated format
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidEmulatedFormat);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetRenderbufferImageANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ if (!context->getExtensions().getImageANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kGetImageExtensionNotEnabled);
+ return false;
+ }
+
+ if (target != GL_RENDERBUFFER)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget);
+ return false;
+ }
+
+ Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
+
+ if (!ValidateGetImageFormatAndType(context, entryPoint, renderbuffer, format, type))
+ {
+ return false;
+ }
+
+ GLsizei width = renderbuffer->getWidth();
+ GLsizei height = renderbuffer->getHeight();
+ if (!ValidatePixelPack(context, entryPoint, format, type, 0, 0, width, height, -1, nullptr,
+ pixels))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDrawElementsBaseVertexEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLint basevertex)
+{
+ if (!context->getExtensions().drawElementsBaseVertexAny())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, 1);
+}
+
+bool ValidateDrawElementsInstancedBaseVertexEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex)
+{
+ if (!context->getExtensions().drawElementsBaseVertexAny())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
+ instancecount);
+}
+
+bool ValidateDrawRangeElementsBaseVertexEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLint basevertex)
+{
+ if (!context->getExtensions().drawElementsBaseVertexAny())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (end < start)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidElementRange);
+ return false;
+ }
+
+ if (!ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, 0))
+ {
+ return false;
+ }
+
+ // Skip range checks for no-op calls.
+ if (count <= 0)
+ {
+ return true;
+ }
+
+ // Note that resolving the index range is a bit slow. We should probably optimize this.
+ IndexRange indexRange;
+ ANGLE_VALIDATION_TRY(context->getState().getVertexArray()->getIndexRange(context, type, count,
+ indices, &indexRange));
+
+ if (indexRange.end > end || indexRange.start < start)
+ {
+ // GL spec says that behavior in this case is undefined - generating an error is fine.
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExceedsElementRange);
+ return false;
+ }
+ return true;
+}
+
+bool ValidateMultiDrawElementsBaseVertexEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ const GLsizei *count,
+ DrawElementsType type,
+ const void *const *indices,
+ GLsizei drawcount,
+ const GLint *basevertex)
+{
+ return true;
+}
+
+bool ValidateMultiDrawArraysIndirectEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride)
+{
+ if (!ValidateMultiDrawIndirectBase(context, entryPoint, drawcount, stride))
+ {
+ return false;
+ }
+
+ if (!ValidateDrawArraysIndirect(context, entryPoint, modePacked, indirect))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateMultiDrawElementsIndirectEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ DrawElementsType typePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride)
+{
+ if (!ValidateMultiDrawIndirectBase(context, entryPoint, drawcount, stride))
+ {
+ return false;
+ }
+
+ const State &state = context->getState();
+ TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
+ if (!ValidateDrawElementsIndirect(context, entryPoint, modePacked, typePacked, indirect))
+ {
+ return false;
+ }
+
+ if (curTransformFeedback && curTransformFeedback->isActive() &&
+ !curTransformFeedback->isPaused())
+ {
+ // EXT_geometry_shader allows transform feedback to work with all draw commands.
+ // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
+ if (context->getExtensions().geometryShaderAny() || context->getClientVersion() >= ES_3_2)
+ {
+ if (!ValidateTransformFeedbackPrimitiveMode(
+ context, entryPoint, curTransformFeedback->getPrimitiveMode(), modePacked))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kInvalidDrawModeTransformFeedback);
+ return false;
+ }
+ }
+ else
+ {
+ // An INVALID_OPERATION error is generated if transform feedback is active and not
+ // paused.
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kUnsupportedDrawModeForTransformFeedback);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateDrawArraysInstancedBaseInstanceEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount,
+ GLuint baseInstance)
+{
+ if (!context->getExtensions().baseInstanceEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, instanceCount);
+}
+
+bool ValidateDrawElementsInstancedBaseInstanceEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ void const *indices,
+ GLsizei instancecount,
+ GLuint baseinstance)
+{
+ if (!context->getExtensions().baseInstanceEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
+ instancecount);
+}
+
+bool ValidateDrawElementsInstancedBaseVertexBaseInstanceEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex,
+ GLuint baseinstance)
+{
+ if (!context->getExtensions().baseInstanceEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, typePacked, indices,
+ instancecount);
+}
+
+bool ValidateDrawElementsBaseVertexOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLint basevertex)
+{
+ if (!context->getExtensions().drawElementsBaseVertexAny())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, 1);
+}
+
+bool ValidateDrawElementsInstancedBaseVertexOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex)
+{
+ if (!context->getExtensions().drawElementsBaseVertexAny())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
+ instancecount);
+}
+
+bool ValidateDrawRangeElementsBaseVertexOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLint basevertex)
+{
+ if (!context->getExtensions().drawElementsBaseVertexAny())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (end < start)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidElementRange);
+ return false;
+ }
+
+ if (!ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, 0))
+ {
+ return false;
+ }
+
+ // Skip range checks for no-op calls.
+ if (count <= 0)
+ {
+ return true;
+ }
+
+ // Note that resolving the index range is a bit slow. We should probably optimize this.
+ IndexRange indexRange;
+ ANGLE_VALIDATION_TRY(context->getState().getVertexArray()->getIndexRange(context, type, count,
+ indices, &indexRange));
+
+ if (indexRange.end > end || indexRange.start < start)
+ {
+ // GL spec says that behavior in this case is undefined - generating an error is fine.
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExceedsElementRange);
+ return false;
+ }
+ return true;
+}
+
+// GL_KHR_blend_equation_advanced
+bool ValidateBlendBarrierKHR(const Context *context, angle::EntryPoint entryPoint)
+{
+ const Extensions &extensions = context->getExtensions();
+
+ if (!extensions.blendEquationAdvancedKHR)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kAdvancedBlendExtensionNotEnabled);
+ }
+
+ return true;
+}
+
+bool ValidateBlendEquationSeparateiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum modeRGB,
+ GLenum modeAlpha)
+{
+ if (!context->getExtensions().drawBuffersIndexedEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateBlendEquationSeparatei(context, entryPoint, buf, modeRGB, modeAlpha);
+}
+
+bool ValidateBlendEquationiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum mode)
+{
+ if (!context->getExtensions().drawBuffersIndexedEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateBlendEquationi(context, entryPoint, buf, mode);
+}
+
+bool ValidateBlendFuncSeparateiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha)
+{
+ if (!context->getExtensions().drawBuffersIndexedEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateBlendFuncSeparatei(context, entryPoint, buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+bool ValidateBlendFunciEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum src,
+ GLenum dst)
+{
+ if (!context->getExtensions().drawBuffersIndexedEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateBlendFunci(context, entryPoint, buf, src, dst);
+}
+
+bool ValidateColorMaskiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLboolean r,
+ GLboolean g,
+ GLboolean b,
+ GLboolean a)
+{
+ if (!context->getExtensions().drawBuffersIndexedEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateColorMaski(context, entryPoint, index, r, g, b, a);
+}
+
+bool ValidateDisableiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index)
+{
+ if (!context->getExtensions().drawBuffersIndexedEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateDisablei(context, entryPoint, target, index);
+}
+
+bool ValidateEnableiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index)
+{
+ if (!context->getExtensions().drawBuffersIndexedEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateEnablei(context, entryPoint, target, index);
+}
+
+bool ValidateIsEnablediEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index)
+{
+ if (!context->getExtensions().drawBuffersIndexedEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateIsEnabledi(context, entryPoint, target, index);
+}
+
+bool ValidateBlendEquationSeparateiOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum modeRGB,
+ GLenum modeAlpha)
+{
+ if (!context->getExtensions().drawBuffersIndexedOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateBlendEquationSeparatei(context, entryPoint, buf, modeRGB, modeAlpha);
+}
+
+bool ValidateBlendEquationiOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum mode)
+{
+ if (!context->getExtensions().drawBuffersIndexedOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateBlendEquationi(context, entryPoint, buf, mode);
+}
+
+bool ValidateBlendFuncSeparateiOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha)
+{
+ if (!context->getExtensions().drawBuffersIndexedOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateBlendFuncSeparatei(context, entryPoint, buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+bool ValidateBlendFunciOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum src,
+ GLenum dst)
+{
+ if (!context->getExtensions().drawBuffersIndexedOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateBlendFunci(context, entryPoint, buf, src, dst);
+}
+
+bool ValidateColorMaskiOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLboolean r,
+ GLboolean g,
+ GLboolean b,
+ GLboolean a)
+{
+ if (!context->getExtensions().drawBuffersIndexedOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateColorMaski(context, entryPoint, index, r, g, b, a);
+}
+
+bool ValidateDisableiOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index)
+{
+ if (!context->getExtensions().drawBuffersIndexedOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateDisablei(context, entryPoint, target, index);
+}
+
+bool ValidateEnableiOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index)
+{
+ if (!context->getExtensions().drawBuffersIndexedOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateEnablei(context, entryPoint, target, index);
+}
+
+bool ValidateIsEnablediOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index)
+{
+ if (!context->getExtensions().drawBuffersIndexedOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateIsEnabledi(context, entryPoint, target, index);
+}
+
+bool ValidateGetInteger64vEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLint64 *data)
+{
+ if (!context->getExtensions().disjointTimerQueryEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ GLenum nativeType = GL_NONE;
+ unsigned int numParams = 0;
+ if (!ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateCopyImageSubDataEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint srcName,
+ GLenum srcTarget,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLuint dstName,
+ GLenum dstTarget,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth)
+{
+ if (!context->getExtensions().copyImageEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateCopyImageSubDataBase(context, entryPoint, srcName, srcTarget, srcLevel, srcX,
+ srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ,
+ srcWidth, srcHeight, srcDepth);
+}
+
+bool ValidateCopyImageSubDataOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint srcName,
+ GLenum srcTarget,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLuint dstName,
+ GLenum dstTarget,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth)
+{
+ if (!context->getExtensions().copyImageEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateCopyImageSubDataBase(context, entryPoint, srcName, srcTarget, srcLevel, srcX,
+ srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ,
+ srcWidth, srcHeight, srcDepth);
+}
+
+bool ValidateBufferStorageMemEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizeiptr size,
+ MemoryObjectID memory,
+ GLuint64 offset)
+{
+ if (!context->getExtensions().memoryObjectEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateCreateMemoryObjectsEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const MemoryObjectID *memoryObjects)
+{
+ if (!context->getExtensions().memoryObjectEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateDeleteMemoryObjectsEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const MemoryObjectID *memoryObjects)
+{
+ if (!context->getExtensions().memoryObjectEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateGetMemoryObjectParameterivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ MemoryObjectID memoryObject,
+ GLenum pname,
+ const GLint *params)
+{
+ if (!context->getExtensions().memoryObjectEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ const MemoryObject *memory = context->getMemoryObject(memoryObject);
+ if (memory == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMemoryObject);
+ }
+
+ if (!IsValidMemoryObjectParamater(context, entryPoint, pname))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMemoryObjectParameter);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetUnsignedBytevEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLubyte *data)
+{
+ if (!context->getExtensions().memoryObjectEXT && !context->getExtensions().semaphoreEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGetUnsignedBytei_vEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ const GLubyte *data)
+{
+ if (!context->getExtensions().memoryObjectEXT && !context->getExtensions().semaphoreEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateIsMemoryObjectEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ MemoryObjectID memoryObject)
+{
+ if (!context->getExtensions().memoryObjectEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateMemoryObjectParameterivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ MemoryObjectID memoryObject,
+ GLenum pname,
+ const GLint *params)
+{
+ if (!context->getExtensions().memoryObjectEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ const MemoryObject *memory = context->getMemoryObject(memoryObject);
+ if (memory == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMemoryObject);
+ return false;
+ }
+
+ if (memory->isImmutable())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kImmutableMemoryObject);
+ return false;
+ }
+
+ if (!IsValidMemoryObjectParamater(context, entryPoint, pname))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMemoryObjectParameter);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTexStorageMem2DEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ MemoryObjectID memory,
+ GLuint64 offset)
+{
+ if (!context->getExtensions().memoryObjectEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (context->getClientMajorVersion() < 3)
+ {
+ return ValidateES2TexStorageParametersBase(context, entryPoint, target, levels,
+ internalFormat, width, height);
+ }
+
+ ASSERT(context->getClientMajorVersion() >= 3);
+ return ValidateES3TexStorage2DParameters(context, entryPoint, target, levels, internalFormat,
+ width, height, 1);
+}
+
+bool ValidateTexStorageMem3DEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType target,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ MemoryObjectID memory,
+ GLuint64 offset)
+{
+ if (!context->getExtensions().memoryObjectEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateImportMemoryFdEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ MemoryObjectID memory,
+ GLuint64 size,
+ HandleType handleType,
+ GLint fd)
+{
+ if (!context->getExtensions().memoryObjectFdEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ switch (handleType)
+ {
+ case HandleType::OpaqueFd:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidHandleType);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateImportMemoryZirconHandleANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ MemoryObjectID memory,
+ GLuint64 size,
+ HandleType handleType,
+ GLuint handle)
+{
+ if (!context->getExtensions().memoryObjectFuchsiaANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ switch (handleType)
+ {
+ case HandleType::ZirconVmo:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidHandleType);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateDeleteSemaphoresEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const SemaphoreID *semaphores)
+{
+ if (!context->getExtensions().semaphoreEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateGenSemaphoresEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const SemaphoreID *semaphores)
+{
+ if (!context->getExtensions().semaphoreEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGenOrDelete(context, entryPoint, n);
+}
+
+bool ValidateGetSemaphoreParameterui64vEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SemaphoreID semaphore,
+ GLenum pname,
+ const GLuint64 *params)
+{
+ if (!context->getExtensions().semaphoreEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateIsSemaphoreEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SemaphoreID semaphore)
+{
+ if (!context->getExtensions().semaphoreEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSemaphoreParameterui64vEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SemaphoreID semaphore,
+ GLenum pname,
+ const GLuint64 *params)
+{
+ if (!context->getExtensions().semaphoreEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateSignalSemaphoreEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SemaphoreID semaphore,
+ GLuint numBufferBarriers,
+ const BufferID *buffers,
+ GLuint numTextureBarriers,
+ const TextureID *textures,
+ const GLenum *dstLayouts)
+{
+ if (!context->getExtensions().semaphoreEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ for (GLuint i = 0; i < numBufferBarriers; ++i)
+ {
+ if (!context->getBuffer(buffers[i]))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidBufferName);
+ return false;
+ }
+ }
+
+ for (GLuint i = 0; i < numTextureBarriers; ++i)
+ {
+ if (!context->getTexture(textures[i]))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureName);
+ return false;
+ }
+ if (!IsValidImageLayout(FromGLenum<ImageLayout>(dstLayouts[i])))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidImageLayout);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateWaitSemaphoreEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SemaphoreID semaphore,
+ GLuint numBufferBarriers,
+ const BufferID *buffers,
+ GLuint numTextureBarriers,
+ const TextureID *textures,
+ const GLenum *srcLayouts)
+{
+ if (!context->getExtensions().semaphoreEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ for (GLuint i = 0; i < numBufferBarriers; ++i)
+ {
+ if (!context->getBuffer(buffers[i]))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidBufferName);
+ return false;
+ }
+ }
+
+ for (GLuint i = 0; i < numTextureBarriers; ++i)
+ {
+ if (!context->getTexture(textures[i]))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureName);
+ return false;
+ }
+ if (!IsValidImageLayout(FromGLenum<ImageLayout>(srcLayouts[i])))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidImageLayout);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateImportSemaphoreFdEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SemaphoreID semaphore,
+ HandleType handleType,
+ GLint fd)
+{
+ if (!context->getExtensions().semaphoreFdEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ switch (handleType)
+ {
+ case HandleType::OpaqueFd:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidHandleType);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetSamplerParameterIivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateGetSamplerParameterBase(context, entryPoint, samplerPacked, pname, nullptr);
+}
+
+bool ValidateGetSamplerParameterIuivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLuint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateGetSamplerParameterBase(context, entryPoint, samplerPacked, pname, nullptr);
+}
+
+bool ValidateGetTexParameterIivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateGetTexParameterBase(context, entryPoint, targetPacked, pname, nullptr);
+}
+
+bool ValidateGetTexParameterIuivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateGetTexParameterBase(context, entryPoint, targetPacked, pname, nullptr);
+}
+
+bool ValidateSamplerParameterIivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *param)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateSamplerParameterBase(context, entryPoint, samplerPacked, pname, -1, true, param);
+}
+
+bool ValidateSamplerParameterIuivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLuint *param)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateSamplerParameterBase(context, entryPoint, samplerPacked, pname, -1, true, param);
+}
+
+bool ValidateTexParameterIivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateTexParameterBase(context, entryPoint, targetPacked, pname, -1, true, params);
+}
+
+bool ValidateTexParameterIuivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params)
+{
+ if (context->getClientMajorVersion() < 3)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
+ return false;
+ }
+ return ValidateTexParameterBase(context, entryPoint, targetPacked, pname, -1, true, params);
+}
+
+bool ValidateImportSemaphoreZirconHandleANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SemaphoreID semaphore,
+ HandleType handleType,
+ GLuint handle)
+{
+ if (!context->getExtensions().semaphoreFuchsiaANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ switch (handleType)
+ {
+ case HandleType::ZirconEvent:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidHandleType);
+ return false;
+ }
+
+ return true;
+}
+
+namespace
+{
+enum class PLSExpectedStatus : bool
+{
+ Inactive,
+ Active
+};
+
+bool ValidatePLSCommon(const Context *context,
+ angle::EntryPoint entryPoint,
+ PLSExpectedStatus expectedStatus)
+{
+ // Check that the pixel local storage extension is enabled at all.
+ if (!context->getExtensions().shaderPixelLocalStorageANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSExtensionNotEnabled);
+ return false;
+ }
+
+ // INVALID_FRAMEBUFFER_OPERATION is generated if the default framebuffer object name 0 is
+ // bound to DRAW_FRAMEBUFFER.
+ if (context->getState().getDrawFramebuffer()->id().value == 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION,
+ kPLSDefaultFramebufferBound);
+ return false;
+ }
+
+ if (expectedStatus == PLSExpectedStatus::Inactive)
+ {
+ // INVALID_OPERATION is generated if PIXEL_LOCAL_STORAGE_ACTIVE_ANGLE is TRUE.
+ if (context->getState().getPixelLocalStorageActive())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSActive);
+ return false;
+ }
+ }
+ else
+ {
+ ASSERT(expectedStatus == PLSExpectedStatus::Active);
+
+ // INVALID_OPERATION is generated if PIXEL_LOCAL_STORAGE_ACTIVE_ANGLE is FALSE.
+ if (!context->getState().getPixelLocalStorageActive())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSInactive);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidatePLSCommon(const Context *context, angle::EntryPoint entryPoint, GLint plane)
+{
+ if (!ValidatePLSCommon(context, entryPoint, PLSExpectedStatus::Inactive))
+ {
+ return false;
+ }
+
+ // INVALID_VALUE is generated if <plane> < 0 or <plane> >= MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.
+ if (plane < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kPLSPlaneLessThanZero);
+ return false;
+ }
+ if (plane >= static_cast<GLint>(context->getCaps().maxPixelLocalStoragePlanes))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kPLSPlaneOutOfRange);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidatePLSInternalformat(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum internalformat)
+{
+ // INVALID_ENUM is generated if <internalformat> is not one of the acceptable values in Table
+ // X.2, or NONE.
+ switch (internalformat)
+ {
+ case GL_RGBA8:
+ case GL_RGBA8I:
+ case GL_RGBA8UI:
+ case GL_R32F:
+ case GL_R32UI:
+ return true;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kPLSInvalidInternalformat);
+ return false;
+ }
+}
+
+bool ValidatePLSTextureType(const Context *context,
+ angle::EntryPoint entryPoint,
+ Texture *tex,
+ size_t *textureDepth)
+{
+ // INVALID_ENUM is generated if <backingtexture> is nonzero and not of type GL_TEXTURE_2D,
+ // GL_TEXTURE_CUBE_MAP, GL_TEXTURE_2D_ARRAY, or GL_TEXTURE_3D.
+ switch (tex->getType())
+ {
+ case TextureType::_2D:
+ *textureDepth = 1;
+ return true;
+ case TextureType::CubeMap:
+ *textureDepth = 6;
+ return true;
+ case TextureType::_2DArray:
+ *textureDepth = tex->getDepth(TextureTarget::_2DArray, 0);
+ return true;
+ case TextureType::_3D:
+ *textureDepth = tex->getDepth(TextureTarget::_3D, 0);
+ return true;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kPLSInvalidTextureType);
+ return false;
+ }
+}
+
+bool ValidatePLSLoadOperation(const Context *context, angle::EntryPoint entryPoint, GLenum loadop)
+{
+ // INVALID_ENUM is generated if <loadops>[0..<planes>-1] is not one of the Load Operations
+ // enumerated in Table X.1.
+ switch (loadop)
+ {
+ case GL_ZERO:
+ case GL_CLEAR_ANGLE:
+ case GL_KEEP:
+ case GL_DONT_CARE:
+ case GL_DISABLE_ANGLE:
+ return true;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kPLSInvalidLoadOperation);
+ return false;
+ }
+}
+} // namespace
+
+bool ValidateFramebufferMemorylessPixelLocalStorageANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint plane,
+ GLenum internalformat)
+{
+ if (!ValidatePLSCommon(context, entryPoint, plane))
+ {
+ return false;
+ }
+
+ // INVALID_ENUM is generated if <internalformat> is not one of the acceptable values in Table
+ // X.2, or NONE.
+ if (internalformat != GL_NONE)
+ {
+ if (!ValidatePLSInternalformat(context, entryPoint, internalformat))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferTexturePixelLocalStorageANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint plane,
+ TextureID backingtexture,
+ GLint level,
+ GLint layer)
+{
+ if (!ValidatePLSCommon(context, entryPoint, plane))
+ {
+ return false;
+ }
+
+ if (backingtexture.value != 0)
+ {
+ Texture *tex = context->getTexture(backingtexture);
+
+ // INVALID_OPERATION is generated if <backingtexture> is not the name of an existing
+ // immutable texture object, or zero.
+ if (!tex)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureName);
+ return false;
+ }
+ if (!tex->getImmutableFormat())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsNotImmutable);
+ return false;
+ }
+
+ // INVALID_ENUM is generated if <backingtexture> is nonzero and not of type GL_TEXTURE_2D,
+ // GL_TEXTURE_CUBE_MAP, GL_TEXTURE_2D_ARRAY, or GL_TEXTURE_3D.
+ size_t textureDepth;
+ if (!ValidatePLSTextureType(context, entryPoint, tex, &textureDepth))
+ {
+ return false;
+ }
+
+ // INVALID_VALUE is generated if <backingtexture> is nonzero and <level> < 0.
+ if (level < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLevel);
+ return false;
+ }
+
+ // INVALID_VALUE is generated if <backingtexture> is nonzero and <level> >= the
+ // immutable number of mipmap levels in <backingtexture>.
+ if (static_cast<GLuint>(level) >= tex->getImmutableLevels())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kTextureLevelOutOfRange);
+ return false;
+ }
+
+ // INVALID_VALUE is generated if <backingtexture> is nonzero and <layer> < 0.
+ if (layer < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLayer);
+ return false;
+ }
+
+ // INVALID_VALUE is generated if <backingtexture> is nonzero and <layer> >= the immutable
+ // number of texture layers in <backingtexture>.
+ if ((size_t)layer >= textureDepth)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kTextureLayerOutOfRange);
+ return false;
+ }
+
+ // INVALID_ENUM is generated if <backingtexture> is nonzero and its internalformat is not
+ // one of the acceptable values in Table X.2.
+ ASSERT(tex->getImmutableFormat());
+ GLenum internalformat = tex->getState().getBaseLevelDesc().format.info->internalFormat;
+ if (!ValidatePLSInternalformat(context, entryPoint, internalformat))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateBeginPixelLocalStorageANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei planes,
+ const GLenum loadops[],
+ const void *cleardata)
+{
+ if (!ValidatePLSCommon(context, entryPoint, PLSExpectedStatus::Inactive))
+ {
+ return false;
+ }
+
+ const State &state = context->getState();
+ const Framebuffer *framebuffer = state.getDrawFramebuffer();
+
+ // INVALID_OPERATION is generated if the value of SAMPLE_BUFFERS is 1 (i.e., if rendering to a
+ // multisampled framebuffer).
+ if (framebuffer->getSamples(context) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSMultisamplingEnabled);
+ return false;
+ }
+
+ // INVALID_OPERATION is generated if DITHER is enabled.
+ if (state.isDitherEnabled())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSDitherEnabled);
+ return false;
+ }
+
+ // INVALID_OPERATION is generated if RASTERIZER_DISCARD is enabled.
+ if (state.isRasterizerDiscardEnabled())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSRasterizerDiscardEnabled);
+ return false;
+ }
+
+ // INVALID_OPERATION is generated if SAMPLE_ALPHA_TO_COVERAGE is enabled.
+ if (state.isSampleAlphaToCoverageEnabled())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kPLSSampleAlphaToCoverageEnabled);
+ return false;
+ }
+
+ // INVALID_OPERATION is generated if SAMPLE_COVERAGE is enabled.
+ if (state.isSampleCoverageEnabled())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSSampleCoverageEnabled);
+ return false;
+ }
+
+ // INVALID_VALUE is generated if <planes> < 1 or <planes> >
+ // MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.
+ if (planes < 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kPLSPlanesLessThanOne);
+ return false;
+ }
+ if (planes > static_cast<GLsizei>(context->getCaps().maxPixelLocalStoragePlanes))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kPLSPlanesOutOfRange);
+ return false;
+ }
+
+ // INVALID_FRAMEBUFFER_OPERATION is generated if the draw framebuffer has an image attached to
+ // any color attachment point on or after:
+ //
+ // COLOR_ATTACHMENT0 +
+ // MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE
+ //
+ const Caps &caps = context->getCaps();
+ for (int i = caps.maxColorAttachmentsWithActivePixelLocalStorage; i < caps.maxColorAttachments;
+ ++i)
+ {
+ if (framebuffer->getColorAttachment(i))
+ {
+ context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION,
+ kPLSMaxColorAttachmentsExceded);
+ return false;
+ }
+ }
+
+ // INVALID_FRAMEBUFFER_OPERATION is generated if the draw framebuffer has an image attached to
+ // any color attachment point on or after:
+ //
+ // COLOR_ATTACHMENT0 +
+ // MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE -
+ // <planes>
+ //
+ for (GLuint i = caps.maxCombinedDrawBuffersAndPixelLocalStoragePlanes - planes;
+ i < caps.maxColorAttachmentsWithActivePixelLocalStorage; ++i)
+ {
+ if (framebuffer->getColorAttachment(i))
+ {
+ context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION,
+ kPLSMaxCombinedDrawBuffersAndPlanesExceded);
+ return false;
+ }
+ }
+
+ // INVALID_VALUE is generated if <loadops> is NULL.
+ if (!loadops)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kPLSNullLoadOps);
+ return false;
+ }
+
+ const PixelLocalStorage *pls = framebuffer->peekPixelLocalStorage();
+ bool hasTextureBackedPLSPlanes = false;
+ Extents textureBackedPLSExtents{};
+
+ for (int i = 0; i < planes; ++i)
+ {
+ // INVALID_ENUM is generated if <loadops>[0..<planes>-1] is not one of the Load
+ // Operations enumerated in Table X.1.
+ if (!ValidatePLSLoadOperation(context, entryPoint, loadops[i]))
+ {
+ return false;
+ }
+
+ if (loadops[i] == GL_DISABLE_ANGLE)
+ {
+ continue;
+ }
+
+ // INVALID_VALUE is generated if <loadops>[0..<planes>-1] is CLEAR_ANGLE and <cleardata> is
+ // NULL.
+ if (loadops[i] == GL_CLEAR_ANGLE && !cleardata)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kPLSNullClearData);
+ return false;
+ }
+
+ // INVALID_OPERATION is generated if <loadops>[0..<planes>-1] is not DISABLE_ANGLE, and
+ // the pixel local storage plane at that same index is is in a deinitialized state.
+ if (pls == nullptr || pls->getPlane(i).isDeinitialized())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kPLSEnablingDeinitializedPlane);
+ return false;
+ }
+
+ // [ANGLE_shader_pixel_local_storage] Section 4.4.2.X "Configuring Pixel Local Storage
+ // on a Framebuffer": When a texture object is deleted, any pixel local storage plane to
+ // which it was bound is automatically converted to a memoryless plane of matching
+ // internalformat.
+ const PixelLocalStoragePlane &plane = pls->getPlane(i);
+
+ Extents textureExtents;
+ if (plane.getTextureImageExtents(context, &textureExtents))
+ {
+ // INVALID_OPERATION is generated if all enabled, texture-backed pixel local storage
+ // planes do not have the same width and height.
+ if (!hasTextureBackedPLSPlanes)
+ {
+ textureBackedPLSExtents = textureExtents;
+ hasTextureBackedPLSPlanes = true;
+ }
+ else if (textureExtents != textureBackedPLSExtents)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kPLSMismatchedBackingTextureSizes);
+ return false;
+ }
+ }
+ else
+ {
+ // INVALID_OPERATION is generated if <loadops>[0..<planes>-1] is KEEP and the pixel
+ // local storage plane at that same index is memoryless.
+ if (loadops[i] == GL_KEEP)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kPLSKeepingMemorylessPlane);
+ return false;
+ }
+ }
+ }
+
+ const FramebufferAttachment *firstAttachment =
+ framebuffer->getState().getFirstNonNullAttachment();
+ if (firstAttachment)
+ {
+ // INVALID_OPERATION is generated if the draw framebuffer has other attachments, and its
+ // enabled, texture-backed pixel local storage planes do not have identical dimensions
+ // with the rendering area.
+ if (hasTextureBackedPLSPlanes &&
+ textureBackedPLSExtents != framebuffer->getState().getAttachmentExtentsIntersection())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kPLSDimensionsDontMatchRenderingArea);
+ return false;
+ }
+ }
+ else
+ {
+ // INVALID_OPERATION is generated if the draw framebuffer has no attachments and no
+ // enabled, texture-backed pixel local storage planes.
+ if (!hasTextureBackedPLSPlanes)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kPLSNoAttachmentsNoTextureBacked);
+ return false;
+ }
+ }
+
+ // INVALID_OPERATION is generated if a single texture image is bound to more than one pixel
+ // local storage plane.
+ //
+ // TODO(anglebug.com/7279): Block feedback loops
+ //
+
+ // INVALID_OPERATION is generated if a single texture image is simultaneously bound to a pixel
+ // local storage plane and attached to the draw framebuffer.
+ //
+ // TODO(anglebug.com/7279): Block feedback loops
+ //
+
+ return true;
+}
+
+bool ValidateEndPixelLocalStorageANGLE(const Context *context, angle::EntryPoint entryPoint)
+{
+ return ValidatePLSCommon(context, entryPoint, PLSExpectedStatus::Active);
+}
+
+bool ValidatePixelLocalStorageBarrierANGLE(const Context *context, angle::EntryPoint entryPoint)
+{
+ return ValidatePLSCommon(context, entryPoint, PLSExpectedStatus::Active);
+}
+
+bool ValidateFramebufferFetchBarrierEXT(const Context *context, angle::EntryPoint entryPoint)
+{
+ if (!context->getExtensions().shaderFramebufferFetchNonCoherentEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kFramebufferFetchNonCoherentExtensionNotEnabled);
+ return false;
+ }
+ return true;
+}
+
+bool ValidatePatchParameteriEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLint value)
+{
+ if (!context->getExtensions().tessellationShaderEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION,
+ kTessellationShaderExtensionNotEnabled);
+ return false;
+ }
+
+ if (pname != GL_PATCH_VERTICES)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+
+ if (value <= 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidValueNonPositive);
+ return false;
+ }
+
+ if (value > context->getCaps().maxPatchVertices)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidValueExceedsMaxPatchSize);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTexStorageMemFlags2DANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext)
+{
+ if (!context->getExtensions().memoryObjectFlagsANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (!ValidateTexStorageMem2DEXT(context, entryPoint, targetPacked, levels, internalFormat,
+ width, height, memoryPacked, offset))
+ {
+ return false;
+ }
+
+ // |createFlags| and |usageFlags| must only have bits specified by the extension.
+ constexpr GLbitfield kAllCreateFlags =
+ GL_CREATE_SPARSE_BINDING_BIT_ANGLE | GL_CREATE_SPARSE_RESIDENCY_BIT_ANGLE |
+ GL_CREATE_SPARSE_ALIASED_BIT_ANGLE | GL_CREATE_MUTABLE_FORMAT_BIT_ANGLE |
+ GL_CREATE_CUBE_COMPATIBLE_BIT_ANGLE | GL_CREATE_ALIAS_BIT_ANGLE |
+ GL_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT_ANGLE | GL_CREATE_2D_ARRAY_COMPATIBLE_BIT_ANGLE |
+ GL_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_ANGLE | GL_CREATE_EXTENDED_USAGE_BIT_ANGLE |
+ GL_CREATE_PROTECTED_BIT_ANGLE | GL_CREATE_DISJOINT_BIT_ANGLE |
+ GL_CREATE_CORNER_SAMPLED_BIT_ANGLE | GL_CREATE_SAMPLE_LOCATIONS_COMPATIBLE_DEPTH_BIT_ANGLE |
+ GL_CREATE_SUBSAMPLED_BIT_ANGLE;
+
+ if ((createFlags & ~kAllCreateFlags) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidExternalCreateFlags);
+ return false;
+ }
+
+ constexpr GLbitfield kAllUsageFlags =
+ GL_USAGE_TRANSFER_SRC_BIT_ANGLE | GL_USAGE_TRANSFER_DST_BIT_ANGLE |
+ GL_USAGE_SAMPLED_BIT_ANGLE | GL_USAGE_STORAGE_BIT_ANGLE |
+ GL_USAGE_COLOR_ATTACHMENT_BIT_ANGLE | GL_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT_ANGLE |
+ GL_USAGE_TRANSIENT_ATTACHMENT_BIT_ANGLE | GL_USAGE_INPUT_ATTACHMENT_BIT_ANGLE |
+ GL_USAGE_SHADING_RATE_IMAGE_BIT_ANGLE | GL_USAGE_FRAGMENT_DENSITY_MAP_BIT_ANGLE;
+
+ if ((usageFlags & ~kAllUsageFlags) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidExternalUsageFlags);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateTexStorageMemFlags2DMultisampleANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateTexStorageMemFlags3DANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateTexStorageMemFlags3DMultisampleANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+// GL_EXT_buffer_storage
+bool ValidateBufferStorageEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags)
+{
+ if (!context->isValidBufferBinding(targetPacked))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
+ return false;
+ }
+
+ if (size <= 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNonPositiveSize);
+ return false;
+ }
+
+ constexpr GLbitfield kAllUsageFlags =
+ (GL_DYNAMIC_STORAGE_BIT_EXT | GL_MAP_READ_BIT | GL_MAP_WRITE_BIT |
+ GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT | GL_CLIENT_STORAGE_BIT_EXT);
+ if ((flags & ~kAllUsageFlags) != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBufferUsageFlags);
+ return false;
+ }
+
+ if (((flags & GL_MAP_PERSISTENT_BIT_EXT) != 0) &&
+ ((flags & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBufferUsageFlags);
+ return false;
+ }
+
+ if (((flags & GL_MAP_COHERENT_BIT_EXT) != 0) && ((flags & GL_MAP_PERSISTENT_BIT_EXT) == 0))
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBufferUsageFlags);
+ return false;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(targetPacked);
+
+ if (buffer == nullptr)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound);
+ return false;
+ }
+
+ if (buffer->isImmutable())
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferImmutable);
+ return false;
+ }
+
+ return true;
+}
+
+// GL_EXT_clip_control
+bool ValidateClipControlEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum origin,
+ GLenum depth)
+{
+ if ((origin != GL_LOWER_LEFT_EXT) && (origin != GL_UPPER_LEFT_EXT))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidOriginEnum);
+ return false;
+ }
+
+ if ((depth != GL_NEGATIVE_ONE_TO_ONE_EXT) && (depth != GL_ZERO_TO_ONE_EXT))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDepthEnum);
+ return false;
+ }
+
+ return true;
+}
+
+// GL_EXT_external_buffer
+bool ValidateBufferStorageExternalEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLeglClientBufferEXT clientBuffer,
+ GLbitfield flags)
+{
+ if (!ValidateBufferStorageEXT(context, entryPoint, targetPacked, size, nullptr, flags))
+ {
+ return false;
+ }
+
+ if (offset != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kExternalBufferInvalidOffset);
+ return false;
+ }
+
+ if (clientBuffer == nullptr && size > 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kClientBufferInvalid);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateNamedBufferStorageExternalEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLeglClientBufferEXT clientBuffer,
+ GLbitfield flags)
+{
+ UNIMPLEMENTED();
+ return false;
+}
+
+// GL_EXT_primitive_bounding_box
+bool ValidatePrimitiveBoundingBoxEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat minX,
+ GLfloat minY,
+ GLfloat minZ,
+ GLfloat minW,
+ GLfloat maxX,
+ GLfloat maxY,
+ GLfloat maxZ,
+ GLfloat maxW)
+{
+ if (!context->getExtensions().primitiveBoundingBoxEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return true;
+}
+
+// GL_OES_primitive_bounding_box
+bool ValidatePrimitiveBoundingBoxOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat minX,
+ GLfloat minY,
+ GLfloat minZ,
+ GLfloat minW,
+ GLfloat maxX,
+ GLfloat maxY,
+ GLfloat maxZ,
+ GLfloat maxW)
+{
+ if (!context->getExtensions().primitiveBoundingBoxOES)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return true;
+}
+
+// GL_EXT_separate_shader_objects
+bool ValidateActiveShaderProgramEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ ShaderProgramID programPacked)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateActiveShaderProgramBase(context, entryPoint, pipelinePacked, programPacked);
+}
+
+bool ValidateBindProgramPipelineEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateBindProgramPipelineBase(context, entryPoint, pipelinePacked);
+}
+
+bool ValidateCreateShaderProgramvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderType typePacked,
+ GLsizei count,
+ const GLchar **strings)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateCreateShaderProgramvBase(context, entryPoint, typePacked, count, strings);
+}
+
+bool ValidateDeleteProgramPipelinesEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const ProgramPipelineID *pipelinesPacked)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateDeleteProgramPipelinesBase(context, entryPoint, n, pipelinesPacked);
+}
+
+bool ValidateGenProgramPipelinesEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const ProgramPipelineID *pipelinesPacked)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGenProgramPipelinesBase(context, entryPoint, n, pipelinesPacked);
+}
+
+bool ValidateGetProgramPipelineInfoLogEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *infoLog)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGetProgramPipelineInfoLogBase(context, entryPoint, pipelinePacked, bufSize,
+ length, infoLog);
+}
+
+bool ValidateGetProgramPipelineivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ GLenum pname,
+ const GLint *params)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateGetProgramPipelineivBase(context, entryPoint, pipelinePacked, pname, params);
+}
+
+bool ValidateIsProgramPipelineEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateIsProgramPipelineBase(context, entryPoint, pipelinePacked);
+}
+
+bool ValidateProgramParameteriEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum pname,
+ GLint value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramParameteriBase(context, entryPoint, programPacked, pname, value);
+}
+
+bool ValidateProgramUniform1fEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform1fBase(context, entryPoint, programPacked, locationPacked, v0);
+}
+
+bool ValidateProgramUniform1fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform1fvBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform1iEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform1iBase(context, entryPoint, programPacked, locationPacked, v0);
+}
+
+bool ValidateProgramUniform1ivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform1ivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform1uiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform1uiBase(context, entryPoint, programPacked, locationPacked, v0);
+}
+
+bool ValidateProgramUniform1uivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform1uivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform2fEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform2fBase(context, entryPoint, programPacked, locationPacked, v0, v1);
+}
+
+bool ValidateProgramUniform2fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform2fvBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform2iEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform2iBase(context, entryPoint, programPacked, locationPacked, v0, v1);
+}
+
+bool ValidateProgramUniform2ivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform2ivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform2uiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform2uiBase(context, entryPoint, programPacked, locationPacked, v0,
+ v1);
+}
+
+bool ValidateProgramUniform2uivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform2uivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform3fEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform3fBase(context, entryPoint, programPacked, locationPacked, v0, v1,
+ v2);
+}
+
+bool ValidateProgramUniform3fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform3fvBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform3iEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform3iBase(context, entryPoint, programPacked, locationPacked, v0, v1,
+ v2);
+}
+
+bool ValidateProgramUniform3ivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform3ivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform3uiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform3uiBase(context, entryPoint, programPacked, locationPacked, v0, v1,
+ v2);
+}
+
+bool ValidateProgramUniform3uivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform3uivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform4fEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2,
+ GLfloat v3)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform4fBase(context, entryPoint, programPacked, locationPacked, v0, v1,
+ v2, v3);
+}
+
+bool ValidateProgramUniform4fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform4fvBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform4iEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2,
+ GLint v3)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform4iBase(context, entryPoint, programPacked, locationPacked, v0, v1,
+ v2, v3);
+}
+
+bool ValidateProgramUniform4ivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value)
+{
+ return ValidateProgramUniform4ivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniform4uiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniform4uiBase(context, entryPoint, programPacked, locationPacked, v0, v1,
+ v2, v3);
+}
+
+bool ValidateProgramUniform4uivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value)
+{
+ return ValidateProgramUniform4uivBase(context, entryPoint, programPacked, locationPacked, count,
+ value);
+}
+
+bool ValidateProgramUniformMatrix2fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix2fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix2x3fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix2x3fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix2x4fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix2x4fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix3fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix3fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix3x2fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix3x2fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix3x4fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix3x4fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix4fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix4fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix4x2fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix4x2fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateProgramUniformMatrix4x3fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateProgramUniformMatrix4x3fvBase(context, entryPoint, programPacked, locationPacked,
+ count, transpose, value);
+}
+
+bool ValidateUseProgramStagesEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ GLbitfield stages,
+ ShaderProgramID programPacked)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateUseProgramStagesBase(context, entryPoint, pipelinePacked, stages, programPacked);
+}
+
+bool ValidateValidateProgramPipelineEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked)
+{
+ if (!context->getExtensions().separateShaderObjectsEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateValidateProgramPipelineBase(context, entryPoint, pipelinePacked);
+}
+
+// GL_EXT_debug_label
+bool ValidateGetObjectLabelEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint object,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *label)
+{
+ if (!context->getExtensions().debugLabelEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (bufSize < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
+ return false;
+ }
+
+ return ValidateObjectIdentifierAndName(context, entryPoint, type, object);
+}
+
+bool ValidateLabelObjectEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint object,
+ GLsizei length,
+ const GLchar *label)
+{
+ if (!context->getExtensions().debugLabelEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (length < 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLength);
+ return false;
+ }
+
+ return ValidateObjectIdentifierAndName(context, entryPoint, type, object);
+}
+
+bool ValidateEGLImageTargetTextureStorageEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint texture,
+ GLeglImageOES image,
+ const GLint *attrib_list)
+{
+ UNREACHABLE();
+ return false;
+}
+
+bool ValidateEGLImageTargetTexStorageEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLeglImageOES image,
+ const GLint *attrib_list)
+{
+ if (!context->getExtensions().EGLImageStorageEXT)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ gl::TextureType targetType = FromGLenum<TextureType>(target);
+ switch (targetType)
+ {
+ case TextureType::External:
+ if (!context->getExtensions().EGLImageExternalOES)
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ ToGLenum(targetType));
+ }
+ break;
+ case TextureType::CubeMapArray:
+ if (!context->getExtensions().textureCubeMapArrayAny())
+ {
+ context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
+ ToGLenum(targetType));
+ }
+ break;
+ case TextureType::_2D:
+ case TextureType::_2DArray:
+ case TextureType::_3D:
+ case TextureType::CubeMap:
+ break;
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
+ return false;
+ }
+
+ // Validate egl source image is valid
+ egl::Image *imageObject = static_cast<egl::Image *>(image);
+ if (!ValidateEGLImageObject(context, entryPoint, targetType, image))
+ {
+ return false;
+ }
+
+ // attrib list validation
+ if (attrib_list != nullptr && attrib_list[0] != GL_NONE)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kAttributeListNotNull);
+ return false;
+ }
+
+ GLsizei levelCount = imageObject->getLevelCount();
+ Extents size = imageObject->getExtents();
+ GLsizei width = static_cast<GLsizei>(size.width);
+ GLsizei height = static_cast<GLsizei>(size.height);
+ GLsizei depth = static_cast<GLsizei>(size.depth);
+ GLenum internalformat = imageObject->getFormat().info->sizedInternalFormat;
+
+ if (width < 1 || height < 1 || depth < 1 || levelCount < 1)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kTextureSizeTooSmall);
+ return false;
+ }
+
+ if (!ValidateES3TexStorageParametersLevel(context, entryPoint, targetType, levelCount, width,
+ height, depth))
+ {
+ // Error already generated.
+ return false;
+ }
+
+ if (targetType == TextureType::External)
+ {
+ const Caps &caps = context->getCaps();
+ if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
+ return false;
+ }
+ }
+ else if (!ValidateES3TexStorageParametersExtent(context, entryPoint, targetType, levelCount,
+ width, height, depth))
+ {
+ // Error already generated.
+ return false;
+ }
+
+ if (!ValidateES3TexStorageParametersTexObject(context, entryPoint, targetType))
+ {
+ // Error already generated.
+ return false;
+ }
+
+ if (!ValidateES3TexStorageParametersFormat(context, entryPoint, targetType, levelCount,
+ internalformat, width, height, depth))
+ {
+ // Error already generated.
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateAcquireTexturesANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint numTextures,
+ const TextureID *textures,
+ const GLenum *layouts)
+{
+ if (!context->getExtensions().vulkanImageANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ for (GLuint i = 0; i < numTextures; ++i)
+ {
+ if (!context->getTexture(textures[i]))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureName);
+ return false;
+ }
+ if (!IsValidImageLayout(FromGLenum<ImageLayout>(layouts[i])))
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidImageLayout);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateReleaseTexturesANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint numTextures,
+ const TextureID *textures,
+ const GLenum *layouts)
+{
+ if (!context->getExtensions().vulkanImageANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+ for (GLuint i = 0; i < numTextures; ++i)
+ {
+ if (!context->getTexture(textures[i]))
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureName);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ValidateFramebufferParameteriMESA(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ GLint param)
+{
+ if (pname != GL_FRAMEBUFFER_FLIP_Y_MESA)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+ return ValidateFramebufferParameteriBase(context, entryPoint, target, pname, param);
+}
+
+bool ValidateGetFramebufferParameterivMESA(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ const GLint *params)
+{
+ if (pname != GL_FRAMEBUFFER_FLIP_Y_MESA)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+ return ValidateGetFramebufferParameterivBase(context, entryPoint, target, pname, params);
+}
+
+// GL_AMD_performance_monitor
+bool ValidateBeginPerfMonitorAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint monitor)
+{
+ if (!context->getExtensions().performanceMonitorAMD)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateDeletePerfMonitorsAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *monitors)
+{
+ if (!context->getExtensions().performanceMonitorAMD)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateEndPerfMonitorAMD(const Context *context, angle::EntryPoint entryPoint, GLuint monitor)
+{
+ if (!context->getExtensions().performanceMonitorAMD)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGenPerfMonitorsAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *monitors)
+{
+ if (!context->getExtensions().performanceMonitorAMD)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateGetPerfMonitorCounterDataAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint monitor,
+ GLenum pname,
+ GLsizei dataSize,
+ const GLuint *data,
+ const GLint *bytesWritten)
+{
+ if (!context->getExtensions().performanceMonitorAMD)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ if (monitor != 0)
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidPerfMonitor);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_PERFMON_RESULT_AVAILABLE_AMD:
+ case GL_PERFMON_RESULT_SIZE_AMD:
+ case GL_PERFMON_RESULT_AMD:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetPerfMonitorCounterInfoAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint group,
+ GLuint counter,
+ GLenum pname,
+ const void *data)
+{
+ if (!context->getExtensions().performanceMonitorAMD)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ const angle::PerfMonitorCounterGroups &groups = context->getPerfMonitorCounterGroups();
+
+ if (group >= groups.size())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidPerfMonitorGroup);
+ return false;
+ }
+
+ if (counter >= groups[group].counters.size())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidPerfMonitorCounter);
+ return false;
+ }
+
+ switch (pname)
+ {
+ case GL_COUNTER_TYPE_AMD:
+ case GL_COUNTER_RANGE_AMD:
+ break;
+
+ default:
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetPerfMonitorCounterStringAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint group,
+ GLuint counter,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *counterString)
+{
+ if (!context->getExtensions().performanceMonitorAMD)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ const angle::PerfMonitorCounterGroups &groups = context->getPerfMonitorCounterGroups();
+
+ if (group >= groups.size())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidPerfMonitorGroup);
+ return false;
+ }
+
+ if (counter >= groups[group].counters.size())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidPerfMonitorCounter);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetPerfMonitorCountersAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint group,
+ const GLint *numCounters,
+ const GLint *maxActiveCounters,
+ GLsizei counterSize,
+ const GLuint *counters)
+{
+ if (!context->getExtensions().performanceMonitorAMD)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ const angle::PerfMonitorCounterGroups &groups = context->getPerfMonitorCounterGroups();
+
+ if (group >= groups.size())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidPerfMonitorGroup);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetPerfMonitorGroupStringAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint group,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *groupString)
+{
+ if (!context->getExtensions().performanceMonitorAMD)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ const angle::PerfMonitorCounterGroups &groups = context->getPerfMonitorCounterGroups();
+
+ if (group >= groups.size())
+ {
+ context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidPerfMonitorGroup);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateGetPerfMonitorGroupsAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLint *numGroups,
+ GLsizei groupsSize,
+ const GLuint *groups)
+{
+ if (!context->getExtensions().performanceMonitorAMD)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateSelectPerfMonitorCountersAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint monitor,
+ GLboolean enable,
+ GLuint group,
+ GLint numCounters,
+ const GLuint *counterList)
+{
+ if (!context->getExtensions().performanceMonitorAMD)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ UNIMPLEMENTED();
+ return false;
+}
+
+bool ValidateShadingRateQCOM(const Context *context, angle::EntryPoint entryPoint, GLenum rate)
+{
+ if (!context->getExtensions().shadingRateQCOM)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ gl::ShadingRate shadingRate = gl::FromGLenum<gl::ShadingRate>(rate);
+ if (shadingRate == gl::ShadingRate::Undefined || shadingRate == gl::ShadingRate::InvalidEnum)
+ {
+ context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShadingRate);
+ return false;
+ }
+
+ return true;
+}
+
+bool ValidateLogicOpANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ LogicalOperation opcodePacked)
+{
+ if (!context->getExtensions().logicOpANGLE)
+ {
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
+ return false;
+ }
+
+ return ValidateLogicOpCommon(context, entryPoint, opcodePacked);
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/validationESEXT.h b/gfx/angle/checkout/src/libANGLE/validationESEXT.h
new file mode 100644
index 0000000000..b22ed4e379
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationESEXT.h
@@ -0,0 +1,20 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationESEXT.h:
+// Inlined validation functions for OpenGL ES extension entry points.
+
+#ifndef LIBANGLE_VALIDATION_ESEXT_H_
+#define LIBANGLE_VALIDATION_ESEXT_H_
+
+#include "libANGLE/ErrorStrings.h"
+#include "libANGLE/validationESEXT_autogen.h"
+
+namespace gl
+{
+// Nothing here yet.
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ESEXT_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationESEXT_autogen.h b/gfx/angle/checkout/src/libANGLE/validationESEXT_autogen.h
new file mode 100644
index 0000000000..47be44ab2f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationESEXT_autogen.h
@@ -0,0 +1,2646 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml and gl_angle_ext.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationESEXT_autogen.h:
+// Validation functions for the OpenGL ES extension entry points.
+
+#ifndef LIBANGLE_VALIDATION_ESEXT_AUTOGEN_H_
+#define LIBANGLE_VALIDATION_ESEXT_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "common/entry_points_enum_autogen.h"
+
+namespace gl
+{
+class Context;
+
+// GL_AMD_performance_monitor
+bool ValidateBeginPerfMonitorAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint monitor);
+bool ValidateDeletePerfMonitorsAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *monitors);
+bool ValidateEndPerfMonitorAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint monitor);
+bool ValidateGenPerfMonitorsAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *monitors);
+bool ValidateGetPerfMonitorCounterDataAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint monitor,
+ GLenum pname,
+ GLsizei dataSize,
+ const GLuint *data,
+ const GLint *bytesWritten);
+bool ValidateGetPerfMonitorCounterInfoAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint group,
+ GLuint counter,
+ GLenum pname,
+ const void *data);
+bool ValidateGetPerfMonitorCounterStringAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint group,
+ GLuint counter,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *counterString);
+bool ValidateGetPerfMonitorCountersAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint group,
+ const GLint *numCounters,
+ const GLint *maxActiveCounters,
+ GLsizei counterSize,
+ const GLuint *counters);
+bool ValidateGetPerfMonitorGroupStringAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint group,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *groupString);
+bool ValidateGetPerfMonitorGroupsAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLint *numGroups,
+ GLsizei groupsSize,
+ const GLuint *groups);
+bool ValidateSelectPerfMonitorCountersAMD(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint monitor,
+ GLboolean enable,
+ GLuint group,
+ GLint numCounters,
+ const GLuint *counterList);
+
+// GL_ANDROID_extension_pack_es31a
+
+// GL_ANGLE_base_vertex_base_instance
+bool ValidateDrawArraysInstancedBaseInstanceANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLint first,
+ GLsizei count,
+ GLsizei instanceCount,
+ GLuint baseInstance);
+bool ValidateDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const GLvoid *indices,
+ GLsizei instanceCount,
+ GLint baseVertex,
+ GLuint baseInstance);
+bool ValidateMultiDrawArraysInstancedBaseInstanceANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ const GLuint *baseInstances,
+ GLsizei drawcount);
+bool ValidateMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ const GLint *baseVertices,
+ const GLuint *baseInstances,
+ GLsizei drawcount);
+
+// GL_ANGLE_copy_texture_3d
+bool ValidateCopyTexture3DANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID sourceIdPacked,
+ GLint sourceLevel,
+ TextureTarget destTargetPacked,
+ TextureID destIdPacked,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+bool ValidateCopySubTexture3DANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID sourceIdPacked,
+ GLint sourceLevel,
+ TextureTarget destTargetPacked,
+ TextureID destIdPacked,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint width,
+ GLint height,
+ GLint depth,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+
+// GL_ANGLE_depth_texture
+
+// GL_ANGLE_framebuffer_blit
+bool ValidateBlitFramebufferANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+
+// GL_ANGLE_framebuffer_multisample
+bool ValidateRenderbufferStorageMultisampleANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+
+// GL_ANGLE_get_image
+bool ValidateGetTexImageANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateGetCompressedTexImageANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ const void *pixels);
+bool ValidateGetRenderbufferImageANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+
+// GL_ANGLE_get_tex_level_parameter
+bool ValidateGetTexLevelParameterivANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetTexLevelParameterfvANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ const GLfloat *params);
+
+// GL_ANGLE_instanced_arrays
+bool ValidateDrawArraysInstancedANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount);
+bool ValidateDrawElementsInstancedANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei primcount);
+bool ValidateVertexAttribDivisorANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLuint divisor);
+
+// GL_ANGLE_logic_op
+bool ValidateLogicOpANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ LogicalOperation opcodePacked);
+
+// GL_ANGLE_memory_object_flags
+bool ValidateTexStorageMemFlags2DANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext);
+bool ValidateTexStorageMemFlags2DMultisampleANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext);
+bool ValidateTexStorageMemFlags3DANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext);
+bool ValidateTexStorageMemFlags3DMultisampleANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset,
+ GLbitfield createFlags,
+ GLbitfield usageFlags,
+ const void *imageCreateInfoPNext);
+
+// GL_ANGLE_memory_object_fuchsia
+bool ValidateImportMemoryZirconHandleANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ MemoryObjectID memoryPacked,
+ GLuint64 size,
+ HandleType handleTypePacked,
+ GLuint handle);
+
+// GL_ANGLE_multi_draw
+bool ValidateMultiDrawArraysANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ GLsizei drawcount);
+bool ValidateMultiDrawArraysInstancedANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const GLint *firsts,
+ const GLsizei *counts,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount);
+bool ValidateMultiDrawElementsANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ GLsizei drawcount);
+bool ValidateMultiDrawElementsInstancedANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const GLsizei *counts,
+ DrawElementsType typePacked,
+ const GLvoid *const *indices,
+ const GLsizei *instanceCounts,
+ GLsizei drawcount);
+
+// GL_ANGLE_pack_reverse_row_order
+
+// GL_ANGLE_program_binary
+
+// GL_ANGLE_provoking_vertex
+bool ValidateProvokingVertexANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProvokingVertexConvention modePacked);
+
+// GL_ANGLE_request_extension
+bool ValidateRequestExtensionANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLchar *name);
+bool ValidateDisableExtensionANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLchar *name);
+
+// GL_ANGLE_robust_client_memory
+bool ValidateGetBooleanvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLboolean *params);
+bool ValidateGetBufferParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetFloatvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params);
+bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetIntegervRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *data);
+bool ValidateGetProgramivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetRenderbufferParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetShaderivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shaderPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetTexParameterfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params);
+bool ValidateGetTexParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetUniformfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params);
+bool ValidateGetUniformivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetVertexAttribfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params);
+bool ValidateGetVertexAttribivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetVertexAttribPointervRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ void *const *pointer);
+bool ValidateReadPixelsRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLsizei *columns,
+ const GLsizei *rows,
+ const void *pixels);
+bool ValidateTexImage2DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+bool ValidateTexParameterfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *params);
+bool ValidateTexParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params);
+bool ValidateTexSubImage2DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+bool ValidateTexImage3DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+bool ValidateTexSubImage3DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+bool ValidateCompressedTexImage2DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data);
+bool ValidateCompressedTexSubImage2DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLsizei xoffset,
+ GLsizei yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data);
+bool ValidateCompressedTexImage3DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data);
+bool ValidateCompressedTexSubImage3DRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ GLsizei dataSize,
+ const GLvoid *data);
+bool ValidateGetQueryivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetQueryObjectuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint *params);
+bool ValidateGetBufferPointervRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ void *const *params);
+bool ValidateGetIntegeri_vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *data);
+bool ValidateGetInternalformativRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetVertexAttribIivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetVertexAttribIuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint *params);
+bool ValidateGetUniformuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint *params);
+bool ValidateGetActiveUniformBlockivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformBlockIndex uniformBlockIndexPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetInteger64vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint64 *data);
+bool ValidateGetInteger64i_vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint64 *data);
+bool ValidateGetBufferParameteri64vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint64 *params);
+bool ValidateSamplerParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLuint pname,
+ GLsizei bufSize,
+ const GLint *param);
+bool ValidateSamplerParameterfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLfloat *param);
+bool ValidateGetSamplerParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetSamplerParameterfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params);
+bool ValidateGetFramebufferParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetProgramInterfaceivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetBooleani_vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLboolean *data);
+bool ValidateGetMultisamplefvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *val);
+bool ValidateGetTexLevelParameterivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetTexLevelParameterfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params);
+bool ValidateGetPointervRobustANGLERobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ void *const *params);
+bool ValidateReadnPixelsRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLsizei *columns,
+ const GLsizei *rows,
+ const void *data);
+bool ValidateGetnUniformfvRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLfloat *params);
+bool ValidateGetnUniformivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetnUniformuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint *params);
+bool ValidateTexParameterIivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *params);
+bool ValidateTexParameterIuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLuint *params);
+bool ValidateGetTexParameterIivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetTexParameterIuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint *params);
+bool ValidateSamplerParameterIivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint *param);
+bool ValidateSamplerParameterIuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLuint *param);
+bool ValidateGetSamplerParameterIivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetSamplerParameterIuivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint *params);
+bool ValidateGetQueryObjectivRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint *params);
+bool ValidateGetQueryObjecti64vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLint64 *params);
+bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID idPacked,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLuint64 *params);
+
+// GL_ANGLE_robust_resource_initialization
+
+// GL_ANGLE_semaphore_fuchsia
+bool ValidateImportSemaphoreZirconHandleANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ SemaphoreID semaphorePacked,
+ HandleType handleTypePacked,
+ GLuint handle);
+
+// GL_ANGLE_shader_pixel_local_storage
+bool ValidateFramebufferMemorylessPixelLocalStorageANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint plane,
+ GLenum internalformat);
+bool ValidateFramebufferTexturePixelLocalStorageANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint plane,
+ TextureID backingtexturePacked,
+ GLint level,
+ GLint layer);
+bool ValidateBeginPixelLocalStorageANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei planes,
+ const GLenum *loadops,
+ const void *cleardata);
+bool ValidateEndPixelLocalStorageANGLE(const Context *context, angle::EntryPoint entryPoint);
+bool ValidatePixelLocalStorageBarrierANGLE(const Context *context, angle::EntryPoint entryPoint);
+
+// GL_ANGLE_texture_compression_dxt3
+
+// GL_ANGLE_texture_compression_dxt5
+
+// GL_ANGLE_texture_external_update
+bool ValidateTexImage2DExternalANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type);
+bool ValidateInvalidateTextureANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked);
+
+// GL_ANGLE_texture_multisample
+bool ValidateTexStorage2DMultisampleANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations);
+bool ValidateGetMultisamplefvANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLuint index,
+ const GLfloat *val);
+bool ValidateSampleMaskiANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint maskNumber,
+ GLbitfield mask);
+
+// GL_ANGLE_texture_usage
+
+// GL_ANGLE_translated_shader_source
+bool ValidateGetTranslatedShaderSourceANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID shaderPacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *source);
+
+// GL_ANGLE_vulkan_image
+bool ValidateAcquireTexturesANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint numTextures,
+ const TextureID *texturesPacked,
+ const GLenum *layouts);
+bool ValidateReleaseTexturesANGLE(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint numTextures,
+ const TextureID *texturesPacked,
+ const GLenum *layouts);
+
+// GL_APPLE_clip_distance
+
+// GL_ARB_sync
+
+// GL_CHROMIUM_bind_uniform_location
+bool ValidateBindUniformLocationCHROMIUM(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ const GLchar *name);
+
+// GL_CHROMIUM_copy_compressed_texture
+bool ValidateCompressedCopyTextureCHROMIUM(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID sourceIdPacked,
+ TextureID destIdPacked);
+
+// GL_CHROMIUM_copy_texture
+bool ValidateCopyTextureCHROMIUM(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID sourceIdPacked,
+ GLint sourceLevel,
+ TextureTarget destTargetPacked,
+ TextureID destIdPacked,
+ GLint destLevel,
+ GLint internalFormat,
+ GLenum destType,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+bool ValidateCopySubTextureCHROMIUM(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID sourceIdPacked,
+ GLint sourceLevel,
+ TextureTarget destTargetPacked,
+ TextureID destIdPacked,
+ GLint destLevel,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLint width,
+ GLint height,
+ GLboolean unpackFlipY,
+ GLboolean unpackPremultiplyAlpha,
+ GLboolean unpackUnmultiplyAlpha);
+
+// GL_CHROMIUM_framebuffer_mixed_samples
+bool ValidateCoverageModulationCHROMIUM(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum components);
+
+// GL_CHROMIUM_lose_context
+bool ValidateLoseContextCHROMIUM(const Context *context,
+ angle::EntryPoint entryPoint,
+ GraphicsResetStatus currentPacked,
+ GraphicsResetStatus otherPacked);
+
+// GL_EXT_EGL_image_array
+
+// GL_EXT_EGL_image_storage
+bool ValidateEGLImageTargetTexStorageEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLeglImageOES image,
+ const GLint *attrib_list);
+bool ValidateEGLImageTargetTextureStorageEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint texture,
+ GLeglImageOES image,
+ const GLint *attrib_list);
+
+// GL_EXT_YUV_target
+
+// GL_EXT_base_instance
+bool ValidateDrawArraysInstancedBaseInstanceEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLint first,
+ GLsizei count,
+ GLsizei instancecount,
+ GLuint baseinstance);
+bool ValidateDrawElementsInstancedBaseInstanceEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLuint baseinstance);
+bool ValidateDrawElementsInstancedBaseVertexBaseInstanceEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex,
+ GLuint baseinstance);
+
+// GL_EXT_blend_func_extended
+bool ValidateBindFragDataLocationEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLuint color,
+ const GLchar *name);
+bool ValidateBindFragDataLocationIndexedEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLuint colorNumber,
+ GLuint index,
+ const GLchar *name);
+bool ValidateGetFragDataIndexEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ const GLchar *name);
+bool ValidateGetProgramResourceLocationIndexEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ const GLchar *name);
+
+// GL_EXT_blend_minmax
+
+// GL_EXT_buffer_storage
+bool ValidateBufferStorageEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags);
+
+// GL_EXT_clip_control
+bool ValidateClipControlEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum origin,
+ GLenum depth);
+
+// GL_EXT_clip_cull_distance
+
+// GL_EXT_color_buffer_float
+
+// GL_EXT_color_buffer_half_float
+
+// GL_EXT_copy_image
+bool ValidateCopyImageSubDataEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint srcName,
+ GLenum srcTarget,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLuint dstName,
+ GLenum dstTarget,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth);
+
+// GL_EXT_debug_label
+bool ValidateGetObjectLabelEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint object,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *label);
+bool ValidateLabelObjectEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint object,
+ GLsizei length,
+ const GLchar *label);
+
+// GL_EXT_debug_marker
+bool ValidateInsertEventMarkerEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei length,
+ const GLchar *marker);
+bool ValidatePopGroupMarkerEXT(const Context *context, angle::EntryPoint entryPoint);
+bool ValidatePushGroupMarkerEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei length,
+ const GLchar *marker);
+
+// GL_EXT_discard_framebuffer
+bool ValidateDiscardFramebufferEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei numAttachments,
+ const GLenum *attachments);
+
+// GL_EXT_disjoint_timer_query
+bool ValidateBeginQueryEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType targetPacked,
+ QueryID idPacked);
+bool ValidateDeleteQueriesEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const QueryID *idsPacked);
+bool ValidateEndQueryEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType targetPacked);
+bool ValidateGenQueriesEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const QueryID *idsPacked);
+bool ValidateGetInteger64vEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLint64 *data);
+bool ValidateGetQueryObjecti64vEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID idPacked,
+ GLenum pname,
+ const GLint64 *params);
+bool ValidateGetQueryObjectivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID idPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetQueryObjectui64vEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID idPacked,
+ GLenum pname,
+ const GLuint64 *params);
+bool ValidateGetQueryObjectuivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID idPacked,
+ GLenum pname,
+ const GLuint *params);
+bool ValidateGetQueryivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryType targetPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateIsQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryID idPacked);
+bool ValidateQueryCounterEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID idPacked,
+ QueryType targetPacked);
+
+// GL_EXT_draw_buffers
+bool ValidateDrawBuffersEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLenum *bufs);
+
+// GL_EXT_draw_buffers_indexed
+bool ValidateBlendEquationSeparateiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum modeRGB,
+ GLenum modeAlpha);
+bool ValidateBlendEquationiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum mode);
+bool ValidateBlendFuncSeparateiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha);
+bool ValidateBlendFunciEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum src,
+ GLenum dst);
+bool ValidateColorMaskiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLboolean r,
+ GLboolean g,
+ GLboolean b,
+ GLboolean a);
+bool ValidateDisableiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index);
+bool ValidateEnableiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index);
+bool ValidateIsEnablediEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index);
+
+// GL_EXT_draw_elements_base_vertex
+bool ValidateDrawElementsBaseVertexEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex);
+bool ValidateDrawElementsInstancedBaseVertexEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex);
+bool ValidateDrawRangeElementsBaseVertexEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex);
+bool ValidateMultiDrawElementsBaseVertexEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const GLsizei *count,
+ DrawElementsType typePacked,
+ const void *const *indices,
+ GLsizei drawcount,
+ const GLint *basevertex);
+
+// GL_EXT_external_buffer
+bool ValidateBufferStorageExternalEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLeglClientBufferEXT clientBuffer,
+ GLbitfield flags);
+bool ValidateNamedBufferStorageExternalEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLeglClientBufferEXT clientBuffer,
+ GLbitfield flags);
+
+// GL_EXT_float_blend
+
+// GL_EXT_geometry_shader
+bool ValidateFramebufferTextureEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureID texturePacked,
+ GLint level);
+
+// GL_EXT_gpu_shader5
+
+// GL_EXT_instanced_arrays
+bool ValidateDrawArraysInstancedEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLint start,
+ GLsizei count,
+ GLsizei primcount);
+bool ValidateDrawElementsInstancedEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei primcount);
+bool ValidateVertexAttribDivisorEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLuint divisor);
+
+// GL_EXT_map_buffer_range
+bool ValidateFlushMappedBufferRangeEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLintptr offset,
+ GLsizeiptr length);
+bool ValidateMapBufferRangeEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access);
+
+// GL_EXT_memory_object
+bool ValidateBufferStorageMemEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizeiptr size,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset);
+bool ValidateCreateMemoryObjectsEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const MemoryObjectID *memoryObjectsPacked);
+bool ValidateDeleteMemoryObjectsEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const MemoryObjectID *memoryObjectsPacked);
+bool ValidateGetMemoryObjectParameterivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ MemoryObjectID memoryObjectPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetUnsignedBytevEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLubyte *data);
+bool ValidateGetUnsignedBytei_vEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ const GLubyte *data);
+bool ValidateIsMemoryObjectEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ MemoryObjectID memoryObjectPacked);
+bool ValidateMemoryObjectParameterivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ MemoryObjectID memoryObjectPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateTexStorageMem2DEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset);
+bool ValidateTexStorageMem2DMultisampleEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset);
+bool ValidateTexStorageMem3DEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset);
+bool ValidateTexStorageMem3DMultisampleEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedSampleLocations,
+ MemoryObjectID memoryPacked,
+ GLuint64 offset);
+
+// GL_EXT_memory_object_fd
+bool ValidateImportMemoryFdEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ MemoryObjectID memoryPacked,
+ GLuint64 size,
+ HandleType handleTypePacked,
+ GLint fd);
+
+// GL_EXT_multi_draw_indirect
+bool ValidateMultiDrawArraysIndirectEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride);
+bool ValidateMultiDrawElementsIndirectEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ DrawElementsType typePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride);
+
+// GL_EXT_multisampled_render_to_texture
+bool ValidateFramebufferTexture2DMultisampleEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texturePacked,
+ GLint level,
+ GLsizei samples);
+bool ValidateRenderbufferStorageMultisampleEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+
+// GL_EXT_multisampled_render_to_texture2
+
+// GL_EXT_occlusion_query_boolean
+
+// GL_EXT_primitive_bounding_box
+bool ValidatePrimitiveBoundingBoxEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat minX,
+ GLfloat minY,
+ GLfloat minZ,
+ GLfloat minW,
+ GLfloat maxX,
+ GLfloat maxY,
+ GLfloat maxZ,
+ GLfloat maxW);
+
+// GL_EXT_protected_textures
+
+// GL_EXT_pvrtc_sRGB
+
+// GL_EXT_read_format_bgra
+
+// GL_EXT_robustness
+bool ValidateGetGraphicsResetStatusEXT(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateGetnUniformfvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ const GLfloat *params);
+bool ValidateGetnUniformivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ const GLint *params);
+bool ValidateReadnPixelsEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *data);
+
+// GL_EXT_sRGB
+
+// GL_EXT_sRGB_write_control
+
+// GL_EXT_semaphore
+bool ValidateDeleteSemaphoresEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const SemaphoreID *semaphoresPacked);
+bool ValidateGenSemaphoresEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const SemaphoreID *semaphoresPacked);
+bool ValidateGetSemaphoreParameterui64vEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SemaphoreID semaphorePacked,
+ GLenum pname,
+ const GLuint64 *params);
+bool ValidateIsSemaphoreEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SemaphoreID semaphorePacked);
+bool ValidateSemaphoreParameterui64vEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SemaphoreID semaphorePacked,
+ GLenum pname,
+ const GLuint64 *params);
+bool ValidateSignalSemaphoreEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SemaphoreID semaphorePacked,
+ GLuint numBufferBarriers,
+ const BufferID *buffersPacked,
+ GLuint numTextureBarriers,
+ const TextureID *texturesPacked,
+ const GLenum *dstLayouts);
+bool ValidateWaitSemaphoreEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SemaphoreID semaphorePacked,
+ GLuint numBufferBarriers,
+ const BufferID *buffersPacked,
+ GLuint numTextureBarriers,
+ const TextureID *texturesPacked,
+ const GLenum *srcLayouts);
+
+// GL_EXT_semaphore_fd
+bool ValidateImportSemaphoreFdEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SemaphoreID semaphorePacked,
+ HandleType handleTypePacked,
+ GLint fd);
+
+// GL_EXT_separate_shader_objects
+bool ValidateActiveShaderProgramEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ ShaderProgramID programPacked);
+bool ValidateBindProgramPipelineEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked);
+bool ValidateCreateShaderProgramvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderType typePacked,
+ GLsizei count,
+ const GLchar **strings);
+bool ValidateDeleteProgramPipelinesEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const ProgramPipelineID *pipelinesPacked);
+bool ValidateGenProgramPipelinesEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const ProgramPipelineID *pipelinesPacked);
+bool ValidateGetProgramPipelineInfoLogEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *infoLog);
+bool ValidateGetProgramPipelineivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateIsProgramPipelineEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked);
+bool ValidateProgramParameteriEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum pname,
+ GLint value);
+bool ValidateProgramUniform1fEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0);
+bool ValidateProgramUniform1fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniform1iEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0);
+bool ValidateProgramUniform1ivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform1uiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0);
+bool ValidateProgramUniform1uivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniform2fEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1);
+bool ValidateProgramUniform2fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniform2iEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1);
+bool ValidateProgramUniform2ivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform2uiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1);
+bool ValidateProgramUniform2uivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniform3fEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2);
+bool ValidateProgramUniform3fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniform3iEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2);
+bool ValidateProgramUniform3ivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform3uiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2);
+bool ValidateProgramUniform3uivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniform4fEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLfloat v0,
+ GLfloat v1,
+ GLfloat v2,
+ GLfloat v3);
+bool ValidateProgramUniform4fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLfloat *value);
+bool ValidateProgramUniform4iEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLint v0,
+ GLint v1,
+ GLint v2,
+ GLint v3);
+bool ValidateProgramUniform4ivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLint *value);
+bool ValidateProgramUniform4uiEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLuint v0,
+ GLuint v1,
+ GLuint v2,
+ GLuint v3);
+bool ValidateProgramUniform4uivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLuint *value);
+bool ValidateProgramUniformMatrix2fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix2x3fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix2x4fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix3fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix3x2fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix3x4fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix4fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix4x2fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateProgramUniformMatrix4x3fvEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat *value);
+bool ValidateUseProgramStagesEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked,
+ GLbitfield stages,
+ ShaderProgramID programPacked);
+bool ValidateValidateProgramPipelineEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProgramPipelineID pipelinePacked);
+
+// GL_EXT_shader_framebuffer_fetch
+
+// GL_EXT_shader_framebuffer_fetch_non_coherent
+bool ValidateFramebufferFetchBarrierEXT(const Context *context, angle::EntryPoint entryPoint);
+
+// GL_EXT_shader_io_blocks
+
+// GL_EXT_shader_non_constant_global_initializers
+
+// GL_EXT_shader_texture_lod
+
+// GL_EXT_shadow_samplers
+
+// GL_EXT_tessellation_shader
+bool ValidatePatchParameteriEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLint value);
+
+// GL_EXT_texture_border_clamp
+bool ValidateGetSamplerParameterIivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetSamplerParameterIuivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLuint *params);
+bool ValidateGetTexParameterIivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetTexParameterIuivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params);
+bool ValidateSamplerParameterIivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *param);
+bool ValidateSamplerParameterIuivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLuint *param);
+bool ValidateTexParameterIivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateTexParameterIuivEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params);
+
+// GL_EXT_texture_buffer
+bool ValidateTexBufferEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum internalformat,
+ BufferID bufferPacked);
+bool ValidateTexBufferRangeEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum internalformat,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size);
+
+// GL_EXT_texture_compression_bptc
+
+// GL_EXT_texture_compression_dxt1
+
+// GL_EXT_texture_compression_rgtc
+
+// GL_EXT_texture_compression_s3tc
+
+// GL_EXT_texture_compression_s3tc_srgb
+
+// GL_EXT_texture_cube_map_array
+
+// GL_EXT_texture_filter_anisotropic
+
+// GL_EXT_texture_format_BGRA8888
+
+// GL_EXT_texture_format_sRGB_override
+
+// GL_EXT_texture_norm16
+
+// GL_EXT_texture_rg
+
+// GL_EXT_texture_sRGB_R8
+
+// GL_EXT_texture_sRGB_RG8
+
+// GL_EXT_texture_sRGB_decode
+
+// GL_EXT_texture_storage
+bool ValidateTexStorage1DEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width);
+bool ValidateTexStorage2DEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+bool ValidateTexStorage3DEXT(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+
+// GL_EXT_texture_type_2_10_10_10_REV
+
+// GL_EXT_unpack_subimage
+
+// GL_IMG_texture_compression_pvrtc
+
+// GL_IMG_texture_compression_pvrtc2
+
+// GL_KHR_blend_equation_advanced
+bool ValidateBlendBarrierKHR(const Context *context, angle::EntryPoint entryPoint);
+
+// GL_KHR_debug
+bool ValidateDebugMessageCallbackKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLDEBUGPROCKHR callback,
+ const void *userParam);
+bool ValidateDebugMessageControlKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled);
+bool ValidateDebugMessageInsertKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *buf);
+bool ValidateGetDebugMessageLogKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint count,
+ GLsizei bufSize,
+ const GLenum *sources,
+ const GLenum *types,
+ const GLuint *ids,
+ const GLenum *severities,
+ const GLsizei *lengths,
+ const GLchar *messageLog);
+bool ValidateGetObjectLabelKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum identifier,
+ GLuint name,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *label);
+bool ValidateGetObjectPtrLabelKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ const void *ptr,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *label);
+bool ValidateGetPointervKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ void *const *params);
+bool ValidateObjectLabelKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum identifier,
+ GLuint name,
+ GLsizei length,
+ const GLchar *label);
+bool ValidateObjectPtrLabelKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ const void *ptr,
+ GLsizei length,
+ const GLchar *label);
+bool ValidatePopDebugGroupKHR(const Context *context, angle::EntryPoint entryPoint);
+bool ValidatePushDebugGroupKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum source,
+ GLuint id,
+ GLsizei length,
+ const GLchar *message);
+
+// GL_KHR_no_error
+
+// GL_KHR_parallel_shader_compile
+bool ValidateMaxShaderCompilerThreadsKHR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint count);
+
+// GL_KHR_robust_buffer_access_behavior
+
+// GL_KHR_texture_compression_astc_hdr
+
+// GL_KHR_texture_compression_astc_ldr
+
+// GL_KHR_texture_compression_astc_sliced_3d
+
+// GL_MESA_framebuffer_flip_y
+bool ValidateFramebufferParameteriMESA(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ GLint param);
+bool ValidateGetFramebufferParameterivMESA(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ const GLint *params);
+
+// GL_NV_fence
+bool ValidateDeleteFencesNV(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const FenceNVID *fencesPacked);
+bool ValidateFinishFenceNV(const Context *context,
+ angle::EntryPoint entryPoint,
+ FenceNVID fencePacked);
+bool ValidateGenFencesNV(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const FenceNVID *fencesPacked);
+bool ValidateGetFenceivNV(const Context *context,
+ angle::EntryPoint entryPoint,
+ FenceNVID fencePacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateIsFenceNV(const Context *context, angle::EntryPoint entryPoint, FenceNVID fencePacked);
+bool ValidateSetFenceNV(const Context *context,
+ angle::EntryPoint entryPoint,
+ FenceNVID fencePacked,
+ GLenum condition);
+bool ValidateTestFenceNV(const Context *context,
+ angle::EntryPoint entryPoint,
+ FenceNVID fencePacked);
+
+// GL_NV_framebuffer_blit
+bool ValidateBlitFramebufferNV(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+
+// GL_NV_pixel_buffer_object
+
+// GL_NV_read_depth
+
+// GL_NV_read_depth_stencil
+
+// GL_NV_read_stencil
+
+// GL_NV_robustness_video_memory_purge
+
+// GL_NV_shader_noperspective_interpolation
+
+// GL_OES_EGL_image
+bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLeglImageOES image);
+bool ValidateEGLImageTargetTexture2DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLeglImageOES image);
+
+// GL_OES_EGL_image_external
+
+// GL_OES_EGL_image_external_essl3
+
+// GL_OES_compressed_ETC1_RGB8_texture
+
+// GL_OES_compressed_paletted_texture
+
+// GL_OES_copy_image
+bool ValidateCopyImageSubDataOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint srcName,
+ GLenum srcTarget,
+ GLint srcLevel,
+ GLint srcX,
+ GLint srcY,
+ GLint srcZ,
+ GLuint dstName,
+ GLenum dstTarget,
+ GLint dstLevel,
+ GLint dstX,
+ GLint dstY,
+ GLint dstZ,
+ GLsizei srcWidth,
+ GLsizei srcHeight,
+ GLsizei srcDepth);
+
+// GL_OES_depth24
+
+// GL_OES_depth32
+
+// GL_OES_depth_texture
+
+// GL_OES_draw_buffers_indexed
+bool ValidateBlendEquationSeparateiOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum modeRGB,
+ GLenum modeAlpha);
+bool ValidateBlendEquationiOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum mode);
+bool ValidateBlendFuncSeparateiOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha);
+bool ValidateBlendFunciOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint buf,
+ GLenum src,
+ GLenum dst);
+bool ValidateColorMaskiOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLboolean r,
+ GLboolean g,
+ GLboolean b,
+ GLboolean a);
+bool ValidateDisableiOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index);
+bool ValidateEnableiOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index);
+bool ValidateIsEnablediOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index);
+
+// GL_OES_draw_elements_base_vertex
+bool ValidateDrawElementsBaseVertexOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex);
+bool ValidateDrawElementsInstancedBaseVertexOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex);
+bool ValidateDrawRangeElementsBaseVertexOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLuint start,
+ GLuint end,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLint basevertex);
+
+// GL_OES_draw_texture
+bool ValidateDrawTexfOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat width,
+ GLfloat height);
+bool ValidateDrawTexfvOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLfloat *coords);
+bool ValidateDrawTexiOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint width,
+ GLint height);
+bool ValidateDrawTexivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLint *coords);
+bool ValidateDrawTexsOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort x,
+ GLshort y,
+ GLshort z,
+ GLshort width,
+ GLshort height);
+bool ValidateDrawTexsvOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLshort *coords);
+bool ValidateDrawTexxOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfixed x,
+ GLfixed y,
+ GLfixed z,
+ GLfixed width,
+ GLfixed height);
+bool ValidateDrawTexxvOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLfixed *coords);
+
+// GL_OES_element_index_uint
+
+// GL_OES_fbo_render_mipmap
+
+// GL_OES_framebuffer_object
+bool ValidateBindFramebufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ FramebufferID framebufferPacked);
+bool ValidateBindRenderbufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ RenderbufferID renderbufferPacked);
+bool ValidateCheckFramebufferStatusOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target);
+bool ValidateDeleteFramebuffersOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const FramebufferID *framebuffersPacked);
+bool ValidateDeleteRenderbuffersOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const RenderbufferID *renderbuffersPacked);
+bool ValidateFramebufferRenderbufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ RenderbufferID renderbufferPacked);
+bool ValidateFramebufferTexture2DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texturePacked,
+ GLint level);
+bool ValidateGenFramebuffersOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const FramebufferID *framebuffersPacked);
+bool ValidateGenRenderbuffersOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const RenderbufferID *renderbuffersPacked);
+bool ValidateGenerateMipmapOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked);
+bool ValidateGetFramebufferAttachmentParameterivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetRenderbufferParameterivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum pname,
+ const GLint *params);
+bool ValidateIsFramebufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked);
+bool ValidateIsRenderbufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ RenderbufferID renderbufferPacked);
+bool ValidateRenderbufferStorageOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+
+// GL_OES_geometry_shader
+bool ValidateFramebufferTextureOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureID texturePacked,
+ GLint level);
+
+// GL_OES_get_program_binary
+bool ValidateGetProgramBinaryOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLenum *binaryFormat,
+ const void *binary);
+bool ValidateProgramBinaryOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum binaryFormat,
+ const void *binary,
+ GLint length);
+
+// GL_OES_mapbuffer
+bool ValidateGetBufferPointervOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLenum pname,
+ void *const *params);
+bool ValidateMapBufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLenum access);
+bool ValidateUnmapBufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked);
+
+// GL_OES_matrix_palette
+bool ValidateCurrentPaletteMatrixOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint matrixpaletteindex);
+bool ValidateLoadPaletteFromModelViewMatrixOES(const Context *context,
+ angle::EntryPoint entryPoint);
+bool ValidateMatrixIndexPointerOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer);
+bool ValidateWeightPointerOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer);
+
+// GL_OES_packed_depth_stencil
+
+// GL_OES_point_size_array
+bool ValidatePointSizePointerOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexAttribType typePacked,
+ GLsizei stride,
+ const void *pointer);
+
+// GL_OES_point_sprite
+
+// GL_OES_primitive_bounding_box
+bool ValidatePrimitiveBoundingBoxOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat minX,
+ GLfloat minY,
+ GLfloat minZ,
+ GLfloat minW,
+ GLfloat maxX,
+ GLfloat maxY,
+ GLfloat maxZ,
+ GLfloat maxW);
+
+// GL_OES_query_matrix
+bool ValidateQueryMatrixxOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLfixed *mantissa,
+ const GLint *exponent);
+
+// GL_OES_rgb8_rgba8
+
+// GL_OES_sample_shading
+bool ValidateMinSampleShadingOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat value);
+
+// GL_OES_sample_variables
+
+// GL_OES_shader_image_atomic
+
+// GL_OES_shader_io_blocks
+
+// GL_OES_shader_multisample_interpolation
+
+// GL_OES_standard_derivatives
+
+// GL_OES_surfaceless_context
+
+// GL_OES_texture_3D
+bool ValidateCompressedTexImage3DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLsizei imageSize,
+ const void *data);
+bool ValidateCompressedTexSubImage3DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+bool ValidateCopyTexSubImage3DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+bool ValidateFramebufferTexture3DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texturePacked,
+ GLint level,
+ GLint zoffset);
+bool ValidateTexImage3DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateTexSubImage3DOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+
+// GL_OES_texture_border_clamp
+bool ValidateGetSamplerParameterIivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetSamplerParameterIuivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLuint *params);
+bool ValidateGetTexParameterIivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetTexParameterIuivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params);
+bool ValidateSamplerParameterIivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLint *param);
+bool ValidateSamplerParameterIuivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ SamplerID samplerPacked,
+ GLenum pname,
+ const GLuint *param);
+bool ValidateTexParameterIivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateTexParameterIuivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum pname,
+ const GLuint *params);
+
+// GL_OES_texture_buffer
+bool ValidateTexBufferOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum internalformat,
+ BufferID bufferPacked);
+bool ValidateTexBufferRangeOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLenum internalformat,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size);
+
+// GL_OES_texture_compression_astc
+
+// GL_OES_texture_cube_map
+bool ValidateGetTexGenfvOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLfloat *params);
+bool ValidateGetTexGenivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetTexGenxvOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLfixed *params);
+bool ValidateTexGenfOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ GLfloat param);
+bool ValidateTexGenfvOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLfloat *params);
+bool ValidateTexGeniOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ GLint param);
+bool ValidateTexGenivOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLint *params);
+bool ValidateTexGenxOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ GLfixed param);
+bool ValidateTexGenxvOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLfixed *params);
+
+// GL_OES_texture_cube_map_array
+
+// GL_OES_texture_float
+
+// GL_OES_texture_float_linear
+
+// GL_OES_texture_half_float
+
+// GL_OES_texture_half_float_linear
+
+// GL_OES_texture_npot
+
+// GL_OES_texture_stencil8
+
+// GL_OES_texture_storage_multisample_2d_array
+bool ValidateTexStorage3DMultisampleOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureType targetPacked,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedsamplelocations);
+
+// GL_OES_vertex_array_object
+bool ValidateBindVertexArrayOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID arrayPacked);
+bool ValidateDeleteVertexArraysOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const VertexArrayID *arraysPacked);
+bool ValidateGenVertexArraysOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const VertexArrayID *arraysPacked);
+bool ValidateIsVertexArrayOES(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID arrayPacked);
+
+// GL_OES_vertex_half_float
+
+// GL_OES_vertex_type_10_10_10_2
+
+// GL_OVR_multiview
+bool ValidateFramebufferTextureMultiviewOVR(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureID texturePacked,
+ GLint level,
+ GLint baseViewIndex,
+ GLsizei numViews);
+
+// GL_OVR_multiview2
+
+// GL_QCOM_shading_rate
+bool ValidateShadingRateQCOM(const Context *context, angle::EntryPoint entryPoint, GLenum rate);
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_ESEXT_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationGL1.cpp b/gfx/angle/checkout/src/libANGLE/validationGL1.cpp
new file mode 100644
index 0000000000..3e884d4014
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationGL1.cpp
@@ -0,0 +1,2421 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationGL1.cpp: Validation functions for OpenGL 1.0 entry point parameters
+
+#include "libANGLE/validationGL1_autogen.h"
+
+namespace gl
+{
+
+bool ValidateAccum(const Context *, angle::EntryPoint entryPoint, GLenum op, GLfloat value)
+{
+ return true;
+}
+
+bool ValidateBegin(const Context *, angle::EntryPoint entryPoint, GLenum mode)
+{
+ return true;
+}
+
+bool ValidateBitmap(const Context *,
+ angle::EntryPoint entryPoint,
+ GLsizei width,
+ GLsizei height,
+ GLfloat xorig,
+ GLfloat yorig,
+ GLfloat xmove,
+ GLfloat ymove,
+ const GLubyte *bitmap)
+{
+ return true;
+}
+
+bool ValidateCallList(const Context *, angle::EntryPoint entryPoint, GLuint list)
+{
+ return true;
+}
+
+bool ValidateCallLists(const Context *,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ GLenum type,
+ const void *lists)
+{
+ return true;
+}
+
+bool ValidateClearAccum(const Context *,
+ angle::EntryPoint entryPoint,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue,
+ GLfloat alpha)
+{
+ return true;
+}
+
+bool ValidateClearDepth(const Context *, angle::EntryPoint entryPoint, GLdouble depth)
+{
+ return true;
+}
+
+bool ValidateClearIndex(const Context *, angle::EntryPoint entryPoint, GLfloat c)
+{
+ return true;
+}
+
+bool ValidateClipPlane(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum plane,
+ const GLdouble *equation)
+{
+ return true;
+}
+
+bool ValidateColor3b(const Context *,
+ angle::EntryPoint entryPoint,
+ GLbyte red,
+ GLbyte green,
+ GLbyte blue)
+{
+ return true;
+}
+
+bool ValidateColor3bv(const Context *, angle::EntryPoint entryPoint, const GLbyte *v)
+{
+ return true;
+}
+
+bool ValidateColor3d(const Context *,
+ angle::EntryPoint entryPoint,
+ GLdouble red,
+ GLdouble green,
+ GLdouble blue)
+{
+ return true;
+}
+
+bool ValidateColor3dv(const Context *, angle::EntryPoint entryPoint, const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateColor3f(const Context *,
+ angle::EntryPoint entryPoint,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue)
+{
+ return true;
+}
+
+bool ValidateColor3fv(const Context *, angle::EntryPoint entryPoint, const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateColor3i(const Context *,
+ angle::EntryPoint entryPoint,
+ GLint red,
+ GLint green,
+ GLint blue)
+{
+ return true;
+}
+
+bool ValidateColor3iv(const Context *, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateColor3s(const Context *,
+ angle::EntryPoint entryPoint,
+ GLshort red,
+ GLshort green,
+ GLshort blue)
+{
+ return true;
+}
+
+bool ValidateColor3sv(const Context *, angle::EntryPoint entryPoint, const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateColor3ub(const Context *,
+ angle::EntryPoint entryPoint,
+ GLubyte red,
+ GLubyte green,
+ GLubyte blue)
+{
+ return true;
+}
+
+bool ValidateColor3ubv(const Context *, angle::EntryPoint entryPoint, const GLubyte *v)
+{
+ return true;
+}
+
+bool ValidateColor3ui(const Context *,
+ angle::EntryPoint entryPoint,
+ GLuint red,
+ GLuint green,
+ GLuint blue)
+{
+ return true;
+}
+
+bool ValidateColor3uiv(const Context *, angle::EntryPoint entryPoint, const GLuint *v)
+{
+ return true;
+}
+
+bool ValidateColor3us(const Context *,
+ angle::EntryPoint entryPoint,
+ GLushort red,
+ GLushort green,
+ GLushort blue)
+{
+ return true;
+}
+
+bool ValidateColor3usv(const Context *, angle::EntryPoint entryPoint, const GLushort *v)
+{
+ return true;
+}
+
+bool ValidateColor4b(const Context *,
+ angle::EntryPoint entryPoint,
+ GLbyte red,
+ GLbyte green,
+ GLbyte blue,
+ GLbyte alpha)
+{
+ return true;
+}
+
+bool ValidateColor4bv(const Context *, angle::EntryPoint entryPoint, const GLbyte *v)
+{
+ return true;
+}
+
+bool ValidateColor4d(const Context *,
+ angle::EntryPoint entryPoint,
+ GLdouble red,
+ GLdouble green,
+ GLdouble blue,
+ GLdouble alpha)
+{
+ return true;
+}
+
+bool ValidateColor4dv(const Context *, angle::EntryPoint entryPoint, const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateColor4fv(const Context *, angle::EntryPoint entryPoint, const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateColor4i(const Context *,
+ angle::EntryPoint entryPoint,
+ GLint red,
+ GLint green,
+ GLint blue,
+ GLint alpha)
+{
+ return true;
+}
+
+bool ValidateColor4iv(const Context *, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateColor4s(const Context *,
+ angle::EntryPoint entryPoint,
+ GLshort red,
+ GLshort green,
+ GLshort blue,
+ GLshort alpha)
+{
+ return true;
+}
+
+bool ValidateColor4sv(const Context *, angle::EntryPoint entryPoint, const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateColor4ubv(const Context *, angle::EntryPoint entryPoint, const GLubyte *v)
+{
+ return true;
+}
+
+bool ValidateColor4ui(const Context *,
+ angle::EntryPoint entryPoint,
+ GLuint red,
+ GLuint green,
+ GLuint blue,
+ GLuint alpha)
+{
+ return true;
+}
+
+bool ValidateColor4uiv(const Context *, angle::EntryPoint entryPoint, const GLuint *v)
+{
+ return true;
+}
+
+bool ValidateColor4us(const Context *,
+ angle::EntryPoint entryPoint,
+ GLushort red,
+ GLushort green,
+ GLushort blue,
+ GLushort alpha)
+{
+ return true;
+}
+
+bool ValidateColor4usv(const Context *, angle::EntryPoint entryPoint, const GLushort *v)
+{
+ return true;
+}
+
+bool ValidateColorMaterial(const Context *, angle::EntryPoint entryPoint, GLenum face, GLenum mode)
+{
+ return true;
+}
+
+bool ValidateCopyPixels(const Context *,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum type)
+{
+ return true;
+}
+
+bool ValidateDeleteLists(const Context *, angle::EntryPoint entryPoint, GLuint list, GLsizei range)
+{
+ return true;
+}
+
+bool ValidateDepthRange(const Context *, angle::EntryPoint entryPoint, GLdouble n, GLdouble f)
+{
+ return true;
+}
+
+bool ValidateDrawBuffer(const Context *, angle::EntryPoint entryPoint, GLenum buf)
+{
+ return true;
+}
+
+bool ValidateDrawPixels(const Context *,
+ angle::EntryPoint entryPoint,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ return true;
+}
+
+bool ValidateEdgeFlag(const Context *, angle::EntryPoint entryPoint, GLboolean flag)
+{
+ return true;
+}
+
+bool ValidateEdgeFlagv(const Context *, angle::EntryPoint entryPoint, const GLboolean *flag)
+{
+ return true;
+}
+
+bool ValidateEnd(const Context *, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidateEndList(const Context *, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidateEvalCoord1d(const Context *, angle::EntryPoint entryPoint, GLdouble u)
+{
+ return true;
+}
+
+bool ValidateEvalCoord1dv(const Context *, angle::EntryPoint entryPoint, const GLdouble *u)
+{
+ return true;
+}
+
+bool ValidateEvalCoord1f(const Context *, angle::EntryPoint entryPoint, GLfloat u)
+{
+ return true;
+}
+
+bool ValidateEvalCoord1fv(const Context *, angle::EntryPoint entryPoint, const GLfloat *u)
+{
+ return true;
+}
+
+bool ValidateEvalCoord2d(const Context *, angle::EntryPoint entryPoint, GLdouble u, GLdouble v)
+{
+ return true;
+}
+
+bool ValidateEvalCoord2dv(const Context *, angle::EntryPoint entryPoint, const GLdouble *u)
+{
+ return true;
+}
+
+bool ValidateEvalCoord2f(const Context *, angle::EntryPoint entryPoint, GLfloat u, GLfloat v)
+{
+ return true;
+}
+
+bool ValidateEvalCoord2fv(const Context *, angle::EntryPoint entryPoint, const GLfloat *u)
+{
+ return true;
+}
+
+bool ValidateEvalMesh1(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ GLint i1,
+ GLint i2)
+{
+ return true;
+}
+
+bool ValidateEvalMesh2(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ GLint i1,
+ GLint i2,
+ GLint j1,
+ GLint j2)
+{
+ return true;
+}
+
+bool ValidateEvalPoint1(const Context *, angle::EntryPoint entryPoint, GLint i)
+{
+ return true;
+}
+
+bool ValidateEvalPoint2(const Context *, angle::EntryPoint entryPoint, GLint i, GLint j)
+{
+ return true;
+}
+
+bool ValidateFeedbackBuffer(const Context *,
+ angle::EntryPoint entryPoint,
+ GLsizei size,
+ GLenum type,
+ const GLfloat *buffer)
+{
+ return true;
+}
+
+bool ValidateFogi(const Context *, angle::EntryPoint entryPoint, GLenum pname, GLint param)
+{
+ return true;
+}
+
+bool ValidateFogiv(const Context *, angle::EntryPoint entryPoint, GLenum pname, const GLint *params)
+{
+ return true;
+}
+
+bool ValidateFrustum(const Context *,
+ angle::EntryPoint entryPoint,
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble zNear,
+ GLdouble zFar)
+{
+ return true;
+}
+
+bool ValidateGenLists(const Context *, angle::EntryPoint entryPoint, GLsizei range)
+{
+ return true;
+}
+
+bool ValidateGetClipPlane(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum plane,
+ const GLdouble *equation)
+{
+ return true;
+}
+
+bool ValidateGetDoublev(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLdouble *data)
+{
+ return true;
+}
+
+bool ValidateGetLightiv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateGetMapdv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum query,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateGetMapfv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum query,
+ const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateGetMapiv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum query,
+ const GLint *v)
+{
+ return true;
+}
+
+bool ValidateGetMaterialiv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateGetPixelMapfv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ const GLfloat *values)
+{
+ return true;
+}
+
+bool ValidateGetPixelMapuiv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ const GLuint *values)
+{
+ return true;
+}
+
+bool ValidateGetPixelMapusv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ const GLushort *values)
+{
+ return true;
+}
+
+bool ValidateGetPolygonStipple(const Context *, angle::EntryPoint entryPoint, const GLubyte *mask)
+{
+ return true;
+}
+
+bool ValidateGetTexGendv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLdouble *params)
+{
+ return true;
+}
+
+bool ValidateGetTexGenfv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLfloat *params)
+{
+ return true;
+}
+
+bool ValidateGetTexGeniv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateGetTexImage(const Context *,
+ angle::EntryPoint entryPoint,
+ TextureTarget target,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ return true;
+}
+
+bool ValidateIndexMask(const Context *, angle::EntryPoint entryPoint, GLuint mask)
+{
+ return true;
+}
+
+bool ValidateIndexd(const Context *, angle::EntryPoint entryPoint, GLdouble c)
+{
+ return true;
+}
+
+bool ValidateIndexdv(const Context *, angle::EntryPoint entryPoint, const GLdouble *c)
+{
+ return true;
+}
+
+bool ValidateIndexf(const Context *, angle::EntryPoint entryPoint, GLfloat c)
+{
+ return true;
+}
+
+bool ValidateIndexfv(const Context *, angle::EntryPoint entryPoint, const GLfloat *c)
+{
+ return true;
+}
+
+bool ValidateIndexi(const Context *, angle::EntryPoint entryPoint, GLint c)
+{
+ return true;
+}
+
+bool ValidateIndexiv(const Context *, angle::EntryPoint entryPoint, const GLint *c)
+{
+ return true;
+}
+
+bool ValidateIndexs(const Context *, angle::EntryPoint entryPoint, GLshort c)
+{
+ return true;
+}
+
+bool ValidateIndexsv(const Context *, angle::EntryPoint entryPoint, const GLshort *c)
+{
+ return true;
+}
+
+bool ValidateInitNames(const Context *, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidateIsList(const Context *, angle::EntryPoint entryPoint, GLuint list)
+{
+ return true;
+}
+
+bool ValidateLightModeli(const Context *, angle::EntryPoint entryPoint, GLenum pname, GLint param)
+{
+ return true;
+}
+
+bool ValidateLightModeliv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateLighti(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ GLenum pname,
+ GLint param)
+{
+ return true;
+}
+
+bool ValidateLightiv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateLineStipple(const Context *,
+ angle::EntryPoint entryPoint,
+ GLint factor,
+ GLushort pattern)
+{
+ return true;
+}
+
+bool ValidateListBase(const Context *, angle::EntryPoint entryPoint, GLuint base)
+{
+ return true;
+}
+
+bool ValidateLoadMatrixd(const Context *, angle::EntryPoint entryPoint, const GLdouble *m)
+{
+ return true;
+}
+
+bool ValidateLoadName(const Context *, angle::EntryPoint entryPoint, GLuint name)
+{
+ return true;
+}
+
+bool ValidateMap1d(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLdouble u1,
+ GLdouble u2,
+ GLint stride,
+ GLint order,
+ const GLdouble *points)
+{
+ return true;
+}
+
+bool ValidateMap1f(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLfloat u1,
+ GLfloat u2,
+ GLint stride,
+ GLint order,
+ const GLfloat *points)
+{
+ return true;
+}
+
+bool ValidateMap2d(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLdouble u1,
+ GLdouble u2,
+ GLint ustride,
+ GLint uorder,
+ GLdouble v1,
+ GLdouble v2,
+ GLint vstride,
+ GLint vorder,
+ const GLdouble *points)
+{
+ return true;
+}
+
+bool ValidateMap2f(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLfloat u1,
+ GLfloat u2,
+ GLint ustride,
+ GLint uorder,
+ GLfloat v1,
+ GLfloat v2,
+ GLint vstride,
+ GLint vorder,
+ const GLfloat *points)
+{
+ return true;
+}
+
+bool ValidateMapGrid1d(const Context *,
+ angle::EntryPoint entryPoint,
+ GLint un,
+ GLdouble u1,
+ GLdouble u2)
+{
+ return true;
+}
+
+bool ValidateMapGrid1f(const Context *,
+ angle::EntryPoint entryPoint,
+ GLint un,
+ GLfloat u1,
+ GLfloat u2)
+{
+ return true;
+}
+
+bool ValidateMapGrid2d(const Context *,
+ angle::EntryPoint entryPoint,
+ GLint un,
+ GLdouble u1,
+ GLdouble u2,
+ GLint vn,
+ GLdouble v1,
+ GLdouble v2)
+{
+ return true;
+}
+
+bool ValidateMapGrid2f(const Context *,
+ angle::EntryPoint entryPoint,
+ GLint un,
+ GLfloat u1,
+ GLfloat u2,
+ GLint vn,
+ GLfloat v1,
+ GLfloat v2)
+{
+ return true;
+}
+
+bool ValidateMateriali(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ GLenum pname,
+ GLint param)
+{
+ return true;
+}
+
+bool ValidateMaterialiv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateMultMatrixd(const Context *, angle::EntryPoint entryPoint, const GLdouble *m)
+{
+ return true;
+}
+
+bool ValidateNewList(const Context *, angle::EntryPoint entryPoint, GLuint list, GLenum mode)
+{
+ return true;
+}
+
+bool ValidateNormal3b(const Context *,
+ angle::EntryPoint entryPoint,
+ GLbyte nx,
+ GLbyte ny,
+ GLbyte nz)
+{
+ return true;
+}
+
+bool ValidateNormal3bv(const Context *, angle::EntryPoint entryPoint, const GLbyte *v)
+{
+ return true;
+}
+
+bool ValidateNormal3d(const Context *,
+ angle::EntryPoint entryPoint,
+ GLdouble nx,
+ GLdouble ny,
+ GLdouble nz)
+{
+ return true;
+}
+
+bool ValidateNormal3dv(const Context *, angle::EntryPoint entryPoint, const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateNormal3fv(const Context *, angle::EntryPoint entryPoint, const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateNormal3i(const Context *, angle::EntryPoint entryPoint, GLint nx, GLint ny, GLint nz)
+{
+ return true;
+}
+
+bool ValidateNormal3iv(const Context *, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateNormal3s(const Context *,
+ angle::EntryPoint entryPoint,
+ GLshort nx,
+ GLshort ny,
+ GLshort nz)
+{
+ return true;
+}
+
+bool ValidateNormal3sv(const Context *, angle::EntryPoint entryPoint, const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateOrtho(const Context *,
+ angle::EntryPoint entryPoint,
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble zNear,
+ GLdouble zFar)
+{
+ return true;
+}
+
+bool ValidatePassThrough(const Context *, angle::EntryPoint entryPoint, GLfloat token)
+{
+ return true;
+}
+
+bool ValidatePixelMapfv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ GLsizei mapsize,
+ const GLfloat *values)
+{
+ return true;
+}
+
+bool ValidatePixelMapuiv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ GLsizei mapsize,
+ const GLuint *values)
+{
+ return true;
+}
+
+bool ValidatePixelMapusv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ GLsizei mapsize,
+ const GLushort *values)
+{
+ return true;
+}
+
+bool ValidatePixelStoref(const Context *, angle::EntryPoint entryPoint, GLenum pname, GLfloat param)
+{
+ return true;
+}
+
+bool ValidatePixelTransferf(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLfloat param)
+{
+ return true;
+}
+
+bool ValidatePixelTransferi(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLint param)
+{
+ return true;
+}
+
+bool ValidatePixelZoom(const Context *,
+ angle::EntryPoint entryPoint,
+ GLfloat xfactor,
+ GLfloat yfactor)
+{
+ return true;
+}
+
+bool ValidatePolygonMode(const Context *, angle::EntryPoint entryPoint, GLenum face, GLenum mode)
+{
+ return true;
+}
+
+bool ValidatePolygonStipple(const Context *, angle::EntryPoint entryPoint, const GLubyte *mask)
+{
+ return true;
+}
+
+bool ValidatePopAttrib(const Context *, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidatePopName(const Context *, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidatePushAttrib(const Context *, angle::EntryPoint entryPoint, GLbitfield mask)
+{
+ return true;
+}
+
+bool ValidatePushName(const Context *, angle::EntryPoint entryPoint, GLuint name)
+{
+ return true;
+}
+
+bool ValidateRasterPos2d(const Context *, angle::EntryPoint entryPoint, GLdouble x, GLdouble y)
+{
+ return true;
+}
+
+bool ValidateRasterPos2dv(const Context *, angle::EntryPoint entryPoint, const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateRasterPos2f(const Context *, angle::EntryPoint entryPoint, GLfloat x, GLfloat y)
+{
+ return true;
+}
+
+bool ValidateRasterPos2fv(const Context *, angle::EntryPoint entryPoint, const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateRasterPos2i(const Context *, angle::EntryPoint entryPoint, GLint x, GLint y)
+{
+ return true;
+}
+
+bool ValidateRasterPos2iv(const Context *, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateRasterPos2s(const Context *, angle::EntryPoint entryPoint, GLshort x, GLshort y)
+{
+ return true;
+}
+
+bool ValidateRasterPos2sv(const Context *, angle::EntryPoint entryPoint, const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateRasterPos3d(const Context *,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z)
+{
+ return true;
+}
+
+bool ValidateRasterPos3dv(const Context *, angle::EntryPoint entryPoint, const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateRasterPos3f(const Context *,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z)
+{
+ return true;
+}
+
+bool ValidateRasterPos3fv(const Context *, angle::EntryPoint entryPoint, const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateRasterPos3i(const Context *, angle::EntryPoint entryPoint, GLint x, GLint y, GLint z)
+{
+ return true;
+}
+
+bool ValidateRasterPos3iv(const Context *, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateRasterPos3s(const Context *,
+ angle::EntryPoint entryPoint,
+ GLshort x,
+ GLshort y,
+ GLshort z)
+{
+ return true;
+}
+
+bool ValidateRasterPos3sv(const Context *, angle::EntryPoint entryPoint, const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateRasterPos4d(const Context *,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z,
+ GLdouble w)
+{
+ return true;
+}
+
+bool ValidateRasterPos4dv(const Context *, angle::EntryPoint entryPoint, const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateRasterPos4f(const Context *,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w)
+{
+ return true;
+}
+
+bool ValidateRasterPos4fv(const Context *, angle::EntryPoint entryPoint, const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateRasterPos4i(const Context *,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint w)
+{
+ return true;
+}
+
+bool ValidateRasterPos4iv(const Context *, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateRasterPos4s(const Context *,
+ angle::EntryPoint entryPoint,
+ GLshort x,
+ GLshort y,
+ GLshort z,
+ GLshort w)
+{
+ return true;
+}
+
+bool ValidateRasterPos4sv(const Context *, angle::EntryPoint entryPoint, const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateRectd(const Context *,
+ angle::EntryPoint entryPoint,
+ GLdouble x1,
+ GLdouble y1,
+ GLdouble x2,
+ GLdouble y2)
+{
+ return true;
+}
+
+bool ValidateRectdv(const Context *,
+ angle::EntryPoint entryPoint,
+ const GLdouble *v1,
+ const GLdouble *v2)
+{
+ return true;
+}
+
+bool ValidateRectf(const Context *,
+ angle::EntryPoint entryPoint,
+ GLfloat x1,
+ GLfloat y1,
+ GLfloat x2,
+ GLfloat y2)
+{
+ return true;
+}
+
+bool ValidateRectfv(const Context *,
+ angle::EntryPoint entryPoint,
+ const GLfloat *v1,
+ const GLfloat *v2)
+{
+ return true;
+}
+
+bool ValidateRecti(const Context *,
+ angle::EntryPoint entryPoint,
+ GLint x1,
+ GLint y1,
+ GLint x2,
+ GLint y2)
+{
+ return true;
+}
+
+bool ValidateRectiv(const Context *, angle::EntryPoint entryPoint, const GLint *v1, const GLint *v2)
+{
+ return true;
+}
+
+bool ValidateRects(const Context *,
+ angle::EntryPoint entryPoint,
+ GLshort x1,
+ GLshort y1,
+ GLshort x2,
+ GLshort y2)
+{
+ return true;
+}
+
+bool ValidateRectsv(const Context *,
+ angle::EntryPoint entryPoint,
+ const GLshort *v1,
+ const GLshort *v2)
+{
+ return true;
+}
+
+bool ValidateRenderMode(const Context *, angle::EntryPoint entryPoint, GLenum mode)
+{
+ return true;
+}
+
+bool ValidateRotated(const Context *,
+ angle::EntryPoint entryPoint,
+ GLdouble angle,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z)
+{
+ return true;
+}
+
+bool ValidateScaled(const Context *,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z)
+{
+ return true;
+}
+
+bool ValidateSelectBuffer(const Context *,
+ angle::EntryPoint entryPoint,
+ GLsizei size,
+ const GLuint *buffer)
+{
+ return true;
+}
+
+bool ValidateTexCoord1d(const Context *, angle::EntryPoint entryPoint, GLdouble s)
+{
+ return true;
+}
+
+bool ValidateTexCoord1dv(const Context *, angle::EntryPoint entryPoint, const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateTexCoord1f(const Context *, angle::EntryPoint entryPoint, GLfloat s)
+{
+ return true;
+}
+
+bool ValidateTexCoord1fv(const Context *, angle::EntryPoint entryPoint, const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateTexCoord1i(const Context *, angle::EntryPoint entryPoint, GLint s)
+{
+ return true;
+}
+
+bool ValidateTexCoord1iv(const Context *, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateTexCoord1s(const Context *, angle::EntryPoint entryPoint, GLshort s)
+{
+ return true;
+}
+
+bool ValidateTexCoord1sv(const Context *, angle::EntryPoint entryPoint, const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateTexCoord2d(const Context *, angle::EntryPoint entryPoint, GLdouble s, GLdouble t)
+{
+ return true;
+}
+
+bool ValidateTexCoord2dv(const Context *, angle::EntryPoint entryPoint, const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateTexCoord2f(const Context *, angle::EntryPoint entryPoint, GLfloat s, GLfloat t)
+{
+ return true;
+}
+
+bool ValidateTexCoord2fv(const Context *, angle::EntryPoint entryPoint, const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateTexCoord2i(const Context *, angle::EntryPoint entryPoint, GLint s, GLint t)
+{
+ return true;
+}
+
+bool ValidateTexCoord2iv(const Context *, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateTexCoord2s(const Context *, angle::EntryPoint entryPoint, GLshort s, GLshort t)
+{
+ return true;
+}
+
+bool ValidateTexCoord2sv(const Context *, angle::EntryPoint entryPoint, const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateTexCoord3d(const Context *,
+ angle::EntryPoint entryPoint,
+ GLdouble s,
+ GLdouble t,
+ GLdouble r)
+{
+ return true;
+}
+
+bool ValidateTexCoord3dv(const Context *, angle::EntryPoint entryPoint, const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateTexCoord3f(const Context *,
+ angle::EntryPoint entryPoint,
+ GLfloat s,
+ GLfloat t,
+ GLfloat r)
+{
+ return true;
+}
+
+bool ValidateTexCoord3fv(const Context *, angle::EntryPoint entryPoint, const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateTexCoord3i(const Context *, angle::EntryPoint entryPoint, GLint s, GLint t, GLint r)
+{
+ return true;
+}
+
+bool ValidateTexCoord3iv(const Context *, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateTexCoord3s(const Context *,
+ angle::EntryPoint entryPoint,
+ GLshort s,
+ GLshort t,
+ GLshort r)
+{
+ return true;
+}
+
+bool ValidateTexCoord3sv(const Context *, angle::EntryPoint entryPoint, const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateTexCoord4d(const Context *,
+ angle::EntryPoint entryPoint,
+ GLdouble s,
+ GLdouble t,
+ GLdouble r,
+ GLdouble q)
+{
+ return true;
+}
+
+bool ValidateTexCoord4dv(const Context *, angle::EntryPoint entryPoint, const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateTexCoord4f(const Context *,
+ angle::EntryPoint entryPoint,
+ GLfloat s,
+ GLfloat t,
+ GLfloat r,
+ GLfloat q)
+{
+ return true;
+}
+
+bool ValidateTexCoord4fv(const Context *, angle::EntryPoint entryPoint, const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateTexCoord4i(const Context *,
+ angle::EntryPoint entryPoint,
+ GLint s,
+ GLint t,
+ GLint r,
+ GLint q)
+{
+ return true;
+}
+
+bool ValidateTexCoord4iv(const Context *, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateTexCoord4s(const Context *,
+ angle::EntryPoint entryPoint,
+ GLshort s,
+ GLshort t,
+ GLshort r,
+ GLshort q)
+{
+ return true;
+}
+
+bool ValidateTexCoord4sv(const Context *, angle::EntryPoint entryPoint, const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateTexGend(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ GLdouble param)
+{
+ return true;
+}
+
+bool ValidateTexGendv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLdouble *params)
+{
+ return true;
+}
+
+bool ValidateTexGenf(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ GLfloat param)
+{
+ return true;
+}
+bool ValidateTexGenfv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLfloat *params)
+{
+ return true;
+}
+
+bool ValidateTexGeni(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ GLint param)
+{
+ return true;
+}
+
+bool ValidateTexGeniv(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateTexImage1D(const Context *,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ return true;
+}
+
+bool ValidateTranslated(const Context *,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z)
+{
+ return true;
+}
+
+bool ValidateVertex2d(const Context *, angle::EntryPoint entryPoint, GLdouble x, GLdouble y)
+{
+ return true;
+}
+
+bool ValidateVertex2dv(const Context *, angle::EntryPoint entryPoint, const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateVertex2f(const Context *, angle::EntryPoint entryPoint, GLfloat x, GLfloat y)
+{
+ return true;
+}
+
+bool ValidateVertex2fv(const Context *, angle::EntryPoint entryPoint, const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateVertex2i(const Context *, angle::EntryPoint entryPoint, GLint x, GLint y)
+{
+ return true;
+}
+
+bool ValidateVertex2iv(const Context *, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateVertex2s(const Context *, angle::EntryPoint entryPoint, GLshort x, GLshort y)
+{
+ return true;
+}
+
+bool ValidateVertex2sv(const Context *, angle::EntryPoint entryPoint, const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateVertex3d(const Context *,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z)
+{
+ return true;
+}
+
+bool ValidateVertex3dv(const Context *, angle::EntryPoint entryPoint, const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateVertex3f(const Context *,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z)
+{
+ return true;
+}
+
+bool ValidateVertex3fv(const Context *, angle::EntryPoint entryPoint, const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateVertex3i(const Context *, angle::EntryPoint entryPoint, GLint x, GLint y, GLint z)
+{
+ return true;
+}
+
+bool ValidateVertex3iv(const Context *, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateVertex3s(const Context *,
+ angle::EntryPoint entryPoint,
+ GLshort x,
+ GLshort y,
+ GLshort z)
+{
+ return true;
+}
+
+bool ValidateVertex3sv(const Context *, angle::EntryPoint entryPoint, const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateVertex4d(const Context *,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z,
+ GLdouble w)
+{
+ return true;
+}
+
+bool ValidateVertex4dv(const Context *, angle::EntryPoint entryPoint, const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateVertex4f(const Context *,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w)
+{
+ return true;
+}
+
+bool ValidateVertex4fv(const Context *, angle::EntryPoint entryPoint, const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateVertex4i(const Context *,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint w)
+{
+ return true;
+}
+
+bool ValidateVertex4iv(const Context *, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateVertex4s(const Context *,
+ angle::EntryPoint entryPoint,
+ GLshort x,
+ GLshort y,
+ GLshort z,
+ GLshort w)
+{
+ return true;
+}
+
+bool ValidateVertex4sv(const Context *, angle::EntryPoint entryPoint, const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateAreTexturesResident(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *textures,
+ const GLboolean *residences)
+{
+ return true;
+}
+
+bool ValidateArrayElement(const Context *context, angle::EntryPoint entryPoint, GLint i)
+{
+ return true;
+}
+
+bool ValidateCopyTexImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLint border)
+{
+ return true;
+}
+
+bool ValidateCopyTexSubImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint x,
+ GLint y,
+ GLsizei width)
+{
+ return true;
+}
+
+bool ValidateEdgeFlagPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei stride,
+ const void *pointer)
+{
+ return true;
+}
+
+bool ValidateIndexPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer)
+{
+ return true;
+}
+
+bool ValidateIndexub(const Context *context, angle::EntryPoint entryPoint, GLubyte c)
+{
+ return true;
+}
+
+bool ValidateIndexubv(const Context *context, angle::EntryPoint entryPoint, const GLubyte *c)
+{
+ return true;
+}
+
+bool ValidateInterleavedArrays(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum format,
+ GLsizei stride,
+ const void *pointer)
+{
+ return true;
+}
+
+bool ValidatePopClientAttrib(const Context *context, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidatePrioritizeTextures(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *textures,
+ const GLfloat *priorities)
+{
+ return true;
+}
+
+bool ValidatePushClientAttrib(const Context *context, angle::EntryPoint entryPoint, GLbitfield mask)
+{
+ return true;
+}
+
+bool ValidateTexSubImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ return true;
+}
+
+bool ValidateCompressedTexImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLint border,
+ GLsizei imageSize,
+ const void *data)
+{
+ return true;
+}
+
+bool ValidateCompressedTexSubImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ return true;
+}
+
+bool ValidateGetCompressedTexImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ const void *img)
+{
+ return true;
+}
+
+bool ValidateLoadTransposeMatrixd(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLdouble *m)
+{
+ return true;
+}
+
+bool ValidateLoadTransposeMatrixf(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLfloat *m)
+{
+ return true;
+}
+
+bool ValidateMultTransposeMatrixd(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLdouble *m)
+{
+ return true;
+}
+
+bool ValidateMultTransposeMatrixf(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLfloat *m)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord1d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLdouble s)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord1dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord1f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLfloat s)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord1fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord1i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint s)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord1iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLint *v)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord1s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLshort s)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord1sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLdouble s,
+ GLdouble t)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord2f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLfloat s,
+ GLfloat t)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord2i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint s,
+ GLint t)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord2iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLint *v)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord2s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLshort s,
+ GLshort t)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord2sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLdouble s,
+ GLdouble t,
+ GLdouble r)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLfloat s,
+ GLfloat t,
+ GLfloat r)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint s,
+ GLint t,
+ GLint r)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord3iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLint *v)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord3s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLshort s,
+ GLshort t,
+ GLshort r)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord3sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord4d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLdouble s,
+ GLdouble t,
+ GLdouble r,
+ GLdouble q)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord4i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint s,
+ GLint t,
+ GLint r,
+ GLint q)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord4iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLint *v)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord4s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLshort s,
+ GLshort t,
+ GLshort r,
+ GLshort q)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoord4sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateFogCoordPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer)
+{
+ return true;
+}
+
+bool ValidateFogCoordd(const Context *context, angle::EntryPoint entryPoint, GLdouble coord)
+{
+ return true;
+}
+
+bool ValidateFogCoorddv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *coord)
+{
+ return true;
+}
+
+bool ValidateFogCoordf(const Context *context, angle::EntryPoint entryPoint, GLfloat coord)
+{
+ return true;
+}
+
+bool ValidateFogCoordfv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *coord)
+{
+ return true;
+}
+
+bool ValidateMultiDrawArrays(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const GLint *first,
+ const GLsizei *count,
+ GLsizei drawcount)
+{
+ return true;
+}
+
+bool ValidateMultiDrawElements(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const GLsizei *count,
+ DrawElementsType typePacked,
+ const void *const *indices,
+ GLsizei drawcount)
+{
+ return true;
+}
+
+bool ValidatePointParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLint param)
+{
+ return true;
+}
+
+bool ValidatePointParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3b(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLbyte red,
+ GLbyte green,
+ GLbyte blue)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3bv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLbyte *v)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble red,
+ GLdouble green,
+ GLdouble blue)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint red,
+ GLint green,
+ GLint blue)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort red,
+ GLshort green,
+ GLshort blue)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3ub(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLubyte red,
+ GLubyte green,
+ GLubyte blue)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3ubv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLubyte *v)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint red,
+ GLuint green,
+ GLuint blue)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLuint *v)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3us(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLushort red,
+ GLushort green,
+ GLushort blue)
+{
+ return true;
+}
+
+bool ValidateSecondaryColor3usv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLushort *v)
+{
+ return true;
+}
+
+bool ValidateSecondaryColorPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer)
+{
+ return true;
+}
+
+bool ValidateWindowPos2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y)
+{
+ return true;
+}
+
+bool ValidateWindowPos2dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateWindowPos2f(const Context *context, angle::EntryPoint entryPoint, GLfloat x, GLfloat y)
+{
+ return true;
+}
+
+bool ValidateWindowPos2fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateWindowPos2i(const Context *context, angle::EntryPoint entryPoint, GLint x, GLint y)
+{
+ return true;
+}
+
+bool ValidateWindowPos2iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateWindowPos2s(const Context *context, angle::EntryPoint entryPoint, GLshort x, GLshort y)
+{
+ return true;
+}
+
+bool ValidateWindowPos2sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateWindowPos3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z)
+{
+ return true;
+}
+
+bool ValidateWindowPos3dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateWindowPos3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z)
+{
+ return true;
+}
+
+bool ValidateWindowPos3fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateWindowPos3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLint z)
+{
+ return true;
+}
+
+bool ValidateWindowPos3iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v)
+{
+ return true;
+}
+
+bool ValidateWindowPos3s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort x,
+ GLshort y,
+ GLshort z)
+{
+ return true;
+}
+
+bool ValidateWindowPos3sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateGetBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data)
+{
+ return true;
+}
+
+bool ValidateGetQueryObjectiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateMapBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLenum access)
+{
+ return true;
+}
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/validationGL1_autogen.h b/gfx/angle/checkout/src/libANGLE/validationGL1_autogen.h
new file mode 100644
index 0000000000..3e04829ea7
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationGL1_autogen.h
@@ -0,0 +1,1192 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationGL1_autogen.h:
+// Validation functions for the OpenGL Desktop GL 1.x entry points.
+
+#ifndef LIBANGLE_VALIDATION_GL1_AUTOGEN_H_
+#define LIBANGLE_VALIDATION_GL1_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "common/entry_points_enum_autogen.h"
+
+namespace gl
+{
+class Context;
+
+// GL 1.0
+bool ValidateAccum(const Context *context, angle::EntryPoint entryPoint, GLenum op, GLfloat value);
+bool ValidateBegin(const Context *context, angle::EntryPoint entryPoint, GLenum mode);
+bool ValidateBitmap(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei width,
+ GLsizei height,
+ GLfloat xorig,
+ GLfloat yorig,
+ GLfloat xmove,
+ GLfloat ymove,
+ const GLubyte *bitmap);
+bool ValidateCallList(const Context *context, angle::EntryPoint entryPoint, GLuint list);
+bool ValidateCallLists(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ GLenum type,
+ const void *lists);
+bool ValidateClearAccum(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue,
+ GLfloat alpha);
+bool ValidateClearDepth(const Context *context, angle::EntryPoint entryPoint, GLdouble depth);
+bool ValidateClearIndex(const Context *context, angle::EntryPoint entryPoint, GLfloat c);
+bool ValidateClipPlane(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum plane,
+ const GLdouble *equation);
+bool ValidateColor3b(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLbyte red,
+ GLbyte green,
+ GLbyte blue);
+bool ValidateColor3bv(const Context *context, angle::EntryPoint entryPoint, const GLbyte *v);
+bool ValidateColor3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble red,
+ GLdouble green,
+ GLdouble blue);
+bool ValidateColor3dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v);
+bool ValidateColor3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue);
+bool ValidateColor3fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v);
+bool ValidateColor3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint red,
+ GLint green,
+ GLint blue);
+bool ValidateColor3iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v);
+bool ValidateColor3s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort red,
+ GLshort green,
+ GLshort blue);
+bool ValidateColor3sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v);
+bool ValidateColor3ub(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLubyte red,
+ GLubyte green,
+ GLubyte blue);
+bool ValidateColor3ubv(const Context *context, angle::EntryPoint entryPoint, const GLubyte *v);
+bool ValidateColor3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint red,
+ GLuint green,
+ GLuint blue);
+bool ValidateColor3uiv(const Context *context, angle::EntryPoint entryPoint, const GLuint *v);
+bool ValidateColor3us(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLushort red,
+ GLushort green,
+ GLushort blue);
+bool ValidateColor3usv(const Context *context, angle::EntryPoint entryPoint, const GLushort *v);
+bool ValidateColor4b(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLbyte red,
+ GLbyte green,
+ GLbyte blue,
+ GLbyte alpha);
+bool ValidateColor4bv(const Context *context, angle::EntryPoint entryPoint, const GLbyte *v);
+bool ValidateColor4d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble red,
+ GLdouble green,
+ GLdouble blue,
+ GLdouble alpha);
+bool ValidateColor4dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v);
+bool ValidateColor4fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v);
+bool ValidateColor4i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint red,
+ GLint green,
+ GLint blue,
+ GLint alpha);
+bool ValidateColor4iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v);
+bool ValidateColor4s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort red,
+ GLshort green,
+ GLshort blue,
+ GLshort alpha);
+bool ValidateColor4sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v);
+bool ValidateColor4ubv(const Context *context, angle::EntryPoint entryPoint, const GLubyte *v);
+bool ValidateColor4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint red,
+ GLuint green,
+ GLuint blue,
+ GLuint alpha);
+bool ValidateColor4uiv(const Context *context, angle::EntryPoint entryPoint, const GLuint *v);
+bool ValidateColor4us(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLushort red,
+ GLushort green,
+ GLushort blue,
+ GLushort alpha);
+bool ValidateColor4usv(const Context *context, angle::EntryPoint entryPoint, const GLushort *v);
+bool ValidateColorMaterial(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ GLenum mode);
+bool ValidateCopyPixels(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height,
+ GLenum type);
+bool ValidateDeleteLists(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint list,
+ GLsizei range);
+bool ValidateDepthRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble n,
+ GLdouble f);
+bool ValidateDrawBuffer(const Context *context, angle::EntryPoint entryPoint, GLenum buf);
+bool ValidateDrawPixels(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateEdgeFlag(const Context *context, angle::EntryPoint entryPoint, GLboolean flag);
+bool ValidateEdgeFlagv(const Context *context, angle::EntryPoint entryPoint, const GLboolean *flag);
+bool ValidateEnd(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateEndList(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateEvalCoord1d(const Context *context, angle::EntryPoint entryPoint, GLdouble u);
+bool ValidateEvalCoord1dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *u);
+bool ValidateEvalCoord1f(const Context *context, angle::EntryPoint entryPoint, GLfloat u);
+bool ValidateEvalCoord1fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *u);
+bool ValidateEvalCoord2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble u,
+ GLdouble v);
+bool ValidateEvalCoord2dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *u);
+bool ValidateEvalCoord2f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat u,
+ GLfloat v);
+bool ValidateEvalCoord2fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *u);
+bool ValidateEvalMesh1(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ GLint i1,
+ GLint i2);
+bool ValidateEvalMesh2(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ GLint i1,
+ GLint i2,
+ GLint j1,
+ GLint j2);
+bool ValidateEvalPoint1(const Context *context, angle::EntryPoint entryPoint, GLint i);
+bool ValidateEvalPoint2(const Context *context, angle::EntryPoint entryPoint, GLint i, GLint j);
+bool ValidateFeedbackBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei size,
+ GLenum type,
+ const GLfloat *buffer);
+bool ValidateFogi(const Context *context, angle::EntryPoint entryPoint, GLenum pname, GLint param);
+bool ValidateFogiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLint *params);
+bool ValidateFrustum(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble zNear,
+ GLdouble zFar);
+bool ValidateGenLists(const Context *context, angle::EntryPoint entryPoint, GLsizei range);
+bool ValidateGetClipPlane(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum plane,
+ const GLdouble *equation);
+bool ValidateGetDoublev(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLdouble *data);
+bool ValidateGetLightiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetMapdv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum query,
+ const GLdouble *v);
+bool ValidateGetMapfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum query,
+ const GLfloat *v);
+bool ValidateGetMapiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum query,
+ const GLint *v);
+bool ValidateGetMaterialiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetPixelMapfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ const GLfloat *values);
+bool ValidateGetPixelMapuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ const GLuint *values);
+bool ValidateGetPixelMapusv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ const GLushort *values);
+bool ValidateGetPolygonStipple(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLubyte *mask);
+bool ValidateGetTexGendv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLdouble *params);
+bool ValidateGetTexGenfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLfloat *params);
+bool ValidateGetTexGeniv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetTexImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateIndexMask(const Context *context, angle::EntryPoint entryPoint, GLuint mask);
+bool ValidateIndexd(const Context *context, angle::EntryPoint entryPoint, GLdouble c);
+bool ValidateIndexdv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *c);
+bool ValidateIndexf(const Context *context, angle::EntryPoint entryPoint, GLfloat c);
+bool ValidateIndexfv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *c);
+bool ValidateIndexi(const Context *context, angle::EntryPoint entryPoint, GLint c);
+bool ValidateIndexiv(const Context *context, angle::EntryPoint entryPoint, const GLint *c);
+bool ValidateIndexs(const Context *context, angle::EntryPoint entryPoint, GLshort c);
+bool ValidateIndexsv(const Context *context, angle::EntryPoint entryPoint, const GLshort *c);
+bool ValidateInitNames(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateIsList(const Context *context, angle::EntryPoint entryPoint, GLuint list);
+bool ValidateLightModeli(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLint param);
+bool ValidateLightModeliv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLint *params);
+bool ValidateLighti(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ GLenum pname,
+ GLint param);
+bool ValidateLightiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum light,
+ GLenum pname,
+ const GLint *params);
+bool ValidateLineStipple(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint factor,
+ GLushort pattern);
+bool ValidateListBase(const Context *context, angle::EntryPoint entryPoint, GLuint base);
+bool ValidateLoadMatrixd(const Context *context, angle::EntryPoint entryPoint, const GLdouble *m);
+bool ValidateLoadName(const Context *context, angle::EntryPoint entryPoint, GLuint name);
+bool ValidateMap1d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLdouble u1,
+ GLdouble u2,
+ GLint stride,
+ GLint order,
+ const GLdouble *points);
+bool ValidateMap1f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLfloat u1,
+ GLfloat u2,
+ GLint stride,
+ GLint order,
+ const GLfloat *points);
+bool ValidateMap2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLdouble u1,
+ GLdouble u2,
+ GLint ustride,
+ GLint uorder,
+ GLdouble v1,
+ GLdouble v2,
+ GLint vstride,
+ GLint vorder,
+ const GLdouble *points);
+bool ValidateMap2f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLfloat u1,
+ GLfloat u2,
+ GLint ustride,
+ GLint uorder,
+ GLfloat v1,
+ GLfloat v2,
+ GLint vstride,
+ GLint vorder,
+ const GLfloat *points);
+bool ValidateMapGrid1d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint un,
+ GLdouble u1,
+ GLdouble u2);
+bool ValidateMapGrid1f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint un,
+ GLfloat u1,
+ GLfloat u2);
+bool ValidateMapGrid2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint un,
+ GLdouble u1,
+ GLdouble u2,
+ GLint vn,
+ GLdouble v1,
+ GLdouble v2);
+bool ValidateMapGrid2f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint un,
+ GLfloat u1,
+ GLfloat u2,
+ GLint vn,
+ GLfloat v1,
+ GLfloat v2);
+bool ValidateMateriali(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ GLenum pname,
+ GLint param);
+bool ValidateMaterialiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ GLenum pname,
+ const GLint *params);
+bool ValidateMultMatrixd(const Context *context, angle::EntryPoint entryPoint, const GLdouble *m);
+bool ValidateNewList(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint list,
+ GLenum mode);
+bool ValidateNormal3b(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLbyte nx,
+ GLbyte ny,
+ GLbyte nz);
+bool ValidateNormal3bv(const Context *context, angle::EntryPoint entryPoint, const GLbyte *v);
+bool ValidateNormal3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble nx,
+ GLdouble ny,
+ GLdouble nz);
+bool ValidateNormal3dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v);
+bool ValidateNormal3fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v);
+bool ValidateNormal3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint nx,
+ GLint ny,
+ GLint nz);
+bool ValidateNormal3iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v);
+bool ValidateNormal3s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort nx,
+ GLshort ny,
+ GLshort nz);
+bool ValidateNormal3sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v);
+bool ValidateOrtho(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble left,
+ GLdouble right,
+ GLdouble bottom,
+ GLdouble top,
+ GLdouble zNear,
+ GLdouble zFar);
+bool ValidatePassThrough(const Context *context, angle::EntryPoint entryPoint, GLfloat token);
+bool ValidatePixelMapfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ GLsizei mapsize,
+ const GLfloat *values);
+bool ValidatePixelMapuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ GLsizei mapsize,
+ const GLuint *values);
+bool ValidatePixelMapusv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ GLsizei mapsize,
+ const GLushort *values);
+bool ValidatePixelStoref(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLfloat param);
+bool ValidatePixelTransferf(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLfloat param);
+bool ValidatePixelTransferi(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLint param);
+bool ValidatePixelZoom(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat xfactor,
+ GLfloat yfactor);
+bool ValidatePolygonMode(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum face,
+ GLenum mode);
+bool ValidatePolygonStipple(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLubyte *mask);
+bool ValidatePopAttrib(const Context *context, angle::EntryPoint entryPoint);
+bool ValidatePopName(const Context *context, angle::EntryPoint entryPoint);
+bool ValidatePushAttrib(const Context *context, angle::EntryPoint entryPoint, GLbitfield mask);
+bool ValidatePushName(const Context *context, angle::EntryPoint entryPoint, GLuint name);
+bool ValidateRasterPos2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y);
+bool ValidateRasterPos2dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v);
+bool ValidateRasterPos2f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y);
+bool ValidateRasterPos2fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v);
+bool ValidateRasterPos2i(const Context *context, angle::EntryPoint entryPoint, GLint x, GLint y);
+bool ValidateRasterPos2iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v);
+bool ValidateRasterPos2s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort x,
+ GLshort y);
+bool ValidateRasterPos2sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v);
+bool ValidateRasterPos3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+bool ValidateRasterPos3dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v);
+bool ValidateRasterPos3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z);
+bool ValidateRasterPos3fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v);
+bool ValidateRasterPos3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLint z);
+bool ValidateRasterPos3iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v);
+bool ValidateRasterPos3s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort x,
+ GLshort y,
+ GLshort z);
+bool ValidateRasterPos3sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v);
+bool ValidateRasterPos4d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z,
+ GLdouble w);
+bool ValidateRasterPos4dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v);
+bool ValidateRasterPos4f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w);
+bool ValidateRasterPos4fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v);
+bool ValidateRasterPos4i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint w);
+bool ValidateRasterPos4iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v);
+bool ValidateRasterPos4s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort x,
+ GLshort y,
+ GLshort z,
+ GLshort w);
+bool ValidateRasterPos4sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v);
+bool ValidateRectd(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble x1,
+ GLdouble y1,
+ GLdouble x2,
+ GLdouble y2);
+bool ValidateRectdv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLdouble *v1,
+ const GLdouble *v2);
+bool ValidateRectf(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat x1,
+ GLfloat y1,
+ GLfloat x2,
+ GLfloat y2);
+bool ValidateRectfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLfloat *v1,
+ const GLfloat *v2);
+bool ValidateRecti(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x1,
+ GLint y1,
+ GLint x2,
+ GLint y2);
+bool ValidateRectiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLint *v1,
+ const GLint *v2);
+bool ValidateRects(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort x1,
+ GLshort y1,
+ GLshort x2,
+ GLshort y2);
+bool ValidateRectsv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLshort *v1,
+ const GLshort *v2);
+bool ValidateRenderMode(const Context *context, angle::EntryPoint entryPoint, GLenum mode);
+bool ValidateRotated(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble angle,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+bool ValidateScaled(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+bool ValidateSelectBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei size,
+ const GLuint *buffer);
+bool ValidateTexCoord1d(const Context *context, angle::EntryPoint entryPoint, GLdouble s);
+bool ValidateTexCoord1dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v);
+bool ValidateTexCoord1f(const Context *context, angle::EntryPoint entryPoint, GLfloat s);
+bool ValidateTexCoord1fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v);
+bool ValidateTexCoord1i(const Context *context, angle::EntryPoint entryPoint, GLint s);
+bool ValidateTexCoord1iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v);
+bool ValidateTexCoord1s(const Context *context, angle::EntryPoint entryPoint, GLshort s);
+bool ValidateTexCoord1sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v);
+bool ValidateTexCoord2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble s,
+ GLdouble t);
+bool ValidateTexCoord2dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v);
+bool ValidateTexCoord2f(const Context *context, angle::EntryPoint entryPoint, GLfloat s, GLfloat t);
+bool ValidateTexCoord2fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v);
+bool ValidateTexCoord2i(const Context *context, angle::EntryPoint entryPoint, GLint s, GLint t);
+bool ValidateTexCoord2iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v);
+bool ValidateTexCoord2s(const Context *context, angle::EntryPoint entryPoint, GLshort s, GLshort t);
+bool ValidateTexCoord2sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v);
+bool ValidateTexCoord3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble s,
+ GLdouble t,
+ GLdouble r);
+bool ValidateTexCoord3dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v);
+bool ValidateTexCoord3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat s,
+ GLfloat t,
+ GLfloat r);
+bool ValidateTexCoord3fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v);
+bool ValidateTexCoord3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint s,
+ GLint t,
+ GLint r);
+bool ValidateTexCoord3iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v);
+bool ValidateTexCoord3s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort s,
+ GLshort t,
+ GLshort r);
+bool ValidateTexCoord3sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v);
+bool ValidateTexCoord4d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble s,
+ GLdouble t,
+ GLdouble r,
+ GLdouble q);
+bool ValidateTexCoord4dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v);
+bool ValidateTexCoord4f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat s,
+ GLfloat t,
+ GLfloat r,
+ GLfloat q);
+bool ValidateTexCoord4fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v);
+bool ValidateTexCoord4i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint s,
+ GLint t,
+ GLint r,
+ GLint q);
+bool ValidateTexCoord4iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v);
+bool ValidateTexCoord4s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort s,
+ GLshort t,
+ GLshort r,
+ GLshort q);
+bool ValidateTexCoord4sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v);
+bool ValidateTexGend(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ GLdouble param);
+bool ValidateTexGendv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLdouble *params);
+bool ValidateTexGenf(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ GLfloat param);
+bool ValidateTexGenfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLfloat *params);
+bool ValidateTexGeni(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ GLint param);
+bool ValidateTexGeniv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum coord,
+ GLenum pname,
+ const GLint *params);
+bool ValidateTexImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateTranslated(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+bool ValidateVertex2d(const Context *context, angle::EntryPoint entryPoint, GLdouble x, GLdouble y);
+bool ValidateVertex2dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v);
+bool ValidateVertex2f(const Context *context, angle::EntryPoint entryPoint, GLfloat x, GLfloat y);
+bool ValidateVertex2fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v);
+bool ValidateVertex2i(const Context *context, angle::EntryPoint entryPoint, GLint x, GLint y);
+bool ValidateVertex2iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v);
+bool ValidateVertex2s(const Context *context, angle::EntryPoint entryPoint, GLshort x, GLshort y);
+bool ValidateVertex2sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v);
+bool ValidateVertex3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+bool ValidateVertex3dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v);
+bool ValidateVertex3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z);
+bool ValidateVertex3fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v);
+bool ValidateVertex3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLint z);
+bool ValidateVertex3iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v);
+bool ValidateVertex3s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort x,
+ GLshort y,
+ GLshort z);
+bool ValidateVertex3sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v);
+bool ValidateVertex4d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z,
+ GLdouble w);
+bool ValidateVertex4dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v);
+bool ValidateVertex4f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w);
+bool ValidateVertex4fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v);
+bool ValidateVertex4i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint w);
+bool ValidateVertex4iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v);
+bool ValidateVertex4s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort x,
+ GLshort y,
+ GLshort z,
+ GLshort w);
+bool ValidateVertex4sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v);
+
+// GL 1.1
+bool ValidateAreTexturesResident(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *textures,
+ const GLboolean *residences);
+bool ValidateArrayElement(const Context *context, angle::EntryPoint entryPoint, GLint i);
+bool ValidateCopyTexImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLint border);
+bool ValidateCopyTexSubImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint x,
+ GLint y,
+ GLsizei width);
+bool ValidateEdgeFlagPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei stride,
+ const void *pointer);
+bool ValidateIndexPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer);
+bool ValidateIndexub(const Context *context, angle::EntryPoint entryPoint, GLubyte c);
+bool ValidateIndexubv(const Context *context, angle::EntryPoint entryPoint, const GLubyte *c);
+bool ValidateInterleavedArrays(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum format,
+ GLsizei stride,
+ const void *pointer);
+bool ValidatePopClientAttrib(const Context *context, angle::EntryPoint entryPoint);
+bool ValidatePrioritizeTextures(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *textures,
+ const GLfloat *priorities);
+bool ValidatePushClientAttrib(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLbitfield mask);
+bool ValidateTexSubImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+
+// GL 1.2
+
+// GL 1.3
+bool ValidateCompressedTexImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLint border,
+ GLsizei imageSize,
+ const void *data);
+bool ValidateCompressedTexSubImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+bool ValidateGetCompressedTexImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureTarget targetPacked,
+ GLint level,
+ const void *img);
+bool ValidateLoadTransposeMatrixd(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLdouble *m);
+bool ValidateLoadTransposeMatrixf(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLfloat *m);
+bool ValidateMultTransposeMatrixd(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLdouble *m);
+bool ValidateMultTransposeMatrixf(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLfloat *m);
+bool ValidateMultiTexCoord1d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLdouble s);
+bool ValidateMultiTexCoord1dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLdouble *v);
+bool ValidateMultiTexCoord1f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLfloat s);
+bool ValidateMultiTexCoord1fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLfloat *v);
+bool ValidateMultiTexCoord1i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint s);
+bool ValidateMultiTexCoord1iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLint *v);
+bool ValidateMultiTexCoord1s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLshort s);
+bool ValidateMultiTexCoord1sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLshort *v);
+bool ValidateMultiTexCoord2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLdouble s,
+ GLdouble t);
+bool ValidateMultiTexCoord2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLdouble *v);
+bool ValidateMultiTexCoord2f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLfloat s,
+ GLfloat t);
+bool ValidateMultiTexCoord2fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLfloat *v);
+bool ValidateMultiTexCoord2i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint s,
+ GLint t);
+bool ValidateMultiTexCoord2iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLint *v);
+bool ValidateMultiTexCoord2s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLshort s,
+ GLshort t);
+bool ValidateMultiTexCoord2sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLshort *v);
+bool ValidateMultiTexCoord3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLdouble s,
+ GLdouble t,
+ GLdouble r);
+bool ValidateMultiTexCoord3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLdouble *v);
+bool ValidateMultiTexCoord3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLfloat s,
+ GLfloat t,
+ GLfloat r);
+bool ValidateMultiTexCoord3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLfloat *v);
+bool ValidateMultiTexCoord3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint s,
+ GLint t,
+ GLint r);
+bool ValidateMultiTexCoord3iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLint *v);
+bool ValidateMultiTexCoord3s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLshort s,
+ GLshort t,
+ GLshort r);
+bool ValidateMultiTexCoord3sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLshort *v);
+bool ValidateMultiTexCoord4d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLdouble s,
+ GLdouble t,
+ GLdouble r,
+ GLdouble q);
+bool ValidateMultiTexCoord4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLdouble *v);
+bool ValidateMultiTexCoord4fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLfloat *v);
+bool ValidateMultiTexCoord4i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint s,
+ GLint t,
+ GLint r,
+ GLint q);
+bool ValidateMultiTexCoord4iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLint *v);
+bool ValidateMultiTexCoord4s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLshort s,
+ GLshort t,
+ GLshort r,
+ GLshort q);
+bool ValidateMultiTexCoord4sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ const GLshort *v);
+
+// GL 1.4
+bool ValidateFogCoordPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer);
+bool ValidateFogCoordd(const Context *context, angle::EntryPoint entryPoint, GLdouble coord);
+bool ValidateFogCoorddv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLdouble *coord);
+bool ValidateFogCoordf(const Context *context, angle::EntryPoint entryPoint, GLfloat coord);
+bool ValidateFogCoordfv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *coord);
+bool ValidateMultiDrawArrays(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const GLint *first,
+ const GLsizei *count,
+ GLsizei drawcount);
+bool ValidateMultiDrawElements(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const GLsizei *count,
+ DrawElementsType typePacked,
+ const void *const *indices,
+ GLsizei drawcount);
+bool ValidatePointParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ GLint param);
+bool ValidatePointParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLint *params);
+bool ValidateSecondaryColor3b(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLbyte red,
+ GLbyte green,
+ GLbyte blue);
+bool ValidateSecondaryColor3bv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLbyte *v);
+bool ValidateSecondaryColor3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble red,
+ GLdouble green,
+ GLdouble blue);
+bool ValidateSecondaryColor3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLdouble *v);
+bool ValidateSecondaryColor3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat red,
+ GLfloat green,
+ GLfloat blue);
+bool ValidateSecondaryColor3fv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLfloat *v);
+bool ValidateSecondaryColor3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint red,
+ GLint green,
+ GLint blue);
+bool ValidateSecondaryColor3iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLint *v);
+bool ValidateSecondaryColor3s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort red,
+ GLshort green,
+ GLshort blue);
+bool ValidateSecondaryColor3sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLshort *v);
+bool ValidateSecondaryColor3ub(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLubyte red,
+ GLubyte green,
+ GLubyte blue);
+bool ValidateSecondaryColor3ubv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLubyte *v);
+bool ValidateSecondaryColor3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint red,
+ GLuint green,
+ GLuint blue);
+bool ValidateSecondaryColor3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLuint *v);
+bool ValidateSecondaryColor3us(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLushort red,
+ GLushort green,
+ GLushort blue);
+bool ValidateSecondaryColor3usv(const Context *context,
+ angle::EntryPoint entryPoint,
+ const GLushort *v);
+bool ValidateSecondaryColorPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer);
+bool ValidateWindowPos2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y);
+bool ValidateWindowPos2dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v);
+bool ValidateWindowPos2f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y);
+bool ValidateWindowPos2fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v);
+bool ValidateWindowPos2i(const Context *context, angle::EntryPoint entryPoint, GLint x, GLint y);
+bool ValidateWindowPos2iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v);
+bool ValidateWindowPos2s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort x,
+ GLshort y);
+bool ValidateWindowPos2sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v);
+bool ValidateWindowPos3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+bool ValidateWindowPos3dv(const Context *context, angle::EntryPoint entryPoint, const GLdouble *v);
+bool ValidateWindowPos3f(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z);
+bool ValidateWindowPos3fv(const Context *context, angle::EntryPoint entryPoint, const GLfloat *v);
+bool ValidateWindowPos3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLint x,
+ GLint y,
+ GLint z);
+bool ValidateWindowPos3iv(const Context *context, angle::EntryPoint entryPoint, const GLint *v);
+bool ValidateWindowPos3s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLshort x,
+ GLshort y,
+ GLshort z);
+bool ValidateWindowPos3sv(const Context *context, angle::EntryPoint entryPoint, const GLshort *v);
+
+// GL 1.5
+bool ValidateGetBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data);
+bool ValidateGetQueryObjectiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID idPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateMapBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLenum access);
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_GL1_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationGL2.cpp b/gfx/angle/checkout/src/libANGLE/validationGL2.cpp
new file mode 100644
index 0000000000..9eb97b2f94
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationGL2.cpp
@@ -0,0 +1,262 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationGL2.cpp: Validation functions for OpenGL 2.0 entry point parameters
+
+#include "libANGLE/validationGL2_autogen.h"
+
+namespace gl
+{
+
+bool ValidateGetVertexAttribdv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ const GLdouble *params)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib1d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib1dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib1s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLshort x)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib1sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x,
+ GLdouble y)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib2s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLshort x,
+ GLshort y)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib2sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib3s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLshort x,
+ GLshort y,
+ GLshort z)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib3sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4Nbv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLbyte *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4Niv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLint *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4Nsv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4Nub(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLubyte x,
+ GLubyte y,
+ GLubyte z,
+ GLubyte w)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4Nubv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLubyte *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4Nuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLuint *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4Nusv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLushort *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4bv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLbyte *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z,
+ GLdouble w)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLint *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLshort x,
+ GLshort y,
+ GLshort z,
+ GLshort w)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4ubv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLubyte *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLuint *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttrib4usv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLushort *v)
+{
+ return true;
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/validationGL2_autogen.h b/gfx/angle/checkout/src/libANGLE/validationGL2_autogen.h
new file mode 100644
index 0000000000..5a6e0b375f
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationGL2_autogen.h
@@ -0,0 +1,158 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationGL2_autogen.h:
+// Validation functions for the OpenGL Desktop GL 2.x entry points.
+
+#ifndef LIBANGLE_VALIDATION_GL2_AUTOGEN_H_
+#define LIBANGLE_VALIDATION_GL2_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "common/entry_points_enum_autogen.h"
+
+namespace gl
+{
+class Context;
+
+// GL 2.0
+bool ValidateGetVertexAttribdv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ const GLdouble *params);
+bool ValidateVertexAttrib1d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x);
+bool ValidateVertexAttrib1dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v);
+bool ValidateVertexAttrib1s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLshort x);
+bool ValidateVertexAttrib1sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLshort *v);
+bool ValidateVertexAttrib2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x,
+ GLdouble y);
+bool ValidateVertexAttrib2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v);
+bool ValidateVertexAttrib2s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLshort x,
+ GLshort y);
+bool ValidateVertexAttrib2sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLshort *v);
+bool ValidateVertexAttrib3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+bool ValidateVertexAttrib3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v);
+bool ValidateVertexAttrib3s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLshort x,
+ GLshort y,
+ GLshort z);
+bool ValidateVertexAttrib3sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLshort *v);
+bool ValidateVertexAttrib4Nbv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLbyte *v);
+bool ValidateVertexAttrib4Niv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLint *v);
+bool ValidateVertexAttrib4Nsv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLshort *v);
+bool ValidateVertexAttrib4Nub(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLubyte x,
+ GLubyte y,
+ GLubyte z,
+ GLubyte w);
+bool ValidateVertexAttrib4Nubv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLubyte *v);
+bool ValidateVertexAttrib4Nuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLuint *v);
+bool ValidateVertexAttrib4Nusv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLushort *v);
+bool ValidateVertexAttrib4bv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLbyte *v);
+bool ValidateVertexAttrib4d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z,
+ GLdouble w);
+bool ValidateVertexAttrib4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v);
+bool ValidateVertexAttrib4iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLint *v);
+bool ValidateVertexAttrib4s(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLshort x,
+ GLshort y,
+ GLshort z,
+ GLshort w);
+bool ValidateVertexAttrib4sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLshort *v);
+bool ValidateVertexAttrib4ubv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLubyte *v);
+bool ValidateVertexAttrib4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLuint *v);
+bool ValidateVertexAttrib4usv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLushort *v);
+
+// GL 2.1
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_GL2_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationGL3.cpp b/gfx/angle/checkout/src/libANGLE/validationGL3.cpp
new file mode 100644
index 0000000000..1e452bd0f4
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationGL3.cpp
@@ -0,0 +1,634 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationGL3.cpp: Validation functions for OpenGL 3.0 entry point parameters
+
+#include "libANGLE/validationGL3_autogen.h"
+
+namespace gl
+{
+
+bool ValidateBeginConditionalRender(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint id,
+ GLenum mode)
+{
+ return true;
+}
+
+bool ValidateBindFragDataLocation(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLuint color,
+ const GLchar *name)
+{
+ return true;
+}
+
+bool ValidateClampColor(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum clamp)
+{
+ return true;
+}
+
+bool ValidateEndConditionalRender(const Context *context, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidateFramebufferTexture1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texture,
+ GLint level)
+{
+ return true;
+}
+
+bool ValidateFramebufferTexture3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texture,
+ GLint level,
+ GLint zoffset)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI1i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint x)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI1iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLint *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI1ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLuint x)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI1uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLuint *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI2i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint x,
+ GLint y)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI2iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLint *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI2ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLuint x,
+ GLuint y)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI2uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLuint *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint x,
+ GLint y,
+ GLint z)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI3iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLint *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLuint x,
+ GLuint y,
+ GLuint z)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLuint *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI4bv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLbyte *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI4sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLshort *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI4ubv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLubyte *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttribI4usv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLushort *v)
+{
+ return true;
+}
+
+bool ValidateGetActiveUniformName(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLuint uniformIndex,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *uniformName)
+{
+ return true;
+}
+
+bool ValidatePrimitiveRestartIndex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index)
+{
+ return true;
+}
+
+bool ValidateMultiDrawElementsBaseVertex(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ const GLsizei *count,
+ DrawElementsType type,
+ const void *const *indices,
+ GLsizei drawcount,
+ const GLint *basevertex)
+{
+ return true;
+}
+
+bool ValidateProvokingVertex(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProvokingVertexConvention modePacked)
+{
+ return true;
+}
+
+bool ValidateTexImage2DMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations)
+{
+ return true;
+}
+
+bool ValidateTexImage3DMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedsamplelocations)
+{
+ return true;
+}
+
+bool ValidateBindFragDataLocationIndexed(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLuint colorNumber,
+ GLuint index,
+ const GLchar *name)
+{
+ return true;
+}
+
+bool ValidateColorP3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint color)
+{
+ return true;
+}
+
+bool ValidateColorP3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *color)
+{
+ return true;
+}
+
+bool ValidateColorP4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint color)
+{
+ return true;
+}
+
+bool ValidateColorP4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *color)
+{
+ return true;
+}
+
+bool ValidateGetFragDataIndex(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ const GLchar *name)
+{
+ return true;
+}
+
+bool ValidateGetQueryObjecti64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ const GLint64 *params)
+{
+ return true;
+}
+
+bool ValidateGetQueryObjectui64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ GLenum pname,
+ const GLuint64 *params)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoordP1ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ GLuint coords)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoordP1uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoordP2ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ GLuint coords)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoordP2uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoordP3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ GLuint coords)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoordP3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoordP4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ GLuint coords)
+{
+ return true;
+}
+
+bool ValidateMultiTexCoordP4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords)
+{
+ return true;
+}
+
+bool ValidateNormalP3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint coords)
+{
+ return true;
+}
+
+bool ValidateNormalP3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *coords)
+{
+ return true;
+}
+
+bool ValidateQueryCounter(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID id,
+ QueryType targetPacked)
+{
+ return true;
+}
+
+bool ValidateSecondaryColorP3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint color)
+{
+ return true;
+}
+
+bool ValidateSecondaryColorP3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *color)
+{
+ return true;
+}
+
+bool ValidateTexCoordP1ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint coords)
+{
+ return true;
+}
+
+bool ValidateTexCoordP1uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *coords)
+{
+ return true;
+}
+
+bool ValidateTexCoordP2ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint coords)
+{
+ return true;
+}
+
+bool ValidateTexCoordP2uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *coords)
+{
+ return true;
+}
+
+bool ValidateTexCoordP3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint coords)
+{
+ return true;
+}
+
+bool ValidateTexCoordP3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *coords)
+{
+ return true;
+}
+
+bool ValidateTexCoordP4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint coords)
+{
+ return true;
+}
+
+bool ValidateTexCoordP4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *coords)
+{
+ return true;
+}
+
+bool ValidateVertexAttribP1ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ GLuint value)
+{
+ return true;
+}
+
+bool ValidateVertexAttribP1uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value)
+{
+ return true;
+}
+
+bool ValidateVertexAttribP2ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ GLuint value)
+{
+ return true;
+}
+
+bool ValidateVertexAttribP2uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value)
+{
+ return true;
+}
+
+bool ValidateVertexAttribP3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ GLuint value)
+{
+ return true;
+}
+
+bool ValidateVertexAttribP3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value)
+{
+ return true;
+}
+
+bool ValidateVertexAttribP4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ GLuint value)
+{
+ return true;
+}
+
+bool ValidateVertexAttribP4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value)
+{
+ return true;
+}
+
+bool ValidateVertexP2ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint value)
+{
+ return true;
+}
+
+bool ValidateVertexP2uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *value)
+{
+ return true;
+}
+
+bool ValidateVertexP3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint value)
+{
+ return true;
+}
+
+bool ValidateVertexP3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *value)
+{
+ return true;
+}
+
+bool ValidateVertexP4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint value)
+{
+ return true;
+}
+
+bool ValidateVertexP4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *value)
+{
+ return true;
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/validationGL3_autogen.h b/gfx/angle/checkout/src/libANGLE/validationGL3_autogen.h
new file mode 100644
index 0000000000..1f71153cb1
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationGL3_autogen.h
@@ -0,0 +1,367 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationGL3_autogen.h:
+// Validation functions for the OpenGL Desktop GL 3.x entry points.
+
+#ifndef LIBANGLE_VALIDATION_GL3_AUTOGEN_H_
+#define LIBANGLE_VALIDATION_GL3_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "common/entry_points_enum_autogen.h"
+
+namespace gl
+{
+class Context;
+
+// GL 3.0
+bool ValidateBeginConditionalRender(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint id,
+ GLenum mode);
+bool ValidateBindFragDataLocation(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLuint color,
+ const GLchar *name);
+bool ValidateClampColor(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum clamp);
+bool ValidateEndConditionalRender(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateFramebufferTexture1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texturePacked,
+ GLint level);
+bool ValidateFramebufferTexture3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum attachment,
+ TextureTarget textargetPacked,
+ TextureID texturePacked,
+ GLint level,
+ GLint zoffset);
+bool ValidateVertexAttribI1i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint x);
+bool ValidateVertexAttribI1iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLint *v);
+bool ValidateVertexAttribI1ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLuint x);
+bool ValidateVertexAttribI1uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLuint *v);
+bool ValidateVertexAttribI2i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint x,
+ GLint y);
+bool ValidateVertexAttribI2iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLint *v);
+bool ValidateVertexAttribI2ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLuint x,
+ GLuint y);
+bool ValidateVertexAttribI2uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLuint *v);
+bool ValidateVertexAttribI3i(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint x,
+ GLint y,
+ GLint z);
+bool ValidateVertexAttribI3iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLint *v);
+bool ValidateVertexAttribI3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLuint x,
+ GLuint y,
+ GLuint z);
+bool ValidateVertexAttribI3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLuint *v);
+bool ValidateVertexAttribI4bv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLbyte *v);
+bool ValidateVertexAttribI4sv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLshort *v);
+bool ValidateVertexAttribI4ubv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLubyte *v);
+bool ValidateVertexAttribI4usv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLushort *v);
+
+// GL 3.1
+bool ValidateGetActiveUniformName(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLuint uniformIndex,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *uniformName);
+bool ValidatePrimitiveRestartIndex(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index);
+
+// GL 3.2
+bool ValidateMultiDrawElementsBaseVertex(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const GLsizei *count,
+ DrawElementsType typePacked,
+ const void *const *indices,
+ GLsizei drawcount,
+ const GLint *basevertex);
+bool ValidateProvokingVertex(const Context *context,
+ angle::EntryPoint entryPoint,
+ ProvokingVertexConvention modePacked);
+bool ValidateTexImage2DMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations);
+bool ValidateTexImage3DMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedsamplelocations);
+
+// GL 3.3
+bool ValidateBindFragDataLocationIndexed(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLuint colorNumber,
+ GLuint index,
+ const GLchar *name);
+bool ValidateColorP3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint color);
+bool ValidateColorP3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *color);
+bool ValidateColorP4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint color);
+bool ValidateColorP4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *color);
+bool ValidateGetFragDataIndex(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ const GLchar *name);
+bool ValidateGetQueryObjecti64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID idPacked,
+ GLenum pname,
+ const GLint64 *params);
+bool ValidateGetQueryObjectui64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID idPacked,
+ GLenum pname,
+ const GLuint64 *params);
+bool ValidateMultiTexCoordP1ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ GLuint coords);
+bool ValidateMultiTexCoordP1uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords);
+bool ValidateMultiTexCoordP2ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ GLuint coords);
+bool ValidateMultiTexCoordP2uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords);
+bool ValidateMultiTexCoordP3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ GLuint coords);
+bool ValidateMultiTexCoordP3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords);
+bool ValidateMultiTexCoordP4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ GLuint coords);
+bool ValidateMultiTexCoordP4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum texture,
+ GLenum type,
+ const GLuint *coords);
+bool ValidateNormalP3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint coords);
+bool ValidateNormalP3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *coords);
+bool ValidateQueryCounter(const Context *context,
+ angle::EntryPoint entryPoint,
+ QueryID idPacked,
+ QueryType targetPacked);
+bool ValidateSecondaryColorP3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint color);
+bool ValidateSecondaryColorP3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *color);
+bool ValidateTexCoordP1ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint coords);
+bool ValidateTexCoordP1uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *coords);
+bool ValidateTexCoordP2ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint coords);
+bool ValidateTexCoordP2uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *coords);
+bool ValidateTexCoordP3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint coords);
+bool ValidateTexCoordP3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *coords);
+bool ValidateTexCoordP4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint coords);
+bool ValidateTexCoordP4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *coords);
+bool ValidateVertexAttribP1ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ GLuint value);
+bool ValidateVertexAttribP1uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value);
+bool ValidateVertexAttribP2ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ GLuint value);
+bool ValidateVertexAttribP2uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value);
+bool ValidateVertexAttribP3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ GLuint value);
+bool ValidateVertexAttribP3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value);
+bool ValidateVertexAttribP4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ GLuint value);
+bool ValidateVertexAttribP4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum type,
+ GLboolean normalized,
+ const GLuint *value);
+bool ValidateVertexP2ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint value);
+bool ValidateVertexP2uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *value);
+bool ValidateVertexP3ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint value);
+bool ValidateVertexP3uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *value);
+bool ValidateVertexP4ui(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ GLuint value);
+bool ValidateVertexP4uiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum type,
+ const GLuint *value);
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_GL3_AUTOGEN_H_
diff --git a/gfx/angle/checkout/src/libANGLE/validationGL4.cpp b/gfx/angle/checkout/src/libANGLE/validationGL4.cpp
new file mode 100644
index 0000000000..066391d1d9
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationGL4.cpp
@@ -0,0 +1,2223 @@
+//
+// Copyright 2019 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationGL4.cpp: Validation functions for OpenGL 4.0 entry point parameters
+
+#include "libANGLE/validationGL4_autogen.h"
+
+namespace gl
+{
+
+bool ValidateBeginQueryIndexed(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ QueryID id)
+{
+ return true;
+}
+
+bool ValidateDrawTransformFeedback(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ TransformFeedbackID id)
+{
+ return true;
+}
+
+bool ValidateDrawTransformFeedbackStream(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ TransformFeedbackID id,
+ GLuint stream)
+{
+ return true;
+}
+
+bool ValidateEndQueryIndexed(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index)
+{
+ return true;
+}
+
+bool ValidateGetActiveSubroutineName(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum shadertype,
+ GLuint index,
+ GLsizei bufsize,
+ const GLsizei *length,
+ const GLchar *name)
+{
+ return true;
+}
+
+bool ValidateGetActiveSubroutineUniformName(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum shadertype,
+ GLuint index,
+ GLsizei bufsize,
+ const GLsizei *length,
+ const GLchar *name)
+{
+ return true;
+}
+
+bool ValidateGetActiveSubroutineUniformiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum shadertype,
+ GLuint index,
+ GLenum pname,
+ const GLint *values)
+{
+ return true;
+}
+
+bool ValidateGetProgramStageiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum shadertype,
+ GLenum pname,
+ const GLint *values)
+{
+ return true;
+}
+
+bool ValidateGetQueryIndexediv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateGetSubroutineIndex(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum shadertype,
+ const GLchar *name)
+{
+ return true;
+}
+
+bool ValidateGetSubroutineUniformLocation(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum shadertype,
+ const GLchar *name)
+{
+ return true;
+}
+
+bool ValidateGetUniformSubroutineuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum shadertype,
+ GLint location,
+ const GLuint *params)
+{
+ return true;
+}
+
+bool ValidateGetUniformdv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ const GLdouble *params)
+{
+ return true;
+}
+
+bool ValidatePatchParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLfloat *values)
+{
+ return true;
+}
+
+bool ValidateUniform1d(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLdouble x)
+{
+ return true;
+}
+
+bool ValidateUniform1dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateUniform2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLdouble x,
+ GLdouble y)
+{
+ return true;
+}
+
+bool ValidateUniform2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateUniform3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z)
+{
+ return true;
+}
+
+bool ValidateUniform3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateUniform4d(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z,
+ GLdouble w)
+{
+ return true;
+}
+
+bool ValidateUniform4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateUniformMatrix2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateUniformMatrix2x3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateUniformMatrix2x4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateUniformMatrix3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateUniformMatrix3x2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateUniformMatrix3x4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateUniformMatrix4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateUniformMatrix4x2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateUniformMatrix4x3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateUniformSubroutinesuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum shadertype,
+ GLsizei count,
+ const GLuint *indices)
+{
+ return true;
+}
+
+bool ValidateDepthRangeArrayv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint first,
+ GLsizei count,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateDepthRangeIndexed(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble n,
+ GLdouble f)
+{
+ return true;
+}
+
+bool ValidateGetDoublei_v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ const GLdouble *data)
+{
+ return true;
+}
+
+bool ValidateGetFloati_v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ const GLfloat *data)
+{
+ return true;
+}
+
+bool ValidateGetVertexAttribLdv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ const GLdouble *params)
+{
+ return true;
+}
+
+bool ValidateProgramUniform1d(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLdouble v0)
+{
+ return true;
+}
+
+bool ValidateProgramUniform1dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateProgramUniform2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLdouble v0,
+ GLdouble v1)
+{
+ return true;
+}
+
+bool ValidateProgramUniform2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateProgramUniform3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLdouble v0,
+ GLdouble v1,
+ GLdouble v2)
+{
+ return true;
+}
+
+bool ValidateProgramUniform3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateProgramUniform4d(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLdouble v0,
+ GLdouble v1,
+ GLdouble v2,
+ GLdouble v3)
+{
+ return true;
+}
+
+bool ValidateProgramUniform4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateProgramUniformMatrix2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateProgramUniformMatrix2x3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateProgramUniformMatrix2x4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateProgramUniformMatrix3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateProgramUniformMatrix3x2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateProgramUniformMatrix3x4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateProgramUniformMatrix4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateProgramUniformMatrix4x2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateProgramUniformMatrix4x3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value)
+{
+ return true;
+}
+
+bool ValidateScissorArrayv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint first,
+ GLsizei count,
+ const GLint *v)
+{
+ return true;
+}
+
+bool ValidateScissorIndexed(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint left,
+ GLint bottom,
+ GLsizei width,
+ GLsizei height)
+{
+ return true;
+}
+
+bool ValidateScissorIndexedv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLint *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttribL1d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x)
+{
+ return true;
+}
+
+bool ValidateVertexAttribL1dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttribL2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x,
+ GLdouble y)
+{
+ return true;
+}
+
+bool ValidateVertexAttribL2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttribL3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z)
+{
+ return true;
+}
+
+bool ValidateVertexAttribL3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttribL4d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z,
+ GLdouble w)
+{
+ return true;
+}
+
+bool ValidateVertexAttribL4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateVertexAttribLPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer)
+{
+ return true;
+}
+
+bool ValidateViewportArrayv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint first,
+ GLsizei count,
+ const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateViewportIndexedf(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLfloat x,
+ GLfloat y,
+ GLfloat w,
+ GLfloat h)
+{
+ return true;
+}
+
+bool ValidateViewportIndexedfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateDrawArraysInstancedBaseInstance(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLint first,
+ GLsizei count,
+ GLsizei instancecount,
+ GLuint baseinstance)
+{
+ return true;
+}
+
+bool ValidateDrawElementsInstancedBaseInstance(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei instancecount,
+ GLuint baseinstance)
+{
+ return true;
+}
+
+bool ValidateDrawElementsInstancedBaseVertexBaseInstance(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode mode,
+ GLsizei count,
+ DrawElementsType type,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex,
+ GLuint baseinstance)
+{
+ return true;
+}
+
+bool ValidateDrawTransformFeedbackInstanced(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ TransformFeedbackID id,
+ GLsizei instancecount)
+{
+ return true;
+}
+
+bool ValidateDrawTransformFeedbackStreamInstanced(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ TransformFeedbackID id,
+ GLuint stream,
+ GLsizei instancecount)
+{
+ return true;
+}
+
+bool ValidateGetActiveAtomicCounterBufferiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLuint bufferIndex,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateTexStorage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width)
+{
+ return true;
+}
+
+bool ValidateClearBufferData(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLenum format,
+ GLenum type,
+ const void *data)
+{
+ return true;
+}
+
+bool ValidateClearBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLenum format,
+ GLenum type,
+ const void *data)
+{
+ return true;
+}
+
+bool ValidateGetInternalformati64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei bufSize,
+ const GLint64 *params)
+{
+ return true;
+}
+
+bool ValidateGetProgramResourceLocationIndex(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLenum programInterface,
+ const GLchar *name)
+{
+ return true;
+}
+
+bool ValidateInvalidateBufferData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID buffer)
+{
+ return true;
+}
+
+bool ValidateInvalidateBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr length)
+{
+ return true;
+}
+
+bool ValidateInvalidateTexImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level)
+{
+ return true;
+}
+
+bool ValidateInvalidateTexSubImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ return true;
+}
+
+bool ValidateMultiDrawArraysIndirect(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride)
+{
+ return true;
+}
+
+bool ValidateMultiDrawElementsIndirect(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ DrawElementsType typePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride)
+{
+ return true;
+}
+
+bool ValidateShaderStorageBlockBinding(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ GLuint storageBlockIndex,
+ GLuint storageBlockBinding)
+{
+ return true;
+}
+
+bool ValidateTextureView(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLenum target,
+ GLuint origtexture,
+ GLenum internalformat,
+ GLuint minlevel,
+ GLuint numlevels,
+ GLuint minlayer,
+ GLuint numlayers)
+{
+ return true;
+}
+
+bool ValidateVertexAttribLFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset)
+{
+ return true;
+}
+
+bool ValidateBindBuffersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffers)
+{
+ return true;
+}
+
+bool ValidateBindBuffersRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffers,
+ const GLintptr *offsets,
+ const GLsizeiptr *sizes)
+{
+ return true;
+}
+
+bool ValidateBindImageTextures(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint first,
+ GLsizei count,
+ const GLuint *textures)
+{
+ return true;
+}
+
+bool ValidateBindSamplers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint first,
+ GLsizei count,
+ const GLuint *samplers)
+{
+ return true;
+}
+
+bool ValidateBindTextures(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint first,
+ GLsizei count,
+ const GLuint *textures)
+{
+ return true;
+}
+
+bool ValidateBindVertexBuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffers,
+ const GLintptr *offsets,
+ const GLsizei *strides)
+{
+ return true;
+}
+
+bool ValidateBufferStorage(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags)
+{
+ return true;
+}
+
+bool ValidateClearTexImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ const void *data)
+{
+ return true;
+}
+
+bool ValidateClearTexSubImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *data)
+{
+ return true;
+}
+
+bool ValidateBindTextureUnit(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint unit,
+ TextureID texture)
+{
+ return true;
+}
+
+bool ValidateBlitNamedFramebuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint readFramebuffer,
+ GLuint drawFramebuffer,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter)
+{
+ return true;
+}
+
+bool ValidateCheckNamedFramebufferStatus(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLenum target)
+{
+ return true;
+}
+
+bool ValidateClearNamedBufferData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID buffer,
+ GLenum internalformat,
+ GLenum format,
+ GLenum type,
+ const void *data)
+{
+ return true;
+}
+
+bool ValidateClearNamedBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID buffer,
+ GLenum internalformat,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLenum format,
+ GLenum type,
+ const void *data)
+{
+ return true;
+}
+
+bool ValidateClearNamedFramebufferfi(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil)
+{
+ return true;
+}
+
+bool ValidateClearNamedFramebufferfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *value)
+{
+ return true;
+}
+
+bool ValidateClearNamedFramebufferiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *value)
+{
+ return true;
+}
+
+bool ValidateClearNamedFramebufferuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *value)
+{
+ return true;
+}
+
+bool ValidateClipControl(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum origin,
+ GLenum depth)
+{
+ return true;
+}
+
+bool ValidateCompressedTextureSubImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ return true;
+}
+
+bool ValidateCompressedTextureSubImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ return true;
+}
+
+bool ValidateCompressedTextureSubImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data)
+{
+ return true;
+}
+
+bool ValidateCopyNamedBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint readBuffer,
+ GLuint writeBuffer,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size)
+{
+ return true;
+}
+
+bool ValidateCopyTextureSubImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint x,
+ GLint y,
+ GLsizei width)
+{
+ return true;
+}
+
+bool ValidateCopyTextureSubImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ return true;
+}
+
+bool ValidateCopyTextureSubImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ return true;
+}
+
+bool ValidateCreateBuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const BufferID *buffers)
+{
+ return true;
+}
+
+bool ValidateCreateFramebuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *framebuffers)
+{
+ return true;
+}
+
+bool ValidateCreateProgramPipelines(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *pipelines)
+{
+ return true;
+}
+
+bool ValidateCreateQueries(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei n,
+ const GLuint *ids)
+{
+ return true;
+}
+
+bool ValidateCreateRenderbuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const RenderbufferID *renderbuffers)
+{
+ return true;
+}
+
+bool ValidateCreateSamplers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *samplers)
+{
+ return true;
+}
+
+bool ValidateCreateTextures(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei n,
+ const GLuint *textures)
+{
+ return true;
+}
+
+bool ValidateCreateTransformFeedbacks(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *ids)
+{
+ return true;
+}
+
+bool ValidateCreateVertexArrays(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const VertexArrayID *arrays)
+{
+ return true;
+}
+
+bool ValidateDisableVertexArrayAttrib(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobj,
+ GLuint index)
+{
+ return true;
+}
+
+bool ValidateEnableVertexArrayAttrib(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobj,
+ GLuint index)
+{
+ return true;
+}
+
+bool ValidateFlushMappedNamedBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr length)
+{
+ return true;
+}
+
+bool ValidateGenerateTextureMipmap(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture)
+{
+ return true;
+}
+
+bool ValidateGetCompressedTextureImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ return true;
+}
+
+bool ValidateGetCompressedTextureSubImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ return true;
+}
+
+bool ValidateGetNamedBufferParameteri64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID buffer,
+ GLenum pname,
+ const GLint64 *params)
+{
+ return true;
+}
+
+bool ValidateGetNamedBufferParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID buffer,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateGetNamedBufferPointerv(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID buffer,
+ GLenum pname,
+ void *const *params)
+{
+ return true;
+}
+
+bool ValidateGetNamedBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data)
+{
+ return true;
+}
+
+bool ValidateGetNamedFramebufferAttachmentParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLenum attachment,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateGetNamedFramebufferParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLenum pname,
+ const GLint *param)
+{
+ return true;
+}
+
+bool ValidateGetNamedRenderbufferParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ RenderbufferID renderbuffer,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateGetQueryBufferObjecti64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint id,
+ BufferID buffer,
+ GLenum pname,
+ GLintptr offset)
+{
+ return true;
+}
+
+bool ValidateGetQueryBufferObjectiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint id,
+ BufferID buffer,
+ GLenum pname,
+ GLintptr offset)
+{
+ return true;
+}
+
+bool ValidateGetQueryBufferObjectui64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint id,
+ BufferID buffer,
+ GLenum pname,
+ GLintptr offset)
+{
+ return true;
+}
+
+bool ValidateGetQueryBufferObjectuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint id,
+ BufferID buffer,
+ GLenum pname,
+ GLintptr offset)
+{
+ return true;
+}
+
+bool ValidateGetTextureImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ return true;
+}
+
+bool ValidateGetTextureLevelParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLenum pname,
+ const GLfloat *params)
+{
+ return true;
+}
+
+bool ValidateGetTextureLevelParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateGetTextureParameterIiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateGetTextureParameterIuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLenum pname,
+ const GLuint *params)
+{
+ return true;
+}
+
+bool ValidateGetTextureParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLenum pname,
+ const GLfloat *params)
+{
+ return true;
+}
+
+bool ValidateGetTextureParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateGetTextureSubImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ return true;
+}
+
+bool ValidateGetTransformFeedbacki64_v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint xfb,
+ GLenum pname,
+ GLuint index,
+ const GLint64 *param)
+{
+ return true;
+}
+
+bool ValidateGetTransformFeedbacki_v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint xfb,
+ GLenum pname,
+ GLuint index,
+ const GLint *param)
+{
+ return true;
+}
+
+bool ValidateGetTransformFeedbackiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint xfb,
+ GLenum pname,
+ const GLint *param)
+{
+ return true;
+}
+
+bool ValidateGetVertexArrayIndexed64iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobj,
+ GLuint index,
+ GLenum pname,
+ const GLint64 *param)
+{
+ return true;
+}
+
+bool ValidateGetVertexArrayIndexediv(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobj,
+ GLuint index,
+ GLenum pname,
+ const GLint *param)
+{
+ return true;
+}
+
+bool ValidateGetVertexArrayiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobj,
+ GLenum pname,
+ const GLint *param)
+{
+ return true;
+}
+
+bool ValidateGetnColorTable(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *table)
+{
+ return true;
+}
+
+bool ValidateGetnCompressedTexImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint lod,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ return true;
+}
+
+bool ValidateGetnConvolutionFilter(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *image)
+{
+ return true;
+}
+
+bool ValidateGetnHistogram(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLboolean reset,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *values)
+{
+ return true;
+}
+
+bool ValidateGetnMapdv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum query,
+ GLsizei bufSize,
+ const GLdouble *v)
+{
+ return true;
+}
+
+bool ValidateGetnMapfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum query,
+ GLsizei bufSize,
+ const GLfloat *v)
+{
+ return true;
+}
+
+bool ValidateGetnMapiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum query,
+ GLsizei bufSize,
+ const GLint *v)
+{
+ return true;
+}
+
+bool ValidateGetnMinmax(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLboolean reset,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *values)
+{
+ return true;
+}
+
+bool ValidateGetnPixelMapfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ GLsizei bufSize,
+ const GLfloat *values)
+{
+ return true;
+}
+
+bool ValidateGetnPixelMapuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ GLsizei bufSize,
+ const GLuint *values)
+{
+ return true;
+}
+
+bool ValidateGetnPixelMapusv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ GLsizei bufSize,
+ const GLushort *values)
+{
+ return true;
+}
+
+bool ValidateGetnPolygonStipple(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei bufSize,
+ const GLubyte *pattern)
+{
+ return true;
+}
+
+bool ValidateGetnSeparableFilter(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei rowBufSize,
+ const void *row,
+ GLsizei columnBufSize,
+ const void *column,
+ const void *span)
+{
+ return true;
+}
+
+bool ValidateGetnTexImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels)
+{
+ return true;
+}
+
+bool ValidateGetnUniformdv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID program,
+ UniformLocation location,
+ GLsizei bufSize,
+ const GLdouble *params)
+{
+ return true;
+}
+
+bool ValidateInvalidateNamedFramebufferData(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLsizei numAttachments,
+ const GLenum *attachments)
+{
+ return true;
+}
+
+bool ValidateInvalidateNamedFramebufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height)
+{
+ return true;
+}
+
+bool ValidateMapNamedBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID buffer,
+ GLenum access)
+{
+ return true;
+}
+
+bool ValidateMapNamedBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access)
+{
+ return true;
+}
+
+bool ValidateNamedBufferData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID buffer,
+ GLsizeiptr size,
+ const void *data,
+ GLenum usage)
+{
+ return true;
+}
+
+bool ValidateNamedBufferStorage(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID buffer,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags)
+{
+ return true;
+}
+
+bool ValidateNamedBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data)
+{
+ return true;
+}
+
+bool ValidateNamedFramebufferDrawBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLenum buf)
+{
+ return true;
+}
+
+bool ValidateNamedFramebufferDrawBuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLsizei n,
+ const GLenum *bufs)
+{
+ return true;
+}
+
+bool ValidateNamedFramebufferParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLenum pname,
+ GLint param)
+{
+ return true;
+}
+
+bool ValidateNamedFramebufferReadBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLenum src)
+{
+ return true;
+}
+
+bool ValidateNamedFramebufferRenderbuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ RenderbufferID renderbuffer)
+{
+ return true;
+}
+
+bool ValidateNamedFramebufferTexture(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLenum attachment,
+ TextureID texture,
+ GLint level)
+{
+ return true;
+}
+
+bool ValidateNamedFramebufferTextureLayer(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebuffer,
+ GLenum attachment,
+ TextureID texture,
+ GLint level,
+ GLint layer)
+{
+ return true;
+}
+
+bool ValidateNamedRenderbufferStorage(const Context *context,
+ angle::EntryPoint entryPoint,
+ RenderbufferID renderbuffer,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ return true;
+}
+
+bool ValidateNamedRenderbufferStorageMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ RenderbufferID renderbuffer,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ return true;
+}
+
+bool ValidateTextureBarrier(const Context *context, angle::EntryPoint entryPoint)
+{
+ return true;
+}
+
+bool ValidateTextureBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLenum internalformat,
+ BufferID buffer)
+{
+ return true;
+}
+
+bool ValidateTextureBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLenum internalformat,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ return true;
+}
+
+bool ValidateTextureParameterIiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLenum pname,
+ const GLint *params)
+{
+ return true;
+}
+
+bool ValidateTextureParameterIuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLenum pname,
+ const GLuint *params)
+{
+ return true;
+}
+
+bool ValidateTextureParameterf(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLenum pname,
+ GLfloat param)
+{
+ return true;
+}
+
+bool ValidateTextureParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLenum pname,
+ const GLfloat *param)
+{
+ return true;
+}
+
+bool ValidateTextureParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLenum pname,
+ GLint param)
+{
+ return true;
+}
+
+bool ValidateTextureParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLenum pname,
+ const GLint *param)
+{
+ return true;
+}
+
+bool ValidateTextureStorage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width)
+{
+ return true;
+}
+
+bool ValidateTextureStorage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height)
+{
+ return true;
+}
+
+bool ValidateTextureStorage2DMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations)
+{
+ return true;
+}
+
+bool ValidateTextureStorage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth)
+{
+ return true;
+}
+
+bool ValidateTextureStorage3DMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedsamplelocations)
+{
+ return true;
+}
+
+bool ValidateTextureSubImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ return true;
+}
+
+bool ValidateTextureSubImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ return true;
+}
+
+bool ValidateTextureSubImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texture,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels)
+{
+ return true;
+}
+
+bool ValidateTransformFeedbackBufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint xfb,
+ GLuint index,
+ BufferID buffer)
+{
+ return true;
+}
+
+bool ValidateTransformFeedbackBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint xfb,
+ GLuint index,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizeiptr size)
+{
+ return true;
+}
+
+bool ValidateUnmapNamedBuffer(const Context *context, angle::EntryPoint entryPoint, BufferID buffer)
+{
+ return true;
+}
+
+bool ValidateVertexArrayAttribBinding(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobj,
+ GLuint attribindex,
+ GLuint bindingindex)
+{
+ return true;
+}
+
+bool ValidateVertexArrayAttribFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobj,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLuint relativeoffset)
+{
+ return true;
+}
+
+bool ValidateVertexArrayAttribIFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobj,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset)
+{
+ return true;
+}
+
+bool ValidateVertexArrayAttribLFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobj,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset)
+{
+ return true;
+}
+
+bool ValidateVertexArrayBindingDivisor(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobj,
+ GLuint bindingindex,
+ GLuint divisor)
+{
+ return true;
+}
+
+bool ValidateVertexArrayElementBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobj,
+ BufferID buffer)
+{
+ return true;
+}
+
+bool ValidateVertexArrayVertexBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobj,
+ GLuint bindingindex,
+ BufferID buffer,
+ GLintptr offset,
+ GLsizei stride)
+{
+ return true;
+}
+
+bool ValidateVertexArrayVertexBuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobj,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffers,
+ const GLintptr *offsets,
+ const GLsizei *strides)
+{
+ return true;
+}
+
+bool ValidateMultiDrawArraysIndirectCount(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ const void *indirect,
+ GLintptr drawcount,
+ GLsizei maxdrawcount,
+ GLsizei stride)
+{
+ return true;
+}
+
+bool ValidateMultiDrawElementsIndirectCount(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ GLenum type,
+ const void *indirect,
+ GLintptr drawcount,
+ GLsizei maxdrawcount,
+ GLsizei stride)
+{
+ return true;
+}
+
+bool ValidatePolygonOffsetClamp(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat factor,
+ GLfloat units,
+ GLfloat clamp)
+{
+ return true;
+}
+
+bool ValidateSpecializeShader(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint shader,
+ const GLchar *pEntryPoint,
+ GLuint numSpecializationConstants,
+ const GLuint *pConstantIndex,
+ const GLuint *pConstantValue)
+{
+ return true;
+}
+
+} // namespace gl
diff --git a/gfx/angle/checkout/src/libANGLE/validationGL4_autogen.h b/gfx/angle/checkout/src/libANGLE/validationGL4_autogen.h
new file mode 100644
index 0000000000..a69a1f2092
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/validationGL4_autogen.h
@@ -0,0 +1,1375 @@
+// GENERATED FILE - DO NOT EDIT.
+// Generated by generate_entry_points.py using data from gl.xml.
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// validationGL4_autogen.h:
+// Validation functions for the OpenGL Desktop GL 4.x entry points.
+
+#ifndef LIBANGLE_VALIDATION_GL4_AUTOGEN_H_
+#define LIBANGLE_VALIDATION_GL4_AUTOGEN_H_
+
+#include "common/PackedEnums.h"
+#include "common/entry_points_enum_autogen.h"
+
+namespace gl
+{
+class Context;
+
+// GL 4.0
+bool ValidateBeginQueryIndexed(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ QueryID idPacked);
+bool ValidateDrawTransformFeedback(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ TransformFeedbackID idPacked);
+bool ValidateDrawTransformFeedbackStream(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ TransformFeedbackID idPacked,
+ GLuint stream);
+bool ValidateEndQueryIndexed(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index);
+bool ValidateGetActiveSubroutineName(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *name);
+bool ValidateGetActiveSubroutineUniformName(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ GLuint index,
+ GLsizei bufSize,
+ const GLsizei *length,
+ const GLchar *name);
+bool ValidateGetActiveSubroutineUniformiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ GLuint index,
+ GLenum pname,
+ const GLint *values);
+bool ValidateGetProgramStageiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ GLenum pname,
+ const GLint *values);
+bool ValidateGetQueryIndexediv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetSubroutineIndex(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ const GLchar *name);
+bool ValidateGetSubroutineUniformLocation(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum shadertype,
+ const GLchar *name);
+bool ValidateGetUniformSubroutineuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum shadertype,
+ GLint location,
+ const GLuint *params);
+bool ValidateGetUniformdv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ const GLdouble *params);
+bool ValidatePatchParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum pname,
+ const GLfloat *values);
+bool ValidateUniform1d(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLdouble x);
+bool ValidateUniform1dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+bool ValidateUniform2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLdouble x,
+ GLdouble y);
+bool ValidateUniform2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+bool ValidateUniform3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+bool ValidateUniform3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+bool ValidateUniform4d(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z,
+ GLdouble w);
+bool ValidateUniform4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+bool ValidateUniformMatrix2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateUniformMatrix2x3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateUniformMatrix2x4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateUniformMatrix3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateUniformMatrix3x2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateUniformMatrix3x4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateUniformMatrix4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateUniformMatrix4x2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateUniformMatrix4x3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateUniformSubroutinesuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum shadertype,
+ GLsizei count,
+ const GLuint *indices);
+
+// GL 4.1
+bool ValidateDepthRangeArrayv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint first,
+ GLsizei count,
+ const GLdouble *v);
+bool ValidateDepthRangeIndexed(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble n,
+ GLdouble f);
+bool ValidateGetDoublei_v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ const GLdouble *data);
+bool ValidateGetFloati_v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint index,
+ const GLfloat *data);
+bool ValidateGetVertexAttribLdv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLenum pname,
+ const GLdouble *params);
+bool ValidateProgramUniform1d(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLdouble v0);
+bool ValidateProgramUniform1dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+bool ValidateProgramUniform2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLdouble v0,
+ GLdouble v1);
+bool ValidateProgramUniform2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+bool ValidateProgramUniform3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLdouble v0,
+ GLdouble v1,
+ GLdouble v2);
+bool ValidateProgramUniform3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+bool ValidateProgramUniform4d(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLdouble v0,
+ GLdouble v1,
+ GLdouble v2,
+ GLdouble v3);
+bool ValidateProgramUniform4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ const GLdouble *value);
+bool ValidateProgramUniformMatrix2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateProgramUniformMatrix2x3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateProgramUniformMatrix2x4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateProgramUniformMatrix3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateProgramUniformMatrix3x2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateProgramUniformMatrix3x4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateProgramUniformMatrix4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateProgramUniformMatrix4x2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateProgramUniformMatrix4x3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei count,
+ GLboolean transpose,
+ const GLdouble *value);
+bool ValidateScissorArrayv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint first,
+ GLsizei count,
+ const GLint *v);
+bool ValidateScissorIndexed(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint left,
+ GLint bottom,
+ GLsizei width,
+ GLsizei height);
+bool ValidateScissorIndexedv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLint *v);
+bool ValidateVertexAttribL1d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x);
+bool ValidateVertexAttribL1dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v);
+bool ValidateVertexAttribL2d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x,
+ GLdouble y);
+bool ValidateVertexAttribL2dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v);
+bool ValidateVertexAttribL3d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z);
+bool ValidateVertexAttribL3dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v);
+bool ValidateVertexAttribL4d(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLdouble x,
+ GLdouble y,
+ GLdouble z,
+ GLdouble w);
+bool ValidateVertexAttribL4dv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLdouble *v);
+bool ValidateVertexAttribLPointer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLint size,
+ GLenum type,
+ GLsizei stride,
+ const void *pointer);
+bool ValidateViewportArrayv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint first,
+ GLsizei count,
+ const GLfloat *v);
+bool ValidateViewportIndexedf(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ GLfloat x,
+ GLfloat y,
+ GLfloat w,
+ GLfloat h);
+bool ValidateViewportIndexedfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint index,
+ const GLfloat *v);
+
+// GL 4.2
+bool ValidateDrawArraysInstancedBaseInstance(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLint first,
+ GLsizei count,
+ GLsizei instancecount,
+ GLuint baseinstance);
+bool ValidateDrawElementsInstancedBaseInstance(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLuint baseinstance);
+bool ValidateDrawElementsInstancedBaseVertexBaseInstance(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ GLsizei count,
+ DrawElementsType typePacked,
+ const void *indices,
+ GLsizei instancecount,
+ GLint basevertex,
+ GLuint baseinstance);
+bool ValidateDrawTransformFeedbackInstanced(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ TransformFeedbackID idPacked,
+ GLsizei instancecount);
+bool ValidateDrawTransformFeedbackStreamInstanced(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ TransformFeedbackID idPacked,
+ GLuint stream,
+ GLsizei instancecount);
+bool ValidateGetActiveAtomicCounterBufferiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLuint bufferIndex,
+ GLenum pname,
+ const GLint *params);
+bool ValidateTexStorage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width);
+
+// GL 4.3
+bool ValidateClearBufferData(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLenum format,
+ GLenum type,
+ const void *data);
+bool ValidateClearBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLenum format,
+ GLenum type,
+ const void *data);
+bool ValidateGetInternalformati64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum internalformat,
+ GLenum pname,
+ GLsizei count,
+ const GLint64 *params);
+bool ValidateGetProgramResourceLocationIndex(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLenum programInterface,
+ const GLchar *name);
+bool ValidateInvalidateBufferData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID bufferPacked);
+bool ValidateInvalidateBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr length);
+bool ValidateInvalidateTexImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level);
+bool ValidateInvalidateTexSubImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+bool ValidateMultiDrawArraysIndirect(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride);
+bool ValidateMultiDrawElementsIndirect(const Context *context,
+ angle::EntryPoint entryPoint,
+ PrimitiveMode modePacked,
+ DrawElementsType typePacked,
+ const void *indirect,
+ GLsizei drawcount,
+ GLsizei stride);
+bool ValidateShaderStorageBlockBinding(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ GLuint storageBlockIndex,
+ GLuint storageBlockBinding);
+bool ValidateTextureView(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLenum target,
+ GLuint origtexture,
+ GLenum internalformat,
+ GLuint minlevel,
+ GLuint numlevels,
+ GLuint minlayer,
+ GLuint numlayers);
+bool ValidateVertexAttribLFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset);
+
+// GL 4.4
+bool ValidateBindBuffersBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked);
+bool ValidateBindBuffersRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ const GLintptr *offsets,
+ const GLsizeiptr *sizes);
+bool ValidateBindImageTextures(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint first,
+ GLsizei count,
+ const GLuint *textures);
+bool ValidateBindSamplers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint first,
+ GLsizei count,
+ const GLuint *samplers);
+bool ValidateBindTextures(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint first,
+ GLsizei count,
+ const GLuint *textures);
+bool ValidateBindVertexBuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ const GLintptr *offsets,
+ const GLsizei *strides);
+bool ValidateBufferStorage(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferBinding targetPacked,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags);
+bool ValidateClearTexImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ const void *data);
+bool ValidateClearTexSubImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *data);
+
+// GL 4.5
+bool ValidateBindTextureUnit(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint unit,
+ TextureID texturePacked);
+bool ValidateBlitNamedFramebuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint readFramebuffer,
+ GLuint drawFramebuffer,
+ GLint srcX0,
+ GLint srcY0,
+ GLint srcX1,
+ GLint srcY1,
+ GLint dstX0,
+ GLint dstY0,
+ GLint dstX1,
+ GLint dstY1,
+ GLbitfield mask,
+ GLenum filter);
+bool ValidateCheckNamedFramebufferStatus(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLenum target);
+bool ValidateClearNamedBufferData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID bufferPacked,
+ GLenum internalformat,
+ GLenum format,
+ GLenum type,
+ const void *data);
+bool ValidateClearNamedBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID bufferPacked,
+ GLenum internalformat,
+ GLintptr offset,
+ GLsizeiptr size,
+ GLenum format,
+ GLenum type,
+ const void *data);
+bool ValidateClearNamedFramebufferfi(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLenum buffer,
+ GLint drawbuffer,
+ GLfloat depth,
+ GLint stencil);
+bool ValidateClearNamedFramebufferfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLfloat *value);
+bool ValidateClearNamedFramebufferiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLint *value);
+bool ValidateClearNamedFramebufferuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLenum buffer,
+ GLint drawbuffer,
+ const GLuint *value);
+bool ValidateClipControl(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum origin,
+ GLenum depth);
+bool ValidateCompressedTextureSubImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+bool ValidateCompressedTextureSubImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+bool ValidateCompressedTextureSubImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLsizei imageSize,
+ const void *data);
+bool ValidateCopyNamedBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint readBuffer,
+ GLuint writeBuffer,
+ GLintptr readOffset,
+ GLintptr writeOffset,
+ GLsizeiptr size);
+bool ValidateCopyTextureSubImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint x,
+ GLint y,
+ GLsizei width);
+bool ValidateCopyTextureSubImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+bool ValidateCopyTextureSubImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+bool ValidateCreateBuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const BufferID *buffersPacked);
+bool ValidateCreateFramebuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *framebuffers);
+bool ValidateCreateProgramPipelines(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *pipelines);
+bool ValidateCreateQueries(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei n,
+ const GLuint *ids);
+bool ValidateCreateRenderbuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const RenderbufferID *renderbuffersPacked);
+bool ValidateCreateSamplers(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *samplers);
+bool ValidateCreateTextures(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLsizei n,
+ const GLuint *textures);
+bool ValidateCreateTransformFeedbacks(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const GLuint *ids);
+bool ValidateCreateVertexArrays(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei n,
+ const VertexArrayID *arraysPacked);
+bool ValidateDisableVertexArrayAttrib(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobjPacked,
+ GLuint index);
+bool ValidateEnableVertexArrayAttrib(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobjPacked,
+ GLuint index);
+bool ValidateFlushMappedNamedBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr length);
+bool ValidateGenerateTextureMipmap(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked);
+bool ValidateGetCompressedTextureImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLsizei bufSize,
+ const void *pixels);
+bool ValidateGetCompressedTextureSubImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLsizei bufSize,
+ const void *pixels);
+bool ValidateGetNamedBufferParameteri64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID bufferPacked,
+ GLenum pname,
+ const GLint64 *params);
+bool ValidateGetNamedBufferParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID bufferPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetNamedBufferPointerv(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID bufferPacked,
+ GLenum pname,
+ void *const *params);
+bool ValidateGetNamedBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data);
+bool ValidateGetNamedFramebufferAttachmentParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLenum attachment,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetNamedFramebufferParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLenum pname,
+ const GLint *param);
+bool ValidateGetNamedRenderbufferParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ RenderbufferID renderbufferPacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetQueryBufferObjecti64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint id,
+ BufferID bufferPacked,
+ GLenum pname,
+ GLintptr offset);
+bool ValidateGetQueryBufferObjectiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint id,
+ BufferID bufferPacked,
+ GLenum pname,
+ GLintptr offset);
+bool ValidateGetQueryBufferObjectui64v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint id,
+ BufferID bufferPacked,
+ GLenum pname,
+ GLintptr offset);
+bool ValidateGetQueryBufferObjectuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint id,
+ BufferID bufferPacked,
+ GLenum pname,
+ GLintptr offset);
+bool ValidateGetTextureImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+bool ValidateGetTextureLevelParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLenum pname,
+ const GLfloat *params);
+bool ValidateGetTextureLevelParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetTextureParameterIiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetTextureParameterIuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLuint *params);
+bool ValidateGetTextureParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLfloat *params);
+bool ValidateGetTextureParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateGetTextureSubImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+bool ValidateGetTransformFeedbacki64_v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint xfb,
+ GLenum pname,
+ GLuint index,
+ const GLint64 *param);
+bool ValidateGetTransformFeedbacki_v(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint xfb,
+ GLenum pname,
+ GLuint index,
+ const GLint *param);
+bool ValidateGetTransformFeedbackiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint xfb,
+ GLenum pname,
+ const GLint *param);
+bool ValidateGetVertexArrayIndexed64iv(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobjPacked,
+ GLuint index,
+ GLenum pname,
+ const GLint64 *param);
+bool ValidateGetVertexArrayIndexediv(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobjPacked,
+ GLuint index,
+ GLenum pname,
+ const GLint *param);
+bool ValidateGetVertexArrayiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobjPacked,
+ GLenum pname,
+ const GLint *param);
+bool ValidateGetnColorTable(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *table);
+bool ValidateGetnCompressedTexImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint lod,
+ GLsizei bufSize,
+ const void *pixels);
+bool ValidateGetnConvolutionFilter(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *image);
+bool ValidateGetnHistogram(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLboolean reset,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *values);
+bool ValidateGetnMapdv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum query,
+ GLsizei bufSize,
+ const GLdouble *v);
+bool ValidateGetnMapfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum query,
+ GLsizei bufSize,
+ const GLfloat *v);
+bool ValidateGetnMapiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum query,
+ GLsizei bufSize,
+ const GLint *v);
+bool ValidateGetnMinmax(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLboolean reset,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *values);
+bool ValidateGetnPixelMapfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ GLsizei bufSize,
+ const GLfloat *values);
+bool ValidateGetnPixelMapuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ GLsizei bufSize,
+ const GLuint *values);
+bool ValidateGetnPixelMapusv(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum map,
+ GLsizei bufSize,
+ const GLushort *values);
+bool ValidateGetnPolygonStipple(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLsizei bufSize,
+ const GLubyte *pattern);
+bool ValidateGetnSeparableFilter(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLenum format,
+ GLenum type,
+ GLsizei rowBufSize,
+ const void *row,
+ GLsizei columnBufSize,
+ const void *column,
+ const void *span);
+bool ValidateGetnTexImage(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum target,
+ GLint level,
+ GLenum format,
+ GLenum type,
+ GLsizei bufSize,
+ const void *pixels);
+bool ValidateGetnUniformdv(const Context *context,
+ angle::EntryPoint entryPoint,
+ ShaderProgramID programPacked,
+ UniformLocation locationPacked,
+ GLsizei bufSize,
+ const GLdouble *params);
+bool ValidateInvalidateNamedFramebufferData(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLsizei numAttachments,
+ const GLenum *attachments);
+bool ValidateInvalidateNamedFramebufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLsizei numAttachments,
+ const GLenum *attachments,
+ GLint x,
+ GLint y,
+ GLsizei width,
+ GLsizei height);
+bool ValidateMapNamedBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID bufferPacked,
+ GLenum access);
+bool ValidateMapNamedBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr length,
+ GLbitfield access);
+bool ValidateNamedBufferData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID bufferPacked,
+ GLsizeiptr size,
+ const void *data,
+ GLenum usage);
+bool ValidateNamedBufferStorage(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID bufferPacked,
+ GLsizeiptr size,
+ const void *data,
+ GLbitfield flags);
+bool ValidateNamedBufferSubData(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void *data);
+bool ValidateNamedFramebufferDrawBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLenum buf);
+bool ValidateNamedFramebufferDrawBuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLsizei n,
+ const GLenum *bufs);
+bool ValidateNamedFramebufferParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLenum pname,
+ GLint param);
+bool ValidateNamedFramebufferReadBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLenum src);
+bool ValidateNamedFramebufferRenderbuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ RenderbufferID renderbufferPacked);
+bool ValidateNamedFramebufferTexture(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLenum attachment,
+ TextureID texturePacked,
+ GLint level);
+bool ValidateNamedFramebufferTextureLayer(const Context *context,
+ angle::EntryPoint entryPoint,
+ FramebufferID framebufferPacked,
+ GLenum attachment,
+ TextureID texturePacked,
+ GLint level,
+ GLint layer);
+bool ValidateNamedRenderbufferStorage(const Context *context,
+ angle::EntryPoint entryPoint,
+ RenderbufferID renderbufferPacked,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+bool ValidateNamedRenderbufferStorageMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ RenderbufferID renderbufferPacked,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+bool ValidateTextureBarrier(const Context *context, angle::EntryPoint entryPoint);
+bool ValidateTextureBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLenum internalformat,
+ BufferID bufferPacked);
+bool ValidateTextureBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLenum internalformat,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size);
+bool ValidateTextureParameterIiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLint *params);
+bool ValidateTextureParameterIuiv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLuint *params);
+bool ValidateTextureParameterf(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLenum pname,
+ GLfloat param);
+bool ValidateTextureParameterfv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLfloat *param);
+bool ValidateTextureParameteri(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLenum pname,
+ GLint param);
+bool ValidateTextureParameteriv(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLenum pname,
+ const GLint *param);
+bool ValidateTextureStorage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width);
+bool ValidateTextureStorage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height);
+bool ValidateTextureStorage2DMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLboolean fixedsamplelocations);
+bool ValidateTextureStorage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth);
+bool ValidateTextureStorage3DMultisample(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLboolean fixedsamplelocations);
+bool ValidateTextureSubImage1D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateTextureSubImage2D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateTextureSubImage3D(const Context *context,
+ angle::EntryPoint entryPoint,
+ TextureID texturePacked,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLint zoffset,
+ GLsizei width,
+ GLsizei height,
+ GLsizei depth,
+ GLenum format,
+ GLenum type,
+ const void *pixels);
+bool ValidateTransformFeedbackBufferBase(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint xfb,
+ GLuint index,
+ BufferID bufferPacked);
+bool ValidateTransformFeedbackBufferRange(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint xfb,
+ GLuint index,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizeiptr size);
+bool ValidateUnmapNamedBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ BufferID bufferPacked);
+bool ValidateVertexArrayAttribBinding(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobjPacked,
+ GLuint attribindex,
+ GLuint bindingindex);
+bool ValidateVertexArrayAttribFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobjPacked,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLuint relativeoffset);
+bool ValidateVertexArrayAttribIFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobjPacked,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset);
+bool ValidateVertexArrayAttribLFormat(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobjPacked,
+ GLuint attribindex,
+ GLint size,
+ GLenum type,
+ GLuint relativeoffset);
+bool ValidateVertexArrayBindingDivisor(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobjPacked,
+ GLuint bindingindex,
+ GLuint divisor);
+bool ValidateVertexArrayElementBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobjPacked,
+ BufferID bufferPacked);
+bool ValidateVertexArrayVertexBuffer(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobjPacked,
+ GLuint bindingindex,
+ BufferID bufferPacked,
+ GLintptr offset,
+ GLsizei stride);
+bool ValidateVertexArrayVertexBuffers(const Context *context,
+ angle::EntryPoint entryPoint,
+ VertexArrayID vaobjPacked,
+ GLuint first,
+ GLsizei count,
+ const BufferID *buffersPacked,
+ const GLintptr *offsets,
+ const GLsizei *strides);
+
+// GL 4.6
+bool ValidateMultiDrawArraysIndirectCount(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ const void *indirect,
+ GLintptr drawcount,
+ GLsizei maxdrawcount,
+ GLsizei stride);
+bool ValidateMultiDrawElementsIndirectCount(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLenum mode,
+ GLenum type,
+ const void *indirect,
+ GLintptr drawcount,
+ GLsizei maxdrawcount,
+ GLsizei stride);
+bool ValidatePolygonOffsetClamp(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLfloat factor,
+ GLfloat units,
+ GLfloat clamp);
+bool ValidateSpecializeShader(const Context *context,
+ angle::EntryPoint entryPoint,
+ GLuint shader,
+ const GLchar *pEntryPoint,
+ GLuint numSpecializationConstants,
+ const GLuint *pConstantIndex,
+ const GLuint *pConstantValue);
+} // namespace gl
+
+#endif // LIBANGLE_VALIDATION_GL4_AUTOGEN_H_